0

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

1 Answer 1

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.