OpenStreetMap-Karten mit dem deutschen Stil selbst rendern
Marvin Gülker · 10.12.2016
Dieser Artikel erläutert die Erstellung von druckfähigen Karten auf der Basis des OpenStreetMap-Kartenmaterials mit dem sog. „deutschen“ OpenStreetMap-Stil.
Kategorien: OpenStreetMap, Software
Ein früherer Artikel hat sich damit beschäftigt, wie man auf unterschiedliche Arten aus den OpenStreetMap-Daten auf seinem eigenen Rechner Kartengraphiken beliebiger Größe erstellen kann. Dazu kam der internationale OpenStreetMap-Stil, openstreetmap-carto, zum Einsatz. Hier soll es nunmehr darum gehen, nach derselben Methode den deutschen OpenStreetMap-Stil — wie er etwa auf der Karte von openstreetmap.de zu sehen ist — für eigene Karten einzusetzen.
Vorbereitungen
Wie üblich empfiehlt es sich, ein eigenes Verzeichnis für die folgenden Arbeiten anzulegen.
$ mkdir ~/osmtest $ cd ~/osmtest
Danach sollte man sogleich den Download des Kartenmaterials anstoßen, da dies erfahrungsgemäß sehr lange dauern kann. Auch dieses Mal kommen wieder die OSM-Auszüge von Geofabrik zum Einsatz.
$ wget http://download.geofabrik.de/europe/germany/nordrhein-westfalen/arnsberg-regbez-latest.osm.pbf
Virtuelenv
Da einige Python-Software zum Einsatz kommt, empfiehlt es sich, zur sauberen Abschottung von Software virtualenv zu benutzen.
$ virtualenv -p /usr/bin/python2.7 env $ . ./env/bin/activate
Mapnik
Ohne Mapnik kein OpenStreetMap. Mapnik muss daher installiert werden, sollte aber auch in den Repositories aller gängigen Linux-Distributionen enthalten sein. Für die Zwecke dieses Artikels wurde mit Mapnik 3.0.9 gearbeitet.
PostgreSQL + PostGIS
Für die Arbeit mit dem Kartenmaterial ist
PostgreSQL mit der Erweiterung
PostGIS erforderlich. Beides ist in den
Repositories der üblichen Linux-Distributionen enthalten; speziell im
Falle von Gentoo ist es allerdings erforderlich, das PostGIS-Paket von
seiner Keyword-Markierung zu befreien, da das als stabil markierte
dev-db/postgis
nicht mit der als stabil markierten PostgreSQL-Version
9.5 zusammenarbeitet.
Die Standardeinstellungen von PostgreSQL sollten verändert werden, da sie auf Systeme mit eher kleinen Arbeitsspeichern zugeschnitten zu sein scheinen; im Zweifel sollten sie eher zu groß als zu klein bemessen werden. Dabei sollte man aber nicht aus den Augen verlieren, dass Mapnik beim Rendern der Karten ebenfalls erhebliche Mengen Arbeitsspeicher für sich beanspricht.
Die relevanten Einstellungen befinden sich in der Konfigurationsdatei
postgresql.conf
:
work_mem=16MB maintenance_work_mem=128MB
Noch Memory Overcomitting zulassen und PostgreSQL neu starten:
# sysctl -w vm/overcommit_memory=1 # /etc/init.d/postgresql-9.5 restart
Abhängigkeiten des deutschen OSM-Stils
An dieser Stelle ging der vorige Artikel bereits zur Erstellung der Datenbank über. Dies ist hier noch nicht ratsam, da zunächst einige spezielle Abhängigkeiten des deutschen OpenStreetMap-Stils berücksichtigt werden müssen. Die offizielle Installationsanleitung fällt eher mau aus, weshalb der Installationsprozess hier im Einzelnen festgehalten wird.
Zunächst ergibt sich folgender Abhängigkeitsbaum:
- openstreetmap-carto-de
- mapnik-german-l10n
- PostgreSQL
- PostGIS
- kakasi
- icu
- utf8proc (nicht wirklich dokumentiert)
- pandoc (nicht wirklich dokumentiert)
- pyyaml (undokumentiert)
- carto
- NodeJS
- mapnik-german-l10n
Diese Abhängigkeiten sind nicht alle dokumentiert und nicht immer einfach zu installieren. Insbesondere kakasi und utf8proc sind nicht immer in den Repositorien der gängigen Linux-Distributionen enthalten. Schlimmer noch, Gentoo liefert eine derart veraltete Version von utf8proc aus, dass eine Verwendung mit dem deutschen OSM-Stil unmöglich ist. Es scheint, als ob utf8proc irgendwann einmal wegen Inaktivität geforkt wurde und Gentoo noch das alte, inaktive Projekt im Portage-Tree hat. kakasi im Portage-Tree ist aber aktuell.
Sofern die eigene Linux-Distribution kakasi und utf8proc also nicht oder
nicht in der aktuellen Version bereitstellt, sind sie aus den Quellen zu
kompilieren und zu installieren. Dabei bitte darauf achten, ein stabiles
Release zu installieren. ldconfig
nicht vergessen.
$ git clone git://github.com/JuliaLang/utf8proc.git Cloning into 'utf8proc'... remote: Counting objects: 1050, done. remote: Compressing objects: 100% (19/19), done. remote: Total 1050 (delta 5), reused 0 (delta 0), pack-reused 1031 Receiving objects: 100% (1050/1050), 3.57 MiB | 1.03 MiB/s, done. Resolving deltas: 100% (635/635), done. Checking connectivity... done. $ cd utf8proc $ git checkout v2.0.2 Note: checking out 'v2.0.2'. $ make cc -O2 -fPIC -std=c99 -Wall -pedantic -DUTF8PROC_EXPORTS -c -o utf8proc.o utf8proc.c rm -f libutf8proc.a ar rs libutf8proc.a utf8proc.o ar: creating libutf8proc.a cc -shared -o libutf8proc.so.2.0.2 -Wl,-soname -Wl,libutf8proc.so.2 utf8proc.o chmod a-x libutf8proc.so.2.0.2 ln -f -s libutf8proc.so.2.0.2 libutf8proc.so ln -f -s libutf8proc.so.2.0.2 libutf8proc.so.2 # make install mkdir -m 755 -p /usr/local/include install -m 644 utf8proc.h /usr/local/include mkdir -m 755 -p /usr/local/lib install -m 644 libutf8proc.a /usr/local/lib install -m 755 libutf8proc.so.2.0.2 /usr/local/lib ln -f -s libutf8proc.so.2.0.2 /usr/local/lib/libutf8proc.so ln -f -s libutf8proc.so.2.0.2 /usr/local/lib/libutf8proc.so.2 # ldconfig # emerge app-i18n/kakasi [...Portage installiert kakasi...]
mapnik-german-l10n ist eine Erweiterung (extension) für PostgreSQL, die insbesondere Transkriptionsfunktionen für asiatische Ortsnamen zur Verfügung stellt. Zwar ist es wohl möglich, den Stil irgendwie ohne sie zu verwenden und so die Abhängigkeiten von kakasi und utf8proc zu vermeiden (wenn man auf Karten asiatischer Lande verzichten kann), aber dieses Vorgehen ist nicht dokumentiert (im Gegensatz zum hier vorgestellten, das zumindest in Ansätzen dokumentiert ist) und wird daher hier nicht weiter verfolgt.
Die README von mapnik-german-l10n ist auf Nicht-Debian-Systemen
vollständig zu ignorieren. Die korrekte Installationsanleitung befindet
sich in der Datei
INSTALL.md.
Dabei ist zwingend darauf zu achten, eine stabile Version von
mapnik-german-l10n zu installieren und nicht einfach das zu bauen, was
aktuell in master
ist. Als dieser Artikel verfasst wurde, war
Version 2.1.5 aktuell.
Den Inhalt und die Implikationen der INSTALL-Datei kurz zusammengefasst läuft die Installation so ab:
$ git clone git://github.com/giggls/mapnik-german-l10n.git $ cd mapnik-german-l10n.git $ git checkout v2.1.5 $ make # make install
Das installiert die PostgreSQL-Erweiterung unmittelbar nach
/usr/share/postgresql-9.5/extension
, was recht misslich ist, wenn
man sie irgendwann einmal wieder deinstallieren möchte. So bleibt es
jedem überlassen, die Ausgabe von make install
kleinlich zu
verfolgen oder die Paketeigentumsverhältnisse unterhalb des
Verzeichnisses /usr/share/postgresql-9.5/extension
manuell
festzustellen. Die installierten Dateien sind dann eben diejenigen,
die keinem Paket zugeordnet sind.
Zu pyyaml und carto sogleich.
Datenbank erstellen
Jetzt kann mit der Erstellung der Datenbank weitergemacht werden. Dazu zunächst zum Datenbank-Superuser wechseln:
$ su - # su - postgres $ psql
Anschließend mit den folgenden Befehlen einen Nutzer erstellen und die
Datebank namens osm
einrichten. Der Datenbankname ist zwingend, es sei
denn, man möchte alle Vorkomnisse dieses Datenbanknamens im Stil ändern
(was vermutlich wegen der „Allerweltszeichenfolge“ osm, die in
OpenStreetMap-Projekten überall vorkommen dürfte, nicht ganz einfach
wäre).
CREATE USER quintus WITH PASSWORD 'geheimespasswort'; CREATE DATABASE osm WITH OWNER quintus; \q
Die verschiedenen CREATE EXTENSION
-Anweisungen gehen zum Teil auf
die letzte
Anleitung, zum anderen Teil auf die
Installationsbeschreibung
von mapnik-german-l10n zurück, wobei die unaccent
-Extension
vermutlich zZt. noch unnötig ist, da sie erst im master
-Branch
erwähnt
wird. Sie wird hier dokumentiert, um sie für die nähere Zukunft präsent
zu haben.
$ psql osm
CREATE EXTENSION hstore; CREATE EXTENSION postgis; CREATE EXTENSION unaccent; CREATE EXTENSION osml10n; \q
Python-Software
Die erforderliche Python-Software lässt sich wie folgt installieren (bitte darauf achten, dass das oben eingerichtete Virtualenv aktiv ist):
$ pip install pyyaml lxml mapnik nik4
Wie oben schon erwähnt, ist pyyaml erforderlich, aber nicht
dokumentiert. Es wird vom später aufzurufenden Skript yaml2mml.py
des
deutschen OSM-Stils benötigt. Die übrige Python-Software ist
Nik4 mit seinem Abhängigkeiten, dazu
schon im letzten
Artikel.
carto
Das offizielle carto
Auch der deutsche OpenStreetMap-Stil ist in CartoCSS realisiert, also einem Format, das durch Übersetzen zunächst in das von Mapnik verstandene XML-Format übersetzt werden muss. Dies erfolgt herkömmlicherweise mit dem NodeJS-Werkzeug carto, einer für NodeJS geschriebenen Software. Installation wie gehabt:
$ git clone git://github.com/mapbox/carto.git $ cd carto $ git checkout v0.16.3 $ npm install $ export PATH="$PWD/bin:$PATH"
Magnacarto?
Alternativ soll es möglich sein, eine Alternativimplementation von CartoCSS, Magnacarto, zu benutzen, die aber schon laut Selbstbeschreibung Probleme mit dem offiziellen OSM-Stil hat, und zwar insbesondere im Bereich der Variablennamensubstitution. Versucht man die Anwendung, quittiert Magnacarto auch tatsächlich mit den folgenden Warnungen:
$ magnacarto -mml project-de.mml -builder mapnik3 > de.xml 2016/12/10 12:29:23 File not found: symbols-de/shields/motorway_[width]x[height].svg 2016/12/10 12:29:23 File not found: symbols-de/shields/motorway_[width]x[height]_z16.svg 2016/12/10 12:29:23 File not found: symbols-de/shields/motorway_[width]x[height]_z18.svg 2016/12/10 12:29:23 File not found: symbols-de/shields/primary_[width]x[height].svg 2016/12/10 12:29:23 File not found: symbols-de/shields/primary_[width]x[height]_z16.svg 2016/12/10 12:29:23 File not found: symbols-de/shields/primary_[width]x[height]_z18.svg 2016/12/10 12:29:23 File not found: symbols-de/shields/secondary_[width]x[height].svg 2016/12/10 12:29:23 File not found: symbols-de/shields/secondary_[width]x[height]_z16.svg 2016/12/10 12:29:23 File not found: symbols-de/shields/secondary_[width]x[height]_z18.svg
Es schließt aber trotzdem erfolgreich ab. Auf den ersten Blick konnte ich keine Fehler in den generierten Karten entdecken, aber um subtile Probleme zu vermeiden, rate ich daher bis auf weiteres von der Verwendung ab. Magnacarto ist in Go geschrieben, weshalb es für jemanden, der unter der unfassbar schnellen Entwicklung von NodeJS leidet, durchaus seinen Charme hat. Solange dieses Problem aber nicht gelöst ist, soll darauf nicht weiter eingegangen werden. Der Rest des Artikels benutzt das offizielle carto.
Deutschen OpenStreetMap-Stil herunterladen
Der deutsche OpenStreetMap-Stil ist ein Fork vom internationalen
openstreetmap-carto, der versucht, mit ihm möglichst Schritt zu halten.
Es sei in diesem Kontext besonders darauf hinweisen, dass die auf
GitHub angegebenen
Releases
nichts mit dem deutschen Stil zu tun haben, sondern einfach
nur die Tags aus dem internationalen Stil sind. Sie zu verwenden, würde
dazu führen, dass man den internationalen Stil benutzt (das ist der
Eigenart von Git geschuldet). Der deutsche Stil ist daher zumindest
momentan immer vom Branch master
aus zu benutzen; er tätigt keine
eigenen Releases.
$ git clone git://github.com/giggls/openstreetmap-carto-de.git $ cd openstreetmap-carto-de
Daten importieren
Nun kann dazu übergegangen werden, die OpenStreetMap-Daten in die neue
Datenbank osm
zu importieren. Da der deutsche Stil einen anderen
Gebrauch von HSTORE-Spalten in PostgreSQL macht, unterscheidet sich das
Import-Kommando von demjenigen für den internationalen Stil; Details
dazu finden sich in der
Installationsbeschreibung
des Stils. Zusammen mit den Angaben aus dem
vorigen
Artikel ergibt sich folgendes Bild:
$ osm2pgsql --style hstore-only.style \ --database osm --hstore --hstore-match-only \ --prefix planet_osm_hstore --number-processes 3 \ arnsberg-regbez-latest.osm.pbf
Im Gegensatz zu den Erklärungen im
letzten
Artikel sollte man erwägen, die Option --slim
(und die davon
abhängige Option --cache
) wegzulassen, wenn man genug Arbeitsspeicher
(vermutlich ab ca. 8 GiB) hat; dies führt zu einem überaus erheblichen
Geschwindigkeitszuwachs beim Import. Die im letzten Artikel noch
verwandte Option --multi-geometry
scheint zwischenzeitlich aus
osm2pgsql
entfernt worden zu sein und muss daher wohl nicht mehr
übergeben werden.
Die Shapefiles können ganz normal (also wie beim internationalen Stil) heruntergeladen werden (dafür einige Zeit einplanen, es werden ca. 700 MiB an Daten heruntergeladen):
$ ./get-shapefiles.sh
Views erzeugen
Der deutsche OSM-Stil benutzt SQL-Views (eine Art virtuelle Tabellen), die erst erstellt werden müssen. Dafür liefert er einige Skripte mit, die nunmehr auszuführen sind:
$ psql -d osm -f osm_tag2num.sql $ psql -d osm -f views_osmde/view-line.sql $ psql -d osm -f views_osmde/view-point.sql $ psql -d osm -f views_osmde/view-polygon.sql $ psql -d osm -f views_osmde/view-roads.sql
Das sollte anstandslos funktionieren. Taucht dagegen die folgende Fehlermeldung auf, dann wurde mapnik-german-l10n nicht in einer stabilen, sondern in einer Entwicklerversion installiert. Die Lösung des Problems besteht darin, es wieder zu deinstallieren und die letzte stabile Version zu installieren.
$ psql -d osm -f views_osmde/view-line.sql psql:views_osmde/view-line.sql:55: FEHLER: ungültige Eingabesyntax für Typ boolean: »de« ZEILE 48: osml10n_get_placename_from_tags(tags,true,'de',way) as local... ^ psql:views_osmde/view-line.sql:57: FEHLER: Relation »planet_osm_line« existiert nicht
Anwendung
Jetzt kann der deutsche OSM-Stil in Mapnik-XML übersetzt
werden. Dazu genügt ein schlichter Aufruf von make
; dieser ruft dann
das Skript yaml2mml.py
auf, um die MML-Datei zu erzeugen, die Carto
benötigt, und sodann Carto selbst, um das Mapnik-XML zu erzeugen,
welches dann in der Datei osm-de.xml
abgelegt wird.
$ make scripts/yaml2mml.py --yaml project.yaml --check >project-de.mml carto -a 3.0.9 project-de.mml > /tmp/tmp.13CgCx3nzp mv /tmp/tmp.13CgCx3nzp osm-de.xml
Nun kann die eigentliche Kartenerstellung beginnen. An Nik4 hat sich
seit dem letzten Artikel nichts maßgeblich verändert, sodass auf ihn
verwiesen werden kann. Zu beachten ist lediglich, dass das zu übergebene XML
das in der soeben erzeugten osm-de.xml
ist. Beispielaufruf:
$ nik4.py -s 60000 --ppi 600 -a 4 \ -c 7.6829 51.5329 --margin 10 \ osm-de.xml print.png
Das Ergebnis sieht dann so aus wie dieses Bild (Stadt Unna und Umgebung im Maßstab 1:60000 bei 600 DPI).