TransWikia.com

Creating polygon outside buffer according to its area using R

Geographic Information Systems Asked by Wei Liao on May 10, 2021

I have a lot of polygons (shapefile) and need to creat their own buffer according to the area of each polygons,despite I have found some infomation in Creating OUTSIDE_ONLY buffer around polygon using R?.

# create basic function
outerBuffer<-function(x, dist){
  buff<-buffer(x, width =dist - 1, dissolve = F)
  e<-erase(buff,x)
  return(e)
}

library(maptools)  
library(rgdal) 
# create data
p1 = shapefile('42gp.shp')

# apply function, create only outside buffer
a2<-outerBuffer(p1,500)

# highlight isobath with the buffer and add outline
plot(buf, outline=FALSE, n = 10, col = 2, lwd=.4)
plot(buf, lwd = 0.7, fg = 2)
# }

# tradaaa ! :)
plot(a2, col = "white", main= "Outer buffer only")  

What can I write the R script for creating their own buffer according to the area of each polygons?

enter image description here

One Answer

I don't think you can easily compute the required buffer distance to return a buffer of a given area, except for simple figures like squares and circles.

The solution will depend on the fact that the buffer area always increases with buffer width (it is "monotone increasing"). Write a function that takes a polygon and a buffer size and returns the difference between the ring area and the area of the polygon. Your problem is then finding a buffer width where this function returns zero, which you can do with the uniroot function.

So in full you need these three functions:

outerBuffer<-function(x, dist){
    ## I don't udnerstand why you had "dist-1" here:
    buff<-buffer(x, width =dist, dissolve = F)
    e<-erase(buff,x)
    return(e)
}

areadiff <- function(dist, x){
    area(x)-area(outerBuffer(x, dist))
}

matchAreaBuff <- function(shp, bufferarea,
                          min=0.000001, max=10*sqrt(area(shp))){
    zerofind = uniroot(areadiff, c(min, max), x=shp)
    return(list(
        buffer = outerBuffer(shp, zerofind$root),
        root = zerofind
    ))
        
}

Then for some single shape shp you can do:

Get a buffer with the area equal to the area of shp:

> matchedbuffer = matchAreaBuff(shp, area(shp))

Plot the buffer and the original polygon:

> plot(matchedbuffer$buffer)
> plot(shp, add=TRUE, col="red")

Check the areas match:

> area(shp)
[1] 0.1416047
> area(matchedbuffer$buffer)
[1] 0.1416076

The buffer width was:

> matchedbuffer$root$root
[1] 0.06890648

The other parts of matchedbuffer$root are the output from uniroot and will tell you if the process converged well and the precision.

Note you may have to change the min and max parameters if your shape is on a wildly different scale to mine, or there might be some extra parameters to uniroot that let it search for an interval that has a zero crossing in it.

Answered by Spacedman on May 10, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP