Here is my solution. Guessing the required bufferwidth on the perimeter gives more accurate estimates and will require less steps.

abuff <- function(spgeom, ratio = 1.1, precision = 0.0001, maxsteps = 20){
    require(rgeos)
    spgeom.area <- gArea(spgeom)
    spgeom.perimeter <- gLength(spgeom)
    buffer.width <- (ratio - 1) * spgeom.area / spgeom.perimeter
    buffered.spgeom <- gBuffer(spgeom, width = buffer.width)
    achieved.precision <- gArea(buffered.spgeom) / spgeom.area - ratio
    steps <- 1
    while(abs(achieved.precision) > precision & steps < maxsteps){
      buffered.perimeter <- gLength(buffered.spgeom)
      buffer.width <- buffer.width - achieved.precision * spgeom.area / buffered.perimeter
      buffered.spgeom <- gBuffer(spgeom, width = buffer.width)
      achieved.precision <- gArea(buffered.spgeom) / spgeom.area - ratio
      steps <- steps + 1
    }
    if(steps == maxsteps & abs(achieved.precision) > precision){
      warning("Required precision not reached after ", maxsteps, " steps. Achieved precision = ", achieved.precision)
    }
    return(buffered.spgeom)
}

https://gist.github.com/ThierryO/03c496c44db1a3c349cf

ir. Thierry Onkelinx
Instituut voor natuur- en bosonderzoek / Research Institute for Nature and Forest
team Biometrie & Kwaliteitszorg / team Biometrics & Quality Assurance
Kliniekstraat 25
1070 Anderlecht
Belgium
+ 32 2 525 02 51
+ 32 54 43 61 85
Thierry.Onkelinx@inbo.be
www.inbo.be

To call in the statistician after the experiment is done may be no more than asking him to perform a post-mortem examination: he may be able to say what the experiment died of.
~ Sir Ronald Aylmer Fisher

The plural of anecdote is not data.
~ Roger Brinner

The combination of some data and an aching desire for an answer does not ensure that a reasonable answer can be extracted from a given body of data.
~ John Tukey


-----Oorspronkelijk bericht-----
Van: r-sig-geo-bounces@r-project.org [mailto:r-sig-geo-bounces@r-project.org] Namens Barry Rowlingson
Verzonden: woensdag 28 mei 2014 14:39
Aan: Julie Lee-Yaw
CC: r-sig-geo@r-project.org
Onderwerp: Re: [R-sig-Geo] How to buffer a polygon by area

On Wed, May 28, 2014 at 11:37 AM, Julie Lee-Yaw <julleeyaw@yahoo.ca<mailto:julleeyaw@yahoo.ca>> wrote:
> Hello,
> Can anyone tell me how to buffer a polygon by area?
> I have a simple (no-holes and only one feature) polygon shapefile in an equal area projection and I need to buffer it to extend the boundaries so that the resulting polygon is 10% bigger by area. I know how to buffer by a fixed distance using the rgeos package but I will have to repeat this process across many different shapefiles that are of different sizes and a fixed buffer does not make sense in my case.
> Thanks in advance for the help!

 Since the area of a buffered feature must be increasing with increasing buffer width I think you could use a binary search algorithm on the buffer width. This might require doing five or six buffers on each feature until you get to your required accuracy.

Here's something:

abuff <- function(f, percent, precision, maxsteps = 20){
    require(rgeos)
    A0 = gArea(f)

    targetA = A0 + A0 * (percent/100)
    e = bbox(f)
    w0 = 0
    w2 = diff(e[1,])/10 # initial w

    ## initial expansion until we pass the solution:

    repeat{
        b1 = gBuffer(f, width=w2)
        if(gArea(b1) < targetA){
            w2 = w2 * 2
        }else{
            break
        }
    }
    w1 = (w0 + w2)/2

    ## solution is between w0 and w2

    steps = 1

    repeat{
        b = gBuffer(f, width=w1)
        A = gArea(b)
        if(abs(100*(A-targetA)/targetA) < precision){
            return(list(steps = steps, poly = b, target=targetA))
        }
        if(A < targetA){
            w0 = w1
            w1 = (w1+w2)/2
        }
        if(A > targetA){
            w2 = w1
            w1 = (w2+w0)/2
        }
        steps = steps + 1
        if(steps > maxsteps){
            return(NA)
        }
    }
}

Sample usage is, given 'london' as a single row spatial polygons data frame:

 > lbuff = abuff(london, 10, .5)

 - for a 10% area increase to a 0.5% precision

 > lbuff$steps
[1] 6

 - it took 6 steps, so had to compute 6 buffers.

 > plot(lbuff$poly)
 > plot(london,add=TRUE)

 - plots the buffer and the source.

 > lbuff$target
[1] 1766883778
 > gArea(lbuff$poly)
[1] 1768395765

The target element is the area we were trying to find, and the next line computes the area of the result. If you want more accuracy, increase the precision at the expense of needing to do more buffers.

I've put this function in a gist if anyone wants to improve it:

https://gist.github.com/barryrowlingson/d1d21c537777cfda8178

Barry

_______________________________________________
R-sig-Geo mailing list
R-sig-Geo@r-project.org<mailto:R-sig-Geo@r-project.org>
https://stat.ethz.ch/mailman/listinfo/r-sig-geo

* * * * * * * * * * * * * D I S C L A I M E R * * * * * * * * * * * * *
Dit bericht en eventuele bijlagen geven enkel de visie van de schrijver weer en binden het INBO onder geen enkel beding, zolang dit bericht niet bevestigd is door een geldig ondertekend document.
The views expressed in this message and any annex are purely those of the writer and may not be regarded as stating an official position of INBO, as long as the message is not confirmed by a duly signed document.

	[[alternative HTML version deleted]]

