Makina Blog
Générer un fichier PMTiles avec Tippecanoe
Exemple de génération et d’affichage d’un jeu de tuiles vectorielles en PMTiles à partir de données publiques.
Prérequis techniques
Pour ne pas avoir à installer des dépendances complexes, nous utilisons Tippecanoe à travers Docker et des conteneurs éphémères.
Nous avons donc besoin d’avoir une image Docker de Tippecanoe que nous pouvons générer nous même à partir des sources :
git clone https://github.com/felt/tippecanoe
cd tippecanoe
docker build -t tippecanoe:latest .
Après le traitement qui dure quelques minutes, vous pouvez vérifier la présence d’une image de Tippecanoe avec la commande : docker images
Récupérer et préparer les données
Le jeu de données qui est utilisé pour cet exemple est une base des aménagements cyclables de France Métropolitaine, numérisés dans OpenStreetMap et traités par Geovelo.
On télécharge le jeu de données au format GeoJSON :
wget https://www.data.gouv.fr/fr/datasets/r/d03abb03-9197-4a4f-b758-5062595eb9ce -O amenagements.geojson
À noter : nous utilisons ici des données GeoJSON pour produire les tuiles, mais Tippecanoe accepte aussi des données CSV ou FlatGeobuf.
Pour faciliter le traitement de la source de données, nous allons convertir le GeoJSON original en un fichier GeoJSON-NL : au lieu d’un objet racine unique de type FeatureCollection contenant ensuite toutes les Features, nous aurons un fichier dont chaque ligne est une Feature. Cela permettra à Tippecanoe de paralléliser ses traitements.
docker run -it --rm -v .:/app tippecanoe:latest \
tippecanoe-json-tool amenagements.geojson > amenagements.geojson-nl
GeoJSON :
GeoJSON-NL :
D’autres possibilités pour faire cette même conversion :
# Avec jq : https://jqlang.github.io/jq/
cat amenagements.geojson | jq -c ".features[]" > amenagements.geojson-nl
# Avec GDAL : https://gdal.org/programs/ogr2ogr.html
ogr2ogr -f GeoJSONSeq amenagements.geojson-nl amenagements.geojson
Générer la pyramide de tuiles en PMTiles
On peut ensuite produire notre fichier PMTiles :
docker run -u $UID:$GID -it --rm -v .:/app tippecanoe:latest \
tippecanoe --read-parallel \
--maximum-zoom=g --drop-densest-as-needed --extend-zooms-if-still-dropping \
--output=amenagements.pmtiles \
amenagements.geojson-nl
À noter : Il est important paramétrer Tippecanoe avec des options de simplification adaptées au type des données : réseau de linéaires, géométries de zones, ensemble de points, …
Après quelques minutes, le fichier .pmtiles est créé, et on peut visualiser le résultat en le faisant glisser sur https://protomaps.github.io/PMTiles/.
Pour un GeoJSON initial de 235 Mo, nous obtenons ici une pyramide complète de tuiles de 40 Mo !
Afficher le fichier PMTiles
Nous partons d’un simple fichier carte.html
, dans lequel on va charger MapLibre GL JS et un petit complément pour le rendre capable d’utiliser le fichier PMTiles :
<script src="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/pmtiles@3/dist/pmtiles.js"></script>
<link href="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css" rel="stylesheet" />
Pour anticiper un peu le rendu, on ajoute un peu de CSS :
<style>
html { box-sizing: border-box; font-size: 16px; }
*, *:before, *:after { box-sizing: inherit; }
html, body { margin: 0; padding: 0; }
pre { white-space: pre-wrap; }
</style>
Dans le corps de la page, on place la balise où se chargera la carte :
<div id="map" style="height: 100vh;"></div>
Puis enfin, le script qui va permettre de créer la carte :
<script>
// Ajoute à MapLibre la gestion des PMTiles
const protocol = new pmtiles.Protocol();
maplibregl.addProtocol('pmtiles', protocol.tile);
// Instancie la carte avec un fond de démo (coloré)
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [1.5, 47],
zoom: 6,
});
// Crée une Popup qu'on affichera au survol des Features
const popup = new maplibregl.Popup({ closeButton: false, closeOnClick: false });
// Une fois que la carte est instanciée…
map.on('load', () => {
// Ajoute notre fichier PMTiles en tant que source vectorielle
map.addSource('id-de-ma-source', {
type: 'vector',
// La syntaxe ici est "pmtiles://" puis le chemin d'accès au fichier.
// Ce chemin peut-être relatif ("./fichier", "fichier", "dossier/fichier"),
// absolu ("/fichier", "/fichier", "/dossier/fichier")
// ou distant ('https://domaine.tld/cheminfichier")
url: 'pmtiles://amenagements.pmtiles',
});
// Ajoute à la carte une couche linéaire utilisant notre source PMTiles
map.addLayer({
id: 'id-de-ma-couche',
source: 'id-de-ma-source',
// "source-layer" est le nom de notre couche "dans" le fichier PMTiles
// Si on ne l'a pas précisé à la création du PMTiles, Tippecanoe génère
// un identifiant à partir du fichier source.
// Il est facile de vérifier les couches d'un PMtiles en le chargeant
// sur https://protomaps.github.io/PMTiles
'source-layer': 'amenagementsgeojsonnl',
type: 'line',
paint: {
'line-color': '#198EC8',
'line-width': 3,
'line-opacity': 0.7,
},
layout: {
'line-join': 'round',
'line-cap': 'round',
},
});
// Au survol de notre couche, affiche une Popup
map.on('mouseenter', 'id-de-ma-couche', ({ lngLat, features } = {}) => {
map.getCanvas().style.cursor = 'pointer';
popup
.setHTML(
features.map(feature => '<pre>' + JSON.stringify(feature.properties, null, 2) + '</pre>').join('</br >')
)
.setLngLat(lngLat)
.addTo(map);
});
map.on('mouseleave', 'id-de-ma-couche', () => {
map.getCanvas().style.cursor = '';
popup.remove();
});
});
</script>
Pour afficher votre page HTML avec la carte, il sera nécessaire d’utiliser un serveur http supportant les entêtes HTTP Range.
À noter : charger le fichier html directement dans le navigateur ne fonctionnera pas.
Par exemple :
# Avec Nodejs :
npx serve
# ou bien
npx http-server
Liens utiles
- L’outil protomaps.github.io/PMTiles : visualiser rapidement le contenu d’un fichier PMTiles, local ou distant.
- L’outil Tippecanoe : utilisé ici pour générer la pyramide de tuiles à partir de données géographiques
- La documentation de MapLibre GL JS : maplibre.org/maplibre-gl-js/docs
- Le paquet JavaScript npmjs.com/package/pmtiles : pour la prise en charge de pmtiles:// dans MapLibre
Formations associées
Formations SIG / Cartographie
Formation MapLibre
Aucune session de formation n'est prévue pour le moment.
Pour plus d'informations, n'hésitez pas à nous contacter.
Voir la formationFormations SIG / Cartographie
Formation QGIS
À distance (FOAD) Du 2 au 6 décembre 2024
Voir la formationFormations SIG / Cartographie
Formation Développer avec l'écosystème d'OpenStreetMap
Aucune session de formation n'est prévue pour le moment.
Pour plus d'informations, n'hésitez pas à nous contacter.
Voir la formationActualités en lien
Mini-guide à l’usage des collectivités : l’Open Data, entre nécessité et opportunité
Tout ce que vous avez toujours voulu savoir sur l’Open Data. Petit guide à destination des collectivités pour l’appréhender et se l’approprier.
Une rentrée riche autour de la donnée et des rencontres pour Makina Corpus Territoires
Chaque rentrée apporte son lot d’opportunités pour faire avancer les projets autour de la données au service des territoires. Le calendrier de Makina Corpus en la matière a été particulièrement dense en événements.
Servir sa couche raster QGIS en tuiles sans effort avec le format PMTiles
Cet article vous présente une approche permettant de tuiler et de publier une couche raster fabriquée avec QGIS.