Beispiel für eine Overpass-Abfrage

Höhenprofil einer Bergbahn

Den Anstieg einer Bahnlinie aus ihrer Routengeometrie und der API für Höhenprofile zeichnen. Beispiel: die Pilatusbahn, die steilste Zahnradbahn.

Eine Routen-Relation enthält die Ways einer Linie in ihrer Reihenfolge. Fügen Sie ihre Geometrie zu einem Pfad zusammen und schicken Sie ihn an /elevation/profile: Sie erhalten alle 90 m eine Höhe mit der Distanz vom Start, den gesamten Anstieg und den tiefsten und höchsten Punkt.

Die Pilatusbahn bei Luzern ist die steilste Zahnradbahn der Welt, mit Steigungen bis 48%.

Die Abfrage

[out:json][timeout:25];
rel["route"="train"]["ref"="CC83"]["to"="Pilatus Kulm"];
out geom;

Ausführen

Die Abfrage läuft…

Live-Ergebnis von overpass.ch, bis zu 12 Stunden zwischengespeichert. Kartendaten © OpenStreetMap-Mitwirkende (ODbL). Heights produced using Copernicus WorldDEM™-90 © DLR e.V. 2010-2014 and © Airbus Defence and Space GmbH 2014-2018 provided under COPERNICUS by the European Union and ESA; all rights reserved. Meerestiefen: GEBCO Compilation Group (2026) GEBCO 2026 Grid.

So funktioniert es

  1. rel["route"="train"]["ref"="CC83"]["to"="Pilatus Kulm"] wählt die Bergfahrt der Linie CC83. Die Talfahrt ist eine eigene Relation.
  2. out geom; liefert die Relation mit den Koordinaten jedes Mitglieds.
  3. Die Mitglieder mit leerer Rolle sind das Gleis; Mitglieder stop und platform fallen weg. Fügen Sie die Ways der Reihe nach zusammen, und drehen Sie einen Way um, wenn sein Ende statt seines Anfangs den vorherigen berührt.
  4. Schicken Sie den Pfad als {"path": [[lat, lon], …]} an /elevation/profile. In diesen Daten ist die Linie etwa 4,3 km lang und steigt etwa 1'590 m.

Varianten

  • Die Gornergratbahn in Zermatt: rel["route"="train"]["name"="R48 (CC): Zermatt GGB => Gornergrat"]; (9,3 km, etwa 1'490 m Anstieg).
  • Den Abstand ändern Sie mit interval (in Metern, mindestens 10) oder samples, wie in der Dokumentation beschrieben.
  • Ein GPX-Track statt einer OSM-Route: Schicken Sie die Datei selbst an /elevation/profile, siehe Höhen zu einer GPX-Datei hinzufügen.

Aus Ihrem Code ausführen

Zwei Anfragen: Die Abfrage liefert die Route, und ihre zusammengesetzte Geometrie geht an /elevation/profile.

import math
import requests

API = "https://api.overpass.ch/v1/IHR_API_SCHLÜSSEL"
query = open("query.overpassql").read()
r = requests.post(f"{API}/interpreter", data={"data": query}, timeout=120)
r.raise_for_status()
route = r.json()["elements"][0]

def gap(a, b):  # Abstand in Grad, genügt zum Vergleichen
    return math.hypot(a[0] - b[0], (a[1] - b[1]) * math.cos(math.radians(a[0])))

ways = [[[p["lat"], p["lon"]] for p in m["geometry"]] for m in route["members"]
        if m["type"] == "way" and m["role"] in ("", "forward", "backward")]
path = list(ways[0])
for i, way in enumerate(ways[1:]):
    near = lambda p: min(gap(p, way[0]), gap(p, way[-1]))
    if i == 0 and near(path[0]) < near(path[-1]):
        path.reverse()      # der erste Weg zeigt rückwärts
    if gap(path[-1], way[-1]) < gap(path[-1], way[0]):
        way = way[::-1]     # dieser auch
    path += way

r = requests.post(f"{API}/elevation/profile", json={"path": path}, timeout=60)
r.raise_for_status()
answer = r.json()
print(answer["profile"])    # distance_m, ascent_m, descent_m, min_m, max_m, …
for p in answer["results"][:5]:
    print(p["distance"], p["elevation"])

Speichern Sie die Abfrage als query.overpassql. Sie funktioniert genauso in Overpass Turbo, QGIS und JOSM.

Weitere Beispiele

Alle Beispiele →