Accueil / Blog / Métier / 2020 / Optimisation de la production de tuiles vectorielles de fond de carte OpenStreetMap pour un service à la demande : Makina Maps

Optimisation de la production de tuiles vectorielles de fond de carte OpenStreetMap pour un service à la demande : Makina Maps

Par Frédéric Rodrigo — publié 04/02/2020, édité le 11/09/2020
Frédéric Rodrigo, expert OpenStreetMap, présente Makina Maps, une solution permettant de servir des tuiles vectorielles construites à la volée. Cette pile logicielle repose sur l’utilisation et l’optimisation d'OpenMapTiles et de Kartotherian.
Optimisation de la production de tuiles vectorielles de fond de carte OpenStreetMap pour un service à la demande : Makina Maps

Les fonds de cartes web et mobiles utilisant des données issues d’OpenStreetMap, ou d’alternatives, sont diffusés sous forme de tuiles images – nommées « rasters » – ou tuiles de données – nommées « vectorielles ». Ces tuiles sont le résultat d’un découpage de la carte suivant une grille (exemple interactif). Il existe une grille par niveau d’échelle (zoom) que l’on souhaite représenter.

image pyramide de tuiles

Pyramide de tuiles

Les tuiles vectorielles offrent plus de possibilités que les tuiles rasters. Parmi ces avantages, l’interactivité ou encore le changement de style graphique à la volée directement coté client (navigateur, application mobile). Côté serveur, cela permet aussi de n’avoir à envoyer à tous les utilisateurs que les mêmes tuiles vectorielles sans tenir compte d’un style graphique à appliquer : l'unique préoccupation est de servir de la donnée.

Makina Corpus a souhaité mettre en place un service de tuiles vectorielles à la demande pour la génération de fonds de plan OpenStreetMap nommé « Makina Maps ».

État des lieux

Tuiles vectorielles

Dans le cas de solutions de cartographie en ligne, les tuiles vectorielles sont disponibles à des URL qui suivent le schéma {zoom}/{x}/{y}.<extension>. L'extension est .mvt pour Mapbox Vector Tiles, mais peut également être .pbf, le contenu restant le même. Ces tuiles sont de taille légère – quelques dizaines ou centaines de kilo-octets – elles décrivent les géométries et les attributs des objets.

Les géométries incluses dans les tuiles vectorielles sont le résultat de découpes de celles d’origine suivant la grille des tuiles. Ce contenu est également filtré et simplifié en fonction du niveau de zoom, tant sur la géométrie que sur l’ensemble des attributs et leurs valeurs, dans l'objectif de conserver la légèreté des tuiles.

Production des tuiles vectorielles

Ces tuiles sont pré-calculées et stockées pour être ensuite servies par le serveur web.

Dans le cas d’applications hors lignes, ces tuiles sont archivées dans des MBTiles et embarquées avec l’application. Mais les volumes, fonction de la zone géographique à couvrir, sont vite très importants.

Plusieurs piles logicielles existent pour produire ces tuiles : parmi les solutions libres, et donc ouvertes, se trouvent OpenMapTiles et Kartotherian. À noter que Mapbox possède également sa propre solution en interne.

Pour plus de détails sur les différentes étapes pour la production de tuiles vectorielles, lire l’article Tour d’horizon des serveurs de tuiles vectorielles pour fond de carte.

Production de tuiles : une industrie lourde

Toutes ces solutions servent à proposer une couverture mondiale, elles ont également en commun le fait de pré-calculer les tuiles sur le monde entier. Pour produire toutes les tuiles 20 à 30 jours sont nécessaires avec 8 CPU à une instance OpenMapTiles. L’alternative est de paralléliser le calcul sur un ensemble de machines, pour arriver à tout traiter plus rapidement, voire en un jour.

Le temps de calcul d’une tuile est variable en fonction des données qu’elle contient : il dépend du volume de données mais surtout de la complexité de la requête en base de données pour les obtenir. Les requêtes les plus simples, pour des tuiles « vides », de nature de terrain uniforme, en plein milieu de l’océan ou du désert par exemple, ne prennent que quelques millisecondes. À l’opposé, une tuile du niveau de zoom 14 – niveau le plus détaillé chez OpenMapTiles – peut prendre jusqu’à 15 secondes sur un terrain complexe – tout en utilisant une base de données sur SSD, plus rapide en lecture-écriture que du HDD.

Mise à jour des données OpenStreetMap

