Gelöst: Overpass-API: Union

Hallo

im Rahmen eines Analyse-Tools für ÖPNV-Verbünde habe ich z.B. folgende Overpass-API_Abfrage:

http://overpass-api.de/api/interpreter?data=area[boundary=administrative][admin_level=6][name=‘Landkreis Dingolfing-Landau’]->.L; rel(area.L)[route~‘(bus||share_taxi)’]->.R; rel(br.R); out; rel.R; out; rel(r.R); out; way(r.R); out; node(r.R); out;"

Sprich alles was man von ÖPNV-Relationen (Ptv1, PTv2) so braucht.

  • Im Landkreis Dingolfing-Landau suche (area[boundary=administrative][admin_level=6][name=‘Landkreis Dingolfing-Landau’]->.L)
  • alle Bus und Share_Taxi Routen-Relationen (rel(area.L)[route~‘(bus||share_taxi)’])->.R
    1. Ausgabe deren Route-Master (sofern existent) (rel(br.R); out)
    1. Ausgabe der Routen selbst (rel.R; out)
    1. Ausgabe deren enthaltenen Relationen (rel(r.R); out)
    1. Ausgabe deren enthaltenen Ways (way(r.R); out)
    1. Ausgabe deren enthaltenen Nodes (node(r.R))

Nun kann es passieren, dass Route-Master (aus 1.) wiederum Routen als Member haben, die in 2. nicht enthalten sind, da sie im Suchgebiet nicht gefunden wurden. Dafür gibt es mehrere Gründe, die hier weniger wichtig sind.

Wie kann ich eine weitere Abfrage 2b. machen, die alle Routen der Route-Master aus 1. ausgibt, aber nicht die, die schon in 2. ausgegeben wurden?
Quasi nur noch die Routen ausgeben, die noch fehlen.

Evtl:

rel(br.R)->M; ( rel.R; rel.M )->A; rel.A; out; rel.M; out; rel(r.A); out; way(r.A); out; node(r.A); out;

rel.R sind auch Routen ohne Route-Master, ein einfaches rel.M reicht nicht aus.

Evtl. ist rel.A; out; auch nicht optimal da “A” eh nur Relationen enthält.

Mein Tool käme mit doppelt vorhandenen Relation-ID im XML zurecht, ich will nur die Datenmenge klein halten.
Bei größeren Verbünden wie MVV in München und Umgebung sind das eh schon > 50 MB.

VG
Toni

Ich hab zwar den Anfang noch nicht ganz verstanden, aber die Differenzmenge sollte deine Lösung sein.
(.AbfrageEins - .AbfrageZwei) ->.RestZweiB

Gruß, Axel

Kleine Datenmenge sollte mit out geom möglich sein, das passt aber wahrscheinlich nicht zu deinem Parser…


area[boundary=administrative][admin_level=6]
  [name='Landkreis Dingolfing-Landau'];
( 
  rel(area)[route~'(bus|share_taxi)'];
  rel[type=route_master](br);
  rel(r);  
);
out geom;

Ansonsten würde ich mal noch probieren:


area[boundary=administrative][admin_level=6]
  [name='Landkreis Dingolfing-Landau'];
(
  (
    rel(area)[route~'(bus|share_taxi)'];
    rel[type=route_master](br);
  );
 >>;
);
out;

Ich arbeite hier bewusst nur mit einem out Statement, die Reihenfolge der Ausgabe ist OSM XML typisch Node, Way, Relation.

Falls die route_master nicht komplett aufgelöst werden sollen (da kann ja noch einiges anderes Zeugs drin sein, was kein bus oder share_taxi ist):


area[boundary=administrative][admin_level=6]
  [name='Landkreis Dingolfing-Landau'];
(
  rel(area)[route~'(bus|share_taxi)'] -> .routes; .routes >>;
  rel[type=route_master](br.routes);
);
out;

Ich bin mir nicht sicher, ob ich das verständlich erklärt habe.

Die Differenzmenge ja, aber dann noch die ursprüngliche Menge hinzu.
Also eventuell:

area[boundary=administrative][admin_level=6][name=‘Landkreis Dingolfing-Landau’]->.Landkreis;

rel(area.Landkreis)[route~‘(bus|share_taxi)’]->.Routen_im_Landkreis;

rel(br.Routen_im_Landkreis)->Route_Master_im_Landkreis;

( .Routen_im_Landkreis - rel.Route_Master_im_Landkreis )->.Verlinkte_Routen_außerhalb_des_Landkreises;

( .Routen_im_Landkreis; Verlinkte_Routen_außerhalb_des_Landkreises; )->.Alle_Routen;

.Route_Master_im_Landkreis; out;

.Alle_Routen; out;

rel(r.Alle_Routen); out;

way(r.Alle_Routen); out;

node(r.Alle_Routen); out;

Einfacher wird es dadurch auch nicht. Ich versuche es mal mit mmds Ansatz, der sieht intelligenter aus.

Danke Axel.

VG Toni

Danke mmd,

der Ansatz gefällt mir, wenn ich denn die Wirkung von ‘>>’ richtig verstehe. Der “recurse down relations” doch nur durch Relationen, oder?

Denn von allen Route-Master_Relationen brauche ich die

  • ID und tags der Relation
  • alle role, ID und type der Member
  • sofern die Member wiederum Route-Relationen sind … siehe folgendes

Von allen Route-Relationen brauche ich

  • ID und tags der Relation
  • alle role, ID und type der Member
  • tags der Member-Relationen
  • tags der Member-Ways
  • ID der Member-Nodes der Member-Ways
  • tags der Member-Nodes

Dazu müsste ich u.U. way(r); und node(r); an der richtigen Stelle mit einbauen und ein einfaches ‘>’, recurse down?

Ich spiele mal ein wenig damit rum, mal sehen, wie ich alles, aber nicht zu viel bekomme.

N.B.: mein Parser ist derzeit XML::Simple in Perl. Der ist aber grotten-langsam. Den will ich durch Geo::OSM::Parse ersetzen, wodurch ich für den MVV dann nicht mehr 6 Minuten sondern nur noch 40 Sekunden (allein) zum Parsen brauche. Die Analyse geht in 2-4 Sekunden.

Danke und viele Grüße
Toni

Nicht ganz, >> löst zusätzlich auch noch die Relationen auf, aber nur eine Ebene. Ich weiß nicht, wie tief die route_master geschachtelt sind, ggfs. hilft da ein weiteres “>>;” weiter, um eine weitere Ebene aufzulösen. Ein generisches Auflösen wird mit 0.7.55 und “complete” möglich sein.

https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Recurse_down_.28.3E.29

Danke mmd,

Ich habe es ausprobiert. Leider liefert ‘>>’ zu viele Infos (die tags) von Nodes, die mich nicht interessieren: Stop-Schilder, Traffic-Islands, Zug-Signale, Ampeln, … (tags aller Nodes, die auf den ÖPNV-Wegen liegen). Ich brauche “nur” die tags von Bus-Stops, … (Nodes, die Member einer Relation sind).

Aber das Thema scheint gelöst zu sein. Ich habe es auf einem kleineren Gebiet ausprobiert.

Alt:

http://overpass-api.de/api/interpreter?data=
area[boundary=administrative][admin_level=8][name='Ottobrunn']->.O;
rel(area.O)[route~'(bus|train)']->.R;
rel(br.R); out;
rel.R; out;
rel(r.R); out;
way(r.R); out;
node(r.R); out;

Neu:

http://overpass-api.de/api/interpreter?data=
area[boundary=administrative][admin_level=8][name='Ottobrunn'];
rel(area)[route~'(bus|train)']->.Routen_innerhalb;
rel[type~'route_master'](br.Routen_innerhalb)->.Route_Master_innerhalb;
rel[type~'route'](r.Route_Master_innerhalb)->.Routen_mit_RM;
( rel.Routen_innerhalb; - rel.Routen_mit_RM;)->.Routen_ohne_RM;
( rel.Routen_ohne_RM; rel.Routen_mit_RM; )->.Alle_Routen;
rel.Route_Master_innerhalb; out;
rel.Alle_Routen; out;
rel(r.Alle_Routen); out;
way(r.Alle_Routen); out;
node(r.Alle_Routen); out;

Die neue Query scheint zu tun was ich will. Es war ein langer Weg, bis ich die Query syntaktisch korrekt hatte.

Danke nochmals für die Anregungen und den Hirnschmalz.

VG
Toni

Ich hab die Query mal etwas schlanker gemacht, Ergebnis ist dasselbe, bis auf die Node/Way/Rel Reihenfolge. Auch gehe ich davon aus, dass in den route_master Relationen nur andere Relationen drin sind, ansonsten würde die Query auch hier Nodes und Ways auflösen:


area[boundary=administrative][admin_level=8][name='Ottobrunn'];
(
  rel(area)[route~'(bus|train)']; 
  rel[type~'route_master'](br);
  rel[type~'route'](r);
)->.routes;
(
  .routes;
  rel(r.routes); 
  way(r.routes);
  node(r.routes);
);
out;

Super,

das sieht deutlich eleganter aus und liefert das gleiche Ergebnis. Ich bin beeindruckt.

Ansonsten wäre das ein Fehler, der durch das Tool gefunden und gemeldet würde. Es wäre somit ein temporärer, weil zu korrigierender Fehler.

Danke nochmals und ein dickes Wow!

Toni

Wow, es hat den gewünschten Effekt. Super! Danke!

Nachtrag:

Ich musste das

[type~'route_master']

rausnehmen.

Grund: z.B. beim DE-BY-VGN wurden einige Relationen als type=route getagged, obwohl sie vom Verwendungszweck her als type=route_master hätten getagged werden müssen.

Diese Fehler werden nur erkannt, wenn [type~‘route_master’] nicht im Spiel ist.

Toni

Hier geht es weiter, da die Query ein paar Probleme bereitete

https://forum.openstreetmap.org/viewtopic.php?id=62099

Toni