Площа кругового буфера - це монотонно зростаюча функція радіусу буфера (так чи інакше на планарній системі координат). Таким чином, проста стратегія пошуку може знайти радіус, 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)а верхній не так важливий, оскільки алгоритм пошуку збільшуватиме його, поки він не захопить інтервал.
Алгоритм пошуку може вийти з ладу, якщо початковий максимальний радіус дійсно занадто великий, оскільки ви, можливо, буферизуєте весь ваш регіон з величезним радіусом, і в цьому випадку зміна радіусу не може змінити область ... Але розумні межі повинні зупинити це.