Les données d'OpenStreetMap évoluent quotidiennement et il est souhaitable de garder son fond de plan actualisé. La mise à jour se fait par application des changements d’OpenStreetMap sur la base de données (changements nommés « diff »). Ce processus permet de déterminer les tuiles qui contiennent des données qui ont évoluées et qu’il est nécessaire de régénérer.

Répartition des données

Dans le cas d’OpenMapTiles, la base de données contient trois natures d’objets.

  1. Tout d’abord, des objets sélectionnés dans OpenStreetMap car souhaités dans les tuiles vectorielles.
  2. Ces mêmes objets sont généralisés. C’est-à-dire simplifiés, filtrés ou regroupés pour être utilisés dans des niveaux de zoom intermédiaires ne nécessitant pas l’ensemble du détail d’OpenStreetMap. Cette généralisation est un pré-calcul pour rendre les données plus légères. L’avantage est de pouvoir ensuite produire plus rapidement les tuiles vectorielles.
  3. Pour les niveaux de zoom les plus faibles, d’autres sources de données externes à OpenStreetMap sont utilisées. Elles sont encore plus simples donc plus légères et particulièrement adaptées à ces niveaux de détails. Il s’agit par exemple des données de Natural Earth.

Cette répartition des données, notamment à l’aide de pré-calcul, font que les tuiles vectorielles sont plus rapides à produire. Il en résulte que les tuiles les plus longues à calculer sont celles du niveau de détail le plus élevé et contenant le plus de données : zoom 14. À l’opposé, les tuiles rasters produites dans le cadre du style cartographique par défaut d’OpenStreetMap – nommé OpenStreetMap Carto – n’utilisent pas d’étape de généralisation.

Stratégie de pré-calcul et rendu à la demande des tuiles rasters

La stratégie pour les tuiles raster est de pré-calculer celles de bas niveau de zoom de 0 à 13 par exemple. C’est cette étape qui prend du temps, car elle fait appel à de gros volumes de données et des calculs de simplification. Les autres niveaux de zoom de 14 à 20 sont calculés et rendus à la volée sous forme de tuiles images, depuis la base de données.

À noter que là où il est obligatoire de calculer côté serveur tous les niveaux de zoom de 0 à 20 pour les tuiles raster, les tuiles vectorielles ne vont qu’au niveau de zoom 14. Ce dernier niveau contient déjà tous les détails pour les échelles suivantes. Les tuiles vectorielles de niveau 14 doivent donc extraire et contenir un volume de données plus important que leurs équivalents rasters.

Constat sur les stratégies et contraintes

Les tuiles de faible niveau de détails nécessitent des pré-calculs de généralisation en base de données ou lors de l’extraction des tuiles, car elles couvrent de grandes portions du territoire utilisant des données détaillées dans OpenStreetMap. Par contre, les solutions rasters peuvent calculer à la demande les tuiles pour les niveaux détaillés. Malheureusement, cette stratégie n’est pas disponible avec les tuiles vectorielles, car le niveau le plus détaillé, le zoom 14, reste lourd.

Il serait donc profitable de pouvoir bénéficier des avantages du rendu à la demande dans les piles logicielles pour la génération de tuiles vectorielles. Le service à la demande permet en premier lieu de réduire notablement la puissance de calcul nécessaire. Ainsi, on se passe de l’étape de pré-génération de toutes les tuiles qui, pour le monde entier, prend des semaines ou beaucoup de ressources matérielles. L’autre avantage est de pouvoir réduire le délai entre la mise à jour des données dans OpenStreetMap et leurs disponibilités dans les fonds de cartes vectorielles.

Identification de goulet d’étranglement

Tout d’abord, une analyse des performances de la production des tuiles vectorielles par OpenMapTiles permet de comprendre quels sont les niveaux de zoom dont les tuiles sont les plus lentes à être produites.

Per-zoom generation speed (longer is better)
###############################################################################################
███████████████████████████████████                  7.6 tiles/s at z0,    1 tiles in 0:00:00.1
███████████████████████████████████████████████████ 14.4 tiles/s at z1,    1 tiles in 0:00:00.1
███████████████                                      3.1 tiles/s at z2,    1 tiles in 0:00:00.3
███████████████████████████████████████████         11.8 tiles/s at z3,    1 tiles in 0:00:00.1
██████████████████████████                           5.5 tiles/s at z4,    1 tiles in 0:00:00.1
████████████████                                     3.4 tiles/s at z5,    2 tiles in 0:00:00.5
███████████                                          2.3 tiles/s at z6,    2 tiles in 0:00:00.8
█████████████████████                                4.6 tiles/s at z7,    2 tiles in 0:00:00.4
██████████████                                       3.1 tiles/s at z8,    2 tiles in 0:00:00.6
████████                                             1.7 tiles/s at z9,    2 tiles in 0:00:01.1
██████████████████                                   3.8 tiles/s at z10,   4 tiles in 0:00:01.1
██████████████████████                               4.8 tiles/s at z11,   9 tiles in 0:00:01.8
██████████                                           2.0 tiles/s at z12,  20 tiles in 0:00:09.7
████████████████████████████████                     7.0 tiles/s at z13,  80 tiles in 0:00:11.3
████                                                 0.9 tiles/s at z14, 252 tiles in 0:04:40.0

Performances de génération des niveaux de zoom de toutes les tuiles en milieu urbain – Île-de-France – en tuiles par seconde.

L’analyse des performances montre bien que le niveau de zoom 14 est clairement en deçà des autres. Compte tenu du pré-calcul de généralisation et de l’usage de données simplifiées, les niveaux de zoom les plus détaillés sont bien ceux qui sont les plus lents. À noter que cette lenteur sur les tuiles de zoom les plus détaillées est amplifiée – de façon exponentielle – par le fait que chaque niveau de zoom contient quatre fois plus de tuiles que le précédent.

Les tuiles sont composées de couches thématiques de données. Chaque couche est le résultat d’une requête en base de données. Ces requêtes sont limitées à l’emprise géographique de la tuile mais peuvent être plus ou moins complexes en fonction de la thématique et du niveau de zoom. Il est intéressant de se pencher sur les performances de génération de tuile pour chacune de ces couches.

Per-layer generation speed (longer is better)
#########################################################################################################
██                                   1,653.2 tiles/s at layer water,               252 tiles in 0:00:00.1
████████                             5,191.9 tiles/s at layer waterway,            252 tiles in 0:00:00.0
                                       253.0 tiles/s at layer landcover,           252 tiles in 0:00:00.9
                                       313.6 tiles/s at layer landuse,             252 tiles in 0:00:00.7
███████████████████████████████████ 28,975.5 tiles/s at layer mountain_peak,       252 tiles in 0:00:00.0
███████████████████                 12,825.7 tiles/s at layer park,                252 tiles in 0:00:00.0
█                                      905.4 tiles/s at layer boundary,            252 tiles in 0:00:00.2
██████████████                      10,076.8 tiles/s at layer aeroway,             252 tiles in 0:00:00.0
                                        37.1 tiles/s at layer transportation,      252 tiles in 0:00:06.7
                                         1.0 tiles/s at layer building,            252 tiles in 0:04:05.2
██████████                           7,096.4 tiles/s at layer water_name,          252 tiles in 0:00:00.0
                                        84.6 tiles/s at layer transportation_name, 252 tiles in 0:00:02.9
█                                      971.5 tiles/s at layer place,               252 tiles in 0:00:00.2
                                        46.8 tiles/s at layer housenumber,         252 tiles in 0:00:05.3
                                        52.2 tiles/s at layer poi,                 252 tiles in 0:00:04.7
██████████████████████              15,672.6 tiles/s at layer aerodrome_label,     252 tiles in 0:00:00.0

Performances de génération des couches du niveau de zoom 14, en tuiles par secondes.

La couche des bâtiments est de loin celle qui prend le plus temps, avec un temps moyen d’extraction depuis la base de données d’une seconde – 1,04 s – par tuile. Elle est à l’origine de 95 % du temps d’extraction total. C’est donc le premier goulet d’étranglement qui rend impraticable cette génération de tuiles pour un service à la demande.

Optimisation

OpenMapTiles utilise plusieurs tables SQL pour stocker les bâtiments en fonction de leurs attributs ou natures dans OpenStreetMap. Une réduction de ce nombre de tables associée à une restructuration des requêtes SQL allègent la base de données et améliorent les performances.

Per-layer generation speed (longer is better)
##############################################################################################
                                         1.5 tiles/s at layer building, 252 tiles in 0:02:49.6

Le temps d’extraction des bâtiments par tuiles ne prend alors plus que 0,7 seconde. C’est un gain important d’environ 30 %, mais qui reste toutefois insuffisant pour un usage intéractif.

