Getting started with happign

Paul Carteron

2022-01-19

Context

Since January 1, 2021, the French National Institute for Geographic and Forestry Information (IGN) has made its public data on French topography, infrastructure, and terrain freely available. The opening of IGN data under the Etalab 2.0 open license means free access and use for all.

Among the important data that are now open, we can mention the BD TOPO (3D modeling of the territory and its infrastructures), the BD ORTHO (departmental orthophotography), the BD Forêt and the RGE Alti (meshed digital terrain model that describes the French relief). This represents 100 terabytes of data.

To facilitate access to this data, IGN has implemented a set of APIs based on OGC standards. In other words, it is possible with correctly formatted URLs to access IGN data. In spite of a well supplied documentation, the use of APIs remains complex to set up. The happign package has been created to facilitate this, so let’s get started.

Load happign Library

You can install the released version of happign from CRAN with:

install.packages("happign")

And the development version from GitHub with:

# install.packages("devtools")
devtools::install_github("paul-carteron/happign")

We can load the happign package, and some additional packages we will need while we are here.

library(happign)
library(sf)
library(tmap)

The WFS, WMS service

happign use two data type from IGN web service :

More detailed information are available here for WMS and here for WFS.

To download data you need :

The layer name and API key can be directly retrieved on the IGN website in the expert web services (I recommend you at this point to go and have a look).

For example, if I take the first category “Administratif”, I see that the API key is “administratif” and the first layer name in WFS format is “ADMINEXPRESS-COG.LATEST:arrondissement”

With happign, there is no need to go through the website because all api keys are available by running the function get_apikeys().

get_apikeys()
#>  [1] "administratif" "adresse"       "agriculture"   "altimetrie"   
#>  [5] "cartes"        "cartovecto"    "clc"           "economie"     
#>  [9] "environnement" "geodesie"      "lambert93"     "ortho"        
#> [13] "orthohisto"    "parcellaire"   "satellite"     "sol"          
#> [17] "topographie"   "transports"

After choosing the API key containing our resource, you can access all layer names with get_layers_metadata().

Rq :

apikey <- get_apikeys()[1]
get_layers_metadata(apikey = apikey, data_type = "wfs")
#> # A tibble: 36 x 4
#>    keywords               name                              abstract  defaultcrs
#>    <chr>                  <chr>                             <chr>     <chr>     
#>  1 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:ar~ édition ~ EPSG::4326
#>  2 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:ar~ édition ~ EPSG::4326
#>  3 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:ca~ édition ~ EPSG::4326
#>  4 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:ch~ édition ~ EPSG::4326
#>  5 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:ch~ édition ~ EPSG::4326
#>  6 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:ch~ édition ~ EPSG::4326
#>  7 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:co~ édition ~ EPSG::4326
#>  8 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:co~ édition ~ EPSG::4326
#>  9 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:co~ édition ~ EPSG::4326
#> 10 Unités administratives ADMINEXPRESS-COG-CARTO.LATEST:de~ édition ~ EPSG::4326
#> # ... with 26 more rows

Downloading the data

WFS

For the example we will look at the beautiful town of Penmarch in France and we are going to get these borders.

The get_wfs() function connects to WFS service of the IGN that contain borders of the communes. It is also necessary to take a point inside penmarch so that the function detects all the shape that intersect this point.

penmarch_point <- st_sfc(st_point(c(-4.370, 47.800)), crs = 4326)
penmarch_borders <- get_wfs(shape = penmarch_point,
                            apikey = "administratif",
                            layer_name = "LIMITES_ADMINISTRATIVES_EXPRESS.LATEST:commune")
#> Request 1/1 downloading...

# Checking result
tm_shape(penmarch_borders) + # Borders of penmarch
   tm_polygons(alpha = 0, lwd = 2) +
tm_shape(penmarch_point) + # Point use to retrieve data
   tm_dots(col = "red", size = 2) +
   tm_add_legend(type = "symbol", label = "lat : -4.370, long : 47.800",
                 col = "red", size = 1) +
   tm_layout(main.title = "Penmarch borders from IGN",
             main.title.position = "center",
             legend.position = c("right", "bottom"),
             frame = FALSE)

It’s as simple as that! Now you have to rely on your curiosity to explore the multiple possibilities that IGN offers. For example, who has never wondered how many road junctions there are in Penmarch?

Spoiler : there are 220 of them

dikes <- get_wfs(shape = penmarch_borders,
                 apikey = get_apikeys()[6],
                 layer_name = "BDCARTO_BDD_WLD_WGS84G:noeud_routier")
#> Request 1/1 downloading...

# Checking result
tm_shape(penmarch_borders) + # Borders of penmarch
   tm_polygons(alpha = 0, lwd = 2) +
tm_shape(dikes) + # Point use to retrieve data
   tm_dots(col = "red") +
   tm_add_legend(type = "symbol", label = "Road junction", col = "red") +
   tm_layout(main.title = "Road nodes recorded by the IGN in Penmarch",
             main.title.position = "center",
             legend.position = c("right", "bottom"),
             frame = FALSE)

WMS raster

For raster, the process is the same but with the function get_wms_raster(). There’s plenty of elevation resources inside “altimetrie” category. The basic one is the Digital Elevation Model (DEM or MNT in French).

Rq :

apikey <- get_apikeys()[4]
layers_metadata <- get_layers_metadata("altimetrie", "wms")
dem_layer_name <- layers_metadata[2, "name"]

mnt <- get_wms_raster(shape = penmarch_borders,
                      apikey = apikey,
                      layer_name = dem_layer_name,
                      resolution = 25)
#> x cell_size : 24.873 [m]
#> y cell_size : 24.937 [m]
mnt[mnt < 0] <- NA # remove negative values in case of singularity
names(mnt) <- "Elevation [m]" # Rename raster ie the title legend

tm_shape(mnt) +
   tm_raster(colorNA = NULL) +
   tm_layout(title = "DEM of Penmarch", frame = FALSE)