Crie buffers de área limitados por um litoral

10

Estou tentando usar o ArcGIS 10.2 para criar um buffer de pontos com base em uma área predefinida (por exemplo, 400 km quadrados). Além disso, os amortecedores de alguns dos pontos estão próximos ao litoral, o que exige que os amortecedores sejam cortados no litoral e ainda tenham a mesma área que os do interior (400 km2).

Alguém sabe como isso pode ser feito com o Model Builder ou o Arcpy?

Eu tenho habilidades limitadas com Arcpy e R, mas ficaria feliz em trabalhar com alguns scripts para obter uma solução para isso.

Por favor, veja a imagem abaixo mostrando uma representação gráfica do que estou tentando alcançar

[1]

Funkeh-Monkeh
fonte
2
Você seria capaz de incluir uma imagem do que está tentando descrever em palavras?
PolyGeo
Como você aumentaria as áreas quando cortaria? Estendendo o raio do buffer?
Peter Horsbøll Møller

Respostas:

15

A área de um buffer circular é uma função monotonicamente crescente do raio do buffer (em um sistema de coordenadas planas de qualquer maneira). Portanto, uma estratégia de pesquisa simples pode encontrar um raio Rtal que a área do buffer do raio Rcortado na região poligonal Aseja (até alguma tolerância) s.

O algoritmo de pesquisa mais simples seria apenas uma pesquisa binária. Comece com dois raios, um muito pequeno e um muito grande, de modo que a área desejada esteja em algum lugar entre a área dos buffers cortados desses raios. Depois, pegue o ponto médio desses pontos e calcule as áreas de buffer e descubra se o raio desejado está acima ou abaixo do ponto médio. Atualize seus limites de raio e repita até obter alguma tolerância na área desejada.

Escrever uma pesquisa binária em Python e usar a API do ArcGIS Python parece uma boa maneira de aprender! Tenho certeza de que fiz isso em R, anos atrás ...

Aqui está um código 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:

Primeiro, configure uma região poligonal simples do Reino Unido:

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)

Agora defina um ponto:

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

Então você apenas:

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

Esta é uma lista com dois componentes, bé o buffer:

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

e tem a área correta:

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

e ré a saída de uniroot, que inclui o valor do raio do buffer.

> b$r$root
[1] 63338.88

Portanto, neste caso, a largura do buffer era um pouco abaixo dos 64 km.

As únicas coisas a se mexer aqui são os valores iniciais inferior e superior - acho que você pode intuir um raio mais baixo sqrt(A/pi)e o superior não é tão importante quanto o algoritmo de busca aumentará até capturar o intervalo.

O algoritmo de pesquisa pode falhar se o raio máximo inicial for realmente muito grande, pois você pode estar protegendo toda a região com um raio enorme; nesse caso, alterar o raio não mudará a área ... Mas limites sensíveis devem impedir que isso aconteça.

Spacedman
fonte
Como você fez isso no R? Esqueci de mencionar que tenho alguma experiência em R, então não me importaria de uma solução usando R também.
Funkeh-Monkeh
O rgeospacote e sua gBufferfunção, provavelmente ...
Spacedman
Na verdade, eu digo uma mentira, implementei algo parecido no Python como um plug-in QGIS - ele armazenou polígonos em buffer até que o polímero em buffer tivesse 2x (ou Nx) a área do polígono original. Mesmo algoritmo de busca.
Spacedman
+1. As vantagens da abordagem mostrada no Rcódigo são: (a) separa os cálculos de GIS da lógica de pesquisa e (b) capitaliza os algoritmos de pesquisa (in uniroot) que foram otimizados e testados - você não precisa escrever um você mesmo (e provavelmente não será o mais eficiente).
whuber
Eu suspeito que o scipy implementa algoritmos similares de busca de raiz em seu módulo de otimização: docs.scipy.org/doc/scipy/reference/optimize.html (sim, uniroot cita Brent, scipy tem funções Brent-ish)
Spacedman
1

É quase impossível, devido à posição dos pontos. Você pode criar buffers de 400 km 2 , mas os pontos mais próximos da costa sempre terão uma área menor em comparação com os mais distantes (> 400 km 2 ).

A única coisa que você pode fazer é realizar uma análise de buffer nos pontos e recortar os buffers criados com o recurso de costa posteriormente.

Stefan
fonte
2
Pode não ser impossível , mas pode ser um problema do NP Complete que pode confundir a solução. Obter a área perfeita é o desafio (pode levar várias iterações para se aproximar).
Vince
3
Não é impossível, e nem é difícil!
Spacedman