Quiero calcular el ángulo entre dos líneas donde se cruzan en PostGIS.
El punto de partida para los cálculos de ángulo en PostGIS parece ser ST_Azimuth , pero eso toma puntos como entrada. Mi primer pensamiento fue tomar los puntos finales de las líneas que se cruzan y realizar un cálculo de acimut en ellos. Eso no es lo suficientemente bueno, porque la mayoría de las entidades de línea no son rectas, y estoy interesado en el ángulo en la intersección. Entonces, se me ocurrió una operación anidada que sigue los siguientes pasos:
- Identifique todas las intersecciones entre las dos tablas de entidades de línea.
- Cree un búfer muy pequeño alrededor del punto de intersección.
- Identifique los puntos donde las entidades de línea se cruzan con el exterior del búfer (tomando el primer punto si hay más de uno; en realidad solo me interesa saber si el ángulo está cerca de 0, 90 o 180 grados)
- Calcule ST_Azimuth para esos dos puntos.
El SQL completo es un poco largo para publicar aquí, pero lo mencioné aquí si está interesado. (Por cierto, ¿hay una mejor manera que transferir todos los campos que van por las declaraciones WITH?)
Los resultados no se ven bien, así que claramente estoy haciendo algo mal:
EDITAR Rehice los cálculos en EPSG: 3785 y los resultados son un poco diferentes, pero aún no son correctos:
Mi pregunta es dónde están los defectos en este proceso. ¿Estoy malinterpretando lo que hace ST_Azimuth? ¿Hay un problema de CRS? ¿Algo más por completo? ¿O tal vez hay una manera mucho, mucho más simple de hacer esto?
Respuestas:
Tuve la epifanía. Es bastante mundano. Estaba dejando de lado una información esencial para que PostGIS calcule el ángulo correcto.
Lo que estaba calculando era el ángulo entre solo los dos puntos que intersectan el pequeño exterior del búfer. Para calcular el ángulo de la intersección, necesito calcular ambos ángulos entre ambos puntos en el exterior del búfer y el punto de intersección de las dos entidades de línea y restarlas.
Actualicé el SQL completo , pero aquí está el bit sobresaliente:
fuente
ST_IntersectionAngle(...
.Recientemente tuve que calcular lo mismo, pero decidí un enfoque más simple y probablemente más rápido.
Para encontrar los puntos adicionales para el cálculo de acimut, solo verifico una permiría de la longitud detrás de la intersección (o después, en el raro caso de que ocurra al comienzo de la línea) usando ST_Line_Locate_Point y ST_Line_Interpolate_Point :
La permyriad fue arbitraria y para obtener resultados más consistentes sería mejor utilizar un desplazamiento absoluto. Para, por ejemplo, verificar 20m de antemano, cambiaría 0.0001 a
20/ST_Length(line1)
y20/ST_Length(line2)
respectivamente.fuente