Skip to Content

Récupérer des données OpenStreetMap via GDAL/OGR

Niveau Intermédiaire
Logiciels utilisés GDAL/OGR
QGis
Plateforme Windows | Mac | Linux

OpenStreetMap (OSM) est un projet de cartographie collaborative et de constitution d'une base de données géographique libre (sous licence ODbL) du monde. Cette base de données peut être très utile aux géomaticiens qui peuvent en récupérer les données afin de les intégrer dans un SIG. Cependant, cette opération n'est pas forcément très intuitive et j'avoue avoir mis un peu de temps avant de bien saisir les différentes possibilités. Parmi les solutions les plus simples il est possible de passer par les téléchargements gratuits du site Geofabrik, par la fonction d'importation des données OpenStreetMap via QGis, ou via l'appli OSM2GIS développé par Arnaud Vandecasteele de Geotribu (liste non exhaustive!).


Cependant il est également possible d'extraire soi-même les données à partir des fichiers .osm (au format XML) d'OpenStreetMap à l'aide de GDAL/OGR, la puissante bibliothèque permettant de lire, écrire et/ou convertir un très grand nombre de formats de données géospatiales raster et vecteur. C'est cette méthode particulièrement intéressante que je vais tenter de vous exposer dans ce tutoriel. L'avantage de cette méthode est que l'on peut paramétrer soi-même l'extraction et donc choisir exactement les données que l'on veut (grâce à des requêtes sql) et le format que l'on souhaite en sortie (shp, tab, kml, geojson, sqlite, postgis, etc.).


Télécharger le fichier .osm de la zone voulue


Dans un premier temps, téléchargez le fichier .osm de la zone voulue en vous rendant sur le site d'OpenStreetMap, zoomez sur la zone qui vous intéresse, cliquez sur le bouton Exporter et choisissez l'export via l'API passerelle : votre navigateur téléchargera alors le fichier .osm. Attention : il est possible que le fichier téléchargé n'ait pas d'extension, si c'est le cas, renommez-le pour lui adosser l'extension .osm



Extraire les données OSM dans un format SIG via GDAL/OGR


