Index de l'article

IGN

Petite parenthèse, un exemple d'utilisation de l'API isochrones de l'IGN !

Merci aux étudiants du master de géomatique CYU (Cergy) !

import requests
import time
from qgis.core import (QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, QgsField, QgsPointXY, QgsWkbTypes, QgsCoordinateTransform, QgsCoordinateReferenceSystem)
from PyQt5.QtCore import QVariant
 
base_url = "https://data.geopf.fr/navigation/isochrone"
 
# Temps de déplacement en minutes
tempsDeplacement = 15
 
# Direction de déplacement
directionDeplacement = "arrival"
 
# Sélectionne la couche active dans QGIS
input_layer = iface.activeLayer()
 
if not input_layer:
    raise Exception("Aucune couche active sélectionnée")
 
if input_layer.geometryType() != QgsWkbTypes.PointGeometry:
    raise Exception("La couche doit contenir des POINTS")
 
source_crs = input_layer.crs()
target_crs = QgsCoordinateReferenceSystem("EPSG:4326")
 
transform = None
if source_crs != target_crs:
    transform = QgsCoordinateTransform(source_crs, target_crs, QgsProject.instance())
    print("Reprojection activée :", source_crs.authid(), "EPSG:4326")
 
nomCouche = "Isochrones" + " " + str(tempsDeplacement) + " " + directionDeplacement
output_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", nomCouche, "memory")
provider = output_layer.dataProvider()
 
provider.addAttributes([
    QgsField("id_point", QVariant.Int),
    QgsField("minutes", QVariant.Int),
    QgsField("direction", QVariant.String)
])
 
output_layer.updateFields()
total = input_layer.featureCount()
batch = []
 
# ajout toutes les 50 features
batch_size = 50
for i, feat in enumerate(input_layer.getFeatures()):
 
    geom = feat.geometry()
 
    if not geom or geom.isEmpty():
        continue
 
    if geom.isMultipart():
        point = geom.asMultiPoint()[0]
    else:
        point = geom.asPoint()
 
    if transform:
        point = transform.transform(point)
 
    lon = point.x()
    lat = point.y()
 
    params = {
        "resource": "bdtopo-valhalla",
        "profile": "car",
        "costing": "auto",
        "costType": "time",
        "costValue": tempsDeplacement,
        "direction": directionDeplacement,
        "point": f"{lon},{lat}",
        "geometryFormat": "geojson",
        "timeUnit": "minute"
    }
 
    try:
        response = requests.get(base_url, params=params, timeout=30)
        response.raise_for_status()
        data = response.json()
 
        coords = data["geometry"]["coordinates"][0]
 
        polygon = QgsGeometry.fromPolygonXY(
            [[QgsPointXY(x, y) for x, y in coords]]
        )
 
        new_feat = QgsFeature()
        new_feat.setGeometry(polygon)
        new_feat.setAttributes([i, tempsDeplacement, directionDeplacement])
 
        batch.append(new_feat)
 
        # Ajout par paquet pour éviter surcharge mémoire
        if len(batch) >= batch_size:
            provider.addFeatures(batch)
            batch = []
 
        print(f"{i+1}/{total} traité")
 
        # anti rate-limit (2 req/sec max)
        time.sleep(0.5)
 
    except Exception as e:
        print(f"Erreur point {i+1} :", e)
 
# Ajouter le reste
if batch:
    provider.addFeatures(batch)
 
output_layer.updateExtents()
QgsProject.instance().addMapLayer(output_layer)
 
print("Traitement terminé")

 

Liens ou pièces jointes
Télécharger ce fichier (isochrones15m.zip)isochrones15m.zip[Les zones isochrones fusionnées]979 Ko
Télécharger ce fichier (isochrones_ORS.zip)isochrones_ORS.zip[Les 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