Площа кругового буфера - це монотонно зростаюча функція радіусу буфера (так чи інакше на планарній системі координат). Таким чином, проста стратегія пошуку може знайти радіус, R
такий, що площа буфера радіуса, R
обрізана до полігональної області, A
є (до деякого допуску) s
.
Найпростішим алгоритмом пошуку був би просто двійковий пошук. Почніть з двох радіусів, одного дуже малого та одного дуже великого, так що потрібна область знаходиться десь між площею обрізаних буферів цих радіусів. Тоді просто візьміть середню точку цих і обчисліть області буфера і з’ясуйте, чи потрібний радіус вище або нижче середини. Оновіть обмеження радіусу та повторюйте, поки не досягнете деякої толерантності до потрібної області.
Написання двійкового пошуку в Python та використання API ArcGIS Python звучить як хороший спосіб вчитися! Я впевнений, що робив це в R, років тому ...
Ось декілька код 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))
}
Використання:
Спочатку встановіть простий полігональний регіон Великобританії:
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)
Тепер визначте крапку:
p = SpatialPoints(coords=list(x=269042, y=235937), proj4string=CRS("+init=epsg:27700"))
Тоді ви просто:
b = buff_with_area(p, uk, 10000000000, 1, 10000)
Це список з двома компонентами, b
це буфер:
plot(b$b, col=2)
plot(uk, add=TRUE)
і він має потрібну область:
gArea(b$b)
[1] 1e+10
і r
є виходом з uniroot
, який включає значення радіусу буфера.
> b$r$root
[1] 63338.88
Так що в цьому випадку ширина буфера була трохи менше 64 км.
Єдине, з чим тут можна зіткнутися, - це нижнє та верхнє початкові значення - я думаю, ви можете інтуїти нижній радіус як, sqrt(A/pi)
а верхній не так важливий, оскільки алгоритм пошуку збільшуватиме його, поки він не захопить інтервал.
Алгоритм пошуку може вийти з ладу, якщо початковий максимальний радіус дійсно занадто великий, оскільки ви, можливо, буферизуєте весь ваш регіон з величезним радіусом, і в цьому випадку зміна радіусу не може змінити область ... Але розумні межі повинні зупинити це.