Données cartographiques vectorisées, extrudées et spatialisées.
Ou le pipeline GeoJSON, D3.js vers Three.js. Cela fait un moment que nous n'avions pas fait de projet Three.js ! Nous jouons surtout avec Unity, mais c'est toujours agréable de revenir…
AL
Aymeric Lamboley
15 septembre 2020
15 septembre 2020 3 min de lecture
Ou le pipeline GeoJSON, D3.js vers Three.js.
Cela fait un moment que nous n’avions pas fait de projet Three.js ! Nous jouons surtout avec Unity, mais c’est toujours agréable de revenir directement au web.
Pour ce projet, nous devions afficher une carte 3D de la France avec des points d’information sur des sites. La première réflexion a porté sur l’affichage d’une carte 3D : nous savions que nous aurions besoin de svg à un moment donné, mais comment l’afficher avec Three.js ? Et comment placer correctement les sites/villes sur la carte ? Voyons ça !
Nous avons facilement trouvé un svg de la carte de France, mais il devait être bien optimisé et nous avions besoin d’avoir les régions (pour pouvoir les colorer). Avoir de vraies données, plutôt que de simples « paths », avec latitude et longitude, était aussi très important. Nous avons donc commencé avec le format de fichier GeoJSON, et récupéré cette version. Parfait, nous avions les données, mais il fallait maintenant visualiser notre carte !
Évidemment, nous avons d’abord regardé du côté des plugins Three.js pour afficher une carte GeoJSON, mais nous n’en avons pas trouvé qui fonctionne correctement avec une projection de Mercator. Nous sommes donc revenus à notre première intuition concernant le svg. Nous savons que Three.js dispose d’un SVGLoader, et qu’on peut ensuite extruder sa géométrie pour obtenir un modèle 3D, mais comment convertir notre fichier GeoJSON en carte SVG ?
D3.js à la rescousse ! C’est une bibliothèque puissante pour manipuler des données, elle inclut le support SVG et de nombreux utilitaires cartographiques ! Donc, à partir de notre fichier GeoJSON, nous le transformons à l’exécution en SVG, ce qui nous permet d’ajuster les réglages rapidement !
const geojson = JSON.parse(geojsonText);// we translate the projection at 0, 0, so the map is centered on our screenconst projection = geoMercator().scale(700).center(geoCentroid(geojson)).translate([0, 0]);const pathGenerator = geoPath().projection(projection);let mySvg = '<?xml version="1.0" encoding="utf-8"?><svg><g>';for (let i = 0; i < geojson.features.length; i++) mySvg += "<path id=\"" + (i + 1) + "\" name=\"" + geojson.features[i].properties.nom + "\" d=\"" + pathGenerator(geojson.features[i]) + "\"\/>";mySvg += "</g></svg>";// now load the SVG and display the mapconst paths = new SVGLoader(manager).parse(mySvg).paths;const group = new Group();group.scale.y *= - 1;let regionGeometry = null;let regionMesh = null;const regionTextMaterial = new MeshBasicMaterial({ color: new Color(0x666666) });const shapeMaterial = new MeshBasicMaterial({ vertexColors: true, depthWrite: true });for (let i = 0; i < paths.length; ++i){ const path = paths[i]; const region = data.regions.find(x => x.id == path.userData.node.id); const color = new Color(region.color); // we grab some data from a static file // draw region const shapes = path.toShapes(true); for (let j = 0; j < shapes.length; ++j) { const geometry = new ExtrudeGeometry(shapes[j], { depth: 0.001, bevelSize: 0 }); for (let k = 0; k < geometry.faces.length; ++k) geometry.faces[k].vertexColors = [color, color, color]; if (regionGeometry == null) { regionGeometry = geometry regionMesh = new Mesh(regionGeometry, shapeMaterial); regionMesh.name = "regions" } else regionMesh.geometry.merge(geometry); }}group.add(regionMesh);scene.add(group);
Et voilà ! Avez-vous remarqué la fonction merge geometry ? Même si nous dessinons plusieurs régions, elles sont considérées comme un seul mesh. C’est une astuce d’optimisation importante, vous pouvez en lire davantage sur ce site génial.
Afficher les sites et les informations
Nous avions un fichier Excel du client avec tous les sites et leurs informations (type, adresse, téléphone, contact, logo etc.). Puisque nous avons une vraie carte, et de nombreux sites, le moyen le plus rapide de les afficher ne serait-il pas de les positionner via leurs coordonnées GPS ?
Le gouvernement français fournit une API pour faire du géocodage. Nous avons fait un petit script en PHP pour récupérer toutes les adresses. Nous avons utilisé la bibliothèque Guzzle qui permet de faire des requêtes HTTP très facilement !
Un email par mois maximum : nos articles techniques, nos retours de projets et les nouvelles sessions de formation. Pas de spam, désinscription en un clic.
En vous inscrivant, vous acceptez de recevoir nos communications. Vos données ne sont jamais cédées à des tiers.
✓ Merci ! Vous êtes inscrit·e à la newsletter Da Viking Code.