Flussläufe verknüpfen

Hallo,

ist es sinnvoll (oder gab es bereits einen ernsthaften Versuch), Flussläufe (bzw. deren Relationen), die ineinander münden, miteinander zu verknüpfen?

Dass man den Tag destination=* an einer Relation anbringen kann, ist mir geläufig. Aber wäre es

Zum Hintergrund meiner Anfrage: ich habe letztens in https://www.openstreetmap.org/relation/410743 gesehen, dass da einige der hineinführenden Flüsse und Bachläufe als tributary geführt werden. Angefangen hat damit wohl Verfy_p in https://www.openstreetmap.org/changeset/12667526.

Nun gibt es dazu einerseits keine Dokumentation, andererseits fände ich persönlich es nicht unpraktisch, diese Relationen verknüpft zu haben.

Allerdings fände ich es logischer und einfacher, die Verknüpfung andersrum zu haben, nämlich den destination-Fluss, gerne in der Rolle destination, in dem einmündenden Fluss, also genau umgekehrt, wie es bei der Blies der Fall ist.

Weitere Beispiele:

  • der Rhein hat den Vorder- und den Hinterrhein als tributary. Diese haben die Besonderheit, dass sie zusammen erst den Rhein ergeben. Ansonsten hat der Rhein keine tributary-Member.
  • die Mosel hat ebenfalls einige ihrer zuführenden Flüsse als tributary, und zwar über ihren gesamten Verlauf.

Wie ist da die allgemeine Ansicht? Ist das a) komplett Unsinn, ist es b) besser, die hineinführenden Flüsse alle aufzuführen oder wäre es c) geschickter, es wäre umgekehrt?

Moin,

meiner bescheidenen Meinung nach ist das komplett Unsinn. Dass der eine Fluss in den anderen mündet steht ja bereits in den Daten, nämlich durch Verknüpfung der Waterways. Wenn die Waterways nicht verknüpft sind, wird das von allen möglichen QA-Tools erkannt. Man gewinnt durch das zusätzlich nochmal in Relationen hineinschreiben also ausschliesslich eine weitere Fehlerquelle, aber keine nutzbaren Daten die man nicht auch ohne schon gehabt hätte.

Wolfgang

Was aber ein komplexerer Vorgang ist. Wenn ich mir einen Baum eines Flusses und seiner Zuflüsse erstellen will, muss ich dann jeden einzelnen Node fragen, ob er einen anderen Waterway hineinfließen lässt, bildlich gesprochen. Die Relation müsste ich nur nach Eltern bzw. Kindern fragen…

Also Flussgebiete Mitteleuropa hat es definitiv ohne Relationen geschafft.

Wenn man sich darauf beschränkt, nur das OSM-Datenmodell zu nutzen, mag das vielleicht sein. Es kann jedoch schneller sein, die Daten in eine PostgreSQL-Datenbank mit PostGIS-Erweiterung zu importieren. Wenn man das mit osm2pgsql macht, kann man folgende Abfrage machen:


SELECT rhein_osm_id, tributary_osm_id, tributary_name, tributary_name_de
  FROM (
    SELECT DISTINCT ON (b.osm_id)
      a.osm_id AS rhein_osm_id,
      b.osm_id AS tributary_osm_id,
      b.name AS tributary_name,
      b.tags->'name:de' AS tributary_name_de
    FROM planet_osm_line AS a
    JOIN planet_osm_line AS b
    ON (
      a.way && b.way
      AND ST_Touches(a.way, b.way)
      AND a.waterway = 'river'
      AND (a.name = 'Rhein' OR a.tags->'name:de' = 'Rhein')
      AND b.waterway = 'river'
      AND b.name != 'Rhein'
      AND (NOT b.tags?'name:de' OR b.tags->'name:de' != 'Rhein')
    )
    WHERE a.way && st_setsrid( st_makebox2d( st_makepoint(297612,5858912), st_makepoint(1134140,6910687)), 3857)
  ) AS s
  ORDER BY tributary_name;

Diese Abfrage hat 17 Sekunden gedauert. Weil die Datenbank keine passenden Indexe hat, habe ich mit

where a.way && st_setsrid( st_makebox2d( st_makepoint(297612,5858912), st_makepoint(1134140,6910687)), 3857)

dafür gesorgt, dass nicht alle Flüsse auf der Welt berücksichtigt werden.

