Kategorien
Allgemein

Heatmaps im Eigenbau

Heute mal wieder ein Blick hinter die Kulissen: auch in der Vergangenheit hatte ich hier und hier schon darüber geschrieben, wie man Strava und Komoot verbinden kann um die Strava Heatmap bei der Routenplanung berücksichtigen zu können.

Für zahlende Strava-Kunden gibt es außerdem neben der „global heatmap“ noch eine personalisierte Variante, die also darstellt, wo man selbst schon alles gewesen ist (und dementsprechend, wo noch Strecken darauf warten entdeckt zu werden).

Nun ist es aber so, dass ich seit einer Weile um die großen, zentralisierten sozialen Medien (Twitter, Facebook) einen Bogen mache und letztlich nur noch Mastodon (bzw. konkret die wue.social Instanz von Ralf) nutze. In dieses Bild passt natürlich auch nicht der Routen-Upload auf Strava und Komoot — und so kam es letztlich zu diesem Blog als „sharing Alternative“ zu Komoot (und z.B. auch der Kilometerstatistik etc.).

Jetzt fand ich die personalisierte Heatmap von Strava aber schon toll — also habe ich mir meine dezentrale Variante selbst gebaut. So sieht das Ergebnis aus:

In leichtem rot die Strecken, auf denen ich bisher nur einmal war … wenn ich an der Stelle schon ein paar mal war, dann sattes dunkelblau.

Technisch gesehen sind das selbst gerenderte overlay tiles, die man auf beliebige OpenStreetMap Karten (und theoretisch auch Google) legen kann.

Ich hatte mich dann erstmal nach bestehenden OpenSource-Lösungen umgesehen, … und feststellen müssen, dass das eher eine Nische ist. Nach einer Weile bin ich auf das Projekt „gheat“ gestoßen, … letzte Version vom April 2008. Und das setzt auf einen ebenso alten Python Web-Server (Aspen), von dem ich zuvor noch nie gehört hatte. Dort verlinkt ist auch ein Fork, der das ganze als Python CGI Script umgesetzt hatte (wobei der Code ebenso ziemlich alt ist).

Der Fork setzt auf eine MongoDB als Backend, die 2009 erst rausgekommen ist. Das muss definitiv ein early adopter gewesen sein 🙂

So oder so, der Plan stand dann relativ fest. Den alten Python Code zum Laufen bekommen, einen fastcgi-wrapper drumrum und einen modernen nginx davor. Das ganze in Docker verpacken und eben eine MongoDB daneben. Gesagt, getan. Stellt sich raus, dass das original gheat relative fette Kleckse zeichnet (für jeden einzelnen Punkt des GPX Tracks) — also im Format eher so breit wie eine Siedlung statt einer Straße.

Hat eine Weile gedauert zu verstehen, wie das gheat intern arbeitet, … aber eigentlich ist der Ansatz cool: nämlich zweischrittig. Für jeden Punkt des gpx wird erstmal eine (halbtransparente) „dot.png“ (das Teil der Programmquellen ist) auf eine transparente Leinwand projeziert. Das führt dazu, dass dieses Zwischenbild um so dunkler wird, je mehr Punkte gezeichnet werden bzw. um so dunkler/opaker das dot.png ist.
Im zweiten Schritt wird der Alphakanal dieses „Bildes“ wieder ausgelesen und die eigentliche Heatmap unter Berücksichtigung des gewählten Farbverlaufs generiert.

Letztlich ein interessanter Ansatz — heißt nur, dass ich zum Lösen der Klecksproblematik nicht den Code anfassen muss, sondern meine (nicht vorhandenen) Gimp Skills auspacken muss.

Naja, hat dann schon irgendwie funktioniert 🙂

… und die Belohnung ist die oben gezeigte Heatmap. Die ausreichend flott für on-the-fly Generierung ist und seither mit auf dem Webserver lebt. Den aufgefrischten und modifizierten Code findet ihr (ebenso denzentral) hier auf meiner Gitlab Instanz.

Kategorien
Allgemein

Heatmap’ed Komoot 😍

Das mit der Strava Heatmap in Komoot hat mir jetzt doch noch keine Ruhe gelassen …

Also insbesondere, dass man mit der reinen Heatmap-Karte nicht so richtig erkennen kann, welcher Ort das ist. Eben weil sämtliche Beschriftungen fehlen.

Eine Lösung dafür war schnell gefunden: den Tile-Request des Browsers (bzw. von Komoot) auf einen lokalen, kleinen Web-Server verbiegen, der

  • den Request entgegen nimmt
  • das Tile vom Open Street Map Server abruft
  • das Overlay Tile vom Strava Global Heatmap Server abruft
  • die beiden Bilder kombiniert
  • für Caching-Zwecke das Ergebnis lokal vorhält
  • und last but not least an den Browser (bzw. eben Komoot) zur Anzeige ausliefert

Habe als Waffee mal node.js gewählt, Web-Server mit express.js und zum Kombinieren der Tiles habe ich „@mapbox/blend“ entdeckt. Funktioniert auf anhieb, … Source auf Github. (beachte, dass ein Strava Summit Account erforderlich ist)

So sieht das Ergebnis dann aus (weiter raus gezoomed):

Auf diesem Zoom-Level sieht eine Stadt wie Würzburg natürlich nach einem unübersichtlichen Knäuel aus. Aber man bekommt trotzdem einen guten Überblick. Und wenn man in Komoot die „m“-Taste drückt (= gewählte Route ausblenden) kann man auch gut kontrollieren, ob diese auf einem Heatmap-positiven Pfad liegt.

Die Farbtöne des Heatmap-Overlays sind auch ausreichend unterschiedlich von den OSM-Farben, sodasss man z.B. das Heatmap-Rot nicht mit dem „primary road“-Rot von OSM verwechseln kann.

Auf höherem Zoom-Level sieht das dann so aus:

Das Auge kann da schon relativ gut abschätzen, was wohl Waldwege sind oder was z.B. Landstraßen…

Kategorien
Allgemein

Strava ❤️ Komoot

Strava habe ich ja erst vor ein paar Tagen für mich entdeckt (natürlich bedingt dadurch, dass ich jetzt hauptsächlich auf dem Gravelbike rum hänge) — mit Komoot bin ich jedoch seit vielen Monaten schon sehr glücklich. Insbesondere der Routenplaner hat mein Herz schnell erobert – also die Highlights sind auch toll, aber die Art der Wege, die der Auto-Router aussucht, finde ich einfach gut. Soll heißen, dass Teil macht einfach, was es soll.

Das Delta? Ich schau mir öfter die Karte an und frage mich, welchen Weg ich entlang fahren möchte. Also ein paar coole Wege sind auch als Rennrad-Highlights markiert; aber die übrigen Highlights sind eher sehenswerte Dinge oder halt Single Trails.

Strava to the rescue: Strava hat ein Feature namens „global heatmap“, welches einem zeigt, auf welchen Routen sich die meisten Aktivitäten auf der Plattform abspielen.
Das Problem: der Routenplaner von Strava ist eher so mittelgut. Also man bekommt schon eine Route zusammen — aber welche Art von Weg (überhaupt befestigt? asphaltiert? vielleicht eine Bundesstraße?) man sich da ausgesucht hat, verrät einem das Ding nicht.

Jetzt kann Komoot aber nicht die Strava Heatmap anzeigen. Oder vielleicht doch?

In dem Auswahlmenü sind neben den Komoot-eigenen Karten die Open Street Map und die Open Cycle Map aufgeführt … aber eigene Layer bekommt man da natürlich nicht unter.

Was aber gehen sollte ist die URLs einfach umbiegen. Also Komoot will zwar weiter die Open Street Map Tiles laden, z.B. von

https://b.tile.openstreetmap.org/12/2157/1393.png

… das „b“ dient einfach nur der Lastverteilung, 12 ist der Zoom-Level und 2157 die X- und 1393 die Y-Koordinate der Kachel. OSM selbst arbeitet mit 256px Kacheln.

Und so sieht die Kachel-URL der Strava Heatmap aus:

https://heatmap-external-b.strava.com/tiles-auth/ride/bluered/12/2157/1393.png?px=256&Key-Pair-Id=XXX&Signature=XXX&Policy=XXX

das „b“ ist wieder da, Zoom-Level, X- und Y-Koordinate natürlich auch. Und wir können einen Parameter „px“ mitliefern, der steuert welche Kachelgröße wir wollen. Standardmäßig wird mit 512px Kantenlänge gearbeitet.

Für alle Zoom-Level 13 und höher wird ein Strava Summit Account benötigt und der Abruf muss authentifiziert werden. Dazu dienen die Parameter Key-Pair-Id, Signature und Policy. Die Werte dazu findet ihr bei Strava in den Cookies. Also einfach Wert kopieren und da einfügen.

Je nach Browser braucht’s dann nur noch eine Extension a la Redirector für Firefox, der wir beibringen können, dass sie die URLs für Medienabrufe entsprechend verbiegt.

Und tada, so sieht das Ergebnis dann aus:

… gleiches Bild wie auf der Strava Heatmap. Vielbefahrene Routen tauchen in rot auf. Von Radfahrern eher gemiedene Strecken in blau. Dazu kommen dann halt die Routenplaner Features von Komoot links, die die Strecke nach Wegtypen und -beschaffenheit aufschlüsseln.

Einziger Wermutstropfen: die Karte ist nicht beschriftet (letztlich wie die Global Heatmap halt auch — okay, zugegeben, die hat immerhin ein bissl Text dabei). Aber dazu kann man ja zwischen den einzelnen Karten hin und her schalten.