Hallo!

An der Grenze zwischen Deutschland und Österreich ist aufgefallen, dass diese Grenze anders gerendert wird, als andere Grenzen. Am Dreiländereck im Bodensee kann man das ganz gut sehen:

<http://www.openstreetmap.org/browse/node/45072653>

Über die Ursache dafür wurde hier bisher kaum ein Wort verloren (man macht lieber seine Späßchen). Am nächsten dran war bisher Andreas Labres:

<http://lists.openstreetmap.org/pipermail/talk-de/2010-October/078441.html>

<http://lists.openstreetmap.org/pipermail/talk-de/2010-November/078935.html>

Seine Vermutung ist, dass der Mapnik-Style die Relationen type=multipolygon und type=boundary unterschiedlich behandelt.

Schauen wir doch einfach mal nach. Der folgende Text ist ein wenig ausführlicher und erklärender als zur Beschreibung der Ursache notwendig, damit auch Leute, die sich noch nicht mit dem Rendering mit Mapnik beschäftigt haben, auch noch etwas verstehen.

Der Mapnik-Style liegt in

<http://trac.openstreetmap.org/browser/applications/rendering/mapnik>

Unter 'Revision Log' oben rechts gibt es eine Versionsgeschichte. Der eigentliche Style ist die Datei

<http://svn.openstreetmap.org/applications/rendering/mapnik/osm.xml>

Das Rendern der Grenzen ist eine Include-Datei ausgegliedert

<http://svn.openstreetmap.org/applications/rendering/mapnik/inc/layer-admin.xml.inc>

Hier stellen wir folgendes fest:

++ Das alles ist ziemlich übersichtlich.

++ Von type=multipolygon oder type=boundary sieht man hier nichts. Hier kann der Unterschied nicht liegen. Er muss von woanders kommen.

++ Die Geometrie stammt aus der PostGIS-Tabelle prefix_roads. Dies ist eine Teilmenge der Tabelle prefix_line. Diese beiden Tabellen enthalten nur Linien. Die Tabelle prefix_polygon, die alle Flächen enthält, wird nicht erwähnt. Ebenso nicht die Tabelle prefix_point mit allen Punkten.

- Alle Grenzen werden mit sehr geringer Deckkraft (opacity) zwischen 0.1 und 0.3 gezeichnet.

- Die Grenzen werden als lila Linien unterschiedlicher Breite gezeichnet. Sie sehen wie folgt aus:

  - admin_level=2 (Staat)  wird durchgezogen, sehr breit
  - admin_level=4 (Land, Kanton) wird gleichmäßig gestichelt, breit
  - admin_level=5 (Regierungsbezirk) wird gestrichelt (lang, kurz, kurz)
  - admin_level=6 (Kreis, Bezirk) wird gestrichelt (lang, kurz)
  - admin_level=8 (Gemeinde) wird gleichmäßig gestrichelt, schmal

- Die SQL-Anfragen, Layer und Rules sind so angelegt, dass jeder Weg in prefix_roads höchstens einmal gezeichnet wird.


Eine erste Vermutung ist, dass ausschließlich Wege mit boundary=administrative und admin_level=* gerendert werden. Relationen spielen also keine Rolle. Dafür spricht z. B. die folgende Stelle:

<http://www.openstreetmap.org/?lat=50.74158&lon=7.24558&zoom=15&layers=M>

Besser sieht man es hier:

<http://toolserver.org/~osm/styles/?lat=50.74158&lon=7.24558&zoom=15&layers=000BF0FF0000F0FF00>

Der Bach (Pleisbach) bildet die Grenzen zwischen Hennef (im Nord-Osten, Relation 36042) und Königswinter (im Süden, Relation 173113). In den beiden Grenzrelationen (type=multipolygon, beide vollständig) ist nur der waterway=river als outer eingetragen. Ein Weg mit boundary=administrative und admin_level=8 fehlt hier. Überall sonst im Rhein-Sieg-Kreis sind Wege mit diesen Tags an den anderen Grenzen vorhanden. Wir sehen also: Eine Multipolygon-Relation alleine reicht nicht aus, damit sie als Grenze gerendert wird.

Ein Blick auf die gerenderten Karten (Beispiel Bodensee) zeigt, dass die letzten beiden Punkte obiger Liste sich irgendwie widersprechen: Im Bodensee entspricht die Grenze Schweiz-Deutschland keinem der oben beschriebenen Aussehen. Vielmehr scheint hier das Aussehen von admin_level=2 und admin_level=4 übereinander gelegt worden zu sein. Tatsächlich liegen hier zwei Relationen mit type=boundary und dem passendem admin_level (2=Schweiß, 4=Thurgau) übereinander. An der Grenze Österreich-Deutschland ist das genau so – nur werden hier Relationen mit type=multipolygon benutzt.

Die Vermutung ist also, dass irgendwie übereinander liegende Linien mit unterschiedlichem admin_level in die Tabelle prefix=roads eingetragen werden, die aus Relationen mit type=boundary stammen.

Die genannten Tabellen werden vom Programm osm2psql erzeugt. Der Quelltext liegt hier:

<http://trac.openstreetmap.org/browser/applications/utils/export/osm2pgsql>

Das Programm nimmt OSM-Dateien bzw. Differenzen von OSM-Dateien und trägt diese in eine Postgres-Datenbank mit PostGIS-Erweiterung ein. Nodes kommen in die Tabelle prefix_point; Wege, die Linien und kleine Flächen sind, nach Tabelle prefix_line und ggf. als Kopie nach Tabelle prefix_roads und Wege, die Flächen sind, nach Tabelle prefix_polygon. Bei diesen Schritten werden die OSM-Daten so gut wie gar nicht bearbeitet, sondern Geometrie und Tags unverändert übernommen.

In die Tabelle prefix_roads kommen Wege mit boundary=adminstrative, railway=* oder highway=(motoway|trunk|primary|secondary|)(_link)?. Die Tabelle dient dazu bei kleinen Zoomleveln die Anzahl der Linien je Kachel zu begrenzen.

Bei der Unterscheidung zwischen Linien und Flächen hilft eine Konfigurationsdatei,

<http://svn.openstreetmap.org/applications/utils/export/osm2pgsql/default.style>

bei der man für verschiedene Schlüssel angeben kann, ob geschlossene Wege als Linien (highway, barrier) oder Flächen (building, landuse) angesehen werden sollen. Im Zweifel kann der Mapper hier mit area=yes oder area=no nachhelfen und eine Interpretation erzwingen.

Bei Relationen ist das ganz anders. Mapnik kennt keine Relationen, sondern nur Punkte, Linien oder Flächen. Deswegen muss hier osm2psql die ganze Arbeit machen, und die Relationen vorverarbeiten, indem alle Mitglieder der Relationen gesucht und geeignet interpretiert werden. Verarbeitet werden nur Relationen mit type=route, type=multipolygon oder type=boundary. Von den Rollen der Mitglieder wird nur 'inner' erkannt. Andere Rollen wie 'outer', 'enclave' oder 'exclave' sind in Quelltext nicht zu finden.

Die Routen sind hier uninteressant. Hier werden nur neue Tags aus vorhandenen erzeugt und die Route als Linie in die Tabelle prefix_line und ggf. prefix_roads eingetragen.

Multipolygone und Grenzen werden unterschiedlich verarbeitet: Multipolygone werden immer als Flächen aufgefasst und, wenn sie gültig sind (das wird ausführlich nach den Multipolygon-Regeln geprüft, mehrere Flächen und Löcher sind erlaubt), immer in die Tabelle prefix_polygon eingetragen. Grenzen werden sowohl als Linien als auch als Flächen aufgefasst. Sie werden immer in die Tabelle prefix_line und prefix_roads eingetragen und zusätzliche, wenn sie gültig sind, in die Tabelle prefix_polygon eingetragen.

Wer sich das im Quelltext ansehen will:

<http://svn.openstreetmap.org/applications/utils/export/osm2pgsql/output-pgsql.c>

Ich empfehle eine Suche nach 't_line', 't_roads' und 't_poly'. Die werden sehr „symetrisch“ benutzt. Nur an einer Stelle ist eine zusätzliche Benutzung von 't_poly' vorhanden. Diese zusätzliche Benutzung ist des Pudels Kern und man versteht sie, wenn man nach 'make_polygon' und 'make_boundary' sucht und auf den vierten Parameter beim Aufruf von 'build_geometry' achtet.


Damit ist das Rätsel also gelöst. Aufgrund einer Eigenschaft von osm2psql, die außerhalb des Quelltexts offensichtlich nicht dokumentiert ist, und von der nur sehr wenige Leute wissen dürften, werden Relationen mit type=boundary beim Rendern mit Mapnik (oder genauer: bei Syles für Mapnik, die einfach vom Default-Mapnik-Style abgeleitet sind), bevorzugt, indem sie sowohl als Flächen als auch als Linie in die Datenbank eingetragen werden, was viele Leute nicht erwarten würden.

Diese Bevorzugung führt dazu, dass Grenzen mehrfach übereinander gerendert werden können und damit immer fetter und besser sichtbar werden. Hier fällt bei Europa-Ansichten besonders die Grenze der Republik Tschechien auf. Gleichzeitig kann man die Art (d. h. den admin_level) der Grenze aber immer schlechter erkennen. Schon wenn zwei Gemeinde-Grenzen übereinander gelegt werden kann es vorkommen, dass die Strichelchen der einen Grenze genau auf die Lücken der anderen Grenze treffen.

Ich habe bisher ausdrücklich vermieden, von einem Fehler (entweder im Mapnik-Style oder in osm2psql) zu sprechen, denn vielleicht ist dieses Verhalten ja genau so beabsichtigt. In Zeiten, in denen ein admin_level=2 zusammen mit höchstens einer anderen Grenze gerendert wurde, sah das sicher toll aus.

Ich persönlich würde es bevorzugen, wenn jede Grenzlinie nur noch genau einmal gerendert wird. Nur so kann man das Rendering genau kontrollieren und z. B. an der Art der Strichelung der Grenze genau erkennen, um welchen admin_level es sich hier handelt.

Die Lösung des Problems ist sicherlich nicht einfach. Das Unterbreiten von Lösungsvorschlägen möchte ich aber anderen überlassen.

Abschließend sein die Bemerkung erlaubt, dass dieses Beispiel sehr schön zeigt, wie dumm (und das ist nicht abwertend gemeint) Mapnik als Renderer ist. Mapnik übernimmt nur Geometrien aus der Datenbank und stellt sie nach gewissen Regeln graphisch dar. Intelligenz (z. B. in der Form, dass von übereinander liegenden Linien nur die mit dem kleinsten admin_level dargestellt wird), darf man hier nicht erwartet. Diese Intelligenz gehört in eine Vorverarbeitungsstufe (in diesem Fall osm2psql). Wenn viele Leute fordern, dass die Renderer intelligenter werden sollen (Brückenrelationen, Abbiegerelationen, Auswahl von Städtenamen usw.), dann reden sie eigentlich von osm2psql (oder einem zukünftigem Ersatz). Leider ist diese Intelligenz nur schwer veränderbar (C-Programmierung) und nach jeder Änderung ist ein neuer Import der Datenbank (dauert sehr lange) fällig. Bisher ist auch nur sehr wenig Intelligenz vorhanden: Außer den genannten Relationen ist noch einwenig Code für die OpenCycleMap und die Parkplatzkarte vorhanden.

Mit freundlichen Grüßen
  Adjuva

_______________________________________________
Talk-de mailing list
[email protected]
http://lists.openstreetmap.org/listinfo/talk-de

Antwort per Email an