Open Data Comment créer une carte Open Street Map

60
15
juin
2013
Open Data

Vous avez déjà essayé de créer une carte personnalisée sur votre site ? Ce n’est pas toujours une partie de plaisir… Certains fournisseurs de map proposent des cartes très esthétiques, mais peu personnalisables, d’autres sont lourds à implémenter, bref, construire une carte à base d’open data peut être un parcours du combattant.

Mapping : why U no easy ?

Ce guide ne cherche pas à être exhaustif, il s’agit surtout d’un partage d’expérience, fort limité du fait que je ne suis pas un développeur ou mappeur professionnel. En revanche, je pense bien représenter le public non-codeur qui souhaiterait passer ces obstacles, et si cet article peut aider un débutant comme moi à trouver des ressources, des idées et des bouts de code pour parvenir à réaliser son objectif, alors cet article aura joué son rôle.
N’hésitez pas à partager vos avis, critiques et conseils dans les commentaires !
On commencera par lister quelques exemples de cartes, on verra un ou deux exemples de plateformes de création de carte sans coder, puis on entrera dans les détails du code nécessaire pour monter une carte avec OpenLayers.

Sommaire

I. Exemples de cartes

Commençons par voir quelques exemples de projets de carte basés sur OpenStreetMap :

  • opencyclemap.org est une carte des pistes cyclables.

  • openpistemap.org est une carte des pistes de ski.

  • openptmap.org trains, métros, tramways et bus.

  • öpnvkarte.de aéroports, métros, tramways et bus.

  • wheelmap.org accessibilité aux fauteuils roulant.

  • maposmatic.org génération de cartes de villes. Attention, générer la carte d’une grande ville prend beaucoup de temps à la création et à la lecture ! L’export est possible au format pdf, png, svgz et csv. Pour une grande ville, le format png est recommandé. Le format csv liste les noms de rues et de bâtiments publics avec leurs positions sur la carte (pas de coordonnées gps, juste des positions dans la grille générée dans les autres formats).

  • leretourdelautruche.com/map/nuke/ carte des centrales nucléaires dans le monde, avec sites d’explosions nucléaires.

  • gotronic.fr/carte-des-fablabs.htm une carte des FabLabs en France et dans le monde. Disclaimer : j’en suis l'auteur. C’est ma première map donc elle pourrait très certainement être améliorée.

Une liste de cartes beaucoup plus exhaustive est disponible sur le wiki d’openstreetmap

II. Construire une carte sans coder

Si vous souhaitez construire une carte utilisant des données issues d’Open Street Map, mais ne souhaitez pas coder, au moins deux solutions sont disponibles.

  • Umap. Il est possible de dessiner des zones, placer des marqueurs, des lignes, définir le niveau de zoom et le centrage, choisir un fond de carte, le tout en quelques clics.

Umap

On peut importer des données au format GeoJSON, KML, GPX et CSV. Voir section « couches de données ».

Une fois la carte terminée on peut extraire le code html, une URL (compressée) de la carte, ou télécharger les données au format GeoJSON.

Remarque : il est possible de choisir la licence WTFPL, dont l’acronyme signifie « do What The Fuck you want to Public Licence » !

Il va sans dire que ces cartes sont donc sous licence publique.

  • Open Mapquest.
    Un peu limité en fonctionnalités, on ne peut qu’afficher des points d’intérêt parmi une liste proposée ou tracer des itinéraires. J’ignore s’il est possible de personnaliser l’import/export de données. Il en existe probablement d’autres que je n’ai pas cité, n’hésitez pas à me le signaler dans les commentaires !

III. Coder une carte

Coder une carte requiert deux choses :
Des tuiles et une bibliothèque javascript. Les tuiles forment la base de la carte, et des couches (layers) sont ajoutées par-dessus pour afficher des points, des reliefs, zones, popups, etc. par-dessus les couches utilisées.

Représentation simplifiée des couches d’une carte.

1. Les tuiles

Ce sont les blocs qui constitueront la carte. Ces blocs sont chargés en fonction de la zone de la carte affichée.
Voici une liste de quelques serveurs de tuiles avec des exemples de leur rendu.

Typiquement, ce sont les tuiles Mapnik qui sont utilisées par OSM, CloudMade, MapQuest et MapBox, elles ressemblent à cela :

Titre de l'image

2. Une bibliothèque JavaScript

