Utiliser OpenStreetMap grâce à Overpass

Julien Fastré

10 février 2021

Sommaire

  1. OSM, c’est quoi ?
  2. OSM: où sont les données ?
  3. Overpass API
  1. Rappel du modèle de données OSM
  2. Présentation du langage Overpass et requêtes sympas

OSM, c’est quoi ?

Logo officiel OpenStreetMap

OSM, c’est une carte ?

Page d’accueil d’OpenStreetMap.org

Base de donnée géographique ouverte

Permet de générer des cartes…

… de calculer des itinéraires …

Calcul d’itinéraire dans OsmAnd

… de géocoder / reverse geocoder …

… d’analyser le territoire …

OpenStreetMap, c’est qui et comment ?

Contributeurs & communautés

Plus de 17k utilisateurs par semaine

Organisations

Outils de coordination

Outils d’édition

  • iD
  • JOSM
  • Plotlatch
  • Vespucci

Gamification sur Android: StreetComplete

Qualité des données

OSM, modifiable par “n’importe qui”

démo d’une édition

License ODBL

Open Database License

Vous êtes libres de:

  • Partager la base de donnée;
  • Créer des œuvres à partir des données;
  • Adapter ou modifier la base de donnée;

Aussi longtemps que:

  • attribution des auteurs;
  • BDD adaptée sous licence compatible…
  • …et sans DRM;

Les œuvres créées à partir de la base de donnée peuvent être distribuées sous une licence plus restrictive ou propriétaire.

Exemples: cartes, applications, etc.

Où sont les données ?

Des éditions à chaque minute…

Les données brutes

Des extraits géographiques

Zoom sur Geofabrik

Formats:

  • .osm (xml)
  • .pbf (protocol buffer)

Possibilité de s’authentifier => accès à l’username et userid

Comment les exploiter ?

  1. Osmosis (Java, en mode “light-maintenance mode”)

    Permet un filtre par bbox ou par polygone, l’import dans une DB

  2. imposm et osm2pgsql

    Import et mise à jour d’une BDD Postgis, orienté rendu carto.

  1. osmium

    Multiples commandes pour extraire, filtrer les données. Import vers une DB dans un schéma très simple.

     # compter le nombre de point d'adresse en Belgique
     wget --quiet http://download.geofabrik.de/europe/belgium-latest.osm.pbf
     osmium tags-count belgium-latest.osm.pbf 'addr:housenumber'
     2652207    "addr:housenumber"
     # durée: +/- 8 secondes

Conclusion…

  • Gros volume de données;
  • Difficulté de réaliser des scripts;
  • (et on n’a pas encore évoqué le modèle de données…)

Question: n’y a-t-il pas plus simple ?

Overpass API

Logo Overpass API

A quoi ça sert ?

  • Lecture des données OSM;

  • Optimisé pour la requête;

  • Langage de requête dédié;

  • Permet de travailler avec les données historiques;

  • Licence AGPLv3.0;

  • Plusieurs instances publiques:

    https://overpass-api.de

Langages de requêtes

  • Soit en XML;

  • Soit Overpass-QL

    Langage procédural, impératif.

[out:json][timeout:900]; 
area["name"="Liège"]->.sa; 
nw["amenity"="restaurant"](area.sa); 
out;

Résultats

{
  "version": 0.6,
  "generator": "Overpass API 0.7.56.8 7d656e78",
  "osm3s": {
    "timestamp_osm_base": "2021-02-05T14:16:03Z",
    "timestamp_areas_base": "2021-02-05T13:44:03Z",
    "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
  },
  "elements": [

{
  "type": "node",
  "id": 254279248,
  "lat": 50.6260055,
  "lon": 6.2347182,
  "tags": {
    "addr:city": "Raeren",
    "addr:country": "BE",
    "addr:housenumber": "2",
    "addr:postcode": "4730",
    "addr:street": "Fringshaus",
    "amenity": "restaurant",
    "cuisine": "regional",
    "name": "Fringshaus"
  }
}, // ...
]}

Overpass Turbo

Interface pour construire des requêtes Overpass QL

https://overpass-turbo.eu

Rappel du modèle de données OSM

Au commencement, il y a le nœud

Node

Deux nœuds forment un way

Way

Un way fermé ? Un area

Si le premier et le dernier nœud d’un way sont identiques, le way est considéré comme un area (mais, dans le modèle, il s’agit d’un way).

