[GRASS-user] Obtain land use within 50 km buffers around vector points

Moritz Lennert mlennert at club.worldonline.be
Thu Jun 1 07:41:50 PDT 2017


On 01/06/17 13:07, Johannes Radinger wrote:
> Hi,
>
> I have a vector map of 50 km buffers surrounding 4000 points in entire
> Europe. The single buffers where calculated using v.buffer with the -t
> flag. Thus, many of my buffers overlap (i.e. geometries of buffers are
> not merged but split up). Now, I want to obtain for each 50 km buffer
> the underlying land use (from a CORINE land use map). For example, I'd
> like to know the relative share of "forest" within each buffer and I
> want to update this information in the attribute table of the vector
> buffer map.
>
> So what would be the GRASS way for such type of analysis involving
> overlapping buffers? Do I need to loop over the single buffers, extract
> each buffer, and run something like v.rast.stats using maps for the
> single land use classes as raster input?

Ideally one should be able to run v.rast.stats directly on the 
overlapping buffers, and get the results by cat number, but this does 
not work (cf http://trac.osgeo.org/grass/ticket/3300) because of the way 
v.rast.stats works.

Currently, the best way I see is to create a correspondance table 
between the pieces and the original cat values. You can get that by running

v.category buffers op=add layer=2 out=buffers_2_layers
v.category buffers_2_layers layers=1,2 option=print

and massaging the results a bit to create a new database table out that 
(would be a nice enhancement to v.buffer if it created a second layer 
and this lookup table as an option). Here's a very raw version of how 
this could look like in Python. The correspondance_table would then have 
to be written to the database:

correspondance_table = []
for line in g.read_command('v.category', input_='buffers_2layers', 
layer='1,2', option='print').splitlines():
      layers=line.split('|')...     l1 = layers[0].split('/')
      l2 = layers[1]
      for cat in l1:
              correspondance_table.append((cat, l2))

Then just run v.rast.stats once per class (each class raster can just be 
a reclass of the original with classnum = 1\n* = NULL") on layer 2 of 
the entire vector buffer map. Thus you will get the stats per piece of 
buffer.

To calculate total values per buffer you can then use using the 
correspondance table, e.g. something like this (warning: untested) to 
get the total number of pixels for a given class in your entire 50km 
buffers:

db.exectute sql="UPDATE buffer_layer_1_table SET nb_class_X = t.class_X 
FROM (SELECT l1.cat, sum(l2.class_X) as class_X FROM 
buffer_layer_1_table l1 JOIN correspondance_table c ON (l1.cat = 
c.l1_cat) JOIN buffer_layer_2_table l2 ON (l2.cat = c.l1_cat)
GROUP BY l1.cat) t WHERE buffer_layer_1_table.cat = t.cat"

It would be a nice add-on to have a module that calculates shares of 
raster classes per polygon, with either the user providing an optional 
correspondance_table and layers info if the polygons are overlapping or 
the option to just indicate that polygons are overlapping and the module 
would do all this internally.

Moritz


More information about the grass-user mailing list