Changement de stratégie pour les bâtiments

Réduction de la multitude

Les bâtiments posent problème parce qu’ils sont nombreux, omniprésents en ville et avec une géométrie détaillée. C’est un « problème » particulièrement vrai en France. Le cadastre est disponible en OpenData et est utilisé de façon très importante dans OpenStreetMap. Dans une tuile de niveau 14 en milieu urbain dense, en valeur médiane 25 000 bâtiments sont trouvés, les tuiles les plus volumineuses en ont jusqu’à 100 000. Tous ces bâtiments doivent être stockés, mais aussi indexés et remontés depuis la base de données.

À la vue de cette problématique, une première idée pourrait être d’utiliser la fonction de regroupement - aussi appelée fonction de clustering CLUSTER de la base de données. Elle permet de regrouper au sein de la base de données sur le disque, les données qui seront requêtées simultanément. La simultanéité d’accès à la donnée repose ici sur le critère de proximité géographique. À noter, ce regroupement de données dans la base peut être fait lors de la création de la base ou à la demande, mais son état ne se conserve pas au fil des mises à jour.

L’application de la stratégie CLUSTER adresse la problématique de l’accès aux données, mais pas celle du volume d’objets stockés et indexés. Cette idée de regroupement pourrait être reprise à un niveau topologique pour grouper les bâtiments. Un groupe – ou cluster – se définit par des éléments « proches ». Dans le cas ci-dessus la proximité est spatiale, mais elle peut être également sémantique ou visuelle. Un ensemble de bâtiments proches correspond au concept même de ville. En conséquence, une unité de découpe plus fine est nécessaire. Le niveau inférieur sur l’échelle de proximité de bâtiments est le pâté de maisons.

Même si l’extension pour données spatiales PostGIS, de la base de données PostgreSQL, dispose de plusieurs fonctions de regroupement de données géographiques – dont ST_ClusterIntersecting qui permet de regrouper de proche en proche des objets qui se touchent – l'idée, en termes de calculs, est de faire au plus simple et au plus rapide : grouper les bâtiments suivant une grille arbitraire.

L’intérêt est donc de ne plus chercher à stocker et extraire des bâtiments unitairement, mais des groupes de bâtiments contiguës. Si en milieu rural ou urbain peu dense cela ne va changer que peu de choses, en milieu urbain dense le nombre d’objets à traiter va être considérablement réduit. Attention cependant, un cluster ne fait pas la fusion des objets. Au moment de créer les tuiles vectorielles, les clusters sont dégroupés et chaque bâtiment retrouve son indépendance. Ainsi, rien ne change au niveau du contenu des tuiles vectorielles produites mais les performances de génération s'en trouvent nettement améliorées.

Clusters de bâtiments

Clusters de bâtiments suivant une grille, calcul rapide par arrondi des coordonnées minimum X et Y.

Per-layer generation speed (longer is better)
###############################################################################################
                                         4.4 tiles/s at layer building, 252 tiles in 0:00:56.7

Cette nouvelle stratégie permet d’extraire les bâtiments en moyenne en 225 ms. C’est désormais un délai acceptable pour un service de production à la demande, même si ce délai est à la limite haute pour cet usage.

Pré-calcul, le côté obscur

Les techniques de regroupement décrites permettent de diminuer de façon importante le temps de réponse, mais une étape de pré-calcul reste inévitable. Elle consiste à traiter tous les bâtiments lors d’un calcul initial pour les affecter à un cluster. Le nombre de bâtiments étant important, ce temps de calcul n’est pas négligeable. Ces clusters doivent également être stockés, ce qui crée un doublon pour l’une des couches de données les plus volumineuses. Cependant, le poids de la table des clusters est réduit de moité par rapport à la table d’origine.

Lors de la mise à jour des données depuis OpenStreetMap c’est la table d’origine des bâtiments qui est modifiée. Il faut donc en dériver à nouveau la table des clusters. Malheureusement, ce calcul est long : 5 h pour un clustering des bâtiments d’Europe.

Mise à jour différentielle des clusters

Le temps de calcul complet des regroupements étant trop important, il ne faut s’intéresser qu’à ceux ayant réellement changés lors des mises à jour. La stratégie est de suivre les modifications faites dans la table principale des bâtiments à l’aide de mécanismes d’observation – trigger de base de données – qui vont conserver l’historique des changements. Cet historique sert alors à ne reproduire le calcul de regroupement que sur les clusters dans lesquels des bâtiments ont été modifiés : seuls ces clusters sont dégroupés pour actualiser les bâtiments qui ont évolués, puis recalculés.

Pile logicielle de tuiles vectorielles à la demande : « Makina Maps »

Les deux principales piles logicielles libres pour pré-calculer des tuiles vectorielles sont OpenMapTiles et Kartotherian. Elles sont faites d’un ensemble de logiciels libres qu’il est possible de composer ou d’interchanger.

Afin de diffuser des tuiles vectorielles à la demande, un serveur web est nécessaire mais également un ou des styles pour permettre de les afficher. D’autres solutions comme TileServer GL – élaboré par les développeurs d’OpenMapTiles – sont faites pour servir des tuiles pré-calculées et des styles.

Toutefois pour un service à la demande, il faut utiliser l’ensemble de ces composants : de la production depuis la base de données jusqu’au service web des tuiles et de styles. Il faut aussi disposer d’une mise en cache des tuiles pour améliorer les performances et d’une mise à jour des données depuis OpenStreetMap. La mise à jour doit impliquer l’invalidation du cache de tuiles lorsque les données qu’il contient ont changé.

Pour la conception de Makina Maps, le choix s’est arrêté sur l’assemblage d’OpenMapTiles pour le schéma des tuiles ainsi que celui de la base de données et de Kartotherian pour l’extraction et le service de tuiles. Des modules pour servir les styles ont été ajoutés à Kartotherian. Le tout est exposé au travers d’un serveur web NGINX qui sert également de cache de tuiles.

Cette nouvelle pile logicielle libre est disponible sur GitHub ; elle se veut « légère » comparativement à une solution de pré-génération. On peut par exemple servir des tuiles pour :

  • une région française en 10 min au lieu d’1h,
  • l’Europe entière en 15 h à place d’une semaine.

Cette solution contient l’ensemble de ce qui est nécessaire pour servir rapidement et simplement des tuiles vectorielles et des styles en partant de zéro.

https://github.com/makinacorpus/makina-maps

Conclusion

L’amélioration des performances d’OpenMapTiles rend possible le service de tuiles vectorielles à la demande. En chaînant tous les composants serveurs au sein d’une même pile logicielle, les tuiles vectorielles pour fonds de carte utilisant les données d’OpenStreetMap sont plus accessibles et faciles à déployer.

Les améliorations d’OpenMapTiles détaillées ici font l’objet de proposition d’intégration au code source du projet.

La nouvelle pile logicielle Makina Maps est un logiciel libre disponible sur GitHub et ouvert à la contribution : https://github.com/makinacorpus/makina-maps.

Souhaiteriez-vous disposer d’un serveur de tuiles dédié ou personnalisé ? Besoin de conseil ? Contactez-nous !

Abonnez-vous à la newsletter ici !

+ INFOS : découvrez plus d'articles sur ce sujet :

Découvrez les formations associées à cette thématique

ABONNEZ-VOUS À LA NEWSLETTER !
Voir aussi
QGIS : le nouveau support des tuiles rasters et vectorielles QGIS : le nouveau support des tuiles rasters et vectorielles 01/10/2020

La dernière version de QGIS 3.14 apporte deux nouveaux types de calques : les tuiles rasters et ...

Web mapping : comparaison des serveurs de tuiles vectorielles depuis Postgres / PostGIS Web mapping : comparaison des serveurs de tuiles vectorielles depuis Postgres / PostGIS 30/07/2020

Un ensemble de serveurs de tuiles vectorielles basés sur la fonction ST_AsMVT() de PostGIS sont ...

Une Cagnotte reversée à la fondation OpenStreetMap a été organisée par Makina Corpus lors du Paris Open Source Summit ! Une Cagnotte reversée à la fondation OpenStreetMap a été organisée par Makina Corpus lors du Paris Open Source Summit ! 28/01/2020

Les 10 et 11 décembre derniers, Makina Corpus était présente à la 5ème édition du Paris Open ...

SIG : Préparation de données pour la création de tuiles vectorielles 30/01/2020

Pour servir des données sous forme des tuiles vectorielles une préparation est nécessaire comme ...

Créer une carte avec Umap Créer une carte avec Umap 03/07/2019

[ Tuto ] créer une carte utilisant OpenStreetMap et y ajouter ou importer des données, puis ...