C’est un ensemble de fonctions JavaScript prédéfinies pour exploiter les tuiles et les couches qui se superposeront dessus.

  • Leaflet
    Bibliothèque open source. Un exemple simple de création de carte est détaillé pas à pas dans ce guide (en anglais). Voici le résultat.
    Cet exemple utilise les tuiles cloudmade (donc le rendu Mapnik) et reste relativement basique (pas de récupération de données d’OSM).

  • OpenLayers
    Open source. On peut trouver quelques exemples sur cette page. C’est un peu difficile de s’y retrouver sur leur site, à l’image de cette bibliothèque qui est un peu plus difficile à exploiter que leaflet. OpenLayers semble être la bibliothèque la plus complète toutefois.

  • MapQuest

  • MapQuery (http://mapquery.org/) combine OpenLayers et jQuery.

  • Cloudmade

  • Via Michelin

  • Yahoo Map

  • Microsoft Virtual Earth

  • Google Maps

  • etc.

Comparaison du code nécessaire pour créer une carte avec différentes bibliothèques sur trippingthebits.com. Sont testés Bing, ESRI, Google, MapQuest, OpenLayers, OVI et Leaflet.

Voici un résumé des liens entre plusieurs fournisseurs de cartographie Web gratuite, comprenant des bibliothèques javascript mais aussi des applications ou plateformes. Image issue de cet article.

Titre de l'image

3. Des couches de données (optionnelles)

Pouvoir coder une carte est bien, mais l’intérêt est surtout de pouvoir ajouter des POI ou points d’intérêts justement.

a) Première possibilité : utiliser des données fixes

Une méthode est d’aller sur http://overpass-turbo.eu/ (par exemple) et de coller ce bout de code avant de cliquer sur « run » :

<query type="node">
  <has-kv k="LA-CLEF" v="SA-VALEUR"/>
</query>
<print/>

En remplaçant les caractères en majuscule. Par exemple pour retrouver tous les nœuds dont le tag « nom » a pour valeur (exacte) « Charles de Gaulle », cela donnera

<query type="node">
  <has-kv k="name" v="Charles de Gaulle"/>
</query>
<print/>

Il est aussi possible d’utiliser du regex, par exemple pour trouver tous les nœuds comprenant les termes « Charles de Gaulle » :

<query type="node">
  <has-kv k="name" regv="Charles de Gaulle"/>
</query>
<print/>

Dans ce cas on trouvera alors 107 résultats au lieu de 38 seulement avec la valeur exacte :

Titre de l'image

Plus de détails sur l’utilisation d’overpass turbo ici.
On peut exporter ces données en cliquant sur « export » et en choisissant son format.
Ce fichier peut donc être conservé sur le serveur du site sur lequel la carte est codé et ses données seront définitives donc ne prendront pas en compte d’éventuelles modifications apportées sur OpenStreetMap.

Une autre façon de récupérer ce fichier est d’utiliser une URL contenant les commandes destinées à l’API. Dans notre cas la commande serait  ?data=node["name"="Charles de Gaulle"];out+meta;
Et l’url (avec l’encodage des espaces) http://overpass-api.de/api/interpreter?data=node["name"="Charles%20de%20Gaulle"];out+meta;

Ensuite pour exploiter ces données avec OpenLayers, il faut créer une layer exploitant le fichier de données stocké sur le serveur. Par exemple, s’il s’agit d’un fichier osm, cela donnera :

var layer = new OpenLayers.Layer.Vector("POIs", {
    projection: map.displayProjection,
    strategies: [new OpenLayers.Strategy.Fixed()],
    protocol: new OpenLayers.Protocol.HTTP({
                url: "data.osm",
                format: new OpenLayers.Format.OSM()
      })
    });
map.addLayers([layerMapnik, layer]);

Remarque importante : le fichier data.osm doit se trouver sur le même serveur que la page.
Pour utiliser un autre format de fichier, comme un .txt par exemple, il faudra adapter le protocole :

protocol: new OpenLayers.Protocol.HTTP({
          url: "data.txt",
          format: new OpenLayers.Format.Text()
})

On peut trouver la liste des formats supportés sur cette page (dans le menu de gauche)

b) Deuxième possibilité : Données « live »

Afin d’afficher sur sa carte des informations directement extraites d’Open Street Map et toujours à jour, il faut passer par une API, et faire traiter le fichier récupéré directement par l’interpréteur javascript.
Avec OpenLayers, il suffit d’utiliser la variable var data_url
Cela donne par exemple :

