Makina Blog

Le blog Makina-corpus

Créer une heatmap de données raster avec Leaflet


Comment nous avons analysé des images côté client en canvas pour produire une heatmap avec Leaflet

Dans le cadre d'un projet, nous avons du créer une carte de sensibilité du milieu à partir de différents critères paramétrables par l'utilisateur. Plusieurs contraintes nous ont amenés à faire les choix techniques qui seront expliqués par la suite :

  • Les données géographiques prises en compte dans la carte de sensibilité peuvent être nombreuses : jusqu'à une trentaine de couches.
  • Certaines couches de données ont un poids important (plusieurs dizaines de Mo)
  • Les données géographiques pouvant être choisies ont des types de géométrie différents (points, lignes et polygones), alors qu'une heatmap utilise un nuage de points.

Démarche générale

Étant donné le nombre et le poids important des couches de données géographiques à prendre en compte, il n'était pas raisonnable de réaliser toutes les opérations côté client. Nous avons donc choisi de générer sur le serveur des images en noir et transparent de chaque couche de données à prendre en compte, puis de les analyser dans le navigateur pour produire la heatmap.

Servir les données

Nous avons choisi d'utiliser MapServer, simple à mettre en œuvre et flexible pour ajouter ou modifier des couches dans le futur. Il nous permet notamment d'accéder en WMS à des images non tuilées (qui seront plus simples à analyser dans le navigateur).

Chaque couche peut être servie par MapServer, pour les coordonnées désirées et dans un style noir et transparent. Les points et les lignes ont une largeur de 5 pixels, ce qui permettra de n'analyser qu'un pixel sur 25 pour générer la heatmap, tout en étant sûr de ne pas passer à côté d'un objet.

Afficher la carte de sensibilité

Pour chaque couche choisie par l'utilisateur, on demande à MapServer l'image correspondante dans les dimensions de la carte affichée à l'écran. Cette image est ajoutée à un canvas de la taille de la carte. On parcourt cette image dans la largeur et la hauteur tous les 5 pixels :

for (var j = 0; j < canvas.width; j + =5) {
    for (var k = 0; k < canvas.height; k += 5) {
        var pos = (k * canvas.width + j) * 4 + 3;
        var data = imageData[pos];
        if (data > 0) {
            var newcoords = map.unproject(L.point(j + offsetX, k + offsetY), map.getZoom());
            dataHeat.push([newcoords.lat, newcoords.lng, weight]);
        }
    };
};

Si on trouve un pixel noir, alors on convertit les coordonnées en pixels vers des coordonnées en latitude/longitude grâce à la méthode unproject de Leaflet. Les paramètres offsetX et offsetY sont calculées à partir de la position de l'origine de la carte et de la position relative du calque par rapport à la carte. On ajoute alors ces coordonnées ainsi que le poids choisi par l'utilisateur dans un tableau.

On utilise alors le plugin Leaflet.heat pour afficher nos différents points et leurs poids associés. Les poids des points situés aux mêmes coordonnées (issus des différentes couches) sont alors additionnés.

Actualités en lien

Image
Capture d'une partie de carte montrant un réseau de voies sur un fond de carte sombre. Au centre, une popup affiche les information de l'un des tronçons du réseau.
28/02/2024

Géné­rer un fichier PMTiles avec Tippe­ca­noe

Exemple de géné­ra­tion et d’af­fi­chage d’un jeu de tuiles vecto­rielles en PMTiles à partir de données publiques.

Voir l'article
Image
Encart article Protomaps : Illustration d'une portion de pyramide de tuiles
14/02/2024

Protomaps, stockez vos pyramides de tuiles plus simplement

Présentation d'un nouveau format de stockage de tuiles cartographiques

Voir l'article
Image
Read The Docs
01/02/2024

Publier une documentation VitePress sur Read The Docs

À l'origine, le site de documentation Read The Docs n'acceptait que les documentations Sphinx ou MKDocs. Depuis peu, le site laisse les mains libres pour builder sa documentation avec l'outil de son choix. Voici un exemple avec VitePress.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus