Index de l'article

Zones isochrones

iso cergy 5 10 15Rendez-vous sur https://openrouteservice.org/ et créez-vous un compte afin de récupérer une clé d'API (le token).

Il s'agit du service associé au plugin ORS Tools, que vous pouvez aussi installer afin de faire quelques tests.

Limitations

Mais le plugin est bridé à 500 zones isochrones par jour et surtout, à des batchs de 5 zones par traitement et 60 zones par minute. Or nous avons 308 zones isochrones à créer...

Boucle Python

Nous allons essayer d'outrepasser ces limites en créant nos zones isochrones dans une boucle Python.

Extrayez avant cela une dizaine de magasins pour tester notre code. Quand il sera fonctionnel nous le lancerons sur nos 308 magasins.

Construction d'un code de création d'une seule zone isochrone

Rendez-vous ici (une fois connecté au service) pour paramétrer la création d'une zone isochrone de test, la visualiser et en extraire son code Python. Utilisez les coordonnées du magasin de Cergy (2.0495375241349554, 49.05473127094994) afin de vérifier que vos paramètres sont bons.

import requests
 
body = {"locations":[[2.0495375241349554,49.05473127094994]],"range":[900],"attributes":["area","reachfactor","total_pop"],"range_type":"time"}
 
headers = {
    'Accept': 'application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8',
    'Authorization': 'YOUR-API-KEY',
    'Content-Type': 'application/json; charset=utf-8'
}
call = requests.post('https://api.openrouteservice.org/v2/isochrones/driving-car', json=body, headers=headers)
 
print(call.status_code, call.reason)
print(call.text)

Exécutez ce code dans la console Python de QGIS. Le dernier print vous renvoie un GEOJSON (sous forme textuelle pour l'instant).

Vous avez déjà visualisé votre zone isochrone dans la cartographie d'ORS, mais vérifiez que le GEOJSON généré par le code dans QGIS est lui-même correct, en le copiant-collant dans l'outil geojson.io.

Affichage sous QGIS

Si tout va bien, commentez les print et ajoutez à la suite de votre code les lignes suivantes pour afficher le GEOJSON dans QGIS (en modifiant les chemins) :

with open('C:/Users/Georges/Downloads/myfile.geoson', 'w', encoding='utf-8') as outfile:
    outfile.write(call.text)
 
iface.addVectorLayer('C:/Users/Georges/Downloads/myfile.geoson', 'Isochrone', 'ogr')

Exécutez l'ensemble du code dans la console Python de QGIS. La zone isochrone créé avec Python apparaît.

Itération

Bien, nous savons créer une zone isochrone dans QGIS avec Python, mais il nous en faut 308 !

Nous allons devoir itérer à travers la couche de points pour créer les zones isochrones correspondantes à partir de leur coordonnées

Pour contourner les limitations de l'API, et pouvoir relancer notre code à souhait, il nous faudra limiter la boucle à quelques dizaines de points (3 points pour les tests), et marquer les magasins dont la zone a déjà été créée. Ainsi nous n'aurons qu'à ré-exécuter le code plusieurs fois d'affilé pour générer nos 308 zones isochrones. Attention à la limite de 500 zones par jour, qui elle ne pourra pas être dépassée.

import requests
 
mylayer = QgsProject.instance().mapLayersByName("decathlon_france")[0]
 
limit = 3
i = 0
 
for feat in mylayer.getFeatures():
    id_mag = feat['id']
    geom = feat.geometry()
 
    i += 1
    if i > limit:
        break
 
    print(id_mag, geom.asPoint().x(), geom.asPoint().y(), i)

Pour marquer les magasins dont la zone a déjà été créée, ajoutez un champ iso dans votre couche de points de test, en integer, à 0. Nous le faisons passer à 1 à chaque zone isochrone créée, et ajoutons une condition pour ne passer que sur les magasins dont la zone n'a pas encore été créée :

with edit(mylayer):
    for feat in mylayer.getFeatures():
        if feat['iso'] == 0:
            id_mag = feat['id']
            geom = feat.geometry()
 
            i += 1
            if i > limit:
                break
 
            feat['iso'] = 1
            mylayer.updateFeature(feat)
 
            print(id_mag, geom.asPoint().x(), geom.asPoint().y(), i)

Maintenant, à la suite de la boucle, la zone isochrone, où nous remplaçons les coordonnées en dur par nos géométries, avec l'id des magasins en nom de fichier :

            body = {"locations":[[geom.asPoint().x(), geom.asPoint().y()]],"range":[900],"attributes":["area","reachfactor","total_pop"],"range_type":"time"}
            headers = {
                'Accept': 'application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8',
                'Authorization': 'YOUR-API-KEY',
                'Content-Type': 'application/json; charset=utf-8'
            }
            call = requests.post('https://api.openrouteservice.org/v2/isochrones/driving-car', json=body, headers=headers)
            #print(call.status_code, call.reason)
            #print(call.text)
 
            with open('C:/Users/Georges/Downloads/CoursQGIS/data/isochrones/'+id_mag+'.geoson', 'w', encoding='utf-8') as outfile:
                outfile.write(call.text)
 
            iface.addVectorLayer('C:/Users/Georges/Downloads/CoursQGIS/data/isochrones/'+id_mag+'.geoson', id_mag, 'ogr')

Mais nous n'avons aucun attribut pour identifier les zones isochrones par magasin. Et nous en aurons besoin par la suite.

Nous ajoutons donc un champ dans le fichier GEOJSON, que nous remplissons avec l'id des magasins.

            my_geojson = QgsProject.instance().mapLayersByName(id_mag)[0]
 
            pr = my_geojson.dataProvider()
            pr.addAttributes([QgsField("id_mag", QVariant.String)])
            my_geojson.updateFields()
 
            with edit(my_geojson):
                for feature in my_geojson.getFeatures():
                    feature['id_mag'] = id_mag
                    my_geojson.updateFeature(feature)

zones isochrones orsOK. Testez le code sur votre extraction de 10 magasins, si cela fonctionne, vous n'avez plus qu'à remplacer la variable mylayer et à augmenter la limit (n'oubliez pas de supprimer les zones précédemment apparues, à la fois dans QGIS mais aussi les fichiers GEOJSON dans votre machine, et de créer le champ iso dans la couche de vos magasins).

Code complet

Vous obtenez 308 zones isochrones à 15 minutes en voiture pour atteindre un magasin Décathlon.

Liens ou pièces jointes
Télécharger ce fichier (isochrones15m.zip)isochrones15m.zip[Les 308 zones isochrones fusionnées]979 Ko
Télécharger ce fichier (isochrones_ORS.txt)Code complet de création des zones isochrones avec le service ORS[code Python]2 Ko
Télécharger ce fichier (isochrones_ORS.zip)isochrones_ORS.zip[Les 308 fichiers GEOJSON des zones isochrones]786 Ko
Accéder à cette adresse URL (https://hg-map.fr/extern/data/OSM_shop_sport_fr.geojson)Export OSM des magasins de sports français le 27 décembre 2020[key=shop ; value=sport ; in=France]0 Ko