ich arbeite an einem 3D-Programm zur Darstellung von Satellitendaten und Karten
für den Schulbereich. Das Programm heißt “Diercke Globus” (Screenshot:)
Jetzt möchten wir gerne OpenStreet-Daten darstellen. Das funktioniert auch super,
die Position der Tiles stimmen exakt mit den Satellitendaten überein - jedenfalls bei großer
Zoomstufe:
Einen kleinen Schönheitsfehler gibt es aber: im globalen Maßstab (kleine Zoom-Stufe) zeigt sich eine
deutliche Verschiebung, wie man hier am Beispiel der Falkland-Inseln gut sehen kann:
Der helle Bereich ist die OSM-Grafik, die halbtransparent über dem Satellitenbild liegt.
Die Abweichung tritt auf dem gesammten Globus auf, wobei die OSM-Tiles auf der Nordhalbkugel
nach unten und auf der Südhalbkugel nach oben verschoben sind.
Die Formel zum Umrechnen von Tiles in Breitengrad/Längengrad sieht so aus:
void TileNumberToLongLati(int zoom, int xtile, int ytile, double& Long, double& Lati)
{
double n = pow(2.0, zoom);
Long = DEG_TO_RAD((double(xtile) / n * 360.0) - 180.0);;
Lati = atan(sinh(M_PI * (1.0 - (2.0 * ytile / n))));
}
(Ergebnisse in Radians)
Da die Berechnung für hohe Zoomstufen sehr exakt funktioniert, weiß ich nicht, warum sie
für niedrige Zoomstufen so viel abweicht. Vielleicht hat ja jemand einen Tipp für mich.
Kann es sein, dass Deine Formel nur die “äquatornäheren” Kanten der Kacheln ausgibt? Je größer der Maßstab, desto mehr macht sich bemerkbar, dass auch innerhalb der Kacheln die Abbildung verschoben ist.
Im Zoomlevel 2 geht die erste nördlich gelegene Kachel auch nicht von 0° bis 45°, sondern im Norden bis irgendwo bei 60°. Wenn man die Abbildung innerhalb der Kachel nicht berücksichtigt, landet Helsinki im Mittelmeer…
Du hast wahrscheinlich recht. Die Formel stimmt schon. Allerdings berechne ich nur die Eck-Koordinaten der Tiles. Innerhalb der Tiles ist die Grafik aber
ebenfalls projeziert. Danke für den Tipp, mal sehen, was ich da tun kann.
Ich konnte das Problem lösen!
Danke für eure Hilfe.
Das Problem besteht tatsächlich darin, dass die Segmente (oder Tiles) in der sogenannten “Spherical Mercator”-Projektion vorliegen.
Wenn man jetzt für ein Segment die Eck-Koordinaten als Längen/Breitengrad ermittelt und dieses Segment dann in einer
geografischen Projektion auf die Erdkugel projeziert, kommt es innerhalb des Segments zu Verzerrungen. Diese fallen aber
nur bei sehr großen Segmenten auf, da hier die Krümmung sehr groß ist.
Die Lösung besteht darin, die Projektion auch innerhalb des Segments zu berücksichtigen.
Die Formel für die Umrechnung des Breitengrades in die Spherical Mercator-Koordinate ist (in C, Winkel in Radians):
double lat2y(double a) { return log(tan(M_PI/4+a/2)); }
Zum Schluss noch ein Bild von der korrekten Projektion:
Ich habe mir das Programm angesehen. Allerdings verwendet es einen Software-Renderer und verfolgt damit einen völlig anderen
Ansatz als unser Projekt, welches auf OpenGL basiert.
Bei Marble gibt es einen experimentellen Branch für die Portierung auf OpenGL, daran wird u.a. derzeit im Rahmen des Google Summer of Code gearbeitet. Es ist ein erklärtes Ziel des Maintainers, dass das OpenGL-Rendering eine vollwertige Alternative zur software-basierten Implementierung werden soll.
Aber ja, aktuell verwenden sie Software-Rendering. Das Obige ist von meiner Seite also nur als Zusatzinformation gedacht.