Die Fläche eines Kreispuffers ist eine monoton ansteigende Funktion des Pufferradius (auf einem planaren Koordinatensystem sowieso). Eine einfache Suchstrategie kann also einen Radius finden, R
so dass der Bereich des Puffers des Radius, der R
auf den polygonalen Bereich begrenzt A
ist, (bis zu einer gewissen Toleranz) ist s
.
Der einfachste Suchalgorithmus wäre nur eine binäre Suche. Beginnen Sie mit zwei Radien, einem sehr kleinen und einem sehr großen, so dass der gewünschte Bereich irgendwo zwischen dem Bereich der abgeschnittenen Puffer dieser Radien liegt. Nehmen Sie dann einfach den Mittelpunkt dieser und berechnen Sie die Pufferbereiche und stellen Sie fest, ob der gewünschte Radius über oder unter dem Mittelpunkt liegt. Aktualisieren Sie Ihre Radiusgrenzen und wiederholen Sie den Vorgang, bis Sie eine gewisse Toleranz für den gewünschten Bereich erreicht haben.
Das Schreiben einer binären Suche in Python und die Verwendung der ArcGIS Python-API klingt nach einer guten Lernmethode! Ich bin mir ziemlich sicher, dass ich das vor Jahren in R gemacht habe ...
Hier ist ein R-Code:
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))
}
Verwendungszweck:
Richten Sie zunächst eine einfache polygonale Region in Großbritannien ein:
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)
Definieren Sie nun einen Punkt:
p = SpatialPoints(coords=list(x=269042, y=235937), proj4string=CRS("+init=epsg:27700"))
Dann bist du einfach:
b = buff_with_area(p, uk, 10000000000, 1, 10000)
Dies ist eine Liste mit zwei Komponenten, b
ist der Puffer:
plot(b$b, col=2)
plot(uk, add=TRUE)
und es hat den richtigen Bereich:
gArea(b$b)
[1] 1e+10
und r
ist die Ausgabe von uniroot
, die den Pufferradiuswert enthält.
> b$r$root
[1] 63338.88
In diesem Fall lag die Pufferbreite also etwas unter 64 km.
Die einzigen Dinge, mit denen Sie hier herumspielen müssen, sind die unteren und oberen Anfangswerte - ich denke, Sie können einen unteren Radius als intuitiv verstehen, sqrt(A/pi)
und der obere ist nicht so wichtig, da der Suchalgorithmus ihn vergrößert, bis er das Intervall erfasst.
Der Suchalgorithmus schlägt möglicherweise fehl, wenn der anfängliche maximale Radius wirklich zu groß ist, da Sie möglicherweise Ihre gesamte Region mit einem großen Radius puffern. In diesem Fall ändert eine Änderung des Radius nicht den Bereich ... Aber sinnvolle Grenzen sollten dies verhindern.