Calcular o comprimento do polígono ao longo de uma linha?

8

Preciso calcular o comprimento dos polígonos ao longo / projetados em uma linha. Uma imagem para mostrar a ideia:

insira a descrição da imagem aqui

Eu tenho milhares de polígonos a serem "projetados" nas linhas para verificar quantos metros da linha eles pertencem. Os polígonos são irregulares, com orientação diferente, parte deles cruza a linha, parte deles não.

Eu tentei:

  1. Localize os recursos ao longo da ferramenta de linha no ArcGIS Pro, mas fornece apenas o comprimento da linha para sobrepor parte de um polígono (descrição da ferramenta aqui, ajuda da ESRI )

  2. Limite Mínimo Geometria com opção 'casco convexo', mas ele só dá distância entre pontos antípodas de um polígono, que não é parallell a minha linha (descrição ferramenta aqui ESRI ajuda

Estou faltando uma ferramenta para isso no ArcGIS ou QGIS? Você teria uma solução para isso?

Konrad Gje
fonte
Sua linha é uma linha reta?
JiyuuSensei 9/08/19
Como você possui um requisito exclusivo, não parece razoável que essa ferramenta não exista. Você certamente poderia codificar essa ferramenta usando funções trigonométricas e várias funções auxiliares de geometria, mas primeiro você precisa escolher uma plataforma de software.
Vince
@JiyuuSensei não, na verdade é uma rede polilinha - como uma rede rodoviária ou de tubulação. Portanto, isso deve funcionar como calcular esse "comprimento do polígono" para o segmento de linha mais próximo da rede. Portanto, é basicamente a ideia de como funciona a ferramenta Localizar recursos ao longo da linha .
Konrad Gje

Respostas:

7

Usando QGIS:

(1) Crie uma camada de ponto dos vértices do polígono usando a ferramenta Extrair vértices (em QGIS Processing Toolbox> Geometria vetorial).

insira a descrição da imagem aqui

(2) Abra a tabela de atributos da camada Vertices recém-criada .

(3) Inicie a calculadora de campo e;

(3A) Crie um novo campo, vamos chamá-lo de min_poly para armazenar a distância mínima e dar uma expressão:

minimum(
 line_locate_point(
  geometry:=geometry(get_feature_by_id('Lines', '1')), point:=$geometry), 
 group_by:="fid")

Nota: você precisará alterar 'Lines'para o nome da sua linha atual e '1'para o ID da linha que você possui na sua tabela de atributos.

(3B) Crie outro novo campo, vamos chamá-lo de max_poly para armazenar a distância máxima e dar uma expressão:

maximum(
 line_locate_point(
  geometry:=geometry(get_feature_by_id('Lines', '1')), point:=$geometry), 
 group_by:="fid")

insira a descrição da imagem aqui

Como a camada Vertices mantém o campo fid dos IDs originais do polígono, você encontrará min_poly e max_poly é a distância mínima / máxima ao longo da linha para cada polígono.

(O exemplo acima mostra o primeiro polígono fid = 1 se estende de 8,688 a 24,45, enquanto o segundo polígono fid = 2 é de 35,062 a 42,496).

Kazuhito
fonte
5

Não sei como fazer isso com o QGIS ou o ArcGIS, mas o que você quer parece uma largura de uma caixa delimitadora orientada. Como prova de conceito, girei a imagem de amostra para que a linha de projeção fique na horizontal.

insira a descrição da imagem aqui

Digitalizei os polígonos da imagem e gerei envelopes para eles. A largura do envelope responde à sua pergunta.

insira a descrição da imagem aqui

O que está faltando é uma ferramenta que cria caixa delimitadora em um determinado ângulo. O QGIS possui a ferramenta Caixa delimitadora mínima orientada, mas o usuário não pode fornecer um ângulo fixo para isso. Provavelmente, você pode adotar a solução PostGIS a partir da resposta aceita a esta pergunta. Criando "caixa delimitadora oblíqua" com a máxima relação largura / altura? .

user30184
fonte
Essa resposta seria a melhor abordagem, pois é muito fácil obter uma caixa delimitadora orientada no QGIS (com largura e altura do envelope), mas dois lados dessa caixa delimitadora necessariamente precisam ser paralelos à linha de referência e essa condição não é garantida. . Esse é o problema do polígono irregular.
Xunilk
2

Com base na resposta de @ kazuhito, montei uma expressão hacky na Calculadora de Campo QGIS, que deve fazer a mesma coisa em uma única etapa.

No entanto, posso imaginar que isso consome muitos recursos em conjuntos de dados maiores. Eu acho que o problema é mais adequado para uma implementação Python, que obviamente lida com referência e iteração muito melhor do que a Calculadora de Campo.

array_last(array_sort(array_foreach(
generate_series(1,num_points($geometry)-1),
line_locate_point(aggregate('lines','collect',$geometry),
point_n($geometry,@element))),1)) 
- array_first(array_sort(array_foreach(
generate_series(1,num_points($geometry)-1),
line_locate_point(aggregate('lines','collect',$geometry),
point_n($geometry,@element))),1))

Isso primeiro cria uma 'matriz' de números de nós usando generate_series(), especificando o máximo como o número de nós em cada polígono - ou seja num_points($geometry), menos 1 para pular o primeiro / último nó repetido.

Você pode passar os valores dessa matriz por uma função para gerar outra matriz usando array_foreach(). Aqui passamos o número do nó do polígono (representado como @element) para point_n(), que retorna a geometria real desse nó, e o alimentamos line_locate_point()para determinar seu comprimento ao longo da linha especificada (consulte a Nota importante abaixo).

A matriz resultante é então classificada em ordem crescente usando o array_sort()que permite obter as distâncias "mais à esquerda" e "mais à direita" ao longo da linha usando array_last()e array_first(). Subtraia os dois e o resultado é o "comprimento" do polígono ao longo da linha.

Veja abaixo um exemplo da expressão acima mostrada como um rótulo nos polígonos (mais as distâncias da linha "mais à esquerda" e "mais à direita" divididas em relação à expressão acima). Para comparação, incluí também vértices extraídos e valores relevantes de distância da linha. Vértices verdes são os vértices "mais à esquerda" e "mais à direita" ao longo da linha. Observe o polígono superior esquerdo em que o ponto verde está realmente mais ao longo da linha do que o ponto à direita abaixo dele, devido ao ângulo da linha ...

Nota importante :

A geometria da camada de linha é referenciada aqui usando aggregate(). Você vai precisar para mudar o nome da camada ( 'lines') Se necessário, e se você tiver várias linhas, você deve adicionar um filtro para especificar qual linha você quer para o comparar com, por exemplo: aggregate('lines','collect',$geometry,"name"='TrainLine1'). Para que isso funcione automaticamente na linha mais próxima, eu realmente recomendo SQL ou Python sobre o Field Calc.

Além disso, isso calcula o "comprimento" do polígono ao longo da linha, incluindo se a linha é dobrada pelo meu exemplo. Se você deseja a distância em linha reta ... talvez calcule o valor distance()entre os nós relevantes?

insira a descrição da imagem aqui

she_weeds
fonte
1

A melhor abordagem no QGIS para fazer isso (considerando milhares de polígonos a serem "projetados" em uma linha de referência) é determinar a caixa delimitadora girada pelo ângulo entre a linha de referência e o eixo X. Esse ângulo é facilmente determinado usando a ferramenta Extrair vértices (na QGIS Processing Toolbox -> Geometria vetorial) para a linha de referência. A partir do exemplo da imagem a seguir, o ângulo necessário é determinado com valor na tabela de atributos da camada Vertices , empregando esta fórmula:

90 - 63.91873763467915 = 26.081262365320853 graus.

insira a descrição da imagem aqui

Introduzindo o ângulo acima na ferramenta Girar da Processing Toolbox e executando-a:

insira a descrição da imagem aqui

é produzida uma camada girada cuja caixa delimitadora tem em sua tabela de atributos o comprimento do polígono projetado na linha de referência. Por fim, pode ser observado executando esta ferramenta da Processing Toolbox:

insira a descrição da imagem aqui

Na imagem a seguir, o comprimento do polígono projetado em uma linha é o valor encontrado na largura do campo .

insira a descrição da imagem aqui

Pode ser observado na imagem a seguir que o comprimento projetado do polígono considerado, seria o esperado, porque a linha de referência girada em 26,081262365320853 graus (obtida com a ferramenta Girar da caixa de ferramentas de processamento) é paralela ao eixo X.

insira a descrição da imagem aqui

xunilk
fonte