A área de um buffer circular é uma função monotonicamente crescente do raio do buffer (em um sistema de coordenadas planas de qualquer maneira). Portanto, uma estratégia de pesquisa simples pode encontrar um raio R
tal que a área do buffer do raio R
cortado na região poligonal A
seja (até alguma tolerância) s
.
O algoritmo de pesquisa mais simples seria apenas uma pesquisa binária. Comece com dois raios, um muito pequeno e um muito grande, de modo que a área desejada esteja em algum lugar entre a área dos buffers cortados desses raios. Depois, pegue o ponto médio desses pontos e calcule as áreas de buffer e descubra se o raio desejado está acima ou abaixo do ponto médio. Atualize seus limites de raio e repita até obter alguma tolerância na área desejada.
Escrever uma pesquisa binária em Python e usar a API do ArcGIS Python parece uma boa maneira de aprender! Tenho certeza de que fiz isso em R, anos atrás ...
Aqui está um código R:
cropareabuff <- function(pt, region, target){
f = function(r){
b = rgeos::gBuffer(pt, width=r)
return(gArea(gIntersection(b, region)) - target)
}
f
}
buff_with_area <- function(pt, region, target, lower, upper){
f = cropareabuff(pt, region, target)
r = uniroot(f, lower=lower, upper=upper, extendInt="upX")
list(r=r, b=gIntersection(rgeos::gBuffer(pt, width=r$root), region))
}
Uso:
Primeiro, configure uma região poligonal simples do Reino Unido:
library(raster); library(rgeos); library(rgdal)
uk = getData("GADM", country="GBR", level=0)
uk = spTransform(uk,CRS("+init=epsg:27700"))
uk = gSimplify(uk, tol=1000)
Agora defina um ponto:
p = SpatialPoints(coords=list(x=269042, y=235937), proj4string=CRS("+init=epsg:27700"))
Então você apenas:
b = buff_with_area(p, uk, 10000000000, 1, 10000)
Esta é uma lista com dois componentes, b
é o buffer:
plot(b$b, col=2)
plot(uk, add=TRUE)
e tem a área correta:
gArea(b$b)
[1] 1e+10
e r
é a saída de uniroot
, que inclui o valor do raio do buffer.
> b$r$root
[1] 63338.88
Portanto, neste caso, a largura do buffer era um pouco abaixo dos 64 km.
As únicas coisas a se mexer aqui são os valores iniciais inferior e superior - acho que você pode intuir um raio mais baixo sqrt(A/pi)
e o superior não é tão importante quanto o algoritmo de busca aumentará até capturar o intervalo.
O algoritmo de pesquisa pode falhar se o raio máximo inicial for realmente muito grande, pois você pode estar protegendo toda a região com um raio enorme; nesse caso, alterar o raio não mudará a área ... Mas limites sensíveis devem impedir que isso aconteça.