<script type="text/javascript">
      var lat = 50.727;
      var lon = 7.092;
      var zoom = 15;
      var data_url = "api/interpreter?data=node["name"="Charles%20de%20Gaulle"];out+meta;";
      var zoom_data_limit = 13;
      var map;

Pour plusieurs couches de données, il faut plutôt utiliser la fonction make_layer()

map.addLayers([
    make_layer("http://overpass-api.de/api/interpreter?data=node["name"="Charles%20de%20Gaulle"];out+meta;", "blue"),
    make_layer("http://overpass-api.de/api/interpreter?data=node["name"="Charles"];out+meta;", "red"),
    ]);

4. Des popups ou évènements (optionnels)

Il est possible d’afficher des fenêtres lorsqu’un utilisateur clique sur un marker de la carte. En revanche, je n’ai pas trouvé comment le faire sur des données live, mais seulement en exploitant un fichier de données. Si vous savez comment faire ça, décrivez la procédure dans les commentaires et je l’ajouterai à l’article.
Il faut pour cela trois fonctions. Une fonction de création de la popup, une décrivant les informations à présenter dans la fenêtre, et une dernière pour fermer la fenêtre :

function onPopupClose(evt) {
    selectControl.unselectAll();
    var feature = this.feature;
    if (feature.layer) {
        selectControl.unselect(feature);
    } 
    else {
        this.destroy();
    }
}
function onFeatureSelect(event) {
    var feature = event.feature;
    var content=    
    "<h2>"+feature.attributes.name + "</h2>" 
    + feature.attributes.addrfull + "</br>";
    popup = new OpenLayers.Popup.FramedCloud("featurePopup",
        feature.geometry.getBounds().getCenterLonLat(),
        new OpenLayers.Size(100,100),
        content,
        null, true, onPopupClose);
        feature.popup = popup;
    map.addPopup(popup);
}
function onFeatureUnselect(event) {
    var feature = event.feature;
    if (feature.popup) {
        map.removePopup(feature.popup);
        feature.popup.destroy();
        delete feature.popup;
    }
}

Ici on suppose que les données possèdent les attributs name et addrfull.
Remarques :

  • Il semblerait que les « : » posent problème aux fonctions javascript. Il m’a donc fallu les supprimer dans le fichier .osm et remplacer les « addr:full » par « addrfull ». Il existe surement d’autres façons de contourner ce problème.

  • Si la liste des attributs à afficher dans la popup s’allonge, attention de vérifier qu’ils soient tous présents dans le fichier ! Sinon cela affichera un magnifique « undefined » dans la popup…

Une façon de contourner le problème est de tester la présence des attributs avant de les utiliser. Par exemple :

if (feature.attributes.addrfull === undefined) {
    var content=                                
        "<h2>"+feature.attributes.name + "</h2>";
} else {
    var content=    
         "<h2>"+feature.attributes.name + "</h2>" 
         + feature.attributes.addrfull + "</br>";
}

IV. A vous de jouer !

