L'aire d'un tampon circulaire est une fonction monotone augmentant le rayon du tampon (sur un système de coordonnées planaires de toute façon). Ainsi, une stratégie de recherche simple peut trouver un rayon R
tel que la zone du tampon de rayon R
découpée dans la région polygonale A
est (jusqu'à une certaine tolérance) s
.
L'algorithme de recherche le plus simple serait simplement une recherche binaire. Commencez avec deux rayons, un très petit et un très grand, de sorte que la zone souhaitée se situe quelque part entre la zone des tampons écrêtés de ces rayons. Ensuite, prenez simplement le milieu de celles-ci et calculez les zones tampons, et déterminez si le rayon souhaité est au-dessus ou en dessous du point médian. Mettez à jour vos limites de rayon et répétez jusqu'à ce que vous atteigniez une certaine tolérance de la zone souhaitée.
Écrire une recherche binaire en Python et utiliser l'API ArcGIS Python semble être un bon moyen d'apprendre! Je suis presque sûr d'avoir fait ça dans R, il y a des années ...
Voici un code 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))
}
Usage:
Configurez d'abord une simple région polygonale britannique:
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)
Définissez maintenant un point:
p = SpatialPoints(coords=list(x=269042, y=235937), proj4string=CRS("+init=epsg:27700"))
Ensuite, vous venez de:
b = buff_with_area(p, uk, 10000000000, 1, 10000)
Ceci est une liste avec deux composants, b
est le tampon:
plot(b$b, col=2)
plot(uk, add=TRUE)
et il a la bonne zone:
gArea(b$b)
[1] 1e+10
et r
est la sortie de uniroot
, qui inclut la valeur du rayon du tampon.
> b$r$root
[1] 63338.88
Dans ce cas, la largeur du tampon était donc un peu moins de 64 km.
Les seules choses à manipuler ici sont les valeurs initiales inférieures et supérieures - je suppose que vous pouvez intuitivement un rayon inférieur sqrt(A/pi)
et la supérieure n'est pas si importante que l'algorithme de recherche l'augmentera jusqu'à ce qu'il capture l'intervalle.
L'algorithme de recherche peut échouer si le rayon max initial est vraiment trop grand, car vous pouvez tamponner toute votre région avec un rayon énorme, auquel cas le changement de rayon ne changera pas la zone ... Mais des limites raisonnables devraient empêcher cela de se produire.