Eu quero calcular o ângulo entre duas linhas onde elas se cruzam no PostGIS.
O ponto de partida para cálculos de ângulo no PostGIS parece ser ST_Azimuth - mas isso leva pontos como entrada. Meu primeiro pensamento foi pegar os pontos finais das linhas que se cruzam e realizar um cálculo de azimute sobre elas. Isso não é bom o suficiente, porque a maioria dos recursos da linha não é reta e eu estou interessado no ângulo na interseção. Então, o que eu criei é uma operação aninhada que executa as seguintes etapas:
- Identifique todas as interseções entre as duas tabelas de recursos de linha.
- Crie um buffer muito pequeno ao redor do ponto de interseção
- Identifique os pontos em que os recursos da linha cruzam o exterior do buffer (tomando o primeiro ponto se houver mais de um - estou realmente interessado apenas em saber se o ângulo está próximo de 0, 90 ou 180 graus)
- Calcule ST_Azimuth para esses dois pontos.
O SQL completo é demorado para postar aqui, mas eu o gist aqui se você estiver interessado. (A propósito, existe uma maneira melhor do que carregar todos os campos que estão descendo as instruções WITH?)
Os resultados não parecem corretos, então estou claramente fazendo algo errado:
EDIT Refiz os cálculos no EPSG: 3785 e os resultados são um pouco diferentes, mas ainda não estão corretos:
Minha pergunta é onde estão as falhas nesse processo. Estou entendendo mal o que ST_Azimuth faz? Existe um problema de CRS? Algo completamente diferente? Ou talvez haja uma maneira muito, muito mais simples de fazer isso?
Respostas:
Eu tive a epifania. É bastante mundano. Eu estava deixando de fora uma informação essencial para o PostGIS calcular o ângulo certo.
O que eu estava calculando era o ângulo entre apenas os dois pontos que cruzavam o exterior do pequeno buffer. Para calcular o ângulo da interseção, preciso calcular os dois ângulos entre os dois pontos no exterior do buffer e o ponto de interseção dos dois recursos da linha e subtraí-los.
Atualizei o SQL completo , mas aqui está o ponto mais destacado:
fonte
ST_IntersectionAngle(...
?Recentemente, tive que calcular a mesma coisa, mas decidi por uma abordagem mais simples e provavelmente mais rápida.
Para encontrar os pontos extras para o cálculo do azimute, basta verificar uma permíria do comprimento atrás da interseção (ou depois, no raro caso em que isso ocorre no início da linha) usando ST_Line_Locate_Point e ST_Line_Interpolate_Point :
A permíria foi arbitrária e, para resultados mais consistentes, seria melhor usar um deslocamento absoluto. Para, por exemplo, verificar 20m antes, você alteraria 0,0001 para
20/ST_Length(line1)
e20/ST_Length(line2)
respectivamente.fonte