Voilà, les possibilités pour créer une carte à base d'OpenStreetMap sans coder existent, même si elles restent limitées à mon avis (prouvez moi le contraire dans les commentaires ;-). Pour ce qui est de l'utilisation d'OpenLayers (ou Leaflet), c'est certainement d'un niveau assez facile pour un développeur chevronné, et il est possible d'aller beaucoup plus loin que ce qui est décrit dans cet article.

  • # Github

    Posté par (page perso) . Évalué à  6 .

    À noter que Github a ajouté l'affichage des cartes pour les fichier au format GeoJSON.

    « Moi, lorsque je n’ai rien à dire, je veux qu’on le sache. » Raymond Devos

  • # Merci

    Posté par . Évalué à  2 .

    C'est très instructif !!

  • # Super intéressant

    Posté par . Évalué à  4 .

    Merci. On pourrait presque le transformer en wiki :)

  • # Correction

    Posté par . Évalué à  3 .

    Dans ton dernier code JS:

    if (feature.attributes.addrfull = undefined) {
    
    

    devrait être:

    if (feature.attributes.addrfull === undefined) {
    
    

    ou:

    if (!feature.attributes.addrfull) {
    
    
    • [^] # Re: Correction

      Posté par . Évalué à  0 .

      Effectivement, bien vu !

    • [^] # Re: Correction

      Posté par . Évalué à  4 . Dernière modification : le 16/06/13 à 08:53

      Étant donné que undefined n'est pas un mot clef du langage et qu'on pourrait
      faire :
      javascript
      window.undefined = feature.attributes.addrfull ;

      Le premier choix est à proscrire de vos mémoires (horreur ! malheur !)

      Le second choix est déjà plus propre et je me demande si ce n'est pas le plus "perf" (mais aujourd'hui ça change tout les mois avec les nouveaux moteurs qui sortent).

      Pour être vraiment propre il faudrait (il y a plusieurs choix—typeof…—j'en propose un) faire un truc comme
      javascript
      if( "addrfull" in feature.attributes ){
      ...
      }

      Ce qui en plus d'être cohérent (on demande au parent si… plutôt que d'essayer de taper au hasard) est AMHA très lisible.

      C'était la minute du gros lourd en Javascript. Merci d'avoir écouté et bonne Fête_des_Pères (en France).

  • # Court témoignage sur Leaflet et beaucoup de questions

    Posté par . Évalué à  4 .

    En tant que géographe (non informaticien), ce topo sur la cartographie en ligne m'est fort utile ! Merci.

    Il y a quelques semaines je me suis penché sur le cas de Leaflet et je trouve cette librairie plutôt bien. Elle est légère et performante puisqu'il existe une API de base (minimaliste mais suffisante dans la plupart des cas) qui peut être augmentée par un bon nombre d'extensions développées par la communauté.

    J'avais essayé de représenter un tracé GPS sur un fond de carte OpenStreetMap et grâce à ce plugin j'y suis arrivé en 5 min ! Bref, j'ai été assez impressionné par sa simplicité d'utilisation.

    À propos de web mapping, est-ce que quelqu'un connaîtrait des applications de questionnaires en ligne (type limesurvey) où l'on devrait répondre en traçant des points ou des polygones sur des cartes ? Il existe des plugins de Leaflet pour dessiner sur les cartes. Mais il me semble qu'il n'y a rien pour la gestion des données. Il y aurait-il des tutoriels qui pourraient m'aiguiller sur le bon chemin ? GeoJSON me paraît une piste, mais ce format est-il vraiment pertinent pour ce type d'application ?

    Désolé, j'ai casé beaucoup de questions à la fin. Elles auraient sans doute une meilleure place dans les forums.

    Géographiquement votre ;)

  • # Rendu personnalisé

    Posté par . Évalué à  2 .

    Autre possibilité : dessiner directement une carte à partir des données d'OpenStreetMap en utilisant le logiciel Maperitive qui permet d'effectuer un rendu personnalisé au moyen d'une feuille de style. Exemple un rendu topographique : http://osm107.openstreetmap.fr/jbtopo/

  • # trouver une adresse

    Posté par . Évalué à  2 .

    Je ne suis pas un spécialiste et je vais peut être poser une question idiote. Mais quand j'avais utilisé l'api de google maps il y a quelques années, il y avait une fonctionnalité très intéressante qui permettait, à partir d'une adresse postale, d'avoir les coordonnées latitude/longitude afin de pouvoir placer l'info sur la carte.
    Est ce qu'il existe un service similaire avec les données d'OSM ?

    Merci,

    Axel

  • # Zone de déplacement

    Posté par . Évalué à  1 .

    Merci pour ces infos. J'adore faire joujou avec les cartes, juste pour le plaisir.

    Un problème que je ne sais pas résoudre sans sortir la grosse artillerie :
    Autour d'un point, délimiter la zone qui donne un temps de trajet maximum de 15 minutes en prenant les routes. Ou plus simplement qui donne une distance de 15 km.

    Je fais ça avec des appels à Google maps en mode itinéraire. Mon programme balance des points répartis en cercle autour du point de référence, puis rapproche ou éloigne les points en fonction des résultats. C'est long, il faut que mon programme vise les routes sans en oublier. Bon ça reste facile… une fois que c'est écrit. Mais c'est d'une lenteur !

    Il doit y avoir une meilleure solution.

  • # C'est sous quel licence votre code ?

    Posté par . Évalué à  -9 .

    Votre dépêche est sous Licence CC by-sa, mais les codes qui sont dans cette dépêche sont sous quelle licence ?

    C'est très rare de nos jours de lire des infos utiles, et LinuxFR une fois de plus le permet.
    Merci pour cette dépêche JohannCR, et merci à LinuxFR de le mettre en dépêche !

  • # Corriger les noms des villes

    Posté par (page perso) . Évalué à  4 .

    Sympa et utile ce post, je me suis empressé de faire ma carte (méthode sans programmer). Je vois par contre pas mal d'anomalies dans les cartes elles-même, et notamment dans le nom des lieux. Je suis naturellement disposé à aider à la correction mais mes recherches sur comment faire restent vaines. J'ai trouvé comment télécharger des traces GPX mais pas comment indiquer l'emplacement de la ville de Grenoble (par exemple). Peut-être ai-je mal cherché mais une âme charitable saurait sans doute me mettre sur la voie.

    Pas de Grenoble sur la carte

    On voit que Seyssinet-Pariset apparaît où l'on s'attendait à voir Grenoble. Plus haut on voit que Saint-Pierre-en-Faucigny est indiqué en caractères plus gros que Annecy.

    Une vue plus rapprochée de l'agglomération de Grenoble (le nom de la ville n’apparaît toujours pas).

    Toujours pas de Grenoble sur la carte

    • [^] # Re: Corriger les noms des villes

      Posté par . Évalué à  0 .

      C'est sur qu'il y a parfois des imperfections, rien qu'aujourd'hui j'ai du corriger un nom de rue inexact… Personnellement je ne vois pas ton problème d'affichage pour Grenoble (à moins que tu ai corrigé ça dans l'heure qui précède^^).

      • [^] # Re: Corriger les noms des villes

        Posté par (page perso) . Évalué à  2 .

        Ben vois-tu le nom Grenoble indiqué quelque part (à part dans la petite carte en bas à droite de la 2ème capture) ? Si oui il faudra que l'un d'entre nous change ses lunettes :)

    • [^] # Re: Corriger les noms des villes

      Posté par . Évalué à  2 .

      Le problème doit venir des choix fait pour le rendu de ta carte. Si tu regardes sur le rendu OSM-FR http://tile.openstreetmap.fr/?zoom=14&lat=45.17881&lon=5.7088&layers=B00000F et que tu jongles entre les différents fonds tu verras toujours Grenoble d'affiché.
      Sur ta carte, le développeur a dû se dire que puisque Grenoble apparaît dans la miniature pourquoi le remettre sur la grande carte car ça fait doublon.

      • [^] # Re: Corriger les noms des villes

        Posté par (page perso) . Évalué à  2 .

        Sur ton lien les choses sont effectivement conformes à ce que l'on peut attendre. Sur http://umap.openstreetmap.fr/ les choses se gâtent dès que l'on choisit un fond de carte avec relief (c.a.d. courbes de niveaux)

        Sur mon exemple si Grenoble apparaît effectivement dans la miniature du deuxième écran, ce n'est pas le cas dans le premier. De plus l'affichage de cette miniature est une option, quand elle est désactivée cela ne change rien au fond de carte.

        Quand je vais sur http://www.openstreetmap.org/ c'est le fond de carte "transport" qui pose problème. Si je me logue pour corriger ce fond de carte n'est plus proposé. j'ai essayé les 2 programmes en ligne (potlach et id) mais l'un ne me permet pas de zoomer et m'affiche en permanence des messages d'erreur et l'autre me gèle le navigateur, que ce soit firefox ou rekonq (le script, sur cette page, semble présenter un problème. Voulez-vous arrêter le script ?)

        Je vais essayer avec Merkaartor et JOSM mais ce qui m'inquiète c'est de ne pas trouver de doc sur ce point précis

        • [^] # Re: Corriger les noms des villes

          Posté par (page perso) . Évalué à  2 .

          D’après ce que je vois rapidement sur le rendu osmfr et sur le point admin_center, ça m’a l’air correct (cf. http://wiki.openstreetmap.org/wiki/Place) Je n’ai pas vérifié l’état de la relation, ni du boundary=administrative correspondants. Grenoble est bien indiqué plus gros que les autres localités alentours sur différents rendus. Il s’agit certainement d’un bug du rendu que tu utilise qui n’arrive pas à placer le nom à cause de la densité d’informations ayant une priorité plus importante que lui à cet endroit.

  • # carte des FabLabs en France

    Posté par . Évalué à  4 .

    Merci pour ce partage mais cocorico, français avant tout, une petite critique:

    gotronic.fr/carte-des-fablabs.htm une carte des FabLabs en France et dans le monde

    me demande, dans noscript, d'activer le javascript pour "maps.google.com" !
    ben je le ferai pas.

  • # Serveur Chimère

    Posté par . Évalué à  -1 .

    Salut,

    Il y a aussi une application que je trouve très intéressante c'est chimère qui permet d'aggrégé des informations, voir par exemple celui de Suippes : http://carte.cc-regiondesuippes.fr/
    Perso, je suis entrain d'en installer un : http://charlevillemezieres.cartographielibre.fr/

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.