Crea buffer di area limitati da una linea costiera


10

Sto cercando di utilizzare ArcGIS 10.2 per creare un buffer di punti basato su un'area predefinita (ad esempio 400 kmq). Inoltre, i buffer di alcuni dei punti sono vicini alla costa che richiede che i buffer siano tagliati sulla costa e abbiano ancora la stessa area di quelli interni (400 kmq).

Qualcuno sa come si potrebbe fare con Model Builder o Arcpy?

Ho competenze limitate con Arcpy e R, ma sarei felice di lavorare su alcuni script per ottenere una soluzione per questo.

Si prega di vedere l'immagine qui sotto che mostra una rappresentazione grafica di ciò che sto cercando di ottenere

[1]


2
Saresti in grado di includere un'immagine di ciò che stai cercando di descrivere a parole?
PolyGeo

Come ingrandiresti le aree quando tagli allora? Estendendo il raggio del buffer?
Peter Horsbøll Møller,

Risposte:


15

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 Rtale che l'area del buffer del raggio Rtagliato nella regione poligonale Asia (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.


Come hai fatto in R? Ho dimenticato di dire che ho una certa esperienza in R, quindi non mi dispiacerebbe una soluzione usando anche R.
Funkeh-Monkeh,

Il rgeospacchetto e la sua gBufferfunzione, molto probabilmente ...
Spacedman

In realtà dico una bugia, ho implementato qualcosa di simile in Python come plug-in QGIS: ha bufferizzato i poligoni fino a quando il poligono bufferizzato era 2x (o Nx) l'area del poligono originale. Stesso algoritmo di ricerca però.
Spacedman

+1. I vantaggi dell'approccio mostrato nel Rcodice sono (a) separa i calcoli GIS dalla logica di ricerca e (b) capitalizza su algoritmi di ricerca (in uniroot) che sono stati ottimizzati e testati - non è necessario scriverne uno te stesso (e probabilmente non sarà il più efficiente).
whuber

Ho il sospetto che Scipy implementa algoritmi di ricerca di radici simili nel suo modulo di ottimizzazione: docs.scipy.org/doc/scipy/reference/optimize.html (sì,? Uniroot cita Brent, Scipy ha funzioni Brent-ish)
Spacedman

1

È quasi impossibile, a causa della posizione dei punti. Puoi creare buffer di 400 km 2 , ma i punti più vicini alla costa avranno sempre un'area più piccola rispetto a quelli più lontani (> 400 km 2 ).

L'unica cosa che puoi fare è eseguire un'analisi del buffer sui punti e tagliare successivamente i buffer creati con la funzione di linea costiera.


2
Potrebbe non essere impossibile , ma potrebbe essere un problema NP completo che potrebbe confondere la soluzione. Ottenere l'area perfetta è la sfida (potrebbero essere necessarie decine di iterazioni per avvicinarsi).
Vince il

3
Non è impossibile e non è nemmeno difficile!
Spacedman
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.