Ergebnis:


 rhein_osm_id | tributary_osm_id |       tributary_name       | tributary_name_de 
--------------+------------------+----------------------------+-------------------
    106979253 |          4305088 | Aare                       | Aare
     83015485 |        208098220 | Ahr                        | 
    187625884 |         31526384 | Alb                        | 
     83015625 |        104926566 | Alter Rhein                | 
    416388488 |        206865586 | Alte Sandlache             | 
     75319654 |         27581287 | Altrhein                   | 
    330946340 |        200163073 | Altrhein                   | 
    176021667 |         27745148 | Altrhein                   | 
    176021667 |        160377515 | Altrhein                   | 
     58741598 |         52824523 | Altrhein                   | 
     83015625 |        121124205 | Angerbach                  | 
    176021667 |         33902186 | Berghäuser Altrhein        | 
    288783321 |         25644075 | Biber                      | 
    464810149 |        167638891 | Birs                       | 
    464810149 |        278179631 | Birsig                     | 
     83015625 |         74917953 | Boven-Rijn                 | 
    158238964 |         33372973 | Ehbach                     | 
     99022264 |        457416762 | Elz                        | 
     83015625 |         29436681 | Emscher                    | 
    102135980 |        524910227 | Engebach                   | 
     83015625 |          4755948 | Erft                       | 
    158238964 |         29455496 | Frutz                      | 
    106979253 |         15802060 | Glatt                      | 
    322740332 |        239220977 | Hauensteiner Murg          | 
    231714459 |        186296254 | Hinterrhein                | Hinterrhein
    158238964 |          9673934 | Ill                        | 
    103515589 |        132648071 | Isenach                    | 
    237919282 |        109077056 | Kander                     | 
    237919282 |        209070399 | Kander                     | 
    167104415 |         22695888 | Kinzig                     | 
     83015625 |        142742097 | Kittelbach                 | 
     83015625 |        134414843 | Kleine Emscher             | 
    106979253 |        303315231 | Kleiner Rhein              | 
    102135980 |        166467011 | Lahn                       | 
    176021668 |        162868098 | La Moder                   | 
    103515589 |        344726382 | Lampertheimer Altrhein     | 
    159018431 |        174748813 | Landquart                  | 
     75319654 |         54727148 | La Sauer                   | Sauer
     58741598 |          4436731 | Lauter                     | 
     83015625 |         83525810 | Lippe                      | 
    416388488 |        416106357 | Main                       | Main
    103515589 |        154519972 | Maulbeerauer Altrhein      | 
    176021667 |        206822566 | Michelsbach                | 
     83015625 |         85528192 | Moersbach                  | 
    107166992 |         39845055 | Möhlin                     | 
    323304127 |         58282562 | Möhlinbach                 | 
     83075017 |        161572976 | Mosel                      | Mosel
    176021667 |          5073645 | Mundenheimer Altrheinhafen | 
     75319654 |         28745758 | Murg                       | 
    103517558 |         25603800 | Nahe                       | 
    176021667 |        514832816 | Neckar                     | Neckar
     83015485 |        460331787 | Nette                      | 
     83015625 |        143269369 | Nördliche Düssel           | 
    176021667 |          7926430 | Pfinz-Entlastungskanal     | 
    231714459 |         95785820 | Plessur                    | 
    176021667 |         47310400 | Rehbach                    | 
    231714459 |        174752117 | Rein Anteriur              | Vorderrhein
     58741502 |        364238076 | Rheinniederungskanal       | 
    330327227 |        299470697 | Rheinseitenkanal           | 
     75134826 |         41460322 | Riedkanal                  | 
     83015625 |        155555029 | Ruhr                       | 
    242294778 |        142374060 | Sieg                       | 
    323304127 |        166512663 | Sissle                     | 
    176021667 |         26648038 | Speyerbach                 | 
     83015625 |        143272090 | Südliche Düssel            | 
    106979253 |         12373075 | Thur                       | 
    106979253 |          4254242 | Töss                       | 
    237919282 |        471148447 | Vieux Rhin                 | 
     83015485 |        128748464 | Vinxtbach                  | 
    323304127 |         25817666 | Wehra                      | 
     83015485 |        130281205 | Wied                       | 
     91320954 |        285265032 | Wiese                      | 
    102135980 |        206363693 | Wisper                     | 
     83015625 |        147587760 | Wupper                     | 
    106979253 |         34143820 | Wutach                     | 
(75 rows)

Die Flussrelation des Rheins habe ich nicht berücksichtigt, da Relationen mit type=waterway nicht von osm2pgsql importiert werden. Falls sie es würden, würde ich anstelle der einzelnen Flussstücke des Rheins die Rheinrelation verwenden.

EDIT: SQL korrigiert

Wie funktioniert beides bei Bifurkationen?

PostGIS hat Funktionen, die einem den ersten bzw. letzten Punkt eines LineStrings zurückgeben. Bei Mündungen ist der letzte Punkt des Nebenflusses im Hauptfluss, bei Bifurkationen nicht.

Der Ansatz funktioniert schon bei der Norder-/Süderelbe nicht, da ich nicht auf Routenrelationen, welche als MultiLineStrings in der Datenbank sein könnten, sondern auf Basis der einzelnen Ways gearbeitet habe. Wie gesagt, wenn osm2pgsql waterway-Relationen wie Routenrelationen behandeln würde, sollte es gehen.

Eine Abfrage der Zuflüsse zu einem bestimmten Fluss mittels Overpass könnte in etwa so aussehen:
https://overpass-turbo.eu/s/x1q

Für den Ansatz von Nakaner über eine SQL Datenbank lässt sich bei osm2pgsql über das beim Aufruf verwendete .lua Script bestimmen, ob waterway relationen erzeugt werden oder nicht. Das Standard Script style.lua von osm2pgsql beispielsweise überträgt nur Relationen zu SQL wenn type=route|multipolyon|boundary ist. Das zur Erzeugung der Standard-OSM-Tiles verwendete Script openstreetmap-carto.lua führt keine Filterung der Relationen durch.

Ist nicht ganz korrekt:

osm2pgsql legt (auf Wunsch) zwei unterschiedliche Arten von Tabellen an.

a) Die Rohdaten landen in planet_osm_nodes, planet_osm_ways und planet_osm_rels.
b) Die aufbereiteten Daten landen in planet_osm_point, planet_osm_line, planet_osm_roads und planet_osm_polygon

Mit den aufbereiteten Daten wird “normalerweise” gearbeitet, und es stimmt, da sind keine waterway-Relationen drin.

In den Rohdaten steht aber alles drin, allerdings in relativ einfacher Form. Und in planet_osm_rels sind natürlich auch die waterway-Relationen (type=‘waterway’) enthalten.


select tags 
  from planet_osm_rels
 where array_position(tags,'waterway') = array_position(tags,'type')+1
 limit 3;

---->

 {destination,Lahn,name,Laasphe,type,waterway,waterway,river,osm_user,Ratz41,osm_uid,237127,osm_version,2,osm_timestamp,2017-08-10T06:03:43Z,osm_changeset,50989787}
 {destination,"Rio Solimões",name,"Río Yavarí",name:en,"Javary River",name:es,"Río Yavarí",name:pt,"Rio Javari",type,waterway,waterway,river,wikidata,Q941329,wikipedia,"en:Javary River",osm_user,smaprs,osm_uid,1852029,osm_version,9,osm_timestamp,2018-01-31T01:20:42Z,osm_changeset,55914033}
 {destination,Lippe,name,Gunne,ref:fgkz,27836,type,waterway,waterway,river,osm_user,RailAir,osm_uid,1977785,osm_version,8,osm_timestamp,2017-07-14T18:35:41Z,osm_changeset,50290990}
(3 Zeilen)

Es ist nur etwas fiseliger, an die Geometrien ranzukommen, die natürlich in den aufbereiteten Daten (Typ A) enthalten sind.

Ein wesentlich interessantere Ansatz ist mMn die Verwendung von PostGIS-Topologien, was allerding ein erhebliches Umdenken des Entwicklers bedarf. http://strk.kbt.io/projects/postgis/Paris2011_TopologyWithPostGIS_2_0.pdf

Hier mal ein Beispiel zur Bereinigung von Straßennetzwerken:
http://blog.mathieu-leplatre.info/use-postgis-topologies-to-clean-up-road-networks.html

oder hier zur Generalisierung von Grenzpolygonen:
https://trac.osgeo.org/postgis/wiki/UsersWikiSimplifyWithTopologyExt

Hieran hab ich mir bisher die Zähne ausgebissen :frowning:

Gruss
walter