Twórz bufory obszaru ograniczone linią brzegową

10

Próbuję użyć ArcGIS 10.2, aby utworzyć bufor punktów na podstawie wcześniej zdefiniowanego obszaru (np. 400 km kw.). Ponadto zderzaki niektórych punktów znajdują się blisko linii brzegowej, co wymaga, aby zderzaki zostały przycięte na linii brzegowej i nadal miały taką samą powierzchnię jak te znajdujące się w głębi lądu (400 km kw.).

Czy ktoś wie, jak można to zrobić za pomocą Konstruktora modeli lub Arcpy?

Mam ograniczone umiejętności korzystania z Arcpy i R, ale chętnie popracuję nad skryptami, aby znaleźć rozwiązanie tego problemu.

Proszę zobaczyć obraz poniżej pokazujący graficzną reprezentację tego, co próbuję osiągnąć

[1]

Funkeh-Monkeh
źródło
2
Czy byłbyś w stanie zamieścić obraz tego, co próbujesz opisać słowami?
PolyGeo
Jak zwiększysz te obszary, kiedy będziesz ciął? Zwiększając promień bufora?
Peter Horsbøll Møller

Odpowiedzi:

15

Obszar okrągłego bufora jest monotonicznie rosnącą funkcją promienia bufora (w każdym razie na płaskim układzie współrzędnych). Tak więc prosta strategia wyszukiwania może znaleźć taki promień R, że obszar bufora promienia Rprzyciętego do regionu wielokąta Awynosi (do pewnej tolerancji) s.

Najprostszym algorytmem wyszukiwania byłoby po prostu wyszukiwanie binarne. Zacznij od dwóch promieni, jednego bardzo małego i jednego bardzo dużego, tak aby żądany obszar znajdował się między obszarem przyciętych buforów tych promieni. Następnie po prostu weź środkowy punkt tych i oblicz obszary buforowe i dowiedz się, czy żądany promień jest powyżej czy poniżej środkowego punktu. Zaktualizuj granice promienia i powtarzaj, aż osiągniesz tolerancję żądanego obszaru.

Pisanie binarnego wyszukiwania w Pythonie i używanie ArcGIS Python API wydaje się dobrym sposobem na naukę! Jestem całkiem pewien, że zrobiłem to w R, lata temu ...

Oto kod 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))
}

Stosowanie:

Najpierw skonfiguruj prosty wieloboczny region Wielkiej Brytanii:

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)

Teraz zdefiniuj punkt:

p = SpatialPoints(coords=list(x=269042, y=235937), proj4string=CRS("+init=epsg:27700"))

Więc po prostu:

b = buff_with_area(p, uk, 10000000000, 1, 10000)

To jest lista z dwoma składnikami, bto bufor:

plot(b$b, col=2)
plot(uk, add=TRUE)

i ma odpowiedni obszar:

gArea(b$b)
[1] 1e+10

i rjest wyjściem uniroot, które zawiera wartość promienia bufora.

> b$r$root
[1] 63338.88

W tym przypadku szerokość bufora wynosiła nieco poniżej 64 km.

Jedynymi rzeczami, które można tutaj manipulować, są dolne i górne wartości początkowe - myślę, że można intuicyjnie ustalić niższy promień, ponieważ sqrt(A/pi)górna nie jest tak ważna, ponieważ algorytm wyszukiwania zwiększy ją, dopóki nie zarejestruje interwału.

Algorytm wyszukiwania może zawieść, jeśli początkowy maksymalny promień jest naprawdę zbyt duży, ponieważ możesz buforować cały region z dużym promieniem, w którym to przypadku zmiana promienia nie zmieni obszaru ... Ale rozsądne granice powinny temu zapobiec.

Spacedman
źródło
Jak to zrobiłeś w R? Zapomniałem wspomnieć, że mam pewne doświadczenie w R, więc nie miałbym nic przeciwko rozwiązaniu wykorzystującemu R.
Funkeh-Monkeh
rgeosPakiet i jego gBufferfunkcja, najprawdopodobniej ...
Spacedman
Właściwie to kłamię, zaimplementowałem coś takiego w Pythonie jako wtyczkę QGIS - buforowało wielokąty, dopóki buforowany poli nie był 2x (lub Nx) obszarem oryginalnego wielokąta. Jednak ten sam algorytm wyszukiwania.
Spacedman
+1. Zalety podejścia pokazanego w Rkodzie są następujące: (a) oddziela obliczenia GIS od logiki wyszukiwania i (b) wykorzystuje unirootzoptymalizowane i przetestowane algorytmy wyszukiwania (in ) - nie musisz go pisać samemu (i prawdopodobnie nie będzie to najbardziej wydajny).
whuber
Podejrzewam, że scipy implementuje podobne algorytmy wyszukiwania root w swoim module optymalizacji: docs.scipy.org/doc/scipy/reference/optimize.html (tak, uniroot cytuje Brenta, scipy ma funkcje Brenta)
Spacedman
1

Jest to prawie niemożliwe, ze względu na położenie punktów. Możesz tworzyć bufory o powierzchni 400 km 2 , ale punkty bliżej linii brzegowej zawsze będą miały mniejszy obszar w porównaniu do tych położonych dalej (> 400 km 2 ).

Jedyne, co możesz zrobić, to wykonać analizę buforów punktów i następnie przyciąć utworzone bufory za pomocą funkcji linii brzegowej.

Stefan
źródło
2
Może nie być to niemożliwe , ale może to być problem NP Complete, który może wprowadzić w błąd rozwiązanie. Wykończenie obszaru jest wyzwaniem (może zająć kilka iteracji, aby się zbliżyć).
Vince
3
To nie jest niemożliwe, a nawet nie jest trudne!
Spacedman