Pour cela, il faut que GDAL/OGR soit installé sur votre ordinateur. Lancez un terminal (l'invite de commande sur Windows), placez-vous dans le dossier où se trouve votre fichier .osm, nous allons à présent voir comment utiliser GDAL/OGR pour extraire les données OSM dans un format SIG.


Extraction de toutes les données dans un seul fichier Sqlite


Pour un géomaticien habitué aux données réparties en différentes couches thématiques de géométries spécifiques (points, polylignes ou polygones) avec un nombre d'attributs bien défini, le format des données peut être déroutant aux premiers abords : en effet, toutes les informations sont stockées dans un fichier au format XML regroupant tout, mélangeant les points, les polylignes et les polygones et avec un nombre d'attributs (ou de "clés") potentiellement infini.



Exemple d'élément enregistré dans le fichier osm au format XML


Si vous souhaitez exporter la globalités des données de votre fichier .osm vous allez donc devoir choisir en sortie une base de données pouvant accueillir plusieurs tables. Prenons par exemple le format Sqlite ; dans le terminal tapez la ligne suivante :



ogr2ogr -f "SQlite" map.sqlite map.osm


Ouvrez à présent le fichier sqlite créé avec votre logiciel SIG (QGis par exemple), vous constaterez que votre base de données contient 5 tables : une table points, une table lines, une table multilinestrings, une table multipolygons et une table other_relations. Les tables attributaires contiennent plusieurs champs correspondant à certains des tags présents dans la base OSM, pour définir quels tags feront l'objet d'un champ dans la table attributaire de votre fichier SIG, il faut éditer le fichier osmconf.ini (avec un éditeur de fichier texte : par exemple le Bloc Note, ou mieux, Notepad++ pour windows), les autres clés et leurs valeurs sont stockées dans le champ "other_tags" créé par GDAL/OGR.



Le fichier osmconf.ini qu'il faut éditer afin de régler les paramètres d'extraction de GDAL/OGR pour les fichiers .osm


Nous avons donc réussi à importer les données OSM dans un logiciel SIG mais il faut bien avouer qu'il n'est pas très pratique d'utiliser ces données telles quelles pour réaliser des traitements SIG ou appliquer des symbologies à nos couches. C'est pourquoi nous allons à présent voir comment créer différentes couches thématiques contenant uniquement les informations que l'on souhaite grâce à GDAL/OGR et aux requêtes SQL.


Extraction de données OSM par couches thématiques grâce aux requêtes SQL


Premier exemple : vous souhaitez extraire uniquement les routes. Pour cela il faut savoir que dans OSM, la clé du fichier XML indiquant qu'une géométrie de type polyligne est une route est "highway", vous pouvez retrouver la liste des principaux tags sur le wiki d'OSM (pour plus d'informations sur le fonctionnement des tags vous pouvez visiter cette page). Il faut donc vérifier dans le fichier osmconf.ini que la clé "highway" est bien présente dans les champs à créer par GDAL/OGR. Cette information est contenue dans la ligne "attibutes=" de l'élément [lines] du fichier osmconf.ini. Nous pouvons également ajouter au fichier osmconf.ini d'autres clés intéressantes pour notre future couche route : les clés oneway (sens uniques), bridge (pont), tunnel, maxspeed (vitesse maximale) et ref.



ligne à vérifier/modifier dans osmconf.ini


Sauvegardez le fichier osmconf.ini et lancez cette commande dans le terminal :



ogr2ogr -f "ESRI Shapefile" roads.shp -sql "select osm_id, name, ref, highway AS "type", oneway, bridge, tunnel, maxspeed from lines where highway is not null" map.osm


Si vous avez des problème avec l'encodage des caractères ajoutez l'option "-lco ENCODING=UTF-8" à votre commande GDAL/OGR :



ogr2ogr -f "ESRI Shapefile" roads.shp -sql "select osm_id, name, ref, highway AS "type", oneway, bridge, tunnel, maxspeed from lines where highway is not null" -lco ENCODING=UTF-8 map.osm


Regardons de plus près cette ligne de commande :


-f "ESRI Shapefile" nous permet de choisir le format en sortie (pour connaître tous les formats supportés par la commande ogr2ogr, tapez dans votre terminal "ogr2ogr --formats")


roads.shp est le nom du fichier qui contiendra notre extraction


dans la requête sql  -sql "select osm_id, name, ref, highway AS "type", oneway, bridge, tunnel, maxspeed from lines where highway is not null" :


select [...] permet de sélectionner les champs que nous souhaitons parmi les clés que nous avons choisies dans le fichier osmconf.ini. (remarque 1 : pour tous les sélectionner il faut écrire "select *") (remarque 2 : highway AS "type" permet de renommer le nom du champ "highway" en le remplaçant par "type").


from "lines" permet d'indiquer à GDAL/OGR qu'il faut aller chercher ces informations dans les géométries de type ligne.


where highway is not null est la requête qui nous permet de sélectionner uniquement les lignes où la clé "highway" est renseignée (non nulle) afin d'extraire uniquement les routes.


-lco ENCODING=UTF-8 permet de forcer le codage des caractères en UTF-8 (pour éviter les problèmes d'affichage des caractères spéciaux)


map.osm est le nom du fichier .osm en entrée que nous avons téléchargé plus tôt.


Et voilà, vous avez votre couche de routes !



© les contributeurs d'OpenStreetMap


Deuxième exemple : vous souhaitez extraire la liste des bars présents dans votre fichier .osm ? Cela va un peu se compliquer car, dans OSM, les bars peuvent être représentés par des points ou des polygones (information disponible sur le wiki OSM présentant les principales clés et leurs valeurs). Cependant, vous avez de la chance, car depuis la version 1.10 de Gdal, nous pouvons utiliser des requêtes sql avancées grâce à l'utilisation des fonctions sql de Sqlite/SpatiaLite.


Dans votre terminal tapez donc la commande suivante :



ogr2ogr -f "ESRI Shapefile" bars.shp -dialect SQLITE -sql "SELECT * FROM (SELECT st_pointonsurface(GEOMETRY) AS GEOMETRY, coalesce(osm_way_id,osm_id) AS ID, name, amenity FROM multipolygons UNION SELECT GEOMETRY, osm_id AS ID, name, amenity FROM points) WHERE amenity='pub' OR amenity='cafe' OR amenity= 'bar'" -lco ENCODING=UTF-8 map.osm


L'option -dialect SQLITE de la ligne de commande nous permet d'utiliser les fonctions de Sqlite/SpatiaLite.


Analysons à présent la requête SQL suivante :



SELECT * FROM (SELECT st_pointonsurface(GEOMETRY) AS GEOMETRY, coalesce(osm_way_id,osm_id) AS ID, name, amenity FROM multipolygons UNION SELECT GEOMETRY, osm_id AS ID, name, amenity FROM points) WHERE amenity='pub' OR amenity='cafe' OR amenity= 'bar'


Tout d'abord nous sélectionnons les clés GEOMETRY (obligatoire quand on utilise l'option -dialect SQLITE), osm_id, osm_way_id, name et amenity pour les géométries "multipolygons".


Nous appliquons la fonction spatiale st_pointonsurface (fonction de Sqlite/SpatiaLite) à la géométrie afin de transformer notre géométrie de type polygone en un point se trouvant à l'intérieur du polygone.


Nous appliquons la fonction coalesce(osm_way_id,osm_id) pour donner à notre futur champ ID la valeur de la clé "osm_way_id" quand elle existe, sinon la valeur "osm_id" sera donnée (cas particulier pour les éléments de type polygones qui peuvent avoir leur identifiant dans l'un de ces deux champs).


Ensuite nous réalisons une union avec les éléments de type point de notre fichier OSM en sélectionnant les mêmes clés.


Enfin nous englobant cette union dans une requête général : SELECT * FROM (mon_union) WHERE ... . Ici nous choisissons d'extraire les bars qui sont renseignés dans OSM dans la clé "amenity" soit par la valeur "pub"  ou "cafe" ou "bar" (voir le wiki OSM concernant les clés).


Cette requête nous livre donc un Shapefile de type point des bars renseignés dans OSM :



© les contributeurs d'OpenStreetMap, Stamen


Et voilà, vous n'avez plus qu'à choisir dans lequel vous voulez m'offrir un verre ! (Note : si la thématique vous intéresse, je vous conseille d'aller faire un tour sur le projet OpenBeerMap)


Recréer les différentes couches shp proposées en téléchargement par Geofabrik


Parmi les nombreux fichiers que Geofabrik nous propose, nous retrouvons des Shapefiles de données OSM retravaillées en différentes couches thématiques. Nous avons maintenant tous les éléments pour récréer nous-mêmes ces différents Shapefiles.


Cela a plusieurs avantages, en le faisant soi-même on peut :



  • choisir l'étendue dont nous avons besoin (sur Geofabrik ces téléchargements sont uniquement proposés à l'échelle régionale pour la France)

  • choisir une zone pour laquelle ces fichiers ne sont pas disponibles

  • modifier les options des extractions (choix des clés, modification de la requête, etc.)

  • mieux connaître la donnée que l'on va manipuler

  • si ces fichiers changent (comme ça a déjà été le cas par exemple la couche "buildings" a disparu des fichiers proposés) ou si ce service disparait, on sera toujours capable de les créer soi-même pour continuer à les intégrer dans notre SIG.

Voici donc les différentes lignes de commande permettant de recréer ces fichiers :


Note 1 : Par défaut le fichier osmconf.ini ne considère pas les polylignes fermées avec la clé "waterway" comme étant des polygones, ajoutez "waterway" à la ligne "closed_ways_are_polygons=" du fichier osmconf.ini pour corriger ce "problème".


Note 2 : N'oubliez pas d'ajouter les clés que vous allez utiliser pour les requêtes suivantes dans les lignes "attributes=" concernées du fichier osmconf.ini


(À la fin de ce tutoriel vous trouverez le contenu du fichier osmconf.ini que j'ai modifié pour réaliser les requêtes ci-dessous)


places.shp



ogr2ogr -f "ESRI Shapefile" places.shp -sql "select osm_id, name, place AS "type", population from points where place is not null" -lco ENCODING=UTF-8 map.osm


roads.shp



ogr2ogr -f "ESRI Shapefile" roads.shp -sql "select osm_id, name, ref, highway AS "type", oneway, bridge, tunnel, maxspeed from lines where highway is not null" -lco ENCODING=UTF-8 map.osm


buildings



ogr2ogr -f "ESRI Shapefile" buildings.shp -sql "select osm_way_id AS "osm_id", name from multipolygons where building is not null" -lco ENCODING=UTF-8 map.osm


railways



ogr2ogr -f "ESRI Shapefile" railways.shp -sql "select osm_id, name, railway AS "type" from lines where railway is not null" -lco ENCODING=UTF-8 map.osm


waterways



ogr2ogr -f "ESRI Shapefile" waterways.shp -sql "select osm_id, name, waterway AS "type", width from lines where waterway is not null" -lco ENCODING=UTF-8 map.osm


points



ogr2ogr -f "ESRI Shapefile" points.shp -dialect SQLITE -sql "select osm_id, GEOMETRY, name, coalesce(REPLACE(highway,'yes','highway'), REPLACE(man_made,'yes','man_made'), REPLACE(amenity,'yes','amenity'), REPLACE(shop,'yes','shop'), REPLACE(tourism,'yes','tourism'), REPLACE(railway,'yes','railway'), REPLACE(historic,'yes','historic'), REPLACE(office,'yes','office'), REPLACE(craft,'yes','craft')) AS type FROM points WHERE highway is not null OR man_made is not null OR amenity is not null OR shop is not null OR tourism is not null OR railway is not null OR historic is not null OR office is not null OR craft is not null" -lco ENCODING=UTF-8 map.osm


natural



ogr2ogr -f "ESRI Shapefile" natural.shp -dialect SQLITE -sql "select osm_id, GEOMETRY, name, coalesce(waterway,leisure,landuse,REPLACE(natural,'wood','forest')) AS "type" from multipolygons where waterway is not null or leisure='park' or landuse='forest' or landuse='park' or natural='wood' or natural='water'" -lco ENCODING=UTF-8 map.osm


landuse



ogr2ogr -f "ESRI Shapefile" landuse.shp -dialect SQLITE -sql "select osm_way_id AS "osm_id", GEOMETRY, name, coalesce(landuse,leisure) AS "type" from multipolygons where (landuse is not null and landuse <> 'forest' and landuse <> 'park') OR (leisure = 'pitch')" -lco ENCODING=UTF-8 map.osm


Ca y est vous avez vos superbes couches ? Bien joué ! Vous pouvez maintenant faire des traitements sur vos couches, les mettre en forme, etc. ([Mode autopromotion] Vous pouvez, par exemple, faire une jolie carte minimaliste des îlots urbains! [/Mode autopromotion])


Vous pouvez aussi faire un tour sur ce github de Charley Glynn qui nous met à disposition des fichiers de styles QML pour Qgis afin de mettre en forme les couches Shapefiles que nous venons de créer sur le modèle de ceux de Geofabrik :



© les contributeurs d'OpenStreetMap


Conclusion


Evidemment il faut s'y connaitre un peu en langage SQL afin d'affiner vos requêtes et obtenir ce que vous voulez, mais c'est une manière très intéressante de récupérer les données OSM afin de les intégrer à votre SIG. De plus vous pouvez facilement intégrer vos lignes de commande au sein d'un script ou d'un programme ce qui élargit les possibilités !


A vous de jouer !


contenu du fichier osmconf.ini :


osmconf.ini

  1. #
  2. # Configuration file for OSM import
  3. #
  4.  
  5. # put here the name of keys for ways that are assumed to be polygons if they are closed
  6. # see http://wiki.openstreetmap.org/wiki/Map_Features
  7. closed_ways_are_polygons=aeroway,amenity,boundary,building,craft,geological,historic,landuse,leisure,military,natural,office,place,shop,sport,tourism,waterway
  8.  
  9. # comment to avoid laundering of keys ( ':' turned into '_' )
  10. attribute_name_laundering=yes
  11.  
  12. # uncomment to report all nodes, including the ones without any (significant) tag
  13. #report_all_nodes=yes
  14.  
  15. # uncomment to report all ways, including the ones without any (significant) tag
  16. #report_all_ways=yes
  17.  
  18. [points]
  19. # common attributes
  20. osm_id=yes
  21. osm_version=no
  22. osm_timestamp=no
  23. osm_uid=no
  24. osm_user=no
  25. osm_changeset=no
  26.  
  27. # keys to report as OGR fields
  28. attributes=name,barrier,highway,ref,address,is_in,place,man_made,population,amenity,shop,tourism,railway,historic,office,craft
  29. # keys that, alone, are not significant enough to report a node as a OGR point
  30. unsignificant=created_by,converted_by,source,time,ele
  31. # keys that should NOT be reported in the "other_tags" field
  32. ignore=created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
  33. # uncomment to avoid creation of "other_tags" field
  34. #other_tags=no
  35.  
  36. [lines]
  37. # common attributes
  38. osm_id=yes
  39. osm_version=no
  40. osm_timestamp=no
  41. osm_uid=no
  42. osm_user=no
  43. osm_changeset=no
  44.  
  45. # keys to report as OGR fields
  46. attributes=name,highway,waterway,aerialway,barrier,man_made,oneway,bridge,tunnel,maxspeed,ref,railway,width
  47. # keys that should NOT be reported in the "other_tags" field
  48. ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
  49. # uncomment to avoid creation of "other_tags" field
  50. #other_tags=no
  51.  
  52. [multipolygons]
  53. # common attributes
  54. # note: for multipolygons, osm_id=yes instanciates a osm_id field for the id of relations
  55. # and a osm_way_id field for the id of closed ways. Both fields are exclusively set.
  56. osm_id=yes
  57. osm_version=no
  58. osm_timestamp=no
  59. osm_uid=no
  60. osm_user=no
  61. osm_changeset=no
  62.  
  63. # keys to report as OGR fields
  64. attributes=name,type,aeroway,amenity,admin_level,barrier,boundary,building,craft,geological,historic,land_area,landuse,leisure,man_made,military,natural,office,place,shop,sport,tourism,waterway,highway
  65. # keys that should NOT be reported in the "other_tags" field
  66. ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
  67. # uncomment to avoid creation of "other_tags" field
  68. #other_tags=no
  69.  
  70. [multilinestrings]
  71. # common attributes
  72. osm_id=yes
  73. osm_version=no
  74. osm_timestamp=no
  75. osm_uid=no
  76. osm_user=no
  77. osm_changeset=no
  78.  
  79. # keys to report as OGR fields
  80. attributes=name,type
  81. # keys that should NOT be reported in the "other_tags" field
  82. ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
  83. # uncomment to avoid creation of "other_tags" field
  84. #other_tags=no
  85.  
  86. [other_relations]
  87. # common attributes
  88. osm_id=yes
  89. osm_version=no
  90. osm_timestamp=no
  91. osm_uid=no
  92. osm_user=no
  93. osm_changeset=no
  94.  
  95. # keys to report as OGR fields
  96. attributes=name,type
  97. # keys that should NOT be reported in the "other_tags" field
  98. ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
  99. # uncomment to avoid creation of "other_tags" field
  100. #other_tags=no

Site officiel : OpenStreetMap
Site officiel : GDAL/OGR

Commentaires

Volumétrie extraction ogr2ogr sur fichier osm

Bonjour,

Super article, vraiment utile et très clair.
Avez vous des conseils pour la gestion de la volumétrie ?
La requête qui suit (identification de zones ou bâti commerciaux ou industriels) fonctionne bien sur un fichier de type fr_region.osm mais pas sur la france entière fr.osm. Il semble que la base sqlite qui accueille le résultat de la requête ne soit pas calibrée...

ogr2ogr -f "SQlite" FR_Retail_Poly.SQlite -dialect SQLITE -sql "SELECT coalesce(osm_way_id,osm_id) as osm_id, GEOMETRY,name, coalesce(landuse,shop,building,'NA') as type from multipolygons where landuse in ('commercial','retail','industrial') or Shop in ('department_store', 'mall', 'supermarket') or building='retail'" france.osm -lco ENCODING=UTF-8 france.osm –skipfailure

Je peux faire une requête par région et fusionner le tout mais c'est un peu lourd et je souhaiterai trouver les options les plus efficaces pour la gestion des plus grosses extractions.

Encore Merci pour votre article

replace

Bonjour,
et tout d'abord merci pour ce post très très utile ! Carrément génial même !
Comme je suis un newbie en requête SQL, je bute sur un point, si vous pouviez m'aider ça serait vraiment plus que gentil !
La question est la suivante : quand dans un export shp, on veut changer plusieurs items dans une colonne, quelle manip est possible ?
Quand je tente plusieurs REPLACE ça me fait autant de colonnes que de REPLACE (ce qui est logique bien sûr).
L'idée (vous allez comprendre de suite) est de faire ça :
"select osm_id, GEOMETRY, name, REPLACE(admin_level,'8','commune')[AND (admin_level,'10','quartiers')], REPLACE(boundary,'yes','boundary') AS type FROM multipolygons WHERE boundary is not null"
où bien sûr les crochets n'existent pas ; je les ai posés pour montrer ce que je souhaite ajouter.
Le AND ne fonctionne pas, des virgules non plus. J'ai tenté avec UNION, pas mieux. Il faut sans doute un script plus complexe, mais je sèche !
Merci beaucoup.
Cordialement
Cyril

Merci pour le retour

Ha oui exact, c'est une erreur de ma part, je vais corriger ça! Merci pour le retour!

Erreur sur le nom du fichier de config OSM à corriger

En jouant pour modifier le fichier de configuration, j'ai constaté une erreur. Il est fait référence à osmconfig.ini. Or, ce n'est pas le bon nom de fichier.

D'ailleurs à la fin, le fichier encapsulé est osmconf.ini alors que la légende est "contenu du fichier osmconfig.ini :"
J'ai aussi vérifié sur la page officielle GDAL http://www.gdal.org/drv_osm.html qui me dit aussi que le bon nom est osmconf.ini

Merci de votre retour

Poster un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.