Vor einigen Wochen nahm ich an der diesjährigen FOSS4G in Prizren teil (siehe meinen Bericht). Nebst einer ziemlich genialen Typescript-Library namens TerraDraw, welche sich zum Ziel gesetzt hat, die ganze Logik für das Zeichnen von Daten in Webapplikationen zu abstrahieren (und für die ich in der Zwischenzeit noch einen Adapter für die ArcGIS Maps SDK for JavaScript beitragen konnte), blieb mir insbesondere der Fokus auf Cloudnative Geospatial hängen. Schon im Vorfeld habe ich mit einigen derartigen Technologien herumgespielt – höchste Zeit also, einen kleinen Selbstversuch zu wagen.
Das Ziel
Wie es der Zufall so will, brauche ich für ein Hobbyprojekt ein globales Geländemodell, um in einer webbasierten Applikation Höhenlinien anzuzeigen. Der Fokus liegt insbesondere auf den Bergregionen und es dreht sich primär um das Visuelle, weshalb auf eine möglichst akkurate Höheninformation verzichtet werden kann – nichtsdestotrotz sollen die Höhenlinien grosso modo der Realität entsprechen.
Nun gibt es hierfür natürlich bereits verschiedene, pfannenfertige Datenquellen. Gerade im Bereich von Vektortiles drängen sich hier Mapbox oder MapTiler auf, welche beide eigentlich genau den benötigten Datensatz anbieten. Man benötigt nur einen API-Key und schon kann man zum Beispiel mit MapLibre GL JS eine hübsche Karte aufsetzen. Damit wäre der Blog hier eigentlich zu Ende…
… aber weil es sich um ein typisches Hobbyprojekt eines Softwareentwicklers handelt (sprich: Es werden weder Kosten noch Mühen gescheut, das Projekt möglichst over-engineered scheitern zu lassen 😎), ist dies natürlich nicht der Fall: Einerseits möchte ich mich nicht schon von Anfang an in eine Abhängigkeit von den Preismodellen der Anbieter begeben (wohlwissend, dass der Aufwand für die eigene Erarbeitung die Nutzung dieser Dienste für einige Zeit finanzieren würde), andererseits möchte ich ja auch etwas lernen. Deshalb fällt der Entscheid schnell: Ich baue mir mein eigenes Höhenmodell 🚀
Die Grundidee
Bereits im Vorfeld zur FOSS4G habe ich mit Protomaps herumgespielt. Nach Brandon Lius Vortrag an der FOSS4G war ich dann überzeugt, dass ich dies unbedingt weiterverfolgen muss. Damit ist die Technologie für meinen Versuch bereits gefunden! Protomaps erlaubt es, grosse Geodaten als einzelne Files auf einen Object Storage wie S3 zu platzieren und sie danach durch clevere Nutzung von HTTP Range Requests wie normale Kartendienste (z.B. via {z}/{x}/{y}.png
) einzubinden. Gerade für Daten, die sich selten ändern, birgt dies verschiedenste Vorteile – insbesondere aber die Kosteneinsparung, weil Object Storages heutzutage extrem günstig sind (viele Vorteile finden sich auch in den FAQ von Protomaps).
Für MapLibre GL JS gibt es ein Höhenlinien-Plugin, welches mit einem RGB-encoded Höhenmodell als Rasterdatensatz on-the-fly Höhenlinien generieren kann. Als Bonus kann dies gleichzeitig auch noch für die Hillshade-Funktionalität von MapLibre GL JS verwendet werden.
Also ist alles, was es zum Starten braucht, ein entsprechendes Höhenmodell als Rasterdatei. Für den vorliegenden Blog wollen wir uns auf die Schweiz konzentrieren, allerdings funktioniert das Prinzip für andere Regionen genauso.
Die Datensuche
Zunächst brauchen wir also ein Geländemodell auf globaler Ebene. Dabei ist es mir zu aufwändig, alle Länder und Regionen abzuklappern, die jeweils dort verfügbaren Höhenmodelle aufzuspüren und dann in einem aufwändigen Prozess ein einheitliches, globales Höhenmodell zu generieren. Das wäre natürlich der saubere Weg, um möglichst genaue Daten zu erhalten, aber für mein Projekt viel zu aufwändig.
Stattdessen wäre eine mögliche Datenquelle beispielsweise OpenTopography. Diese Seite bietet frei verfügbare, regionale und globale DEM (Digital Elevation Models) und DSM (Digital Surface Models) an. Innerhalb der globalen DEMs finden sich verschiedene Produkte: Einerseits die weitläufig bekannten SRTM-Daten der Space Shuttle Missionen, aber auch die ALOS World-Daten der japanischen Raumfahrtbehörde sowie mit Copernicus Global Digital Elevation Models das europäische Pendant. Die Daten liegen dabei als TIFF-Dateien in jeweils 1°-Zellgrösse vor (z.B. N46E7
, umfasst Daten zwischen 46° Nord/7° Ost und 47° Nord/8° Ost). Dabei können auch on-the-fly auf einer Karte Regionen erstellt werden oder man lädt sich bequem mit der AWS CLI gleich alle Daten aus dem offerierten S3-Bucket herunter.
Ein weiterer Kandidat ist die NASA EarthDataSearch, welche eine unglaubliche Fülle an Satellitendaten anbietet – Registrierung vorausgesetzt. Dort findet man z.B. auch den ASTER-Datensatz. Dieser Datensatz wird unter anderem auch für die erweiterten Versionen des SRTM-DEM verwendet, um Artefakte auszublenden. Auch hier kann man entweder über eine graphische Oberfläche einzelne Rasterzellen herunterladen oder auf verschiedene Wege einen Bulk-Download starten.
Allgemein ist die Suche relativ schwierig, da die Dokumentation nicht immer sehr gut und die Abgrenzung zwischen DEM und DSM nicht immer sichtbar ist (so wird der Copernicus-Datensatz z.B. als DEM beworben, an anderen Stellen jedoch als DSM ausgewiesen). Das soll uns hier aber nicht abhalten, denn es geht ja im vorliegenden Fall um die Sache an sich, nicht um die Genauigkeit.
Datenauswahl und Qualität
Da es zum SRTM-DEM (und entsprechend auch zum NASA-DEM und ASTER-DEM) bei meiner Recherche einige Blogposts gab, in denen grössere Artefakte und schlicht falsche Geländerepräsentation erwähnt wurden, wurde ich etwas stutzig. Da OpenCycleMap gemäss Impressum auf die ASTER-Daten setzt, lässt sich das einfach überschlagsmässig prüfen – und siehe da, beim Matterhorn (ausgerechnet!) sieht die Situation effektiv etwas komisch aus:
Diese Depression beim Matterhorngipfel ist definitiv unsauber. Ich habe dies auch noch mit dem SRTM GL3 sowie dem ASTER-Datensatz geprüft und dasselbe Resultat erhalten:
Vergleichen wir das ganze mit dem Copernicus-Datensatz:
Das sieht schon etwas besser aus. Allerdings sind wir mit 4’300 m über Meer immer noch etwas zu tief. Betrachten wir aber zum Beispiel die Lage bei der Capanna Regina Margherita, ist der ASTER-Datensatz sehr genau, wohingegen der Copernicus-Datensatz fast 50m zu tief liegt:
Grundsätzlich lässt sich also sagen: Einmal sind die ASTER-Daten genauer, einmal die Copernicus-Daten. Insgesamt scheint der Copernicus-Datensatz jedoch weniger Artefakte aufzuweisen, weshalb wir uns auf diesen Datensatz konzentrieren wollen. Schliesslich soll sich das Ganze ja nicht um die Genauigkeit von Geländemodellen drehen, sondern darum, wie wir diese als Protomaps-Datensatz ausliefern können.
Das Endresultat
Die einzelnen Rasterdateien mit einheitlicher Codierung (Min 150, Max 4800) sehen so aus:
Und etwas schöner, transformiert in Pseudomercator (EPSG 3857):
Sieht doch schon mal ganz okay aus.
Ausblick
Damit wären die Grundlagedaten gelegt. Wenngleich die Daten etwas ernüchternd sind und wir mit den Copernicus-Daten jetzt eher ein DSM (als ein DEM) verwenden (wobei das irgendwie auch nicht so sicher ist), bei welchem es ebenfalls Artefakte und Ungenauigkeiten gibt, können wir damit im nächsten Blogpost die technische Umsetzung mit Protomaps durchführen.