OpenStreetMap-Karten mit nik4

Marvin Gülker · 19.08.2015

Dieser Artikel beschäftigt sich 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.

Kategorien: OpenStreetMap, Software

Vor etwas mehr als einem Jahr ging es auf diesem Blog darum, wie man OpenStreetMap-Material in ein druckbares Format überführt. Damals sollten speziell besonders große Karten (konkret im Format A1) erstellt werden, 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 meist ziemlich unförmig und müssen immer noch auf A4 heruntergeschnitten werden; oftmals leiden sie auch unter Skalierproblemen. Für die Erstellung von Druckmaterial ist die OpenStreetMap-Webseite daher eher ungeeignet.

Auch diesmal wird es folglich darum gehen, Teile des OpenStreetMap-Kartenmaterials lokal zu benutzen. Die früher 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 wurde das mangels Bedarf nicht getestet.

Vorbereitungen

Es empfiehlt sich, für die Arbeiten zunächst ein eigenes Verzeichnis anzulegen. Hier kommt ~/maptest zum Einsatz.

$ mkdir ~/maptest
$ cd ~/maptest

Nun muss das OpenStreetMap-Kartenmaterial heruntergeladen werden. 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. Hier wird die Nordrhein-Westfalen-Karte von Geofrabrik benützt.

$ 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.

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; sie wurden 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 wie folgt erfolgt:

# 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 ist. Bis vor ein paar Jahren wurde der offizielle OSM-Stil auch tatsächlich in diesem Format gehalten. Weil XML aber ein 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.

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 neue 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.

virtualenv 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 in einem Verzeichnis auf der Platte halten kann. Damit werden Versions- und Namenskonflikte 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

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 etwa eineinhalb Stunden.

Shapefiles

Neben dem eigentlichen Kartenmaterial verarbeitet Mapnik auch sog. Shapefiles. Dabei handelt es sich vornehmlich um Küstenlinien. Das Skript zum Herunterladen der Shapefiles war früher ja defekt, ist aber mittlerweile repariert worden. 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.

Anwendung

Nun geht es um das eigentliche 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: Vertauscht man Längen- und Breitengradreihenfolge, erzeugt man nur leere Karten. 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 eigener Drucker vermag laut Eigenwerbung sogar 2400 DPI zu drucken, allerdings ist Mapnik beim Rendering eines solch großen Bildes abgestürzt. Es gibt allerdings wohl eine Möglichkeit, dies mit der Option --tiles trotzdem durchzuführen; allerdings entstehen dann Einzelbilder, die ihrerseits wieder erst per Imagemagick zusammengebaut werden müssen.

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.