Offline Kartenmaterial für Java-Swing

Vielleicht hilft Folgendes:
Mit OpenLayers lässt sich das so realisieren:
OpenLayers.js und OpenStreetMap.js lokal speichern, OpenStreetMap.js modifizieren:
// “http://a.tile.openstreetmap.org/${z}/${x}/${y}.png”,
// “http://b.tile.openstreetmap.org/${z}/${x}/${y}.png”,
// “http://c.tile.openstreetmap.org/${z}/${x}/${y}.png
in
“lokales_verzeichnis/${z}/${x}/${y}.png”

Die benötigten Teil in lokales_verzeichnis + entsprechende Unterverzeichnisse ablegen.
Zum letzten Schritt kann ich ein perl Skript bieten.

Das ist ja erst einmal nur das umbiegen der Tiles auf ein lokales Verzeichnis.
Ob man für Vorarlberg mit einem Verzeichnis auskommt, müsste man noch überlegen. Aber das ist im wesentlichen eine Performance Frage und muss nicht im ersten Schritt bedacht werden.

Die eigentliche Frage von Sc0rP1En geht mehr dahin, wie man a) einen eigenen Map-Server aufbaut und b) wie man den Zugriff auf die Tiles in ein Javaprogramm einbaut.

Dazu zwei Anregungen:

  • Der User ajoessen baut eine eigene Karte für NRW und hat im Wiki dokumentiert wie er das macht. Vorteil eines eigenen Mapservers ist, dass ihr in euerem Programm praktisch nur die Adresse, woher ihr die Tiles bezieht, ändern müsst.

  • In den Source von JOSM sehen. JOSM ist in Java geschrieben, holt sich die Daten von der API und stellt sie nach definierten Regeln dar. Vielleicht gibt es ja dort Anregungen wie man Karten-Tiles einbindet oder wie man aus den Daten direkt rendern kann. Letzteres hätte den Vorteil eines nahezu stufenlosen Zooms. Bitte eure DAten nicht direkt von der API holen, das ist für Editoren gedacht, die die Live-Daten benötigen.

Edbert (EvanE)

Hallo

Ich habe mich nun ein bisschen mit Kosmos befasst. Damit kann man ja die Tiles herunterladen, rendern und dann einen eigenen Tile Map Server starten. Diesen Lokalen Webserver sollte ich eigentlich anstelle des Webservers aus dem Internet verwenden können oder nicht?

Leider zeigt er auf der Map nichts an. Als ob er keine Tiles zu Verfügung hat. Kann es an der Ordnerstruktur liegen?
Im ersten Ordner ist die Zoomstufe, im 2. Ordner weiß ich nicht was es darstellt, aber es ist irgendeine Zahl zwischen 0 und 33000 und in diesem Ordner befinden sich die PNGs mit einer fortlaufenden Nummerierung. Sollte diese Struktur nicht eigentlich den Zoom, die Y und die X Koordinate widerspiegeln? So habe ich es zumindest im Internet gelesen.

Ich hoffe ich bin jetzt nicht komplett auf dem Holzweg.

Greets
Sc0rP1En

Ja das spiegeln sie doch wieder? Die Berechnung von Koordinate zu den Index Nummern war ja hier beschrieben: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames

Und ja Kosmos hat einen internen Webserver der dir die Tiles verfügbar macht.

Das komische ist nur, dass der JXMapKit die Tiles nicht findet, da er nach z.b. tiles/12/18/13 sucht. Bei der Zoomstufe 12 habe ich aber keinen Ordner mit 18 sondern 2158 … da verwundert mich schon sehr …

Der lokale Server zeigt mir nur das Zeichen für kaputte Bilder an und keine Tiles…

So sollte es doch die beste Lösung für mein Problem sein oder?

Es sieht so aus, als würde dein JXMapKit den falschen Startpunkt verwenden.
Aus http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#X_and_Y

Tile 12/2158/1432 liefert Bregenz, Tile 12/2156/1436 liefert die westliche Ecke von Vorarlberg/Österreich (Grenze Österreich/Schweiz/Lichtenstein).

Das heißt, die Tile-Nummern in deinem Verzeichnis passen, das was JXMapKit anfordert passt nicht.
Du kannst mit PHP Calc for OSM ein wenig rumspielen (Bounding-Box an Vorarlberg anpassen) und sehen welchen Bewreich an Tile-Nummern du dann erhältst.

Edbert (EvanE)

Hmm was für eine TileFactory verwendest du?

Guten Morgen

@EvanE
ich werde heute Nachmittag mal damit herumprobieren. Vielleicht finde ich eine Umrechnung auf die vom JXMapKit geforderten Tiles. Eine Einstellung zum Ändern habe ich bislang noch nicht gefunden.

@!i!
Ich verwende die standard Swing TileFactoryInfo und TileFactory:



       final int max = 17;
       TileFactoryInfo fact = new TileFactoryInfo(12,17,max,256,true,true,"file:/C:/tiles2/","x","y","z"){
        
    public String getTileUrl(int x,int y,int z){
            //z=max-z;
            return this.baseURL+z+"/"+x+"/"+y+".png";
        }
        };
       
 TileFactory tf = new DefaultTileFactory(fact);
        
    jxmapkit1.setTileFactory(tf);
    jxmapkit1.setDefaultProvider(org.jdesktop.swingx.JXMapKit.DefaultProviders.Custom);
    jxmapkit1.setAddressLocation(new GeoPosition(47.4493,9.7261));

Hmm dann musst du die doch nur anpassen und die Berechnungen aus der Wiki Seite einfügen?

ich weiß ja nicht, was die TileFactory für Daten verwendet. Die korrekten Tile-Nummern scheinen es ja nicht zu sein und wie Koordinaten sieht es auch nicht aus. :-/

Schau dir mal die main-Funktion in der Klasse JXMapKit an. Dort wird in ein paar Zeilen ein OSM-Viewer zusammengebaut (mit dem OpenStreetMap DefaultProvider). Und der Viewer funktioniert, d.h. die Tiles werden korrekt geladen.

Vergleich doch mal den Code dort mit deinem Code. Vielleicht ergibt sich dann, was fehlt.

sry für die blöde Frage, aber wie schau ich die main dieser Klasse an?^^ Die ist doch in der Swinglib drinnen? Wenn ich diese Jar extrahiere und dann die .class Datei öffne, zeigt er mir nichts an :-/

Du kannst dir den Sourcecode von http://swinglabs.org/downloads.jsp herunterladen. Projekt SwingX-WS.

habs mir gerade angeschout. Beim OSM default.provider war es ein bisschen anders, habe es aber nun angepasst. Das Problem war die minimale Zoomstufe. Ich habe nur Tiles ab 12 bis 17… muss aber im Konstruktor 1 angeben, damit er die richtige Ordnerstruktur aufbaut (so wie ich sie habe) … sonst beginnt er bei Zoomstufe 12 mit der Tilenr. 0 und 1 etc…

Wenn ich jetzt auf 12 Zoome bekomme ich die Tiles angezeigt. Leider nur irgendwie zufällig. D.h. sie werden nicht richtig aneinandergereit.

EDIT: habs gelöst!!! Das Problem war, dass meine Tiles unvollständig waren. Nun funktioniert es und ich kenn mich jetzt auch ein bisschen damit aus :smiley:

Danke für eure Hilfe und dass ihr meine “blöden” Fragen beantwortet habt! :slight_smile:

Hi Leute,

sorry dass ich den Thread noch alrauskrame. Ich habe fast genau das gleiche Problem wie Scorpien, für das hier ja schon eine Lösung präsentiert wurde. :slight_smile: Allerdings will ich in meinem Programm nur Deutschland abdecken mit selbstgemachten Tiles. Jetzt habe ich mir mal tstweise die obersten Zoomstufen Tiles Deutschlands von osm runtergeladen, was so um die 100 waren.

Das Problem ist, dass es dem jxmapkit gar nicht gefällt, dass er nicht alle Tiles findet, da man ja auch immer wieder mal mehr als Deutschland sieht beim navigieren Dann kommen dutzendweise Exceptions:

Schwerwiegend: Failed to load a tile at url: file:/C:/tiles2/12/17/16.png, retrying
java.io.FileNotFoundException: C:\tiles2\12\17\16.png (Das System kann den angegebenen Pfad nicht finden)
	at java.io.FileInputStream.open(Native Method)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileInputStream.<init>(FileInputStream.java:97)
	at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
	at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
	at java.net.URL.openStream(URL.java:1035)
	at org.jdesktop.swingx.mapviewer.AbstractTileFactory$TileRunner.cacheInputStream(AbstractTileFactory.java:348)
	at org.jdesktop.swingx.mapviewer.AbstractTileFactory$TileRunner.run(AbstractTileFactory.java:307)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)

Kann ich das getrost ignorieren? Oder muss ich mir selber was programmieren um vorher alle lokalen Tiles in einer Liste zu speichern und das JXMapKit modifizieren, dass er nur Tiles aus der Liste holt? :confused: Was anders fällt mir im Moment nicht ein…

Hallo Krecker

Habe gerade deine PN erhalten. Die Exception kannst du ignorieren. So habe ich es zumindest gemacht, da ich nur einen bestimmten Ausschnitt brauchte und alles andere für mich nicht relevant war.

Ansonsten müsstest du die komplette Weltkarte runterladen und das wäre eine riesen Menge an Daten.

Hoffe ich konnte dir helfen.

greets
Sc0rP1En

hey!

Danke für die Antwort. Dann werde ich es so mal probieren. Den Code abzuändern um das abzufangen wäre wirklich nicht so einfach…