Makina Blog
Web mapping : comparaison des serveurs de tuiles vectorielles depuis Postgres / PostGIS
Un ensemble de serveurs de tuiles vectorielles basés sur la fonction ST_AsMVT() de PostGIS sont disponibles. Makina Corpus vous propose un tour d’horizon des spécificités des différentes solutions.
Tuiles vectorielles
Les cartes sur le web sont constituées de tuiles, c’est-à-dire de morceaux de cartes qui sont chargées au fur et à mesure du déplacement de la carte ou de l'utilisation du zoom. Ces morceaux peuvent être des images, nommées "raster", ou des géométries - point, ligne, polygones - nommées "vecteur". Les cartes composées de tuiles vecteurs représentent une technique plus récente et offrent plus de fluidité et d’interactivité. Cela est dû au fait que les données composant la carte sont dans le navigateur et pas seulement une représentation image de celles-ci.
Un service de tuiles vectorielles peut-être décrit par un TileJSON. C’est un fichier de méta-information qui donne notamment la liste des couches attendues dans les tuiles ainsi que les listes d’attributs disponibles sur les objets. Le TileJSON donne également les plages d’application des couches : zone géographique et niveaux de zooms disponibles.
Technique de production de tuiles vectorielles
Nous nous intéressons ici aux données cartographiques stockées en base de données que nous souhaitons présenter sur le web sous forme de tuiles vectorielles. Le type de base de données utilisé pour faire cela est essentiellement Postgres avec son extension de données spatiales PostGIS.
Pour une vision plus large et l’intégration de ces serveurs de tuiles à un écosystème vous pouvez également consulter l’article Tour d’horizon des serveurs de tuiles vectorielles pour fond de carte.
Historiquement pour une tuile, des requêtes sont faites en base de données. Les données - géométries et attributs - sont récupérées, puis traitées par le programme appelant. Dans le cas de tuiles rasters, les données sont dessinées dans une image puis envoyées au navigateur web. Dans le cas de tuiles vectorielles, elles sont converties au format binaire Mapbox Vector Tile (MVT), puis envoyées au navigateur web.
PostGIS a dans ces dernières versions implémenté, puis optimisé, le support des tuiles vectorielles MVT. Auparavant, il était possible de produire du GeoJSON ou du SVG. Aujourd'hui, le support du format MVT implémenté directement en base de données simplifie les choses. Servir des tuiles ne consiste plus alors qu’à récupérer le MVT et à l’envoyer au navigateur web.
Les tuiles MVT utilisent des coordonnées à valeurs entières pour représenter les géométries. PostGIS se charge de la simplification des géométries, de la discrétisation en valeurs entières et des problèmes de cohérence que cela peut engendrer. Elles peuvent être composées de plusieurs couches, par exemple les cours d’eau, une frontière, la voirie…
Toute une série de logiciels sont progressivement apparus pour produire et servir des tuiles MVT depuis une base Postgres / PostGIS. Ces logiciels permettent de servir en HTTP des tuiles dont le contenu est défini par des requêtes SQL. Ils ont tous en commun d’être construis sur la fonction ST_AsMVT()
de PostGIS.
SELECT ST_AsMVT(*) FROM ( SELECT ST_AsMVTGeom( geom, ST_TileEnvelope(12, 513, 412), extent => 4096, buffer => 64 ) AS geom, name, description FROM points_of_interest WHERE geom && ST_TileEnvelope(12, 513, 412, margin => (64.0 / 4096)) ) AS t
Utilisation de ST_AsMVT()
et de ST_AsMVTGeom()
.
Ces logiciels sont bâtis pour répondre à deux objectifs un peu distincts :
- produire des tuiles pour fond de carte,
- produire des tuiles de données « métiers » qui vont venir être affichées en complément d’un fond de carte.
Serveur de tuiles vectorielles pour fond de carte
Ce type de serveurs retourne des tuiles qui dépendent seulement des cordonnées des tuiles (x, y) et du niveau de zoom (z). Typiquement ces tuiles contiennent beaucoup de couches de données.
Postserv
Postserv est un serveur très simple qui fait partie de l’outillage du projet OpenMapTiles. Il est décrit comme n’étant pas taillé pour de la production.
Il a l’avantage d’utiliser une description des couches au format tm2source (du yaml). Il s'agit d'un format répandu pour lister des couches utilisées dans un fond de carte. Le tm2source inclut une requête SQL par couche. Le SQL peut contenir des variables pour ajuster le comportement, notamment le niveau de zoom.
- Datasource: dbname: openmaptiles geometry_field: geometry max_size: 512 srid: 900913 table: (SELECT geometry, ref, class FROM layer_aeroway(!bbox!, z(!scale_denominator!))) AS t id: aeroway properties: buffer-size: 4
Postile
Postile est une solution proche de Postserv. Il est taillé pour de la production tout en prenant un tm2source comme liste des couches à servir.
Il offre en plus l’accès aux couches une par une. Il permet également d’utiliser une archive MBTiles de tuiles pré-calculées plutôt que de les construire à la demande.
Tilekiln
Réalisé par Paul Norman, Tilekiln est un projet qui n’est pas encore mature. Celui-ci a la particularité d’utiliser des templates jinja2 pour paramétrer les requêtes SQL dans le logiciel avant de les envoyer à Postgres.
SELECT ST_AsMVTGeom(ST_PointOnSurface(way), {{bbox}}, {{extent}}) AS way FROM planet_osm_polygon WHERE way &} AND boundary = 'administrative' AND admin_level = '2' AND name IS NOT NULL {% if zoom <= 12 %} AND way_area > {{tile_area}}*0.05^2 {% endif %} AND osm_id < 0
Le projet est capable de produire un descripteur TileJSON depuis sa configuration.
T-rex
T-rex fait parti des serveurs de sa catégorie le plus abouti. Ce serveur peut, en plus de PostGIS, utiliser des sources de données GDAL. La définition SQL des calques se fait dans un fichier de configuration au format toml. Des variables - comme le zoom - peuvent être injectées dans le code SQL.
[[tileset.layer]] name = "buildings" datasource = "buildings" geometry_field = "geometry" geometry_type = "POLYGON" buffer_size = 10 simplify = true [[tileset.layer.query]] sql = """ SELECT name, type, 0 as osm_id, ST_Union(geometry) AS geometry FROM osm_buildings_gen0 WHERE geometry && !bbox! GROUP BY name, type ORDER BY sum(area) DESC"""
Le serveur fournit un descripteur TileJSON et une interface web de test.
Tegola
Tegola est également une solution très aboutie. Tegola peut utiliser des données depuis PostGIS ou en GeoPackage. cette solution peut servir plusieurs définitions de tuiles et offre un accès par couche. De plus, Tegola possède un système de cache de tuiles et d’invalidation de ce cache.
Ce serveur fournit également un descripteur TileJSON et une interface web de test.
Serveur de tuiles vectorielles en surcouche de données
Les serveurs fournissant des surcouches de données n’incluent que la couche demandée dans la tuile. Certains serveurs autorisent des arguments en paramètre d’URL des tuiles. Ces paramètres sont envoyés à la requête SQL pour influencer sur le contenu des tuiles produites : par exemple filtrer les données par date, par utilisateur…
Ce type de serveur ne s’occupe par des requêtes SQL, ils accèdent à des tables ou des fonctions retournant des enregistrements déjà en place.
Des fonctions retournant des tuiles peuvent être définies en SQL. Ellles peuvent être considérées comme des vues prenant des paramètres.
CREATE OR REPLACE FUNCTION tile_source(z integer, x integer, y integer, query_params json) RETURNS bytea AS $$ DECLARE mvt bytea; BEGIN SELECT INTO mvt ST_AsMVT(tile, 'public.function_source', 4096, 'geom') FROM ( SELECT ST_AsMVTGeom(ST_Transform(geom, 3857), TileBBox(z, x, y, 3857), 4096, 64, true) AS geom FROM public.table_source WHERE geom && TileBBox(z, x, y, 4326) ) as tile WHERE geom IS NOT NULL; RETURN mvt; END $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
Exemple de fonction retournant des tuiles.
Dirt
dirt-simple-postgis-http-api permet d’obtenir le contenu d’une table en tuiles vectorielles ou dans d’autres formats comme le GeoJSON. Il permet aussi d’appliquer certaines fonctions simples, comme obtenir le centroïde des géométries tout en utilisant des filtres.
Il ne permet pas de définir ces propres requêtes SQL.
pg_tileserv
pg_tileserv est un jeune projet, développé par l’emblématique Paul Ramsey (entre autres le créateur de PostGIS). Le projet contient déjà toutes les bonnes idées pour ce type de serveur : données depuis une table ou une fonction retournant des enregistrements, des paramètres pour filtrer les données, des paramètres pour ajuster la création des tuiles vectorielles…
Martin
Martin est un projet plus mature qui a servi de modèle à pg_tileserv. Il peut lui aussi utiliser une table ou une fonction comme source de données et supporte les paramètres pour filtrer les données.
Vue d’ensemble
Postserv | Postile | Tilekiln | T-rex | Tegola | |
Compagnie / Projet / Auteur | OpenMapTiles | Oslandia | Paul Norman | Sourcepole | Go-spatial |
Objectif | fond de carte | fond de carte / couche | fond de carte | fond de carte | fond de carte |
Dépôt | https://github.com/openmaptiles/openmaptiles-tools/blob/master/bin/postserve | https://gitlab.com/Oslandia/postile | https://github.com/pnorman/tilekiln | https://github.com/t-rex-tileserver/t-rex/ | https://github.com/go-spatial/tegola |
Langage | python | python | python | rust | go |
Configuration service | - | - | yaml | toml | toml |
Configuration layer | tm2source (yaml) | tm2source (yaml) | sql / jinja2 | sql / toml | sql / toml |
TileJSON | - | - | x | x | x |
Depuis d’autres sources | - | MBTiles | - | GDAL | GPKG |
Filtre depuis URL | - | - | - | - | - |
Depuis fonction Postgres | - | - | - | - | - |
Interface web de test | - | x | - | x | x |
Remarques | Pas fait pour de la production | Non mature | Support des projections | Plusieurs définitions de tuiles Cache de tuiles |
dirt-simple-postgis-http-api | Martin | pg_tileserv | |
Compagnie / Projet / Auteur | - | Urbica (Yandex) | CrunchyData, Paul Ramsey |
Objectif | couche | couche dynamique | couche dynamique |
Dépôt | https://github.com/tobinbradley/dirt-simple-postgis-http-api | https://github.com/urbica/martin | https://github.com/CrunchyData/pg_tileserv |
Langage | js | rust | go |
Configuration service | json | yaml | toml |
Configuration layer | - | yaml | - |
TileJSON | - | par couche | par couche |
Depuis d’autres sources | - | - | - |
Filtre depuis URL | - | x | x |
Depuis fonction Postgres | - | x | x |
Interface web de test | - | - | - |
Remarques | Non mature |
Les fonctionnalités des différentes solutions présentées sont proches, en particulier pour les projets les plus avancés. Elles offrent cependant des petites différences qui peuvent pousser à les choisir pour certains cas d’usages. Par exemple :
- seul T-rex permet de choisir la projection,
- seul Postserv et Postile peuvent utiliser un tm2source,
- tous les serveurs n’offrent pas de descripteur TileJSON,
- seul Martin et pg_tileserv produisent de la tuile paramétrable par URL.
A retenir, Postserv et Postile pour du fond de carte générique (utilisable avec OpenMapTiles par exemple), T-rex et Tegola pour la richesse de leurs fonctionnalités pour du fond de carte sur-mesure. Pour de la couche de tuiles de données à la demande et paramétrable par URL, Martin est la solution la plus accomplie mais le nouveau pg_tileserv est prometteur.
Formations associées
Formations SIG / Cartographie
Formation Tuiles vectorielles
À distance (FOAD) Du 3 au 4 juin 2025
Voir la formationFormations Outils et bases de données
Formation PostgreSQL
Nantes Du 11 au 13 décembre 2024
Voir la formationFormations SIG / Cartographie
Formation PostGIS
À distance (FOAD) Du 9 au 13 décembre 2024
Voir la formationActualités en lien
SIG : Préparation de données pour la création de tuiles vectorielles
Pour servir des données sous forme des tuiles vectorielles une préparation est nécessaire comme le filtrage et la simplification des géométries. Quelles sont les questions à se poser ? Quels sont les outils pour y répondre ?
SIG : Mettre en place des tuiles vectorielles
Pour les données images « rasters » comme pour les données vectorielles, des techniques de découpage appelées « tuiles » permettent d’améliorer les performances et la flexibilité de l’affichage. Cet article présente : comment créer et afficher des tuiles vectorielles ?