L'area di un buffer circolare è una funzione monotonicamente crescente del raggio del buffer (su un sistema di coordinate planare comunque). Quindi una semplice strategia di ricerca può trovare un raggio R
tale che l'area del buffer del raggio R
tagliato nella regione poligonale A
sia (fino a una certa tolleranza) s
.
L'algoritmo di ricerca più semplice sarebbe solo una ricerca binaria. Inizia con due raggi, uno molto piccolo e uno molto grande, in modo tale che l'area desiderata si trovi da qualche parte tra l'area dei buffer troncati di quei raggi. Quindi prendi solo il punto medio di quelle e calcola le aree del buffer, e scopri se il raggio che vuoi è sopra o sotto il punto medio. Aggiorna i tuoi limiti di raggio e ripeti fino ad arrivare entro una certa tolleranza dell'area desiderata.
Scrivere una ricerca binaria in Python e usare l'API ArcGIS Python sembra un buon modo per imparare! Sono abbastanza sicuro di averlo fatto in R, anni fa ...
Ecco un po 'di codice 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:
Innanzitutto imposta una semplice regione poligonale nel Regno Unito:
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)
Ora definisci un punto:
p = SpatialPoints(coords=list(x=269042, y=235937), proj4string=CRS("+init=epsg:27700"))
Quindi devi solo:
b = buff_with_area(p, uk, 10000000000, 1, 10000)
Questa è una lista con due componenti, b
è il buffer:
plot(b$b, col=2)
plot(uk, add=TRUE)
e ha l'area giusta:
gArea(b$b)
[1] 1e+10
ed r
è l'output di uniroot
, che include il valore del raggio del buffer.
> b$r$root
[1] 63338.88
Quindi in questo caso la larghezza del buffer era leggermente inferiore a 64 km.
Le uniche cose con cui armeggiare qui sono i valori iniziali inferiore e superiore - immagino che tu possa intuire un raggio inferiore in quanto sqrt(A/pi)
la parte superiore non è così importante in quanto l'algoritmo di ricerca lo aumenterà fino a quando non acquisirà l'intervallo.
L'algoritmo di ricerca potrebbe non riuscire se il raggio massimo iniziale è davvero troppo grande, poiché potresti bufferizzare l'intera regione con un raggio enorme, nel qual caso la modifica del raggio non cambierà l'area ... Ma limiti sensibili dovrebbero impedire che ciò accada.