Image for design

WIKI

FACHSCHAFTSRAT SYSTEMS ENGINEERING
UND LEHRAMT INFORMATIK

UNIVERSITÄT DUISBURG-ESSEN

Fachschaftsrat Systems Engineering und Lehramt informatik

Howto: Eigener Maptile Server

Aus FSEwiki

Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

The easy way

Ich habe mit dem unten beschriebenen Ansatz begonnen, da ich vor allem Mapnik als Renderer nutzen wollte. Leider gibt es zur Zeit einige Inkompatibilitäten zwischen den einzelnen Tools. Daher habe ich nach einem Weg gesucht, der wesentlich sicherer und einfacher ist.

Die Idee ist einfach: Der Maptile Server läuft in einer virtuellen Maschine und ist (im Rahmen dieses Tutorials, aber o.B.d.A.) über das lokale Netzwerk zu erreichen. Die virtuelle Maschine, die ich hierbei genutzt habe stammt aus dem Tiles@Home (genauer Virtual Tiles@Home) Projekt, ist aber eigentlich nicht dafür ausgelegt ihn als eigenen Mapserver zu nutzen. Sie ist vielmehr dafür gemacht worden, um die Maptiles dezentral generieren lassen zu können.

Voraussetzungen

VirtualBox

  1. Herunterladen (von hier).
  2. Installieren.
  3. Fertig.

Hinweis: In diesem Howto werde ich nicht großartig erklären, wie man VirtualBox dazu bringt Remote Traffic zu routen bzw. wie man mit dem Gastsystem kommunizieren kann, da das den Rahmen sprengen würde. Hier findet ihr die passenden Anleitungen dazu:

Virtual Tiles@Home - Ubuntu

  1. Herunterladen (z.B. von einer der hier gelisteten Quellen).
  2. Entpacken.
  3. VirtualBox starten.
  4. Eine neue virtuelle Maschine erstellen:
    1. Neu,
    2. Einen Namen eingeben (z.B. virtual tiles@home).
    3. Das Betriebssystem auf Linux setzen.
    4. Die Version auf Ubuntu setzen.
    5. Auf der nächsten Wizardseite ca. 10% des Arbeitsspeichern der virtuellen Maschine genehmigen.
    6. Auf der darauffolgenden Wizardseite Festplatte benutzen wählen und die entpackte vdi-Datei auswählen.
    7. Auf Fertig klicken.
  5. Rechtsklick auf die neue virtuelle Maschine und dann auf Ändern.
  6. Unter Allgemein -> Erweitert muss das Häkchen bei PAE/NX gesetzt werden, sonst wird es nicht funktionieren.
  7. Die virtuelle Maschine kann nun gestartet werden. Beim ersten Bootvorgang wird sie ein paar SVN Checkouts machen, um die benötigten Tools herunterzuladen.

Hinweis: Ich empfehle eine weitere (auto-increasing) Festplatte zu erstellen, da die 2GB, die Virtual Tiles@Home mit sich bringt nicht gerade viel sind. Wie das geht findet man hier. Ich werde im weiteren Verlauf annehmen, dass eine zweite Festplatte erstellt, zugewiesen, partitioniert, formatiert und auf /var/www eingehangen wurde.

Konfiguration

Tiles@Home

Beim Systemstart wird der tiles@home-Client automatisch gestartet. Den kann man getrost mit Strg-C gen Himmel schicken. Wer will kann auch das init-Script /etc/init.d/tiles-gen-client löschen, damit es in Zukunft nicht mehr gestartet wird (es wird aber sowieso sofort abbrechen).

Unter /var/tmp/tilesAtHome befinden sich die Scripts, die für die Maptilegenerierung zuständig sind. Dahin müssen wir.

cd /var/tmp/tilesAtHome

Nun müssen wir den Pfad angeben, in dem die Tiles gespeichert werden sollen. Wir nehmen dafür /var/www:

echo LocalSlippymap=/var/www >> general.conf

Webserver

Nun ist tiles@home eigentlich einsatzbereit. Wir nur noch den Webserver installieren und konfigurieren:

