¿Cómo calcular el ángulo en el que dos líneas se intersecan en PostGIS?

18

Quiero calcular el ángulo entre dos líneas donde se intersecan en PostGIS.

El punto de partida para los cálculos de ángulos 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 Azimut en esas. Eso no es lo suficientemente bueno, porque la mayoría de las entidades de línea no son rectas, y me interesa el ángulo en la intersección. Entonces, se me ocurrió una operación anidada que sigue los siguientes pasos:

  1. Identifique todas las intersecciones entre las dos tablas de entidades de línea.
  2. Crea un búfer muy pequeño alrededor del punto de intersección
  3. Identifique los puntos donde las entidades de línea se intersecan con el exterior del búfer (tomando el primer punto si hay más de uno; realmente solo me interesa si el ángulo está cerca de 0, 90 o 180 grados)
  4. Calcule ST_Azimuth para esos dos puntos.

El SQL completo es un poco largo para publicar aquí, pero lo escribí aquí si estás interesado. (Por cierto, ¿hay una mejor manera de transferir todos los campos que van por las declaraciones WITH?)

Los resultados no se ven bien, así que claramente estoy haciendo algo mal:

EDITAR He vuelto a hacer los cálculos en EPSG: 3785 y los resultados son un poco diferentes pero todavía no son correctos:

Mi pregunta es dónde están las fallas en este proceso. ¿Estoy mal entendiendo lo que hace ST_Azimuth? ¿Hay un problema de CRS? ¿Algo más en conjunto? ¿O tal vez hay una manera mucho más simple de hacer esto?

    
pregunta mvexel 09.05.2012 - 20:03

2 respuestas

10

Tuve la epifanía. Es más bien mundano. Estaba omitiendo una información esencial para que PostGIS calcule el ángulo correcto.

Lo que estaba calculando era el ángulo entre solo los dos puntos que intersecaban el exterior del pequeño 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 restarlos.

Actualicé el SQL completo, pero aquí está el bit más destacado:

SELECT
    ...
    abs
    (
        round
        (
            degrees
            (
            ST_Azimuth
            (
                points.point2,
                points.intersection
            )
            -
            ST_Azimuth
            (
                points.point1,
                points.intersection
            )
        )::decimal % 180.0
        ,2
    )
)
AS angle
...
FROM
points 
    
respondido por el mvexel 10.05.2012 - 01:32
2

Hace poco tuve que calcular lo mismo, pero decidí un enfoque más simple y probablemente más rápido.

Para encontrar los puntos extra para el cálculo del acimut, simplemente verifico una permyriad 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 :

abs(degrees( 
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line1, 
      abs(ST_Line_Locate_Point(line1, intersection) - 0.0001)
    )
  )
  -
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line2, 
      abs(ST_Line_Locate_Point(line2, intersection) - 0.0001)
    )
  )
))

El permyriad era arbitrario y para obtener resultados más consistentes sería mejor usar un desplazamiento absoluto. Por ejemplo, para verificar 20 m de antemano, cambiarías 0,0001 a 20/ST_Length(line1) y 20/ST_Length(line2) respectivamente.

    
respondido por el lynxlynxlynx 05.06.2012 - 00:42

Lea otras preguntas en las etiquetas