Openseamap/DE:KAP-Dateien aus OSeaMap erstellen
Vorwort
BSB-Seekarten (KAP-Dateien) werden in Programmen, wie z.B. OpenCPN verwendet.
Um aus den OpenSeapMap- bzw. OpenStreetMap-Daten eine Seekarte zu erstellen, wird ein Bild mit eingezeichneten Seezeichen als PNG benötigt.
Eine weiter Möglichkeit ist es, eine KAP-Datei direkt aus OSM-Daten mit dem Programm Smrender zu erzeugen.
Beschaffung/Erstellung der Vorlagendatei
eigenen Mapnik-Renderer aufsetzen
- Mapnik aufsetzen
- Renderregeln einpflegen
- berechnen lassen
- ...
Benutzung von vorgefertigten Kacheln
Eine weitere Möglichkeit besteht darin, die fertig gerenderten Kacheln des OpenSeaMap-Tileservers dafür zu verwenden.
Der OpenSeaMap-Server verwendet die Mapnik-Kacheln der OpenStreetMap-Tileserver und überlagert diese mit transparenten, eigenen Kacheln, auf denen die Seezeichen vorhanden sind. Diese Möglichkeit kann man sich auch zu Nutze machen, um eine Seekarte im PNG-Format herzustellen. Man lädt alle benötigten Kacheln vom Tile-Server der OpenStreetMap herunter und überlagert diese mit den Kacheln der OpenSeaMap (wenn überhaupt vorhanden). Als letztes müssen diese Kacheln noch zu einem einzigen Bild (PNG) zusammengefasst werden.
Perl-Skript
Das folgende Perl-Skript erledigt diese Aufgabe, indem zuerst die Kacheln ermittelt werden, welche den benötigten Bereich darstellen. Diese werden durch 'wget' in ein Verzeichnis geladen und durch ImageMagick mit den Kacheln den Seezeichen überlagert. Als nächstes werden die Kacheln wieder mit Hilfe von ImageMagick zu einem einzigen Bild zusammengefasst.
Voraussetzungen:
- Perl-Interpreter
- wget
- ImageMagick
- Internet-Verbindung
- möglichst leeres Verzeichnis zur Speicherung der Kacheln
Sourcecode
#!/usr/bin/perl
use Math::Trig;
$level=15;
$latStart = 54.70;
$lonStart = 9.82;
$latEnde = 54.57;
$lonEnde = 10.08;
($xstart, $ystart) = getTileNumber($latStart,$lonStart,$level);
($xende, $yende) = getTileNumber($latEnde, $lonEnde, $level);
$xanz = $xende-$xstart;
$yanz = $yende-$ystart;
$urlOSM="http://tile.openstreetmap.org";
$urlOSeaMap="http://tiles.openseamap.org/seamark";
# Status anzeigen
print ("Anzahl x: $xanz\n");
print ("Anzahl y: $yanz\n");
($dummy, $lonStart, $latStart, $$dummy) = Project($xstart,$ystart,$level);
($latEnde, $dummy, $dummy, $lonEnde) = Project($xende,$yende,$level);
print (" -> $latStart, $lonStart, $latEnde, $lonEnde \n");
# Aufräumen
`rm *.png *.log`;
# liegt es im Rahmen?
if ($xanz*$yanz > 25*25) {
die "Zu viele Teile";
}
# Hauptschleife
for ($x=$xstart; $x<$xstart+$xanz; $x++){
for ($y=$ystart; $y<$ystart+$yanz; $y++){
print ("Level, X, Y = $level, $x, $y\n");
`wget "$urlOSM/$level/$x/$y.png" -o "$level-$y-$x.log" -O "$level-$y-$x.png" `;
`wget "$urlOSeaMap/$level/$x/$y.png" -o log -O "SeaMap-$level-$y-$x.png" `;
if ( -e "SeaMap-$level-$y-$x.png"){
unless ( -z "SeaMap-$level-$y-$x.png"){
`convert -type PaletteMatte -matte -transparent "#F8F8F8" "SeaMap-$level-$y-$x.png" "SeaMap-$level-$y-$x.png"`;
`composite "SeaMap-$level-$y-$x.png" "$level-$y-$x.png" "$level-$y-$x.png"`
}
`rm "SeaMap-$level-$y-$x.png"`;
}
}
}
`montage +frame +shadow +label -tile "$xanz x $yanz" -geometry 256x256+0+0 *.png joined.png`;
sub getTileNumber {
my ($lat,$lon,$zoom) = @_;
my $xtile = int( ($lon+180)/360 *2**$zoom ) ;
my $ytile = int( (1 - log(tan(deg2rad($lat)) + sec(deg2rad($lat)))/pi)/2 *2**$zoom ) ;
return ($xtile, $ytile);
}
sub Project {
my ($X,$Y, $Zoom) = @_;
my $Unit = 1 / (2 ** $Zoom);
my $relY1 = $Y * $Unit;
my $relY2 = $relY1 + $Unit;
# note: $LimitY = ProjectF(degrees(atan(sinh(pi)))) = log(sinh(pi)+cosh(pi)) = pi
# note: degrees(atan(sinh(pi))) = 85.051128..
# my $LimitY = ProjectF(85.0511);
# so stay simple and more accurate
my $LimitY = pi;
my $RangeY = 2 * $LimitY;
$relY1 = $LimitY - $RangeY * $relY1;
$relY2 = $LimitY - $RangeY * $relY2;
my $Lat1 = ProjectMercToLat($relY1);
my $Lat2 = ProjectMercToLat($relY2);
$Unit = 360 / (2 ** $Zoom);
my $Long1 = -180 + $X * $Unit;
return ($Lat2, $Long1, $Lat1, $Long1 + $Unit); # S,W,N,E
}
sub ProjectMercToLat($){
my $MercY = shift;
return rad2deg(atan(sinh($MercY)));
}
sub ProjectF{
my $Lat = shift;
$Lat = deg2rad($Lat);
my $Y = log(tan($Lat) + sec($Lat));
return $Y;
}
Python-Tool
GMapCatcher (Windows/Linux) ist ein recht komfortables Werkzeug, um Tiles herunterzuladen.
Die Vorteile:
- Tiles können entlang eines GPX-Tracks heruntergeladen werden (geeignet fuer Wasserstrassen)
- die Tiles können in der OSM-Verzeichnisstruktur abgelegt werden (Settings > Custom Maps Directory > OSM statt Files)
Im Falle einer Wasserstraße:
- erstellt man sich einen GPX-Track (z.B. mit JOSM oder dem Wasserstraßenrouter von http://maps.grade.de )
- benutzt das beiliegende Download-Tool
- z.B. Win
download --gpx=ruhr.gpx --width=1 --min-zoom=1 --max-zoom=1
- z.B. Linux
mapdownloader --gpx=ruhr.gpx --width=1 --min-zoom=1 --max-zoom=1
- z.B. Win
- GMapCatcher-zoom=1 entspricht OSM-zoom=16
- Vorausgesetzt, man hat mit einem jungfäulichem Verzeichniss angefangen, sind nun die Tiles für eine Karte beisammen. Im Falle der schiffbaren Ruhr sind das bei zoomlevel=16 ca. 370 Tiles. Würde man den Bereich über eine Bounding-Box herunterladen, wären das ca. 1700 Tiles!
- mit dem bash-Script http://www.openstreetmap.org/user/mkarau/diary/20256 kann man anschliessend die Tiles zu einem großen .png zusammensetzen. Die fehlenden Tiles werden automatisch durch ein z.B. weißes Bild ersetzt. Die linke obere und rechte untere Ecke wird in Tilenames angegeben und kann für diie Kalibrierung genutzt werden.
Alternativ kann man auch im GMapCatcher entlang der gewünschten Route surfen und anschliessend die gespeicherten Tiles zusammenfügen.
weiteres Vorgehen
Mit dem, aus dem obigen Vorgehen, resultierenden Bild, kann nach dieser Anleitung die KAP-Datei erstellt werden. Alternativ mit imgkap.
Referenzen
- http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames Die Unterprogramme zur Berechnung der Kachelnummern
- http://wiki.openstreetmap.org/wiki/FAQ#What_is_the_map_scale_for_a_particular_zoom_level_of_the_map.3F Welcher Zoom-Level hat welchen Maßstab
- http://opencpn.de/handbuecher/elektronische-seekarten-selbst-erstellen/vorwort Sehr interessanter Text über elektronische Seekarten
- IHO Catalogue of INT Charts