Utilisation des APIs cartographiques de l’IGN et du service data.gouv.fr

L’institut National de l’Information Géographique et Forestière (IGN)est une mine d’informations et donc de data. Pour rendre ces données publiques et utilisables ils ont lancé un service d’APIs : https://apicarto.ign.fr/
Si l’on couple ça au service de recherche d’adresses de data.gouv.fr et un fond de carte on peut très rapidement avoir un outil performant pour travailler de manière ludique et intuitive.

Pour Limto (https://limto.io/), une solution d’estimation foncière, j’avais besoin de mettre en place un système de recherche de Plan Local d’Urbanisme (PLU). Ce document régissant les règles d’urbanisme pour une adresse donnée, il est nécessaire à cette application web.

D’un point de vue fonctionnalité, voici le cheminement :

Pour récapituler je vous fais une démo directement sur Limto, je saisis une adresse et j’attends que les APIs fassent leur travail et me présente :

On peut jouer avec la carte et cliquer sur différentes adresses qui se recherchent automatiquement très rapidement.

Pour les non développeurs, l’article s’arrête ici. Je voulais présenter simplement la puissance qu’offre la combinaison de différentes APIs disponibles gratuitement.

D’un point de vue développeur, voici la marche à suivre :

La première étape consiste à mettre en place un champ de recherche d’adresse, pour cela on a du HTML, je me sers de class “js-…” comme sélecteur JS/jQuery :

<input class="js-search ui-autocomplete-input" name="address" type="text" autocomplete="off">

Maintenant on rajoute du code JS/jQuery pour appliquer la recherche via l’API et un système d’autocomplete. L’API https://api-adresse.data.gouv.fr/search/ permet de rechercher une adresse textuelle, on récupère les coordonnées GPS (longitude, lattitude) :

$('.js-search').autocomplete({
source: function(request, response)
{
$.ajax({
url : "https://api-adresse.data.gouv.fr/search/",
dataType : 'json',
data : {
q: request.term,
autocomplete : 1
},
success: function(result)
{
response($.map(result.features, function(object)
{
return {
label: object.properties.label,
geometry: object.geometry
};
}));
}
});
},
select: function(event, ui)
{
$('.js-geometry').val(JSON.stringify(ui.item.geometry));
$('.js-longitude').val(ui.item.geometry.coordinates[0]);
$('.js-latitude').val(ui.item.geometry.coordinates[1]);
}
});

Une fois ces coordonnées récupérées, on peut récupérer le PLU, la zone dont dépend la parcelle et les délimitations de la zone :

currentRequestZoning = $.ajax({
timeout: 5000,
url : "https://apicarto.ign.fr/api/gpu/zone-urba/",
dataType : 'json',
data : {
geom: JSON.stringify(geometry),
},
beforeSend: function()
{
if(currentRequestZoning != null)
{
currentRequestZoning.abort();
}
$('.js-zoning-table').html(svg);
$('.js-zoning_file-table').html(svg);
},
success: function(result)
{
if (isEmpty(result.features))
{
$('.js-zoning-table').text('-');
$('.js-zoning').val('');
$('.js-zoning_file-table').text('-');
$('.js-zoning_file').val('');
}
else
{
var geojsonFeature = result.features[0];
var jsonLayer = L.geoJSON(geojsonFeature);
dataLayer.addLayer(jsonLayer);
map.flyToBounds([
[result.bbox[1], result.bbox[0]],
[result.bbox[3], result.bbox[2]]
]);
if (geojsonFeature.hasOwnProperty('properties') && geojsonFeature.properties.libelle)
{
$('.js-zoning').val(geojsonFeature.properties.libelle);
$('.js-zoning-table').html(geojsonFeature.properties.libelle);
}
else
{
$('.js-zoning').val('');
$('.js-zoning-table').html('-');
$('.js-zoning_file-table').text('-');
}
if (geojsonFeature.hasOwnProperty('properties') && geojsonFeature.properties.nomfic)
{
getDocument(geometry, geojsonFeature.properties.nomfic);
}
else
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').text('-');
}
}
},
error: function(xmlhttprequest, textstatus, message)
{
$('.js-zoning-table').text('-');
$('.js-zoning_file-table').text('-');
}
});

