jeudi 3 décembre 2015

Corine Disco Cover

This post is about the making of an experimental video that dives into the land cover of Paris & its surroundings with a hint of RGB magic. 

You'll see the purpose of gridding, how to cross a vector and a raster layer in R. Finally we'll cover one of the latest functionnality of QGIS 2.12 : data-defined layer combinations in atlases.

If the world were square

do you prefer ice creams or sandwiches ?

Matrix is the first movie approaching grids
Gridding is a way to simplify the representation of data on a large scale. It can be a useful way to "resample" the vision of a territory if you work on bigger units. These units, usually squares, are comparable, on the contrary to administrative units. If you can omit the administrative units, gridding is a way to get an homogeneous view of your territory. The larger your area of interest will be, the bigger the squares from your grid you might configure.

hexagons look ecologic, triangles ecclesiastic

Also, you could prefer hexagonal units to square units for more harmony. Some prefer triangles. Anyway, the number of possible shapes are limited.

Land Cover of Paris & surroundings

I wanted to visualize the land cover of Ile-De-France width a grid. Ile-de-France is a region that includes Paris at its center. Precisely, I decided to study the repartition of urban , agricultural and natural (forests, gardens, etc...) areas, that is 3 variables over the whole area.

the best diagram I've ever made, even if pie charts are the worst

The question was : how to represent 3 variables at a time on each square unit ? One answer could have been "diagrams", that is pie charts, histograms on the map
But I found it cooler to use an RGB representation.
A Freemason way of seeing data

Let's suppose R means urban, G Natural and B Agricultural. If the color of a square approaches red, then it means urban; if it is purple, it means urban & agricultural areas dominate but not natural; if it is desaturated, it means the 3 types of cover are equally mixed.

The recipe

I remember a mushroom im my parents'garden had the same shape

For the land cover of Ile-de-France, we have a nice 2012 Corine Land Cover GeoTiff.

Laurent Manadou exploring data
I wondered if one could adopt a dynamic view that goes from the global view to the zonal one in a sort of "data diving".

beware of the logarithmic launching pad
I wondered what series of sizes to adopt. I decided to generate 100 images. 1km would be the minimum unit and we would reach the BIG square covering all the region, the width of Ile-De-France being precisely 154 451 km according to GÉOFLA. The distribution, as illustrated, will be logarithmic.

The same sensation appears when you dive head first in a municipal pool
Above is a GIF presenting the different calculation canvases.

Here is the video with land cover percentages encoded as colors, with reversed order, from the biggest to the smallest unit. The changing colors make it kind of animated dancefloor.


This illustration, that I had made for a GéoTribu post, illustrates the usual workflow I adopt, from production to design. I generated the distinct grids associated with the land cover percentage values with R. I designed all the layers with QGIS. With the same tool, I generated an atlas. With this atlas, I created a video with ffmpeg.

Technical details

The QGIS part may interest the QGIS fans as it uses a new QGIS 2.12 functionnality : data defined control over map layers and style presets

Generation : R

I created a function in R that generates a grid. The hack consists in polygonizing a raster layer, of which the resolution determinates the square size :
creerGrille = function(pol, size=50000) {
  r = raster(extend(extent(pol), size)); res(r) = size; r[]=1
  grille = rasterToPolygons(r)
  grille = grille[which(gIntersects(grille, pol, byid=T)), ]
  grille = grille[-which(gTouches(grille, reg, byid=T)), ]

The extract function crosses the vector grid and the 2012 CLC raster. The table function gives the number of pixels of each category :
  counts = extract(clc2, grille, 

The prop.table calculates the proportion of urban, natural and agricultural areas :
RGB = round(prop.table(counts[, 1:3], 1)*255)

Design : QGIS

color RGB code from columns, named "R", "G", and "B"
An expression defines the color of each square depending on its column values :

MultiQML plugin
I saved the QML style file, then used the multiQML plugin to apply it to the 99 other layers.

Data defined control over map layers and style presets
To get a static coverage layer, I duplicated my area of interest as many times as the number of pages (or layers) and assigned the square size value to the layer names. In the latest version of QGIS, you can generate an atlas with a list of layers on each page defined by an expression.

Also, I used some generative design tricks to get the animated halo effect around the IDF region.

Shapeburst fill and data-defined color

The color follows the chromatic color circle, covering all the rainbow colors :

riding the wave of generative design

sin wave shade distance

while a sin function defines the shade distance. This way, we get a "flame" effect with increasing then decreasing shade width. scale_linear(sin(scale_linear(@atlas_featurenumber,1,100,0,pi()*2)),0,1,5,10)

Video making: ffmpeg

Finally, this command line generates the video from images :
ffmpeg -framerate 25 -r 10 -i output_%d.jpg -vcodec mpeg4 -b 50000k -qscale:v 1 dancingVideo.avi

The code

The functions

The processing code


Images from The Noun Project : diver by Claire Jones, honey by Angela Horton, sandwich by Gareth Servant, biker by Les vieux garçons, ice cream by Rafaël Massé.

Aucun commentaire:

Enregistrer un commentaire