Skip to contents
library(happign)
#> Please make sure you have an internet connection.
#> Use happign::get_last_news() to display latest geoservice news.
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tmap); tmap_mode("view"); tmap_options(check.and.fix = TRUE)
#> Breaking News: tmap 3.x is retiring. Please test v4, e.g. with
#> remotes::install_github('r-tmap/tmap')
#> tmap mode set to interactive viewing
library(sf)
#> Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE

Presentation

APIs carto were developed to automatically retrieve certain spatial information required in administrative forms. The main advantage of these APIs is that they can be queried without spatial data. To do this with get_wfs, you would have to use an ECQL query with the ecql_filter argument which can be tricky.

happign implements APIs carto through get_apicarto_* functions.

API carto cadastre

Documentation : https://apicarto.ign.fr/api/doc/cadastre

The API carto cadastre provides following informations :

  • the boundaries of a town (type = "commune")
  • the parcel sections or divisions (type = "section" or type = "division")
  • the cadastral parcels (type = "cadastre")
  • information on non-vectorized parcels (type = "localisant")

At least three parameters must be set :

  • x : An indication about the location. Could be a shape, an insee code or a departement code
  • type : What service do you want to use? (see above)
  • source : The data source "PCI" for “Parcellaire Express” or "BDP" for “BD Parcellaire”. The BD Parcellaire product is a historical product that is no longer updated. It is therefore strongly recommended to use the Parcellaire Express product which is updated every six months.

All other parameters are used to refine the query.

Usage

We’ll start with a simple example : retrieve borders of multiple town. Because get_apicaro_cadastre is a vectorized function, it’s possible to set multiple insee code. If you do not know insee codes, you can consult existing codes from the internal dataframe cog_2023.

# all town starting with "Plou"
plou_insee_code <- cog_2023[startsWith(cog_2023$LIBELLE, "Plou"), "COM"]
plou_borders <- get_apicarto_cadastre(plou_insee_code, type = "commune")

# result
tm_shape(plou_borders)+
   tm_borders(col = "black")

Another common case consists in recovering the geometry of the parcels from a “cadastral matrix extract”. The latter lists for each owner all his built and unbuilt properties owned in a commune. It is a private information and to obtain one it is necessary to ask for an extract top the Center of the Land taxes. In this example a false simplified cadastral matrix is used.

cad_mat <- data.frame(CODE_DEP = rep("29", 10),
                      CODE_COM = rep("158", 10),
                      SECTION = rep(c("AX", "AV"), each = 5),
                      N_PARC = c("0001","0002","0003","0004","0005",
                                 "0116","0117","0118","0119","0120"))
                               
parcels <- get_apicarto_cadastre(paste0(cad_mat$CODE_DEP, cad_mat$CODE_COM),
                                 section = cad_mat$SECTION,
                                 numero = cad_mat$N_PARC)


tm_shape(parcels)+
   tm_borders(col = "black")

API carto RPG

Documentation : https://apicarto.ign.fr/api/doc/rpg

The graphic parcel register (RPG) is a geographic information system (GIS) allowing the identification of agricultural parcels. It is useful to the authorities working on agricultural development and land management (community of municipalities, watershed syndicate, etc.) when they need information on the characterization and evolution of the agricultural area.

Usage

Let’s start by finding RPG from Penmarc’h town for years 2015. One of the limitations of the API carto RPG is that complex geometries, such as the precise contours of a commune, are not supported. To get around this problem, get_apicarto_rpg allows to simplify the shape with the dTolerance parameter. The method is illustrated below.

penmarch  <- get_apicarto_cadastre("29158", type = "commune")
rpg <- get_apicarto_rpg(penmarch, annee = 2015, dTolerance = 10) 

# plot result
tm_shape(penmarch)+
   tm_borders()+
tm_shape(rpg)+
   tm_polygons("code_cultu")

The function is vectorized, which mean that query several years at the same time is possible. However, since 2014 the format of the RPG has changed. The function will therefore return a list with the parcels before and after 2014. Below an example showing evolution of RPG from 2013 to 2016.

all_years_rpg <- get_apicarto_rpg(penmarch, annee = 2013:2016, dTolerance = 10) 
#> Warning: Data before and after 2014 are different, returning as list.

# plot evolution of rpg since 2010
tm_shape(penmarch)+
   tm_borders()+
tm_shape(all_years_rpg[["2013"]])+
   tm_polygons(group = "2013")+
tm_shape(all_years_rpg[["2014"]])+
   tm_polygons(group = "2014")+
tm_shape(all_years_rpg[["2015"]])+
   tm_polygons(group = "2015")+
tm_shape(all_years_rpg[["2016"]])+
   tm_polygons(group = "2016")

It is also possible to query from the culture code. Again, there are changes before and after 2014; The user documentation explains:

“For RPG version 1 (before 2014) the value to be entered corresponds to the number contained in the CODE_CULTU attribute of the ILOTS_ANONYMS class with a value ranging from 01 to 28 (0 is mandatory for values less than 10). The list of crop codes can be consulted in the content description of the RPG version 1.0. For the RPG version 2 the value to be entered corresponds to the trigram contained in the attribute CODE_CULTU of the class PARCELLES_GRAPHIQUES by respecting the case (upper case). The list of crop codes can be found in the content description of the GPR version 2.0.

For this example, let’s find all potatoes, carrots and leeks.

rpg <- get_apicarto_rpg(penmarch,
                        annee = 2020,
                        code_cultu = c("PTC", "CAR", "POR"),
                        dTolerance = 10) 

tm_shape(rpg)+
   tm_polygons("code_cultu",
               palette = c("orange", "springgreen", "gold"))
#> Warning: The shape rpg is invalid. See sf::st_is_valid

API carto urbanism

Documentation : https://apicarto.ign.fr/api/doc/gpu

The API carto GPU allows you to obtain urban planning information intersecting a geometry. Beware, not all municipalities are in the geoportal of urbanism!

RNU

First of all, you can check if a commune is under the National Urbanism Regulation from is insee code. The RNU fully apply in communes that have neither a local map nor a local urban plan (PLU, PLUi) nor a document in replacement of a PLU.

is_rnu <- get_apicarto_gpu("29158", ressource = "municipality")
#> Features downloaded : 1
is_rnu$is_rnu 
#> [1] FALSE

# Penmarch is under the RNU and therefore has a document of urbanism

is_rnu <- get_apicarto_gpu("23004", ressource = "municipality")
#> Features downloaded : 1
is_rnu$is_rnu 
#> [1] TRUE

# Anzeme is under the RNU and therefore has a town planning document

PLU, PLUi, POS, CC, PSMV

Urban planning documents can take several forms: * PLU : Local Urbanism Plan * PLUi : Intercommunal Local Urbanism Plan * POS : Land use plan * PSMV : Plan of Safeguarding and Development * CC : Communal map

The first step is to find out if urban planning document are available if it is the case, find the document’s partition i.e. its ID :

# find out if documents are available
penmarch <- get_apicarto_cadastre("29158", "commune")
doc <- get_apicarto_gpu(penmarch, "document", dTolerance = 10) # complex geometry handle with dTolerance
# Because NULL is returned, it means that penmarch dont have available urban planning document

lanildut <- get_apicarto_cadastre("29112", "commune")
doc <- get_apicarto_gpu(lanildut, "document",  dTolerance = 10) # complex geometry handle with dTolerance
# Six documents are available inside the geometry.
# In reality, only one document exists for the commune of lanildut but because borders are not coherent with urban planning document, several communes are returned.

partition <- doc |> 
   filter(grid_title == "LANILDUT") |> 
   pull(partition)

Now that the partition is recovered, it is possible to obtain several resources for a specific document. The different resources available are specified in the documentation of the function ?get_apicarto_gpu()

zone_urba <- get_apicarto_gpu(partition, ressource = "zone-urba")

# click on polygon for legend
tm_shape(zone_urba)+
   tm_polygons("libelong", legend.show = FALSE)

Because get_apicarto_gpu is vectorized, many resources can be returned at the same time. This allows to identify all the prescriptions at once for example :

ressources <- c("prescription-lin",
                "prescription-pct")
prescriptions <- get_apicarto_gpu(partition,
                                  ressource = ressources,
                                  dTolerance = 10)
#> Warning: Resources have different attributes and cannot be joined. List is
#> returned.

tm_shape(prescriptions[[1]])+
   tm_lines("libelle", legend.col.show = FALSE, lwd = 2)+
tm_shape(prescriptions[[2]])+
   tm_dots("libelle",  legend.show = FALSE, size = 0.1)

API carto “Appellations viticoles”

Documentation : https://apicarto.ign.fr/api/doc/aoc

This api returns from a shape : * “Appellation d’origine contrôlée” (AOC) * Protected geographical indication areas (IGP) * Wine growing areas without geographical indication (VSIG)

This function is quite simple to use, only shape is needed.

viticole <- get_apicarto_viticole(penmarch, dTolerance = 10)

# plot result
tm_shape(viticole)+
   tm_borders()

Let’s find how many wine appellations are there in Finistère, France (spoiler, there only VSIG ie wines without geographical indication, we prefer microbreweries).

finistere <- get_wfs(penmarch,
                    "LIMITES_ADMINISTRATIVES_EXPRESS.LATEST:departement")

# finistere borders are quite complex, and dTolerance cant be used. In this case convex hull of shape 
# can be used with intersection of the results 
convex_finistere <- st_convex_hull(finistere)
viticole <- get_apicarto_viticole(convex_finistere) |> 
   st_intersection(finistere)
#> Warning: attribute variables are assumed to be spatially constant throughout
#> all geometries

# plot result
tm_shape(viticole)+
   tm_polygons("appellation")+
tm_shape(finistere)+
   tm_borders()