OpenStreetMap-Karten II
Dieser Artikel beschäftigt sich (erneut) mit der Erstellung von druckfähigen Karten aus dem OpenStreetMap-Material. Zum Einsatz kommt Mapnik, mit dem eine Karte im A4-Format erstellt werden soll.
Vor etwas mehr als einem Jahr habe ich mich zuletzt mit der Frage beschäftigt, wie man OpenStreetMap-Material in ein druckbares Format überführt. Damals ging es speziell um besonders große Karten (konkret im Format A1), die man auf der OpenStreetMap-Website nicht rendern lassen kann. Diesmal soll es um kleinere Karten im handelsüblichen A4-Format gehen. Diese kann man zwar grundsätzlich über die OSM-Website erzeugen, allerdings sind die erzeugten Karten meiner Erfahrung nach meist ziemlich unförmig und müssen immer noch auf A4 heruntergeschnitten werden; oftmals leiden sie auch unter Skalierproblemen. Kurz, ich denke, dass die OSM-Website für die Erstellung von Druckmaterial schlicht ungeeignet ist.
Auch diesmal wird es folglich darum gehen, Teile des OpenStreetMap-Kartenmaterials lokal zu benutzen. Die im o. g. Artikel beschriebene Methode enthält eine Menge Handarbeit unter Nutzung von Tilemill und Inkscape, seitdem gibt es durch ein neues Programm aber die Möglichkeit, diese Handarbeit erheblich zu verringern. Vermutlich ließe sich mit der hier beschriebenen Methode ebenfalls eine Karte im Format A1 erstellen, allerdings habe ich das mangels Bedarf nicht getestet.
Vorbereitungen
Es empfiehlt sich, für die Arbeiten zunächst ein eigenes Verzeichnis
anzulegen. Ich werde in diesem Artikel ~/maptest
benutzen.
$ mkdir ~/maptest
$ cd ~/maptest
Nun muss das OpenStreetMap-Kartenmaterial heruntergeladen werden (vgl. dazu auch den früheren Artikel). Das Material steht auf diversen Spiegelservern sowohl im alten XML-basierten OSM- als auch im neueren binären PBF-Format zur Verfügung. PBF ist erheblich platzsparender und daher empfohlen. Wie zuletzt auch sollte man lediglich den Teil des OSM-Planeten herunterladen, den man auch annähernd benötigt, da sich alle Prozesse sonst erheblich in die Länge ziehen können; ich bleibe bei den Deutschlandkarten von Geofrabrik, genauer bei der Nordrhein-Westfalen-Karte.
$ wget http://download.geofabrik.de/europe/germany/nordrhein-westfalen-latest.osm.pbf
Die nun folgenden Vorbereitungen erscheinen auf den ersten Blick ziemlich umfangreich. Das ist ein wohl auch nicht ganz abwegiger Eindruck, der schwerlich von der Hand zu weisen ist. Auf der anderen Seite muss man all diese Programminstallationen nur ein einziges Mal vornehmen, später kann man sich dann auf aktuelle Versionen des Kartenmaterials beschränken bzw. sogar einfach nur mit dem vorhandenen Kartenmaterial unterschiedliche Gebiete rendern.
PostgreSQL + PostGIS
Während dieser umfangreiche Download läuft, können die übrigen Voraussetzungen erfüllt werden. Benötigt werden eine PostgreSQL-Datenbank mit PostGIS- und seit neustem auch HStore-Erweiterung; zumindest unter ArchLinux ist „postgis“ als eigenständiges Paket verfügbar und nicht im Paket „postgresql“ enthalten. Die Installation von PostgreSQL soll hier nicht dokumentiert werden, für ArchLinux-Nutzer empfiehlt sich ein Blick in das ArchWiki. Nach der Installation muss zunächst die Konfiguration angepasst werden. Dazu die Datei /var/lib/postgres/data/postgresql.conf bearbeiten und folgende Werte setzen:
work_mem=16MB
maintenance_work_mem=128MB
Die Werte dürfen auch größer ausfallen, wenn ausreichend
Arbeitsspeicher vorhanden ist; ich habe sie diesem
Konfigurationsvorschlag entnommen. Je größer sie sind, desto
schneller wird der Import und die Abfrage der OpenStreetMap-Daten
vonstatten gehen. Derselbe Artikel empfiehlt auch die Aktivierung der
Kernel-Funktion overcommit_memory
, die ich daher hier wiedergebe:
# sysctl -w vm/overcommit_memory=1
PostgreSQL (neu) starten:
# systemctl restart postgresql
Danach eine Datenbank mit dem Namen gis
anlegen und einem Nutzer
zuordnen:
$ sudo su - postgres
Passwort:
$ psql
CREATE USER quintus WITH PASSWORD 'geheimespasswort'; CREATE DATABASE gis WITH OWNER quintus;
Der Datenbankname gis
ist zwingend, wenn man wie unten noch erwähnt
den OpenStreetMap-Standard-Kartenstil benutzen will, der diesen
Datenbanknamen (leider) hardkodiert enthält.
In die erstellte Datenbank wechseln und die PostGIS- und HStore-Erweiterungen aktivieren:
$ psql gis
CREATE EXTENSION hstore; CREATE EXTENSION postgis;
Shell für den Nutzer postgres wieder verlassen.
$ exit
OpenStreetMap-Software
Weiter werden das Herzstück des OpenStreetMap-Projekts, Mapnik, und
ein Skript zum Import der OpenStreetMap-Daten in die
PostgreSQL/PostGIS-Datenbank, osm2pgsql, benötigt. Mapnik ist in den
ArchLinux-Repositorien enthälten, osm2pgsql im AUR (osm2pgsql-git
),
beides sollte jetzt installiert werden. Andere Distributionen haben
möglicherweise beides in den Repositories; zu achten ist unbedingt
darauf, dass Mapnik in einer Version größer 2 zum Einsatz kommt, da
mit dieser Veröffentlichung diverse Inkompatbilitäten zum alten
0.x-XML-Format eingeführt wurden.
Da es in diesem Artikel darum geht, mit dem Standard-OpenStreetMap-Stil zu rendern, wird derselbe ebenfalls benötigt. Er kann per Git heruntergeladen werden:
$ git clone git://github.com/gravitystorm/openstreetmap-carto.git
MapBox-Software
Die Rendering-Bibliothek Mapnik erwartet seine Rendering-Parameter eigentlich als XML-Dokument, dessen Format eher schlecht als recht dokumentiert ist1. Bis vor ein paar Jahren wurde der offizielle OSM-Stil auch tatsächlich in diesem Format gehalten. Weil XML aber ein etwas unhandliches Format ist, hat das OSM-Projekt stattdessen auf eine andere Auszeichnungssprache, das von der Firma Mapbox entwickelte CartoCSS, gewechselt, in welcher der oben heruntergeladene OpenStreetMap-Standardstil daher abgefasst ist. CartoCSS wird dann in einem Zwischenschritt in das von Mapnik erwartete XML übersetzt.
(Vorsicht, Meinungseinschub) Sich derartig von einer bestimmten Firma abhängig zu machen, gehört sich für ein freies Projekt eigentlich nicht. Wenn Mapbox die Software einstellt, steht das OSM-Projekt im Regen und kann wieder zurück auf XML-Stylesheets wechseln oder noch etwas anderes versuchen. Wenn man unbedingt CartoCSS einsetzen will, dann sollte man den Parser doch direkt in Mapnik selbst einbauen, statt sich auf von unbekannten Dritten entwickelte Software zu verlassen, wenn es doch faktisch um die Darstellung des eigenen „Gesichts“ geht. Tatsächlich prangt auf der Dokumentationsseite von TileMill, dem Projekt, dessen wesentlicher Teil CartoCSS ist, mittlerweile sogar tatsächlich ein Hinweis darauf, dass die Entwicklung eingestellt wurde. Chaos voraus.
Die Umwandlung von CartoCSS in XML-Mapnik-Stylesheets erfolgt mithilfe
des Programms carto
, welches ebenfalls mithilfe von Git
heruntergeladen werden kann:
$ git clone git://github.com/mapbox/carto.git
Carto ist für NodeJS geschrieben, eine Implementation von JavaScript außerhalb von Webbrowsern und weist darüber hinaus noch einige andere Abhängigkeiten auf, die mithilfe des Node-Paketmanegers, NPM, installiert werden müssen. NodeJS und NPM sollten sich in den Repositorien der eingesetzten Linux-Distribution befinden und sollten nunmehr installiert werden. Anschließend können die Abhängigkeiten installiert werden:
$ cd carto
$ npm install
$ cd ..
TileMill selbst wird wie erwähnt nicht mehr weiterentwickelt und
funktioniert auch nicht mehr mit dem aktuellen NodeJS (>= 0.12.0). Wer
das Programm weiterhin einsetzen möchte, sollte ein NodeJS in Version
0.10.x installieren, das Kommandozeilenprogramm carto
funktioniert
dagegen (noch) mit einer 0.12.x-Version von NodeJS. Da in diesem
Artikel nur das Kommandozeilenprogramm zum Einsatz kommt, stellt die
Problematik sich nicht; 0.12.x funktioniert einwandfrei.
nik4
Die letzte Voraussetzung ist das von mir neu entdeckte Programm nik4, welches mit aktuellen Versionen von Mapnik funktioniert, scheinbar noch aktiv entwickelt wird, und erfreulich umfangreiche Optionen besitzt. nik4 ist ein Python2-Programm, sodass die Installation von Python2 und zwecks weiterer Abhängigkeiten pip und virtualenv erforderlich ist. Alle erwähnten Python-Programme sind bei ArchLinux in den Repositorien enthalten.
Ich bin ja eigentlich kein Pythonista, aber virtualenv habe ich mittlerweile auch kennen und schätzen gelernt. Das Programm ermöglicht das Management von Abhängigkeiten in der Python-Welt (ähnlich wie Rubys Bundler) in solcher Weise, dass man sie nicht gleich global installieren muss, sondern sie einfach in einem Verzeichnis auf der Platte halten kann. Damit werden Versions- und Namenskonflikte angenehm vermieden. Für die Funktionsweise von virtualenv sei auf dessen Website verweisen, hier ist nur die bloße Anwendung wichtig. Zunächst wird eine virtuelle Umgebung eingerichtet und aktiviert:
$ virtualenv env
$ . ./env/bin/activate
Der zweite Schritt, die Aktivierung, muss jedesmal wiederholt werden,
wenn eine neue Shell benutzt wird, weil sie Änderungen an der
PATH
-Variablen vornimmt. Danach gestaltet sich die Installation der
Abhängigkeiten einfach:
$ pip install mapnik lxml nik4
Import des OSM-Kartenmaterials
Damit sind alle Vorbereitungen erledigt. Ich gebe zu, dass man von dem Konglomerat an C++-, NodeJS- und Python-Software förmlich erschlagen wird. Wie erwähnt sind das aber einmalige Vorgänge, durch die man sich später nicht mehr kämpfen muss.
Nachdem also alles installiert ist und der Download der PBF-Daten
abgeschlossen ist, kann man das OpenStreetMap-Kartenmaterial in die
PostgreSQL-Datenbank importieren. Dazu dient das Programm osm2pgsql
,
welches anhand einer .style
-Datei entscheidet, welche Daten aus den
Unmengen an Informationen, die in den OpenStreetMap-Materialien
stecken, in die Datenbank zu importieren sind. Der Aufruf erfolgt wie
folgt:
$ osm2pgsql --database gis --create --slim \
--cache 1000 --number-processes 3 --hstore \
--style openstreetmap-carto/openstreetmap-carto.style \
--multi-geometry \
nordrhein-westfalen-latest.osm.pbf
Eine umfangreiche Erklärung der einzelnen Parameter befindet sich in
diesem Artikel. Es empfiehlt sich, --number-processes
so
anzupassen, dass die maximale Anzahl an CPU-Kernen verwendet wird, da
dies den Importvorgang erheblich beschleunigt. Die Dateien
openstreetmap-carto/openstreetmap-carto.style
und
nordrhein-westfalen-latest.osm.pbf
wurden während der Vorbereitungen
bereits heruntergeladen und bedürfen hier daher keiner weiteren Erläuterung.
Der Import solcher Datenmengen dauert recht lang. Das obige Kommando benötigte bei mir etwa eineinhalb Stunden.
Shapefiles
Neben dem eigentlichen Kartenmaterial verarbeitet Mapnik auch sog. Shapefiles. Dabei handelt es sich vornehmlich um Küstenlinien; für eine ausführlichere Erklärung sei auf meinen früheren Artikel verwiesen. Erfreulicherweise ist das Skript zum Download der Shapefiles seitdem repariert worden, sodass die in jenem Artikel angesprochene Frickelei entfällt. Es genügt nunmehr, das Skript auszuführen, das die für den Standardkartenstil von OpenStreetMap benötigten Shapefiles herunterlädt:
$ cd openstreetmap-carto
$ ./get-shapefiles.sh
$ cd ..
Auch hier werden nicht unwesentliche Datenmengen heruntergeladen, Geduld ist also angebracht.
Anwendung
Nach all diesem Vorgeplänkel kann nun zur eigentlichen Arbeit übergegangen werden, dem Rendern der Karten. Zunächst wird das CartoCSS des OpenStreetMap-Projekts in Mapnik-XML übersetzt:
$ cd openstreetmap-carto
$ ../carto/bin/carto project.mml > openstreetmap-carto.xml
$ cd ..
Das dauert etwas länger, ca. 5 Minuten. Danach kann Nik4 aufgerufen werden, um etwa eine Karte der Kreisstadt Unna im A4-Format zu erzeugen:
$ nik4.py -s 5000 --ppi 300 -a 4 \
-c 7.6867 51.5357 --margin 10 \
openstreetmap-carto/osm-carto.xml print.png
Das ergibt eine Karte im Maßstab 1:5000, die bei einer Druckauflösung
von 300 DPI auf einem A4-Blatt das gesamte Blatt einnimmt, aber
runderherum 10mm Rand lässt. -c 7.6867 51.5357
gibt die Kartenmitte
in Form einer Längen- und Breitengradangabe an. Es ist darauf zu
achten, dass die Längengradangabe zuerst kommt. Ich habe ein paar
Stunden damit verbracht, mich über leere Karten zu wundern, bis ich
festgestellt habe, dass ich die Längen- und Breitengrade vertauscht
hatte. Herausfinden kann man diese Angaben ganz bequem, indem man die
Karte auf
https://www.openstreetmap.org
aufruft, den gewünschten Ort ansteuert und die „Teilen“-Funktion
auswählt. Dort hat man die Möglichkeit, einen Marker auf der Karte zu
platzieren. Diesen stellt man dorthin, wo sich die spätere Kartenmitte
befinden soll, anschließend kann man die Koordinaten in dem Feld
„Geo-URI“ ablesen (die Zoom-Stufe, z
, ist unerheblich; nik4
berechnet den korrekten Zoom aus der Angabe der Papiermaße, der
gewünschten DPI, Skalierung und Ränder).
300 DPI ist noch ein relativ mittelmäßiger Wert. Viele Drucker sind
auch in der Lage, wenigstens 600 DPI zu drucken, was auch tatsächlich
in einem wahrnehmbar größeren Detailreichtum auf der Karte resultiert
und daher sehr empfehlenswert ist; der Parameter --ppi
ist
dementsprechend anzupassen. Mein Drucker vermag laut Eigenwerbung
sogar 2400 DPI zu drucken, allerdings hat Mapnik beim Rendering eines
solch großen Bildes die Waffen gestreckt. Es gibt allerdings wohl eine
Möglichkeit, dies mit der Option --tiles
trotzdem hinzubekommen;
allerdings entstehen dann Einzelbilder, die ihrerseits wieder erst per
Imagemagick zusammengebaut werden müssen. Das habe ich noch nicht
probiert, wer aber mutig ist, darf gern seine Erfahrungen in den
Kommentaren posten.
Ergebnis
Das Ergebnis sieht dann so aus wie dieses Bild (Zentrum der Kreisstadt Unna bei 300 DPI). Den Copyright-Hinweis verlangen die Lizenzbedingungen, man kann ihn leicht mithilfe des GIMPs hinzufügen.
Valete.
-
Für unzählige Projekte scheint es die denkbar allerschwerste Aufgabe überhaupt zu sein, ihre Verwendung zu dokumentieren. Es ist eine Schande! Da gibt es so tolle Projekte, aber außer den Entwicklern kann faktisch niemand sie benutzen, weil sie keine Dokumentation, oder noch schlimmer, veraltete Dokumentation enthalten. ↩