apt-get install apache2 php5 libapache2-mod-php5 php5-gd
a2enmod rewrite

Öffnet nun die /etc/apache2/sites-available/default, sucht nach

<Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
</Directory>

und ersetzt die AllowOverride-Rechte, sodass die Zeile wie folgt aussieht:

AllowOverride All

Der Benutzer openstreetmap sollte der Gruppe www-data angehören:

usermod -G www-data openstreetmap

Jetzt darf der Webserver seine neue Konfiguration anerkennen:

/etc/init.d/apache2 restart

Da ich ein paar Probleme mit den Dateirechten in /var/www hatte, und dieses System auch absolut nicht sicherheitskritisch ist, hier der Workaround:

chown -R www-data:www-data /var/www
chmod -R 0777 /var/www

Hinweis: Der Benutzer heißt openstreetmap und das Passwort ist ebenfalls openstreetmap. Außerdem verlangt sudo kein Passwort, ist also häufig zu verwenden.

Tiles-Umgebung

Wir wechseln nun in das Verzeichnis /var/www, worin wir ein paar Tools erstellen werden.

Da es ganz praktisch ist, ein Tool zu haben, dass aus Längen-, Breitengrad und Zoomstufe die Tile-Koordinaten berechnet, legen wir nun eine Datei mit dem Namen calc.php an und füllen sie wie folgt:

<?php
 
if (isset($_REQUEST['lat']) && !empty($_REQUEST['lat'])
 && isset($_REQUEST['lon']) && !empty($_REQUEST['lon'])
 && isset($_REQUEST['zoom']) && !empty($_REQUEST['zoom']))
{
    $lat = $_REQUEST['lat'];
    $lat = $_REQUEST['lon'];
    $zoom = $_REQUEST['zoom'];
    $xtile = floor((($lon + 180) / 360) * pow(2, $zoom));
    $ytile = floor((1 - log(tan($lat * pi() / 180) + 1 / cos($lat * pi() / 180)) / pi()) / 2 * pow(2, $zoom));
    echo $zoom . "/" . $xtile . "/" . $ytile;
}

?>

Über http://localhost/calc.php?lat=51.xxxx&lon=7.yyyy&zoom=15 kommt man nun praktisch an den Pfad zum Maptile.

Es gibt nun zwei Möglichkeiten:

  • Wir generieren die Kartenteile vor oder
  • wir generieren die Kartenteile on-demand.

Zunächst die on-demand Variante, für die wir eine .htaccess Datei anlegen und sie wie folgt füllen:

RewriteEngine On
RewriteRule ^tile/(-?[0-9]+)/(-?[0-9]+)/(-?[0-9]+).png index.php?x=$2&y=$3&z=$1 [PT,T=image/png]

Jetzt noch die index.php:

<?php

$file = "./tile/" . $_REQUEST['z'] . "/" . $_REQUEST['x'] . "/" . $_REQUEST['y'] . ".png";

if (file_exists($file))
{
    header("Content-Type: image/png");
    readfile($file);
}
else
{
    $cmd = "cd /var/tmp/tilesAtHome; ./tilesGen.pl xy " . $_REQUEST['x'] . " " . $_REQUEST['y'] . " " . $_REQUEST['z'];
    shell_exec($cmd);

    $starttime = time();
    while (!file_exists($file) && time() - $starttime < 10)
    {
    }

    if (file_exists($file))
    {
        header("Content-Type: image/png");
        readfile($file);
    }
    else
    {
        include "404.php";
    }
}

?>

Nun noch die 404.php, die wir auch im zweiten Ansatz gebrauchen werden:

<?php

$img = imagecreatetruecolor(256, 256);

$black = imagecolorallocate($img, 0, 0, 0);
$white = imagecolorallocate($img, 255, 255, 255);

imagefilledrectangle($img, 0, 0, 256, 256, $white);

imagettftext($img, 10, 0, 5, 128, $black, "./sans.ttf", "This tile has not been rendered, yet.");

header("Content-Type: image/png");
imagepng($img);
imagedestroy($img);

?>

