Skip to content

Instantly share code, notes, and snippets.

@ThomasG77
Last active June 16, 2023 17:22
Show Gist options
  • Save ThomasG77/8dafcac4cab52f5242b00c077430c08d to your computer and use it in GitHub Desktop.
Save ThomasG77/8dafcac4cab52f5242b00c077430c08d to your computer and use it in GitHub Desktop.

Sélectionner des parcelles selon l'étendue avec l'API Carto - Module Cadastre de l'IGN

Il faut prendre un GeoJSON en entrée du type Feature comme ci-dessous

{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"coordinates":[[[-1.5567700133586584,47.21868047390478],[-1.5567362349704865,47.21787748555562],[-1.5560156293505258,47.21776277194195],[-1.5554413967479377,47.21783924771219],[-1.5554301372852422,47.21858870442267],[-1.5558917752596528,47.218802832966105],[-1.5560494077386977,47.21878753809898],[-1.556398451085954,47.21872635858563],[-1.5567700133586584,47.21868047390478]]],"type":"Polygon"}}]}

Ensuite, il faut prendre le bloc après "geometry":

Ce qui est compliqué, c'est l'encodage de l'URL. Attention, ma solution est sous Bash et dépend d'un outil tiers nommé jq. Je vous recommande de passer par la solution Python alternative proposée après.

demo='{ "coordinates": [ [ [ -1.5567700133586584, 47.21868047390478 ], [ -1.5567362349704865, 47.21787748555562 ], [ -1.5560156293505258, 47.21776277194195 ], [ -1.5554413967479377, 47.21783924771219 ], [ -1.5554301372852422, 47.21858870442267 ], [ -1.5558917752596528, 47.218802832966105 ], [ -1.5560494077386977, 47.21878753809898 ], [ -1.556398451085954, 47.21872635858563 ], [ -1.5567700133586584, 47.21868047390478 ] ] ], "type": "Polygon" }'
encoded=$(printf %s $demo|jq -sRr @uri)
curl -X 'GET' \
  "https://apicarto.ign.fr/api/cadastre/parcelle?geom=${encoded}" \
  -H 'accept: application/json'

Solution en Python pour la portabilité

import json
import urllib.parse
import urllib.request

url = "https://apicarto.ign.fr/api/cadastre/parcelle"

feature_geojson = {"type":"Feature","properties":{},"geometry":{"coordinates":[[[-1.5567700133586584,47.21868047390478],[-1.5567362349704865,47.21787748555562],[-1.5560156293505258,47.21776277194195],[-1.5554413967479377,47.21783924771219],[-1.5554301372852422,47.21858870442267],[-1.5558917752596528,47.218802832966105],[-1.5560494077386977,47.21878753809898],[-1.556398451085954,47.21872635858563],[-1.5567700133586584,47.21868047390478]]],"type":"Polygon"}}
parameters = 'geom=' + urllib.parse.quote(json.dumps(feature_geojson.get('geometry')))

url_with_parameters = "%s?%s" % (url, parameters)
req = urllib.request.Request(url_with_parameters)
req.add_header('accept', 'application/json')
r = urllib.request.urlopen(req)
data = json.load(r)

with open('out.geojson', 'w') as outfile:
    json.dump(data, outfile)

Pour le besoin, si on veut un GeoJSON avec plusieurs zones pour sélectionner les parcelles chaque fois, il faut ensuite adapter. La solution dans la vraie vie, c'est vous avez votre GeoJSON en entrée. Vous bouclez sur chaque "Feature" pour récupérez leur géométrie, vous appelez l'API, vous stockez soit un fichier pour chaque zone qui sélectionne vos parcelles, soit vous stockez dans un seul fichier les parcelles de toutes les zones mais cela demande de pouvoir retracer quelle zone a sélectionnée quelle(s) parcelle(s).

Attention:

Il faut noter qu'il faut éviter d'utiliser des géométries complexes pour au moins ne pas rencontrer la limite d'un appel http GET https://stackoverflow.com/a/50510203. Si votre géométrie est trop complexe avec trop de points, vous risquez de voir votre géométrie coupée et le serveur ne rien retourné car il recevra un contenu coupé.

Il faut aussi éviter de prendre une zone trop large: si vous demandez toutes les parcelles d'un grande zone, c'est potentiellement des millions de points qui seront retournés et vous surchargerez le serveur (qui pourrait planter) et vous devrez gérer de la pagination pour obtenir toutes les parcelles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment