Benutzer-Werkzeuge

Webseiten-Werkzeuge


osmium

Dies ist eine alte Version des Dokuments!


Inhaltsverzeichnis

Osmium ist ein CLI-Tool für die Arbeit mit OSM-Daten und basiert auf der C-Bibliothek libosmium. Es kann mit mehreren OSM-Datenformaten arbeiten, vor allem:

Osmium ist eher zum Anzeigen und Exportieren gedacht als zum Bearbeiten

Linux

sudo apt update
sudo apt install osmium-tool

osmium extract --bbox 16.20,48.10,16.50,48.35 --strategy smart -o wien.osm.pbf europe-latest.osm.pbf

osmium tags-filter wien.osm.pbf n/highway=bus_stop -o bus_stops.osm.pbf

Python

import osmium
import sys
 
MIN_LON = 16.20
MIN_LAT = 48.10
MAX_LON = 16.50
MAX_LAT = 48.35
 
INPUT_FILE = "europe-latest.osm.pbf"
OUTPUT_FILE = "wien.osm.pbf"
 
 
def in_bbox(lon: float, lat: float) -> bool:
    return MIN_LON <= lon <= MAX_LON and MIN_LAT <= lat <= MAX_LAT
 
 
class BBoxWriter(osmium.SimpleHandler):
    def __init__(self, writer):
        super().__init__()
        self.writer = writer
 
    def node(self, n):
        if n.location.valid() and in_bbox(n.location.lon, n.location.lat):
            self.writer.add_node(n)
 
    def way(self, w):
        for nr in w.nodes:
            if nr.location.valid() and in_bbox(nr.location.lon, nr.location.lat):
                self.writer.add_way(w)
                return
 
    def relation(self, r):
        # Sehr einfache Variante:
        # Relations werden hier nicht sauber räumlich geprüft.
        # Für vollständige OSM-Extrakte ist osmium-tool besser.
        pass
 
 
def main():
    writer = osmium.SimpleWriter(OUTPUT_FILE)
    handler = BBoxWriter(writer)
 
    try:
        # mit_locations() ist nötig, damit Ways Node-Koordinaten bekommen
        handler.apply_file(INPUT_FILE, locations=True)
    finally:
        writer.close()
 
    print(f"Fertig: {OUTPUT_FILE}")
 
 
if __name__ == "__main__":
    main()
python.exe -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
pip install osmium
python script.py

Search-Source extrahieren

wget https://download.geofabrik.de/europe/austria-latest.osm.pbf

osmium tags-filter austria-latest.osm.pbf \
  nwr/place \
  nwr/amenity \
  nwr/shop \
  nwr/tourism \
  nwr/leisure \
  nwr/railway \
  nwr/public_transport \
  nwr/highway \
  nwr/addr:* \
  -o search-source.osm.pbf

osmium export search-source.osm.pbf -o search-source.geojson

search.json bauen

import json
 
INPUT = "search-source.geojson"
OUTPUT = "search.json"
 
def center_of_geometry(geom):
    t = geom.get("type")
    coords = geom.get("coordinates")
 
    if t == "Point":
        return coords[0], coords[1]
 
    if t == "LineString" and coords:
        mid = coords[len(coords) // 2]
        return mid[0], mid[1]
 
    if t == "Polygon" and coords and coords[0]:
        ring = coords[0]
        mid = ring[len(ring) // 2]
        return mid[0], mid[1]
 
    if t == "MultiPolygon" and coords and coords[0] and coords[0][0]:
        ring = coords[0][0]
        mid = ring[len(ring) // 2]
        return mid[0], mid[1]
 
    return None, None
 
def norm(props, *keys):
    for k in keys:
        v = props.get(k)
        if v:
            return str(v).strip()
    return ""
 
with open(INPUT, "r", encoding="utf-8") as f:
    geo = json.load(f)
 
out = []
seen = set()
 
for feat in geo.get("features", []):
    props = feat.get("properties", {})
    geom = feat.get("geometry", {})
 
    lng, lat = center_of_geometry(geom)
    if lng is None or lat is None:
        continue
 
    name = norm(props, "name:de", "name_de", "name")
    place = norm(props, "place")
    housenumber = norm(props, "addr:housenumber")
    street = norm(props, "addr:street")
    city = norm(props, "addr:city", "addr:place")
    postcode = norm(props, "addr:postcode")
    amenity = norm(props, "amenity")
    shop = norm(props, "shop")
    tourism = norm(props, "tourism")
    leisure = norm(props, "leisure")
    railway = norm(props, "railway")
    public_transport = norm(props, "public_transport")
    highway = norm(props, "highway")
 
    item = None
 
    if housenumber and street:
        item = {
            "t": "house",
            "name": f"{street} {housenumber}",
            "street": street,
            "housenumber": housenumber,
            "city": city,
            "postcode": postcode,
            "lat": round(lat, 6),
            "lng": round(lng, 6),
        }
    elif highway and name:
        item = {
            "t": "street",
            "name": name,
            "city": city,
            "postcode": postcode,
            "lat": round(lat, 6),
            "lng": round(lng, 6),
        }
    elif place and name:
        item = {
            "t": "place",
            "name": name,
            "place": place,
            "postcode": postcode,
            "lat": round(lat, 6),
            "lng": round(lng, 6),
        }
    elif name and (amenity or shop or tourism or leisure or railway or public_transport):
        item = {
            "t": "poi",
            "name": name,
            "class": amenity or shop or tourism or leisure or railway or public_transport,
            "lat": round(lat, 6),
            "lng": round(lng, 6),
        }
 
    if not item:
        continue
 
    key = (item["t"], item["name"], item["lat"], item["lng"])
    if key in seen:
        continue
    seen.add(key)
    out.append(item)
 
with open(OUTPUT, "w", encoding="utf-8") as f:
    json.dump(out, f, ensure_ascii=False, separators=(",", ":"))
 
print(f"{len(out)} Einträge nach {OUTPUT} geschrieben")

Im Browser suchen

let SEARCH_INDEX = [];
 
async function loadSearchIndex() {
  const res = await fetch("search.json");
  SEARCH_INDEX = await res.json();
}
 
function searchLocal(query) {
  const q = query.trim().toLowerCase();
  if (!q) return [];
 
  return SEARCH_INDEX
    .filter(item => {
      const hay = [
        item.name || "",
        item.street || "",
        item.city || "",
        item.postcode || ""
      ].join(" ").toLowerCase();
 
      return hay.includes(q);
    })
    .slice(0, 20);
}
osmium.1774880317.txt.gz · Zuletzt geändert: 2026/03/30 16:18 von jango