Le Conseil Général de la Saône-et-Loire (71) a lancé son site Open Data depuis quelques temps déjà (septembre 2011). La Nuit des Cartes Vivantes 2012 (7 fev.) a été l’occasion d’un ballon d’essai avec l’extraction et l’exploitation des parcours des « Balades Vertes » et leur mise en valeur sous la forme d’une couche placée au-dessus du rendu Mapnik. Voici le résultat :
Juste pour faire court, voilà comment transformer le fichier original .shp en pointillés cliquables sur un fond OSM :
Et c’est ici en plein-écran : http://freeroute.fr/71
Lancée par Liness et supportée par le RERS de Courcouronnes, je participe le 25 juin prochain 14h30 à une présentation OpenStreetMap et à petite Mapping Party à suivre.
.entry .olMapViewport img { max-width: none; }#map_1 {padding: 0; margin: 0;}#map_1 img{padding: 0; margin: 0;border:none;margin-top:0px;margin-right:0px;margin-left:0px;margin-bottom:0px;}/* = limit) { return OpenLayers.Util.getImagesLocation() + "404.png"; } else { x = ((x % limit) + limit) % limit; return this.url + z + "/" + x + "/" + y + "." + this.type; } }var lonLat = new OpenLayers.LonLat(2.41480350494385,48.6289510130882).transform(map.displayProjection, map.projection);map.setCenter (lonLat,17);var markers = new OpenLayers.Layer.Markers( "Marker" );map.addLayer(markers);var data = {};var currentPopup;data.icon = new OpenLayers.Icon("http://freeroute.fr/wp-content/plugins/osm/icons/wpttemp-green.png", new OpenLayers.Size(24,24), new OpenLayers.Pixel(0, -24));var ll = new OpenLayers.LonLat(2.41480350494385,48.6289510130882).transform(map.displayProjection, map.projection); var feature = new OpenLayers.Feature(markers, ll, data);feature.closeBox = true;feature.popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {"autoSize": true, minSize: new OpenLayers.Size(150,150),"keepInMap": true } );feature.data.popupContentHTML = "RERS CourcouronnesSuite à un appel à contributeurs sur la liste talk-fr@openstreetmap.org, je me suis lancé dans la manipulation de ces données. Sous la main, j’avais le fichier compressé transmis par la Communauté de Communes et le bel outil SpatiaLite et en particulier son interface graphique.
Finalement, les données sont en ligne mais ne feront pas l’objet d’un import massif. Pour les récupérer, il suffit de passer par freeroute.fr/4c et de sélectionner le cadre dont on souhaite récupérer les données. Une bulle vous propose un lien vers le fichier au format .osm. Les cadres correspondent à ceux de QualityStreetMap afin que le suivi de l’import puisse être facilité.
Vous pourrez retrouver tout le processus décrit en détail.
Je me suis lancé dans la génération automatique de cartes, sous la forme de fichiers .svg directement générés à partir de requêtes SQL sur la base mondiale d’OpenStreetMap. Et voilà le résultat :
Données © OpenStreetMap & contributeurs – cc-by-sa 2.0 & ODbl
Attachons une base pour y mettre les nouvelles tables sans modifier la base « Planet » originale :
?View Code SQL1 ATTACH DATABASE 'boundaries.sqlite' AS boundaries;Suppression d’un historique et création d’une nouvelle table contenant tous les contours (du monde) :
?View Code SQL1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 DROP TABLE IF EXISTS boundaries.contour; CREATE TABLE boundaries.contour AS SELECT w.id AS id_way, ( SELECT LineFromText('LINESTRING(' || group_concat(X(n.coord) || ' ' || Y(n.coord)) || ')', 4326) FROM node AS n JOIN way_nodes AS wn ON wn.id_node=n.id WHERE wn.id_way=w.id ) AS geometrie FROM ( SELECT DISTINCT * FROM ( SELECT w.id FROM way AS w JOIN way_tags AS wt1 ON wt1.id_way=w.id JOIN tag AS t1 ON wt1.id_tag=t1.id AND t1.key="admin_level" AND t1.value="2" UNION SELECT w.id FROM way AS w JOIN way_tags AS wt1 ON wt1.id_way=w.id JOIN tag AS t1 ON wt1.id_tag=t1.id AND t1.key="natural" AND t1.value="coastline" ) EXCEPT SELECT w.id FROM way AS w JOIN way_tags AS wt1 ON wt1.id_way=w.id JOIN tag AS t1 ON wt1.id_tag=t1.id AND t1.key="maritime" AND (t1.value="yes" OR t1.value="true") ) AS w;Dans certains cas, il existe des Ways sans contenu :
?View Code SQL1 DELETE FROM boundaries.contour WHERE geometrie IS NULL;La colonne geometrie doit être déclarée comme spatiale et recevoir un index (MBR en mémoire) :
?View Code SQL1 2 SELECT RecoverGeometryColumn('boundaries.contour', 'geometrie', 4326, 'LINESTRING', 2); SELECT CreateMbrCache('boundaries.contour', 'geometrie');Envoi des prochaines sortie dans le fichier « .svg » :
?View Code SQL1 .output routes.svgCommençons la génération du fichier proprement dite par l’entête du fichier :
?View Code SQL1 2 3 4 5 SELECT '<?xml version="1.0"?>'; SELECT '<svg viewBox="100 -7200 1200 1200" xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny">'; SELECT '<title>Les autoroutes de France</title>'; SELECT '<desc>La France des Autoroutes</desc>';Le trait de cote de fait en recherchant les élément du contour inclus dans la BBOX [-10, 40, 15, 52] (en degrés WGS84). Les tracés sont ensuite projetés en Lambert 93 (SRID 2154) puis simplifiés, avant d’être passés d’une échelle du mètre au kilomètre (ce dernier point évite simplement d’avoir des coordonnées de très grandes valeurs) :
?View Code SQL1 2 3 4 5 6 7 8 9 SELECT <path d="' || AsSVG(ScaleCoords(Simplify(Transform(geometrie, 2154), 2000.0), 0.001)) || '" fill="none" stroke="black" stroke-width="2" />' FROM boundaries.contour WHERE rowid IN (SELECT rowid FROM boundaries.cache_contour_geometrie WHERE mbr = FilterMbrIntersects(-10, 40, 15, 52) );Le dessin des autoroutes se fait par superposition de deux traits (rouge large et jaune étroit). La sélection est faite par les relations type='route' et network='FR:A-road'.
?View Code SQL1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 SELECT (SELECT '<path d="' || AsSVG(ScaleCoords(Simplify(Transform(LineFromText('LINESTRING(' || group_concat(X(n.coord) || ' ' || Y(n.coord)) || ')', 4326), 2154), 1000.0), 0.001)) || '" fill="none" stroke="red" stroke-width="9" />' FROM node AS n JOIN way_nodes AS wn ON wn.id_node=n.id WHERE wn.id_way=rm.id_member ) || ' ' || (SELECT '<path d="' || AsSVG(ScaleCoords(Simplify(Transform(LineFromText('LINESTRING(' || group_concat(X(n.coord) || ' ' || Y(n.coord)) || ')', 4326), 2154), 1000.0), 0.001)) || '" fill="none" stroke="yellow" stroke-width="3" />' FROM node AS n JOIN way_nodes AS wn ON wn.id_node=n.id WHERE wn.id_way=rm.id_member ) FROM road AS r JOIN relation_members AS rm ON r.id_relation=rm.id_relation AND rm.type=2 JOIN way as w ON w.id=rm.id_member WHERE r.network='FR:A-road';Enfin, clôture du fichier .svg :
?View Code SQL1 SELECT '</svg>';Et voilà.
Le code source de cette page est dans le Domaine Public.
Il s’agit d’un nouveau développement, toujours en C++, d’une série de classes permettant l’import des flux XML d’OSM dans une base locale. Les fonctionnalités attendues sont :
Pour éviter de réinventer la roue, voici les librairies existantes sur lesquelles s’appuie ce développement :
Elle permet aussi l’ajout d’index spatiaux sur les éléments géométriques de la base.
Il est sous licence LGPLv3 qui n’est pas la meilleure aux yeux de la Free Software Foundation, Inc., mais comme elle plutôt faite pour les librairies, je l’adopte.
Le mieux, c’est de retrouver tout le code sur GitHub à l’adresse : http://github.com/Marcussacapuces91/LibOsm
Par contre, je ne fournis pas le make file. Il faudra le rédiger vous-même suivant votre environnement de développement.
Il vous faudra aussi le fichier init_spatialite-2.3.sql disponible sur le site de SpatiaLite pour initialiser la base de données.
Le modèle de donnéesAfin de pouvoir utiliser les tables efficacement, il est intéressant de connaitre le modèle de données (le schéma) de la base de données.
Ensuite, j’ai « factorisé » les User (id et nom utilisateur) et les Tags afin d’éviter de multiplier les références dans chaque enregistrement des tables ci-dessus.