Recientemente he estado buscando en las páginas web de las aerolíneas que muestran sus rutas que parten de una determinada ciudad a todas las demás ciudades a las que dan servicio. Me gustaría poder crear rutas curvas similares entre puntos. ¿Alguien ha creado scripts o funciones que generarán los arcos curvos como los que se muestran en este ejemplo ?
En PostGIS, ¿existe una implementación de ST_MakeLine que le permita especificar la cantidad de curva que se utilizará al conectar 2 puntos?
Aunque actualmente estoy usando PostGIS y QGIS, agradecería escuchar sobre otras opciones de software que podrían crear la misma apariencia.
Respuestas:
Crear grandes círculos podría darte el efecto deseado.
Tal vez algo como lo discutido en http://lists.osgeo.org/pipermail/postgis-users/2008-February/018620.html
Actualizar:
He seguido esta idea en "Visualizar conexiones globales" . Es una solución puramente basada en PostGIS que utiliza la reproyección para crear arcos.
(La definición de CRS para 953027 se puede encontrar aquí: http://spatialreference.org/ref/esri/53027/ )
fuente
El problema es calcular cuánto doblar los arcos para mejorar su resolución visual.
Aquí hay una solución (entre las muchas posibles). Consideremos todos los arcos que emanan de un origen común. Los arcos se llenan más aquí. Para separarlos de la mejor manera, organicemos de manera que se extiendan en ángulos igualmente espaciados . Es un problema si dibujamos segmentos de línea recta desde el origen hasta los destinos, porque generalmente habrá grupos de destinos en varias direcciones. Usemos nuestra libertad para doblar los arcos para espaciar los ángulos de salida lo más uniformemente posible.
Para simplificar, usemos arcos circulares en el mapa. Una medida natural de la "curva" en un arco desde el punto y al punto x es la diferencia entre su rumbo en y y el rumbo directamente de y a x . Tal arco es un sector de un círculo en el que se encuentran y y x ; La geometría elemental muestra que el ángulo de flexión es igual a la mitad del ángulo incluido en el arco.
Para describir un algoritmo necesitamos un poco más de notación. Sea y el punto de origen (como se proyecta en el mapa) y sea x_1 , x_2 , ..., x_n los puntos de destino. Defina a_i como el rumbo de y a x_i , i = 1, 2, ..., n .
Como paso preliminar, suponga que los rodamientos (todos entre 0 y 360 grados) están en orden ascendente: esto requiere que calculemos los rodamientos y luego los ordenemos; ambas son tareas sencillas.
Idealmente, nos gustaría que los rumbos de los arcos sean iguales a 360 / n , 2 * 360 / n , etc., en relación con algunos rumbos iniciales. Por lo tanto, las diferencias entre los rodamientos deseados y los rodamientos reales son iguales a i * 360 / n - a_i más el rodamiento inicial, a0 . La diferencia más grande es el máximo de estas n diferencias y la diferencia más pequeña es su mínimo. Configuremos a0 para que esté a medio camino entre el máximo y el mínimo; Este es un buen candidato para el rodamiento inicial porque minimiza la cantidad máxima de flexión que se producirá . En consecuencia, definir
b_i = i * 360 / n - a0 - a_i:
esta es la flexión para usar .
Es una cuestión de geometría elemental dibujar un arco circular de y a x que tenga un ángulo de 2 b_i, así que omitiré los detalles e iré directamente a un ejemplo. Aquí hay ilustraciones de las soluciones para 64, 16 y 4 puntos aleatorios ubicados dentro de un mapa rectangular
Como se puede ver, las soluciones parecen tener más agradable como el número de puntos de destino aumenta. La solución para n = 4 muestra claramente cómo los rodamientos están igualmente espaciados, ya que en este caso la separación es igual a 360/4 = 90 grados y obviamente esa separación se logra exactamente.
Esta solución no es perfecta: probablemente pueda identificar varios arcos que podrían modificarse manualmente para mejorar el gráfico. Pero no hará un trabajo terrible y parece ser un muy buen comienzo.
El algoritmo también tiene el mérito de ser simple: la parte más complicada consiste en ordenar los destinos de acuerdo con sus orientaciones.
Codificación
No conozco PostGIS, pero quizás el código que usé para dibujar los ejemplos puede servir como guía para implementar este algoritmo en PostGIS (o cualquier otro SIG).
Considere lo siguiente como pseudocódigo (pero Mathematica lo ejecutará :-). (Si este sitio admitiera TeX, como lo hacen las matemáticas, estadísticas y TCS, podría hacer que esto sea mucho más legible). La notación incluye:
La parte ejecutable del código es afortunadamente corta, menos de 20 líneas, porque más de la mitad son gastos generales declarativos o comentarios.
Dibujar un mapa
z
es una lista de destinos yy
es el origen.Cree un arco circular de punto
x
a puntoy
comenzando en un ángulo\[Beta]
relativo al rumbo x -> y.Calcule los rumbos desde un origen hasta una lista de puntos.
Calcule el rango medio de los residuos de un conjunto de rodamientos.
x
es una lista de rodamientos en orden ordenado. Idealmente, x [[i]] ~ 2 [Pi] i / n.fuente
Prueba ST_CurveToLine
Algo como por ejemplo:
Puede visualizar esto copiando la consulta en el cuadro de texto y presionando Map1 en http://www.postgisonline.org/map.php
fuente
Creo que solo querría rodar su propia polilínea con algunas matemáticas vectoriales, http://en.wikipedia.org/wiki/B%C3%A9zier_curve , o si su gis tiene una interfaz ICurve .
fuente
Terminé probando esto para curvar un conjunto de cadenas de líneas de "dos puntos" usando la función ST_CurveToLine como lo sugirió @Nicklas Avén.
Pasé los siguientes 3 conjuntos de coordenadas a la función ST_OffsetCurve:
Usé la función ST_OffsetCurve para calcular el desplazamiento: 1/10 de la longitud de la línea original en mi ejemplo.
Aquí está el SQL que utilicé para generar las líneas curvas a partir de las líneas rectas originales:
fuente