Und welch Spass: Hier fehlt auch wieder eine Datei. Wir brauchen nun eine TTF Datei, mit der Schriftart. So habe ich es angestellt:

apt-get install ttf-opensymbol
cp /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf /var/www/sans.ttf
chown www-data:www-data /var/www/sans.ttf
chmod 0755 /var/www/sans.ttf

Wird nun eine Anfrage à la http://localhost/tile/zoom/x/y.png gestellt und die Grafik wurde noch nicht generiert, dann wird die Generierung eines ganzen Tilesets angeschmissen und gleich mehrere Zoomstufen werden generiert. Sollte das nicht innerhalb von 10 Sekunden passiert sein, so werfen wir eine Platzhaltergrafik zurück. Nun muss ich sagen, dass die ersten 10 Stunden, die ich damit verbracht habe, wahrlos Anfragen zu senden, damit genug Grafiken generiert wurden, sehr nervig waren. Deswegen habe ich mich dann dazu entschieden meine Region of Interest vorzugenerieren.

Zunächst geht man - auf Grund der Einfachheit - auf Google Maps und wählt unter Meine Karten den Position Finder aus, um die Koordinaten der nord-westliche Ecke der Boundingbox herauszufinden. Die Koordinaten lat und lon werfen wir jetzt in unser Berechnungstool:

http://localhost/calc.php?lat=lat&lon=lon&zoom=12

Wir bekommen eine Zeichenkette zurückgeliefert, die etwa so aussieht:

12/x1/y1.png

Daraus nehmen wir uns jetzt x1 und y1 und behalten sie erstmal im Hinterkopf, solange bis wir den Vorgang mit der süd-östlichen Ecke der Boundingbox wiederholt haben, wodurch wir x2 und y2 erhalten. Nun wechseln wir in das tilesAtHome-Verzeichnis und generieren unser Tileset:

cd /var/tmp/tilesAtHome
for x in $(seq x1 x2); do for y in $(seq y1 y2); do ./tilesGen.pl xy $x $y 12; done; done

Nun das kann jetzt sehr lange dauern, je nachdem wie groß ihr die Boundingbox gewählt habt, wieviel Arbeitsspeicher ihr der virtuellen Maschine zugewiesen habt und wieviel Power der Prozessor hat.

Nachdem wir nun auf die eine oder auf die andere Weise unser Kartenmaterial erstellt haben, können wir jederzeit über den Browser darauf zugreifen.

Anmerkungen:

  • Es ist möglich eine hybride Herangehensweise zu wählen. Wählt man ausschließlich die Vorgenerierung, dann kann es praktisch sein, folgende .htaccess Datei (statt der oben genannten) zu verwenden:
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule \.(gif|jpe?g|png|bmp|svg) 404.php [NC,L]

The hard way

In diesem Howto wird gezeigt, wie man sich einen eigenen Maptile Server unter Windows installiert, um auch offline die Funktionalität der Slippy Maptiles von OpenStreetMap.org nutzen zu können.

Voraussetzungen

Webserver

  1. Herunterladen.
  2. Entpacken.
  3. setup_xampp.bat ausführen.
  4. Fertig.

Python

  1. Herunterladen.
  2. Installieren.
  3. Fertig.

Mapnik

  1. Herunterladen.
  2. In C:\ entpacken, sodass das Verzeichnis C:\mapnik_0_6_0\ erstellt wird.
  3. C:\mapnik_0_6_0\lib zur PATH Systemvariable hinzufügen.
  4. C:\mapnik_0_6_0\lib zur PATH Benutzervariable hinzufügen.
  5. Die Systemvariable PYTHONPATH mit dem Wert C:\mapnik_0_6_0\site-packages erstellen.
  6. Kommandozeile (cmd.exe) ausführen.
  7. Ins Python-Verzeichnis navigieren und die Python-Commandline starten (z.B. C:\Python25\python.exe).
  8. Folgendes eingeben und fertig:
from mapnik import *

