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
Randonnée
06/09/2022 - 09:43

Créer des vues SQL dans Django et les afficher dans un SIG

Nous allons décrire un processus via la mise en place de vues SQL qui permettent à l'utilisateur de lire de la donnée formatée, sans possibilité d'influer sur le contenu d'une base et tout en se connectant directement à celle-ci.

Voir l'article
Image
Symfony + Vue.js
21/06/2022 - 15:02

Créer une application Symfony/Vue.js

Pour faire des essais ou bien démarrer un nouveau projet, vous avez besoin de créer rapidement une application Symfony couplée avec un front Vue.js ? Suivez le guide !

Voir l'article
Image
SOTM 2022
20/06/2022 - 15:24

Retour d'événement : State of the Map 2022 à Nantes

Après deux ans d'absence, nos collaborateurs ont retrouvé la communauté OpenStreetMap pour partager leur expérience et en savoir plus sur l'évolution de l'outil.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus