Eigene Slippy Tiles Maps mit leaflet und mit busybox httpd ausliefern, eigene qgis overlays erstellen

reinhard@finalmedia.de Thu 25 Nov 2021 08:36:55 PM CET

Disclaimer: Do not download tiles from foreign services without permission. always use ratelimit and only very small geo ranges!

Nur dann Tiles von fremden Tileservern herunterladen, wenn dies offiziell gestattet ist, ein entsprechendes ratelimit verwendet wird um die dortigen Server zu schonen und nur wenn es sich um einen kleinen Ausschnitt handelt. Das nachfolgende Beispiel zu opentopomap/openstreetmap dient nur der Illustration. Verwende das Tool daher möglichst mit deinem eigenen Tileserver, um z.B. Tiles im Anschluss bequem mittels rsync spiegeln zu können. Daher findest du im zweiten Teil des HowTos den Verweis zu QGIS.

openstreetmap/opentopomap: Da die Server aus Spendeneinnahmen finanziert sind, ist die Nutzung nur im geringfügigem Umfang gestattet!

Wenn du außerhalb von Testzwecken Tiles herunterladen willst, so SPENDE bitte an das openstreetmap Projekt, oder erwerbe API Keys bei einem kommerziellen Anbieter wie geofabrik, um dort Tiles regelmäßig herunterzuladen und dann wie nachfolgend beschrieben auf eigene Server zu spiegeln, zu verteilen und zur Offline-Nutzung zur Verfügung zu haben.

Wir werden in diesem Howto OSM Tiles herunterladen, Leaflet Map mit Plugins an den Start bringen, sowie einen eigenen Tileserver. Eigene Tiles erstellen und georeferenziert arbeiten.

Tiles besorgen und ausliefern

Wir werden nun statische Tiles herunterladen und mit einem busybox http als lokalen Tileserver mittels busybox httpd zur Verfügung stellen. Zunächst benötigst du leaflet und meine scripte. Leaflet mit meinen hacks findest du hier: leaflet_map.tgz als mirror. Dann benötigst du noch ein kleines Programm von mir namens tilenames.c. Hier der Quellcode:


/*

        compile: with musl-gcc -O2 -static -o tilenames tilenames.c -lm


        usage: ./tilenames | wget -c -B "https://c.tile.opentopomap.org/" -r -w 0.3 --random-wait -U "YourUserAgent" -i-

        Beispielaufruf:
        export TILE_PREFIX="https://c.tile.opentopomap.org/"
        export TILE_SEPARATOR="/"
        export TILE_ZOOM_START=1
        export TILE_ZOOM_STOP=9
        export TILE_LON_START=6.57
        export TILE_LON_STOP=8.03
        export TILE_LAT_START=49.04
        export TILE_LAT_STOP=49.75
        export TILE_SUFFIX=".png"
        ./tilenames | wget -nH -P opentopo -c -r -i-

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int lon2tilex(double lon, int z)
{
        return (int)(floor((lon + 180.0) / 360.0 * (1 << z)));
}

int lat2tiley(double lat, int z)
{
    double latrad = lat * M_PI/180.0;
        return (int)(floor((1.0 - asinh(tan(latrad)) / M_PI) / 2.0 * (1 << z)));
}

double tilex2lon(int x, int z)
{
        return x / (double)(1 << z) * 360.0 - 180;
}

double tiley2lat(int y, int z)
{
        double n = M_PI - 2.0 * M_PI * y / (double)(1 << z);
        return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
}
int main(int argc, char *argv[])
{

unsigned int z=0,x=0,y=0,a_min=0,a_max=0,b_min=0,b_max=0;

// Set default values and do NOT overwrite, if env already exists
setenv("TILE_PREFIX","",0);
setenv("TILE_SUFFIX","",0);
setenv("TILE_SEPARATOR","/",0);
setenv("TILE_ZOOM_START","1",0);
setenv("TILE_ZOOM_STOP","17",0);
setenv("TILE_LON_START","-180",0);
setenv("TILE_LON_STOP","180",0);
setenv("TILE_LAT_START","-85",0);
setenv("TILE_LAT_STOP","85",0);

char* ptr;
double lon_tile_start=strtod(getenv("TILE_LON_START"),&ptr);
double lon_tile_stop=strtod(getenv("TILE_LON_STOP"),&ptr);
double lat_tile_start=strtod(getenv("TILE_LAT_START"),&ptr);
double lat_tile_stop=strtod(getenv("TILE_LAT_STOP"),&ptr);

for (z=atoi(getenv("TILE_ZOOM_START"));z<=atoi(getenv("TILE_ZOOM_STOP"));z++) {
a_min=lon2tilex(lon_tile_start,z);
a_max=lon2tilex(lon_tile_stop,z);
b_max=lat2tiley(lat_tile_start,z);
b_min=lat2tiley(lat_tile_stop,z);
fprintf(stderr,"processing %d %d %d %d %d %f %f %f %f\n",
z,a_min,a_max,b_min,b_max,lon_tile_start,lon_tile_stop,lat_tile_start,lat_tile_stop);
for (x=a_min;x<=a_max;x++) {
for (y=b_min;y<=b_max;y++) {
printf("%s%d%s%d%s%d%s\n",getenv("TILE_PREFIX"),z,getenv("TILE_SEPARATOR"),x,getenv("TILE_SEPARATOR"),y,getenv("TILE_SUFFIX"));
}}}
return 0;
}

Du kannst den Quellcode hiermit herunterladen und kompilieren:


#!/bin/sh
wget https://finalmedia.de/kb/d4b80f4818a1/tilenames.c
sha1sum tilenames.c 
# muss liefern: 9d00c2e2cad863a0e9787587269c4a7bc529d8e4  tilenames.c
apt-get install musl-tools build-essential
musl-gcc -O2 -static -o tilenames tilenames.c -lm

Das damit erzeugte Programm "tilenames" prozessiert übergebenene Umgebungsvariablen und errechnet die Namen von Tiles nach dem SlippyMap Standard, wie sie bei leaflet und openstreetmap verwendet werden. Diese gibt es auf stdout zeilenweise als vollständige URLs aus.

Daraufhin kannst du mit diesem Shell-Script alle tiles einer Region von openstreetmap herunterladen. Wir verwenden dabei also die URL-Liste als input-Liste für wget und laden mit fairem Verfahren und hinreichend Pause die Tiles langsam und gemächlich von openstreetmap nach, ohne dortige Infrastruktur zu stark zu beinträchtigen. Fair Use! Wird also recht lange laufen.

In diesem Fall habe ich die Region St. Wendel ausgewählt und dabei die Geokoordination in Umgebungsvariablen definiert:

#!/bin/bash

mkdir tiles
cd tiles

#export TILE_PREFIX="https://b.tile.opentopomap.org/"
export TILE_PREFIX="https://tile.openstreetmap.org/"
export TILE_SUFFIX=".png"

# st. wendel (rechteck)
export TILE_ZOOM_START=13
export TILE_ZOOM_STOP=19
export TILE_LON_START=7.1224
export TILE_LON_STOP=7.2139
export TILE_LAT_START=49.44503
export TILE_LAT_STOP=49.48642

../tilenames | wget -T 30 -nH -P "osm" -c -r -w 0.5 --random-wait -U "Mozilla" -T 10 -i-

Wenn das durchgelaufen ist, hast du eine lokale Kopie der OSM Tiles für diese Region und vom Zoomlevel 13 bis Zoomlevel 19 im Ordner "tiles/osm" liegen.

Du kannst nun leaflet und einen minimalistischen httpd aus busybox nutzen, um diese tiles auszuliefern:

wget https://finalmedia.de/kb/d4b80f4818a1/leaflet_map.tgz
tar xvfz leaflet_map.tgz
mv tiles map/tiles
cd map
busybox httpd -f -p 127.0.0.1:8000

Wenn du nun in deinem Browser http://127.0.0.1:8000 aufrufst, liefert dir busybox httpd leaflet und die tiles aus.

Wenn du die opentopomap gewählt hast, wie oben auskommentiert, sieht das so aus und ist zoombar und verschiebbar. Die Aktuellen Geokoordinaten an der Position des Mauscursors siehst du links unten. Ein Doppelklick bringt dir einen Dialog, damit du diese bequeme copy&pasten kannst (z.B. wenn du die Geo-Koordinaten zu einem bestimmten Ort in deiner Zwischenablage benötigst).

Der Vorteil von statischen Tiles ist nun, dass du diese zu einem zweiten Server via rsync spiegeln kannst, (oder auch dort auf dem secondary host einfach mittels wget -Nr primaryhost einen mirror des primary erzeugst (sofern tile index verfügbar). Dann genügt es, wenn du einen zweiten A Record zu deinem gewünschten Domain-Namen setzt und du hast einen einfachen Load-Balancer und Redundanz-Service für deinen Tileserver

WIP: QGIS, eigene Karten und eigene Tiles

Wir werden in QGIS unseren eben erzeugten eigenen Tileserver nutzen, um Karten anzuzeigen und zu laden... Dann werden wir ein Overlay erstellen mit eigenen Karten, die wir als separate Tiles-Layer exportieren...

QGIS ist eine GUI Applikation und fett.

apt-get install qgis

Starte nun qgis und wähle dort im Browser-Fenster in dem Unterpunkt "Tile server (XYZ)" den Eintrag "osm" mittels Rechtsklick und Layer hinzufügen:

Im Layerfenster nun erneut Rechtsklick auf osm, dann Eigenschaften.

Im nun erscheinenden Dialog, wählst du den Reiter Allgemein und trägst dort wie hier ersichtlich bei der Layerquelle ein:

type=xyz&url=http://127.0.0.1:8000/osm/%7Bz%7D/%7Bx%7D/%7By%7D.png

Dann klickst du die Schaltfläche OK. Nun klickst du Im Menü ganz oben auf Layer > Layer erstellen > Shape-Datei-Layer anlegen:

In diesem Layer kannst du nun Polygone zeichnen und zur Referenz die osm Map im Hintergrund verwenden.

Klicke nun im Menü ganz oben auf Erweiterungen > Erweiterungen verwalten und installieren und suche nach "qtiles". Klicke dort auf "Erweiterung installieren".

Über Erweiterungen > QTiles > QTiles kannst du nun jederzeit Tiles in ein Verzeichnis erzeugen: