Overpass Abfrage, Alle Orte mit Straßen eines Landkreises

Hallo Leute,

habe letztens OSM für mich entdeckt und habe viel Spaß daran. Da ich die Daten von OSM auch für ein privates Projekt brauchen kann, stehe ich vor einer mehr oder weniger großen Herausforderung.

Und zwar benötige ich (wenn möglich) eine Abfrage, aller Orte mit den Tags place=village und place=town in einem Landkreis. Dazu brauch ich für jeden Ort, bzw. in meinem Fall jede bestehende PLZ im Landkreis eine Liste mit den dort bestehenden Straßen.

Habe es seither so gemacht, dass ich einen Query für alle place=village und place=town im Landkreis hatte, dann die PLZs in eine Liste gelegt habe und für jede PLZ eine eigene Query gestartet habe. Hat im Grunde auch funktioniert, bis ich logischerweise die Zahl der Anfragen (429:too many requests) überschritten habe. Gibt es eine Möglichkeit das in einer einzigen Abfrage zu verpacken?

Beispiel:

[u][b]Ort 1:[/b][/u]
name:
plz:
population:
etc..
[b]
strassen:[/b] 
strasse1
strasse2
strasse3
strasse4
.
.
.

[u][b]Ort 2:[/b][/u]
name:
plz:
population:
etc..
[b]
strassen:[/b] 
strasse1
strasse2
strasse3
strasse4
.
.
.

MfG

Hallo und willkommen,

schau am besten mal in die Beispielsammlung: http://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_API_by_Example

Hi, habe ich bereits. Finde allerdings kein vergleichbares Beispiel.

Sinngemäß wäre es etwas wie:


- Finde alle Orte im Landkreis x
- Lege alle Orte in Liste y

Für jeden Ort in Liste y:
- Finde alle Straßen im Ort => Lege diese in eine Liste, die zum Ort gehört

“Finde alle Orte im Landkreis x” und “Finde alle Straßen im Ort” kriege ich mit dieser Overpass-Abfrage problemlos hin. Lediglich die Verknüpfung kriege ich nicht hin.

LG

//  alle Straßen im LK BB sortiert nach Gemeinden
[out:csv(::id,::type,"name")][timeout:100];

area[admin_level=6][name="Landkreis Böblingen"]->.boundaryarea;
rel(area.boundaryarea)[admin_level=8][name~"^H"];
map_to_area;

foreach -> .d (
  .d out;
   way(area.d)[highway][name]; 
   out geom;
 );

Vielleicht nicht genau, was Du brauchst.
[name~“^H”] schränkt die Suche auf Ortsnamen mit H am Anfang ein, sonst dauerte es mir zu lang.

Hallo fx99,

danke für deine Antwort. War im Grunde schon genau das, was ich suchte. Wenn ich da meine Versuche anschaue, dann lag ich weit daneben :slight_smile: Meine Codes waren da wesentlich länger. Vielen Dank für dafür.

Mein Code, den ich dann im Endeffekt nutze, sieht dann so aus:

[out:json][timeout:100];

area[admin_level=6][name="Name Landkreis"]->.boundaryarea;
rel(area.boundaryarea)[admin_level=8][name];
map_to_area;

foreach -> .d (
  .d out;
   way(area.d)[highway=residential][name]; 
   out;
 );

Es gibt kein einzelnes Beispiel, aber alle Teile der Query oben sind wirklich in der Beispielsammlung zu finden:

  1. Ermittlung der Gemeinden in einem Landkreis: http://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_API_by_Example#Counties_without_fire_station

  2. Iterieren über die Liste der gefundenen Areas: http://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_API_by_Example#Count_Pharmacies_per_County_.28updated_0.7.54.29

  3. Ausgabe der entsprechenden Ways pro Area: http://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_API_by_Example#List_of_streets

Frage: sollen wir dieses Beispiel auch noch in die Sammlung aufnehmen?

Trotz dessen, dass ich mit einigen Programmiersprachen vertraut bin, fällt es mir insgesamt schwer, mich mit der von Overpass vertraut zu machen. Kann gut sein, dass es nur an mir liegt. Wenn man der Meinung ist, dass dieses Beispiel ein Mehrwert für alle zukünftigen User ist, dann spricht im Grunde nichts dagegen. Aber andererseits kann man es sich u.U. auch herleiten. Ich könnte bzw. konnte es mit diesen Links oben nicht, obwohl es bloß an der Liste lag. Punkt 1 und 3 sind bzw. waren schon vorher klar.

LG

Das enthält prinzipiell doch alles:
a. Berechnen von areas
b. Schleife über die areas
c. Ausgabe von Werten

Mit einfachen Anpassungen sollte das gestellte Problem lösbar sein.

Guten Morgen,

habe es mir alles nochmal in Ruhe vorgelesen und mittlerweile meine ich es auch verstanden zu haben. Das Beispiel mit den Apotheken hatte ich sogar als ich es probiert hatte zur Hand. Ich konnte nur nichts mit der folgenden Zeile anfangen:


[out:csv(::type, "de:regionalschluessel", name,
         ::count, ::"count:nodes", ::"count:ways", ::"count:relations")];

//Alle areas mit Regionalschlüssel beginnend mit 057
area["de:regionalschluessel"~"^057.*"];

// In jeder Area Apotheken zählen
_______foreach->.regio(_________ // <=
  // zunächst Details zur aktuellen Area ausgeben
  .regio out;
  // Alle Knoten, Wege und Relationen mit amenity=pharmacy  in aktueller Area  sammeln
  ( node(area.regio)[amenity=pharmacy];
    way(area.regio)[amenity=pharmacy];
    rel(area.regio)[amenity=pharmacy]);
// Elemente in aktueller Area zählen, noch experimentell in 0.7.51!  
  out count; 
);

Wenn ich es jetzt aber richtig verstanden habe, heißt die Zeile soviel wie “Verwende jede Area, die mit dem Regionalschlüssel 057 anfängt als Variable mit dem Namen regio” und dann wird der Befehl drunter mit den Nodes,Ways und Relations ausgegeben und im Anschluss wird mit dem nächsten Regionalschlüssel angefangen bis man durch ist.

Ich habe die ganze Zeit gedacht, dass .regio ein Befehl oder eine fest in der API bereits definierte Variable sei, was mich beim Befehl “foreach->.regio(” zur Verzweiflung getrieben hat. Ich dachte halt sinngemäß “Ja, toll. Für jede regio führe ich was aus? Was zum Geier soll regio sein?” Die Verbindung area => regio fehlte halt.

Aber wenns so stimmt wie ich glaube es jetzt verstanden zu haben, dann wäre auch kein separates Beispiel mehr nötig. Für mich würde es dann auch Sinn ergeben.

LG

withdrawn!

Nein, ganz sicher nicht. Empirisch ermittelt finden 105% der Benutzer die Sprache schwierig bis völlig unverständlich und sind froh, wenn sie dem Overpass Turbo Wizard passende Queries entlocken können - auch wenn sie damit wirklich nur einen kleinen der Funktionalität nutzen können.

Foreach sieht auf den ersten Blick nicht sehr intuitiv aus. In anderen Sprachen wäre das sowas wie:

for (regio in menge_aller_regio_areas)
{
mache hier irgendwas mit regio;
}

wobei die menge_aller_regios in der Query oben in der implizit vorhandenen Standardmenge ._ steckt. Diese implizite Menge lässt man meistens weg, was manchmal etwas verwirrend sein kann. Ausgeschrieben wäre das:


area["de:regionalschluessel"~"^057.*"] -> ._;
foreach ._ -> .regio ( 
    bla; 
    bla; 
    bla;
    out ...;
 );

Mit benannten Mengen wird das hoffentlich etwas klarer:


[out:csv(::type, "de:regionalschluessel", name,
         ::count, ::"count:nodes", ::"count:ways", ::"count:relations")];

//Alle areas mit Regionalschlüssel beginnend mit 057
area["de:regionalschluessel"~"^057.*"]->.ich_bin_die_menge_aller_areas_mit_regionalschluessel_57;

// In jeder Area Apotheken zählen
   foreach .ich_bin_die_menge_aller_areas_mit_regionalschluessel_57 -> .einzelne_area_aus_der_menge_der_regionalschluessel (
  . .einzelne_area_aus_der_menge_der_regionalschluessel out;
  // Alle Knoten, Wege und Relationen mit amenity=pharmacy  in aktueller Area  sammeln
  ( node(area.einzelne_area_aus_der_menge_der_regionalschluessel)[amenity=pharmacy];
    way(area .einzelne_area_aus_der_menge_der_regionalschluessel)[amenity=pharmacy];
    rel(area .einzelne_area_aus_der_menge_der_regionalschluessel)[amenity=pharmacy]);

  out count; 
);

Ungeschickterweise machen

area["de:regionalschluessel"~"^057.*"] -> .reg;
foreach   .regio ( 
    .regio out ;
   bla; ...
    out ...;
 );

und

area["de:regionalschluessel"~"^057.*"] ;
foreach ->  .regio ( 
    .regio out ;
   bla; ...
    out ...;
 );

unterschiedliche Dinge.

Im ersten Fall werden zunächst alle .regio ausgegeben, danach alle bla; http://overpass-turbo.eu/s/sLQ
im zweiten eine .regio, danach die dazugehörigen bla. http://overpass-turbo.eu/s/sLR

Hier schlägt wieder das implizite Defaultset zu:

foreach .gemeinde ( entspricht: foreach .gemeinde → ._ (

foreach → .gemeinde ( entspricht: foreach ._ → .gemeinde (

Falls das zu verwirrend ist, kann man die einzelnen Eingabe- und Ausgabemengen immer mit eigenem Namen versehen:

foreach .alle_gemeinden → .gemeinde (

.alle_gemeinden ist die Eingabemenge, über die foreach iteriert. Diese wird außerhalb des foreach schon gefüllt.
.gemeinde enthält die jeweils aktuelle Gemeinde in der laufenden Iteration