# Creating polygon outside buffer according to its area using R

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)
# }

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?

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)
}

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)
``````

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.