Zones isochrones
Rendez-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)
OK. 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).
Vous obtenez 308 zones isochrones à 15 minutes en voiture pour atteindre un magasin Décathlon.