Area

(Coût en calcul important)

Des objets ensemble ? Une relation

relation

Les relations sont utilisées pour, par exemple:

  • relier les routes dans un itinéraire:

    • ligne de bus, de chemin de fer, …
    • itinéraire balisé vélo, randonnée pédestre, …
  • relier des équipements entre eux:

    • poteau d’arrêt de bus, plate-forme d’attente, point d’arrêt du bus;
  • créer des objets complexes: multipolygones

Chaque objet a des attributs: clé/valeur

k=v

Chaque objet a un identifiant unique

  • Les identifiants diffèrent pour les nodes, way, relation;

  • Les identifiants sont modifiés en cas de:

    • suppression, et re-création;
    • division d’un objet en deux (par exemple un chemin).

Les clés/valeurs sont documentées dans le wiki

La page wiki des restaurants:

Page wiki “restaurant”

Exemple: parking vélo

Parking vélo
amenity=bicycle_parking

bicycle_parking=stands

capacity=8

operator=Ville de Bruxelles

covered=no

Édition simplifiée dans les éditeurs

Les tags sont pré-sélectionnés dans les interfaces graphiques.

JOSM

Édition d’un restaurant dans JOSM

iD

Édition d’un restaurant à Liège

Édition d’un restaurant dans iD

Requêtes Overpass-QL

Quelques possibilités de requêtes.

Requêtes par identifiant unique

Relation “Université de Liège” (multipolygone):

[out:json][timeout:25];

rel(1376343);

out body geom;

Tester sur overpass-turbo

Sélection par éléments du modèle:

//sélection d'un chemin
way(int);

// sélection d'un noeud
node(int) ;

//sélection d'une relation
rel(int) ;


Sélection par BBOX

BBOX = Boîte englobante, 4 coordonnées: sud, ouest, nord, est

node(44.0918, 6.2356790, 44.09231, 6.2362690);
out skel;

Outil pour générer des bbox: http://bboxfinder.com

Sélection par clé/valeur

[out:json][timeout:900]; 
area["name"="Liège"]->.sa; 

// la parenthèse crée une union des différents éléments
(
  // sélection des nœuds
  node["amenity"="restaurant"](area.sa); 
  // sélection des chemins
  way["amenity"="restaurant"](area.sa);
)

out;
// sélection pour nodes and way
nw["amenity"="restaurant"];

// séleciton pour nodes et relations
nr["amenity"="restaurant"];

// sélection pour way et relations
wr["amenity"="restaurant"];

// sélection des way, relations et nodes
nwr["amenity"="restaurant"];

Exemples de filtres

//équivalent
way[highway=pedestrian];
way["highway"="pedestrian"];

// chemins qui n'ont *pas* le tag pedestrian
way[highway!=pedestrian];
// (sélectionne aussi ceux qui ne sont pas des highway)

// sélectionne les chemins qui ont le tag highway
way[highway];

// sélection selon expression régulière
way[name~"^Rue"]; // tout ce qui commence par "Rue"

Combiner des filtres:

// gather results
way["amenity"="bicycle_parking"]["bicycle_parking"="stands"](area.searchArea);

tester

Area: des aires pré-enregistrées

Les zones administratives sont définies par les limites administratives (très souvent des multipolygones dans OSM):

// Province de Liège :-(
area["name"="Liège"]->.sa; 

// peut être géocodée:
{{geocodeArea:"Liege"}}->.searchArea;

Chercher autour d’un point

Les barbecues proches d’une aire de pique-nique:

[out:json][timeout:250];
// fetch area “Province de Liège” to search in
{{geocodeArea:"Province de Liège"}}->.searchArea;

// rassembler aires de pique-nique dans une variable (.a)
(
  node["tourism"="picnic_site"](area.searchArea);  
  way["tourism"="picnic_site"](area.searchArea);
)->.a;

// chercher les barbecues non-privés à moins de 500 mètres
( 
  node(around.a:500)["amenity"="bbq"]["access"!="private"]["access"!="no"];
  way(around.a:500)["amenity"="bbq"]["access"!="private"]["access"!="no"];
);
// print results
out body;
>;
out skel qt;

Tester

Retrouver tous les objets touchés par un user

// Select nodes last modified by user
node(user:"juminet")({{bbox}});

tester

Sortie en CSV

Liste des musées en province de Liège:

[out:csv( name, fee, wheelchair, "addr:housenumber", "addr:postcode", "addr:street", ::"lat", ::"lon" )];

{{geocodeArea:Province de Liège}}->.searchArea;

(
  // query part for: “tourism=museum”
  node["tourism"="museum"](area.searchArea);
  way["tourism"="museum"](area.searchArea);
  relation["tourism"="museum"](area.searchArea);
);

// sortie: les méta-données et le centre de chaque objet
out meta center;

Tester

Sortie:

name    fee wheelchair  addr:housenumber    addr:postcode   addr:street @lat    @lon
Préhistosite de Ramioul                     50.5786075  5.4268272
Musee de Moresnet                       50.7213483  5.9888327
Archéoforum yes limited             50.6452983  5.5732626
Remember 39-45                      50.6688706  5.8840043
Musée de Fléron                     50.6109969  5.6797217
Charbonnage de Blegny-Mine                      50.6863350  5.7226648
Ikob -Internationales Kunstzentrum Ostbelgien           3   4700    Loten   50.6258969  6.0301564
Mö(h)renmuseum                      50.6918624  6.1057144
Töpfereimuseum Raeren                       50.6787456  6.1206606

Requête avec données de style

Uniquement avec Overpass-Turbo:

[out:json][timeout:25];
// gather results
(
  way["highway"](area:3081749435);
);
// print results
out body;
>;
out skel qt;


{{style:

way {
  text: surface;
}

}}

Tester

[out:json][timeout:25];
// gather results
(
  // query part for: “maxspeed"
  way["maxspeed"="20"]({{bbox}});
  relation["maxspeed"="20"]({{bbox}});
  way["maxspeed"="30"]({{bbox}});
  relation["maxspeed"="30"]({{bbox}});
  way["maxspeed"="signals"]({{bbox}});
  relation["maxspeed"="signals"]({{bbox}});
  // query part for: “maxspeed=50”
  way["maxspeed"="50"]({{bbox}});
  relation["maxspeed"="50"]({{bbox}});
  way["maxspeed:forward"="50"]({{bbox}});
  relation["maxspeed:forward"="50"]({{bbox}});
  way["maxspeed:backward"="50"]({{bbox}});
  relation["maxspeed:backward"="50"]({{bbox}});
  way["maxspeed"="70"]({{bbox}});
  relation["maxspeed"="70"]({{bbox}});
    way["maxspeed"="90"]({{bbox}});
  relation["maxspeed"="90"]({{bbox}});
  way["maxspeed"="120"]({{bbox}});
  relation["maxspeed"="120"]({{bbox}});
  // query part for "amenity=school"
  way["amenity"="school"]({{bbox}});
  way["amenity"="kindergarten"]({{bbox}});
  way["amenity"="college"]({{bbox}});
  
  //relation["amenity"="school"]({{bbox}}); 
);
{{style:
way[amenity]{
 width:0;
  fill-color: #ff0000;
}
  way[highway] {
    width: 3;
    opacity: 1;
    color: #B5B6A5;
  }
  way[maxspeed=signals] {
    color: #5d72d8;
  }
  way[maxspeed=20] {
    color: #8A2BE2;
  }
  way[maxspeed=30] {
    color: #5d72d8;
  }
  way[maxspeed=50] {
    color: #00ff00;
  }
  way[maxspeed:forward=50] {
    color: #00ff00;
  }
  way[maxspeed:backward=50] {
    color: #00ff00;
  }
  way[maxspeed=70] {
    color: #ffa500;
  }
  way[maxspeed=90] {
    color: #ff0000;
  }
  way[maxspeed=120] {
    color: #000000;
  }
  way:placeholder {
    fill-opacity: 0;
    opacity: 5;
    width: 1;
  }
}}
// print results
out body;
>;
out skel qt;

Tester

Requête pour compter des objets

[out:csv(::count)][timeout:900]; 
area["name"="Liège"]->.sa; 
nw["addr:housenumber"](area.sa); 
out count;

Tester

Partage avec Umap

Une requête Overpass peut servir de source de donnée sur une carte umap.

Exemple

Requête overpass originale

Where is the doc ?

https://wiki.openstreetmap.org/wiki/Overpass_API

Merci de votre attention !

Des questions ?

// reveal.js plugins