Voici les fonctions qui vont permettre de récupérer le document et son contenu :

function getZoningValue(geometry)
{
currentRequestZoning = $.ajax({
timeout: 5000,
url : "https://apicarto.ign.fr/api/gpu/zone-urba/",
dataType : 'json',
data : {
geom: JSON.stringify(geometry),
},
beforeSend: function()
{
if(currentRequestZoning != null)
{
currentRequestZoning.abort();
}
$('.js-zoning-table').html(svg);
$('.js-zoning_file-table').html(svg);
},
success: function(result)
{
if (isEmpty(result.features))
{
$('.js-zoning-table').text('-');
$('.js-zoning').val('');
$('.js-zoning_file-table').text('-');
$('.js-zoning_file').val('');
}
else
{
var geojsonFeature = result.features[0];
var jsonLayer = L.geoJSON(geojsonFeature);
dataLayer.addLayer(jsonLayer);
map.flyToBounds([
[result.bbox[1], result.bbox[0]],
[result.bbox[3], result.bbox[2]]
]);
if (geojsonFeature.hasOwnProperty('properties') && geojsonFeature.properties.libelle)
{
$('.js-zoning').val(geojsonFeature.properties.libelle);
$('.js-zoning-table').html(geojsonFeature.properties.libelle);
}
else
{
$('.js-zoning').val('');
$('.js-zoning-table').html('-');
$('.js-zoning_file-table').text('-');
}
if (geojsonFeature.hasOwnProperty('properties') && geojsonFeature.properties.nomfic)
{
getDocument(geometry, geojsonFeature.properties.nomfic);
}
else
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').text('-');
}
}
},
error: function(xmlhttprequest, textstatus, message)
{
$('.js-zoning-table').text('-');
$('.js-zoning_file-table').text('-');
}
});
}
var currentRequestDocument = null;function getDocument(geometry, filename)
{
currentRequestDocument = $.ajax({
timeout: 10000,
url : "https://apicarto.ign.fr/api/gpu/document/",
dataType : 'json',
data : {
geom: JSON.stringify(geometry),
},
beforeSend: function()
{
if(currentRequestDocument != null)
{
currentRequestDocument.abort();
}
},
success: function(result)
{
if (isEmpty(result.features))
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').text('-');
}
else
{
var geojsonFeature = result.features[0];
if (geojsonFeature.hasOwnProperty('properties') && geojsonFeature.properties.id)
{
getDocumentUrl(geojsonFeature.properties.id, filename);
}
else
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').text('-');
}
}
},
error: function(xmlhttprequest, textstatus, message)
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').text('-');
}
});
}
var currentRequestDocumentUrl = null;function getDocumentUrl(docId, filename)
{
currentRequestDocumentUrl = $.ajax({
timeout: 10000,
url : "https://www.geoportail-urbanisme.gouv.fr/api/document/"+docId+"/details",
dataType : 'json',
beforeSend: function()
{
if(currentRequestDocumentUrl != null)
{
currentRequestDocumentUrl.abort();
}
},
success: function(result)
{
if (result == "Aucun Document trouv\u00e9")
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').text('-');
}
else
{
if (result.hasOwnProperty('writingMaterials') && result.writingMaterials.hasOwnProperty(filename))
{
$('.js-zoning_file').val(result.writingMaterials[filename]);
$('.js-zoning_file-table').html('<a href="'+result.writingMaterials[filename]+'" target="_blank"><img src="{{ asset('images/Download-white.svg') }}" style="width:30px;" /></a>');
}
else if (result.hasOwnProperty('archiveUrl'))
{
$('.js-zoning_file').val(result.archiveUrl);
$('.js-zoning_file-table').html('<a href="'+result.archiveUrl+'" target="_blank"><img src="{{ asset('images/Download-white.svg') }}" style="width:30px;" /></a>');
}
else
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').html('-');
}
}
},
error: function(xmlhttprequest, textstatus, message)
{
$('.js-zoning_file').val('');
$('.js-zoning_file-table').text('-');
}
});
}

--

--

Développeur amoureux du monde extérieur

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store