Ich bin neu in der faszinierenden GIS-Welt und habe in den letzten Tagen das gesamte Thema untersucht. Mein Ziel ist es, weltweite Karten mit OSM-Daten auf meinen eigenen Servern bereitzustellen.
Mein Stack ist:
- Postgres + Postgis - Zum Speichern, Transformieren und Verarbeiten von GIS-Daten.
- Mapnik - Bibliothek zum Rendern von Kacheln
- Tilestache - Kacheln servieren und zwischenspeichern
- Nginx - Reverse Proxy zu Tilestache
- Faltblatt ( Slippy Map Client)
Um OSM-Daten zu importieren und zu formatieren, verwende ich
- PBF-Datei (Extrakt / Planet)
- osm2pgsql
- CartoCSS
- openstreetmap-carto
- Kosmtik - Map GUI für Entwicklung / Debugging
Da die vollständige Planetendatei riesig ist, verwende ich derzeit einen Auszug aus Sao Paulo , der zum Testen gut / klein genug ist.
Bevor ich zu dem Problem komme, das ich habe, werde ich durch die Schritte führen, die ich bisher unternommen habe:
Was hat funktioniert
PostgreSQL und PostGIS sind ordnungsgemäß installiert. Ich benutze 9.6 für die erstere, 2.3 für die letztere. Ich habe auch die postgis_topology
und hstore
-Erweiterungen hinzugefügt , die später verwendet werden.
Ich habe osm2pgsql 0.92.0 installiert. Um den Sao Paulo-Extrakt zu importieren, verwende ich
osm2pgsql -G U <user> -d <db> -C 1000 -W --hstore --style openstreetmap-carto.style --tag-transform-script openstreetmap-carto.lua <pbf>
Die hstore
, style
und tag-transform-script
Argumente sind für die ordnungsgemäße Nutzung der OSM Stil erforderlich, wie hier beschrieben .
Wie in der openstreetmap-carto-Installation beschrieben, habe ich auch benutzerdefinierte Indizes hinzugefügt und die erforderlichen Shapefiles und Schriftarten heruntergeladen (mit Ausnahme der Emoji-Indizes).
Ich habe mithilfe von QGIS überprüft, ob die Extraktdaten korrekt in die Datenbank geladen wurden. Ich konnte alle Punkte, Polygone, Linien und Straßen anzeigen und abfragen. Es ist alles da.
Probleme
Der nächste Schritt ist das Rendern der Kacheln, und dort habe ich Probleme. Ich habe Mapnik und Python-Mapnik 3.x sowie Carto 0.18.2.
Aus der project.mml des OSM habe ich meine eigene project.xml mit generiert carto
. Ich habe die folgenden Änderungen am Ergebnis vorgenommen:
- Fügen Sie den Postgres-Benutzernamen hinzu (Parameter
user
in Mapniks XML ). Die verbleibenden Verbindungsinformationen werden von ~ / .pgpass abgerufen . - Ersetzen Sie das relative Verzeichnis
data/<shape>.shp
durch/full/path/data/<shape>.shp
- Ersetzen Sie das relative Verzeichnis
symbols/<symbol>.svg
durch/full/path/symbols/<symbol>.svg
Ich habe diese Änderungen in einer Art Unit-Test durchgeführt: Falsche Verzeichnisse für Shapefiles und Symbole führen zu einem Fehler, wenn Mapnik versucht, den Stil zu laden. Gleiches gilt für falsche DB-Informationen.
Und hier ist das Problem: Jede von Mapnik gerenderte Kachel ist "leer" (blauer Hintergrund, der für OSM als Hintergrund definiert ist). Folgendes habe ich versucht, um dieses Problem zu beheben:
Dinge, die ich versucht habe
Möglicherweise ist der generierte Stil irgendwie ungültig. Vielleicht bedeckt ein Polygon / eine Form (die des Ozeans?) Eine andere.
Ich habe Kosmtik installiert und es hat gut funktioniert! Ich konnte den Auszug durchsuchen, Daten überprüfen, auf allen Ebenen vergrößern und verkleinern.
Vielleicht generiere ich Kacheln am falschen Ort
Ich habe TileStache mit Mapnik als Anbieter eingerichtet. Dann habe ich Umleitungsregeln http://[abc].tile.openstreetmap.org
für die http://myserver/<layer>
Verwendung von switcheroo eingerichtet, wie hier beschrieben . Dies bedeutet, dass beim Zugriff openstreetmaps.org
alle Kacheln auf meinem Server gerendert werden.
Interessanterweise funktioniert Zoom 1 (der mit 4 Kacheln). Ich nehme an, es wird nur das Planet / World-Shapefile verwendet, das mit dem Stil heruntergeladen wurde. Alles andere wird unabhängig von Zoom oder Position auf "leer" gerendert. Selbst wenn Sie am Speicherort des Extrakts surfen, wird er nicht korrekt gerendert.
Beachten Sie, dass ich bei Verwendung von Kosmtik den Namen des Extrakts bereits ab Zoom 4 sehen konnte.
Vielleicht bin ich zu erzeugen Fliesen an der falschen Stelle
Projektionen sind schwer. Vielleicht wird irgendwo etwas "falsch übersetzt".
Also analysierte ich die Anfragen, die Kosmtik stellte (da diese funktionierten). Es verwendet die Modestmaps-Bibliothek, die in das Slippy-Format ( <zoom>/<x>/<y>
) übersetzt wird, das auch von Leaflet, TileStache und verwendet wird openstreetmap.org
.
Das Anfordern 17/48561/74357.png
von Kosmtik funktioniert beispielsweise, aber dieselbe Kachel wird in TileStache als "leer" zurückgegeben. Meine Theorie war, dass TileStache es irgendwie in eine andere Koordinate außerhalb des Extraktbereichs übersetzte. (Obwohl TileStache "sphärischen Mercator" als Projektion verwendete).
Deshalb habe ich mich entschieden, Mapniks Python-Bindungen direkt zu verwenden. Bisher habe ich drei verschiedene Arten von Projektionen bearbeitet. Hier ist, was ich über sie weiß. Bitte korrigiere mich wenn ich falsch liege:
- EPSG4326 / WGS84 - Übliche Lon / Lat-Projektion, wie bei GPS. Einheit ist Grad.
- EPSG3857 / {Web, Google, Pseudo} mercator / 900913 - Wird auf den meisten gekachelten Webkarten verwendet. Die Einheit ist in Metern angegeben (keine "echten" Meter, da sie sich in der Nähe der Pole stark verzerrt).
- "Slippy Format" - Keine Projektion, sondern ein weiteres zu übersetzendes Format.
Der Slippy 17/48561/74357
wäre also in der Nähe -46.632(lon), -23.531(lat)
von EPSG4326 und in der Nähe -5191050.49, -2696361.67
von EPSG3875 / Google Mercator.
Mit Python habe ich die Kacheln dieser Koordinaten direkt bei Mapnik generiert. Das Ergebnis waren immer leere Kacheln. Ich glaube, ich verwende die richtigen Projektionen (dazu später mehr).
Zunächst eine Sache zu beachten. Es ist klar, dass das Problem weder in Mapnik noch im Stil liegt. Zum einen verwendet Kosmtik Mapnik als Backend und es funktioniert gut. Zweitens, wenn ich absichtlich eine Kachel außerhalb des Extraktbereichs auf Kostmik generiere, bekomme ich wie erwartet eine leere Kachel.
Dies lässt mich glauben, dass ich bei Mapniks Python-Skript und TileStache die falsche Projektion verwende. Bevor Sie den Code anzeigen, eine Bemerkung zu OSM (bitte korrigieren Sie mich erneut, wenn ich falsch liege):
- OSM "native" Daten werden in EPSG4326 gespeichert
- osm2pgsql importiert OSM-Daten als EPSG3857, und das ist die Projektion auf Postgis.
- Mapniks Stil (XML) besteht aus zwei Projektionen, Eingabe und Ausgabe, die hier erläutert werden :
- Die Eingabeprojektion wird am Kartenobjekt definiert und ist das "Koordinatensystem, in dem die Karte gerendert wird".
- Die Ausgabeprojektion wird am Layer-Objekt definiert und muss mit meinen Daten übereinstimmen.
Mein resultierendes Mapnik-XML hat:
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="#b5d0d0">
#snip#
<Layer name="world" #snip# srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
So wie ich das sehe, sind sowohl die Eingabe- als auch die Ausgabeprojektion in "merc" (3857), und das ist richtig! Meine Daten werden mit 3857 gespeichert, und die resultierende Karte wird voraussichtlich 3857 sein.
Zum Schluss noch die verschiedenen Mapnik-Aufrufe, die ich ausprobiert habe:
Box2d mit 3857 Koordinaten:
map = mapnik.Map(800, 800)
bbox = Box2d(-5191050.49, -2696361.67, -5191059.49, -2696370.70)
mapnik.load_map(map, '/path/to/style.xml')
map.zoom_to_box(bbox)
mapnik.render_to_file(map, 'output.png') # Blank
Box2d mit 4326 in 3857 transformierten Koordinaten
merc = mapnik.Projection('+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over')
longlat = mapnik.Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
bbox = mapnik.Box2d(-23.53, -46.63, -24.03, -47.03)
transform = mapnik.ProjTransform(longlat, merc)
merc_bbox = transform.forward(bbox)
# load, zoom, render -> Blank
Ich habe es auch mit verschiedenen Stilen versucht. Das Ergebnis ist immer leer, aber das ist unerwartet, da ich glaube, dass diese Koordinaten in meinem Auszug enthalten sind. Wenn Sie versuchen, Koordinaten außerhalb des Extrakts zu rendern, wird dies korrekt als leer dargestellt.
Wie auch immer, ich bin verloren und habe mich gefragt, ob jemand etwas Licht ins Dunkel bringen könnte. Ich muss etwas vermissen. Aber bis jetzt habe ich mehr als 24 Stunden mit diesem Problem gekämpft und ich habe keine Ahnung, was falsch sein könnte.