PostgreSQL und PostGIS

  1. Herunterladen.
  2. Installieren.
  3. Am Ende der Installation den Stack Builder starten lassen.
  4. Kategorien -> Spatial Extensions -> PostGIS 1.3.6 PostgreSQL 8.3 v 1.3.6 aktivieren.
  5. Durch den Installer durchklicken.
  6. Fertig.

osm2pgsql

  1. Herunterladen.
  2. Irgendwo entpacken.
  3. Den Pfad zum osm2pgsql-Verzeichnis zur PATH Systemvariable hinzufügen.
  4. Fertig.

Konfiguration

Datenbank anlegen

  1. pgAdmin III starten (sollte sich im Startmenü befinden).
  2. PostgreSQL 8.3 (localhost:5432) auswählen und unter Werkzeuge -> Verbinden eine Verbindung aufbauen. Die Zugangsdaten wurden bei der PostgreSQL Installation angegeben.
  3. Unter dem o.g. Knoten befindet sich der Knoten Datenbanken. Der muss markiert werden. Ein Rechtsklick darauf erlaubt es mit Neue Datenbank... eine neue Datenbank anzulegen.
  4. Folgende Werte sind praktikabel:
Name: gis
Eigentümer: postgres
Vorlage: template_postgis
  1. Unter Privilegien einfach auf Hinzu/Ändern klicken, die neue Gruppe markieren und den Haken bei ALL setzen.
  2. Unter Login-Rollen einen User durch Rechsklick und Neue Login-Rolle...' anlegen, dessen Name identisch zum Systemnutzer ist.
  3. Jetzt müssen dem neuen Nutzer die Rechte zugewiesen werden. Dazu findet man unter Werkzeuge -> Abfragewerkzeug das passende Tool, indem folgende Queries ausgeführt werden müssen:
ALTER TABLE geometry_columns OWNER TO "username";
ALTER TABLE spatial_ref_sys OWNER TO "username";
  1. Fertig.

Daten importieren

Bis dato war es mir nicht möglich Tiles aus der planet-Datei generieren zu lassen. Man findet bei Geofabrik jedoch kleinere Pakete, die bei mir wunderbar funktioniert haben. Im folgenden nehme ich nordrhein-westfalen.osm.bz2 als Beispiel.

  1. Kommandozeile (cmd.exe) starten.
  2. Ins Verzeichnis von osm2pgsql.exe navigieren (nicht nötig, wenn die PATH Variable richtig gesetzt wurde).
  3. Folgendes ausführen:
osm2pgsql.exe -c -u -d gis path\to\nordrhein-westfalen.osm.bz2

Troubleshooting

Kein Zugriff möglich

Using projection SRS 900913 (Spherical Mercator)
Setting up table: planet_osm_point
SELECT AddGeometryColumn('planet_osm_point', 'way', 900913, 'POINT', 2 );
failed: ERROR: permission denied for relation geometry_columns
CONTEXT: SQL statement "DELETE FROM geometry_columns WHERE f_table_catalog =  AND f_table_schema = 'public' AND f_table_name = 'planet_osm_point' AND f_geometry_column = 'way'"
PL/pgSQL function "addgeometrycolumn" line 102 at EXECUTE statement
SQL statement "SELECT AddGeometryColumn(,, $1 , $2 , $3 , $4 , $5 )"
PL/pgSQL function "addgeometrycolumn" line 4 at SQL statement

Error occurred, cleaning up

Lösung: https://www.baschetti.de/content/osm2pgsql

Falsche Projektion

ALTER TABLE planet_osm_point ALTER COLUMN way SET NOT NULL;
failed: ERROR:  function addgeometrycolumn(unknown, unknown, integer, unknown, integer) does not exist
LINE 2: SELECT AddGeometryColumn('planet_osm_point', 'way', 3395, 'P...
              ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

Error occurred, cleaning up

Folgendes könnte helfen:

path\to\psql -d gis -f path\to\osm2pgsql\900913.sql

psql befindet sich z.B. in C:\Program Files\PostgreSQL\8.3\bin.

Rendering

Es gibt verschiedene Möglichkeiten Maptiles zu generieren.

Hier gibt es die Varianten: Deploying your own Slippy Map / Erstelle deine eigenen Karten.

Siehe auch