En este artículo vamos a ver cómo unir puntos con líneas desde QGIS mediante dos aproximaciones diferentes y plasmarlas en un mapa

Para este artículo he querido investigar un poco más en la metodología que se podría seguir para crear algunos mapas como los que se vieron previamente en este blog. Para ello esta vez he optado por explicar algunas maneras de crear un mapa de conexión de puntos mediante líneas, viendo algunas maneras para crear este tipo de mapas.
Mapas de líneas
Todos hemos visto el mapa que conectaba las relaciones de Facebook (siguiente imagen) que dió la vuelta al mundo, si nos interesan los mapas, seguro que nos hemos topado con muchos otros, pero es cierto que la creación de estos mapas no es algo que se suela explicar (al menos no se muy a menudo), por eso he pensado hacer un pequeño tutorial sobre cómo podríamos utilizar QGIS para unir puntos con líneas y crear la base de un mapa de este estilo.

Para este reto, igual que para cualquier problema en esta vida, existirán diversas maneras de hacerlo, y seguro que ninguna es «la buena», sino que la mejor forma de unir puntos con líneas dependerá de muchos factores, como nuestras preferencias, con qué nos sentimos más cómodos, o incluso de los datos que tengamos, ya sea la cantidad, el formato, etc.
Es por eso por lo que voy a intentar explorar varias maneras de resolver este problema, aunque en todas se emplee QGIS, van a ser muy distintas, ya que en una utilizaré PostGIS, mientras que en otra utilizaré herramientas de interfaz de usuario.
Los datos
Como sabemos, lo primero que necesitaremos para realizar cualquier estudio con GIS será los datos (con calidad a ser posible). Para ello necesitaremos dos tablas primordiales, la de entidades, que será la tabla que guarde las geometrías (puntos) así como sus atributos. Y la de rutas, que será la que relacione dos puntos con líneas. Esta segunda tabla no necesariamente tendrá geometría. Tan sólo será necesario un Id origen y un Id destino, así como un Id único para la ruta, aunque éste último no será necesario.

Estos datos, como prueba, podemos conseguirlos de openflights.com, base de datos libre que relaciona los vuelos comerciales mundiales.
Os pregntaréis «¿por qué no tenemos dos tablas de puntos?» Si no estamos familiarizados con los modelos de datos podemos pensar que la mejor manera de tener estos datos es con dos tablas, una que se llame orígenes, con los puntos y los atributos de los orígenes, y otra que se llame destinos, con los puntos y los atributos de los destinos, pero lo cierto es que cuando creamos un buen modelo de datos, lo primero que hay que hacer es abstraer todas las entidades iguales en una sola tabla, para evitar así redundancia en los datos. ¿Qué sentido tiene tener dos tablas iguales, pero con datos diferentes? Y lo que es peor, si trabajamos con grandes volúmenes de datos, el peso de la tabla se duplicará, lo cuál puede ser muy pesado para nuestro servidor.
Por tanto, esta manera de presentar los datos no sólo debemos aplicarla cuando organicemos nuestras bases de datos, sino que debemos tenerla presente cuando trabajemos con datos externos, pues lo más seguro es que vengan así estructurados.
Una vez entendido esto, somos capaces de saber que tenemos una tabla con todos los puntos, y otra con la relación entre ellos. Ahora tendremos que relacionarlas ambas, para sacar la geometría de los puntos de la tabla de viajes.
Estos datos, si bien es cierto que no son pocos, tampoco podemos decir que lleguen a ser Big Data. Muchos de los mapas de los que se ha hablado han sido elaborado con una cantidad ingente de datos (¡millones de puntos!) pero por temas técnicos y didácticos, voy a trabajar con una parte de éstos. Si bien es cierto, que mediante este método, el estudio se puede escalar sin ningún problema. Es decir, que utilizando esta misma metodología podremos aplicarla a la cantidad de datos que queramos.
Primera aproximación para unir puntos con líneas: «The PostGIS way»
Para la primera aproximación para unir puntos con líneas y crear un mapa en QGIS, he decidido utilizar PostGIS, ya que es en mi opinión mi manera preferida de resolver esto, y así puedo explicar algunos conceptos que me parecen interesantes, ya no de PostGIS, sino de su integración con QGIS.
Como ya sabemos, PostGIS es el complemento para bases de datos espaciales de Postgres y QGIS se lleva muy bien con él, por lo que es muy fácil conectar QGIS con nuestra base de datos. No voy a centrarme ahora en cómo conectarlo, pero seguro que recordaréis este tutorial para conectar POSTGIS a QGIS de este mismo blog, que lo muestra claramente.
Por tanto, una vez conectada nuestra base de datos, accederemos a nuestras tablas.
Como sabemos, necesitamos una tabla con la geometría de ambas columnas id de la tabla de viajes, y que debemos sacarla de la tabla de entidades, por lo que, en SQL este problema se resolverá fácilmente con una relación reflexiva o «self join«.
Este concepto puede sonar extraño si no estamos familiarizados con él, pero si lo entendemos podemos ver que tan sólo estamos «duplicando» una tabla, y simulando que hay dos. Una irá relacionada con la columna de orígenes, y otra con la de destinos. Con un ejemplo se puede entender más claramente:

Esta consulta será la encargada de devolvernos los campos que queremos, la clave está en el alias del «FROM», es decir, de la tabla rutas, seleccionamos los campos Id y Nombre de origen, y los Id y Nombre de los destinos.
En el FROM, es donde haremos la «trampa» y diremos que tabla1 y tabla2 son la tabla de geometrías, es decir, la duplicaremos. En segundo lugar, relacionaremos con «WHERE» la tabla de rutas con las dos tablas de poblaciones. Como sabemos que sus ID son iguales, diremos que tabla1=origen, y tabla2 a destino.
Para el siguiente paso necesitaremos la función de postgis st_makeline(), a la que le pasaremos las geometrías de los puntos, para que cree las líneas entre ellos. También insertaremos la fórmula row_number() con las que nos sacará un ID único para cada entidad, esto nos ayudará a representarlo en QGIS. Y en el último AND, un pequeño filtro para que nos muestre sólo los vuelos que van a Madrid Barajas (MAD).
Siguiendo estas líneas, ejecutaremos la consulta en la consola de Postgres de QGIS, lo cual nos permitirá no sólo ejecutarla, sino que también podremos visualizarla como una capa.
El resultado sería algo similar a esto:

Por último, quedaría para este método la creación de líneas curvas ortodrómicas, ya que es el mejor método para visualizar los datos de vuelos, pero lo dejaremos para un siguiente tutorial.
Segunda aproximación: MMQGIS
Si no te gusta PostGIS, o no te sientes agusto con el SQL, he elegido otra forma de resolver este problema en la que sólo se utilice la interfaz de usuario de QGIS.
Para ello necesitaremos el plugin MMQGIS. MMQGIS es un plugin para QGIS bastante completo, de los mejores en mi opinión, que se encarga de manejar datos vectoriales. Tiene infinidad de herramientas que otro día pasaré a documentar por si alguien no las conoce, pero ahora vamos a centrarnos en su funcionalidad para este proceso.
Por tanto, para abordar esta tarea, una vez instalado el plugin podremos acceder al menú MMQGIS > Create > Hub Lines.
Cabe señalar que para este método sí necesitaremos dos tablas (no valdrá, como hemos hecho, con simularlas) por lo que tendremos los datos duplicados. Lo ideal para ello es un ESRI Shapefile de orígenes, y otro de destinos, que serán los que seleccionaremos en nuestro formulario.

El proceso se encargará de crear una salida de líneas que una nuestras dos capas de puntos. Tan simple como eso.
Conclusiones
Si has hecho el mismo trabajo con ambos métodos habrás podido ver la diferencia de tiempo que hay entre ambos. Por eso me decanto por el método PostGIS, ya que, aunque parezca algo más complejo, el tiempo de respuesta y los recursos que maneja serán mucho menores.
Por tanto, podemos concluir este estudio diciendo que de una manera bastante sencilla podemos representar una información puntual de un modo diferente, uniendo con líneas nuestros nodos, pero que, a pesar de su simplicidad, no pierde información.
Este tipo de mapas de líneas se está popularizando en los últimos años en disciplinas como la visualización de datos o el «Big Data», ya sea por los avances técnicos para gestionar datos, o incluso por el auge de recopilación de datos geolocalizados que estamos viviendo.
Así que con esta manera puedes tener una aproximación de la potencialidad de QGIS o de QGIS+PostGIS como primera aproximación para realizar este tipo de estudios y unir puntos con líneas. A partir de aquí, se podría perfectamente generar algunos mapas tan visuales como este, también hecho con QGIS.

Autor: Pablo Pardo
Descubre más en nuestro blog sobre Tutoriales GIS y de nuestro Curso de QGIS
Hola Pablo,
Gracias por este tutorial, muy útil!
Una vez que se ha creado la tabla con las conexiones entre los puntos, aparece una columna llamada «st_makeline» con la geometría de esas líneas (entiendo yo..)
Mi duda es cómo puedo exportar esa tabla para importarla a QGIS, me da error porque el formato de esa columna es geometry y no tiene unas coordenadas en particular, sino que una serie de números y letras, como por ejemplo para la fila 1 se le asocia en la columna st_makeline: 102000000020000007034805791FF2041022B873A2A415241F3033A01AE1821412F77FC7F91455241
En resumen, ¿Habría algún modo de importar la tabla a QGIS?
Muchas gracias
hola buenas queria saber como puedo contar los puntos que esta sobre una lineas desde ya muchas gracias esperando su pronta respuesta
Hola buenas.
Podrías por favor explicar como conseguir la creación de líneas curvas ortodrómicas.
Muchas gracias
Hola Jesús.
Iba a hacer otro tutorial con esto, per se resume en:
SELECT 1 as id, ST_Transform(
ST_Segmentize(
ST_MakeLine(
(select ST_Transform((geom from aeropuerto where cod_IATA = ‘MAD’),953027)), –el primer aeropuerto
(select ST_Transform((geom from aeropuerto where cod_IATA = ‘LAX’),953027)) –el segundo aeropuerto
), 100000 ), 4326 )
Se trata de transformar las dos geometrías al EPSG: 953027, para después crear la lnea, dividirla, y luego volver a transformarla a 4326.
Esta función desglosada lo demuestra.
Con st_segmentize(geom, 100000) la dividimos
Con st_makeline(geom, geom) la cramos
Con st_transform(geom, 953027) la transformamos.
adaptando esta sentencia a tus tablas obtendrás una línea que una los dos aeropuertos.
Espero te sirva.
Un saludo.
Tengo una pregunta. En los ejemplos que das son viajes de un origen a varios destinos. Como puedo hacer para desarrollar un mapa entre muchos origenes y muchos destinos con muchas relaciones
Hola Mario.
Con este método es tan fácil como cambiar los datos de entrada. Es decir, en vez de una tabla de rutas: A-B, A-c, A-D, A-F, A-G, puedes generar las líneas a partir de los datos relacionados de otra manera. Por ejemplo: A-B, B-C, B-D, D-E, E-A, E-B, E-F, F-G. En este caso, sin tocar la tabla de aeropuertos se crearía un modelo distribuido en lugar del centralizado que puse. Ten en cuenta que cada registro en la tabla routes marca una relación. El modelo que sigan ya dependerá de tu proyecto.
Si lo que quieres es sacar un modelo que relacione todos los aeropuertos con todos, una solución podría ser hacer un producto cartesiano, para eso tendrías quitar los WHERE de la tabla, pero no te lo recomiendo ya que no tienes control de los datos, y el número de elementos se elevaría al cuadrado, pudiendo generar una tabla enorme.
Hola Paul.
¿Puedes concretarme un poco más el error que te da?
Por asegurarnos, si dices que los nombres de las tablas están bien, ¿te has asegurado de que los campos lo estén?
Otra cosa: Intenta hacer la query por partes, primero un select a routes, luego un select a aeropuertos, y luego uno uniéndolos ambos (where routes.aeroId = aeropuertos=aeroId) antes de hacer la unión final, a ver si así te deja, por depurar el error.
Si me comentas los resultados puedo seguir ayudándote.
Una consulta al ingresar al FROM me aparece un error que dice que no existe la relación, estoy seguro de que los nombres de tablas estan bien escritos, no se a que se deba el error
Hola Paul.
¿Puedes concretarme un poco más el error que te da?
Por asegurarnos, si dices que los nombres de las tablas están bien, ¿te has asegurado de que los campos lo estén?
Otra cosa: Intenta hacer la query por partes, primero un select a routes, luego un select a aeropuertos, y luego uno uniéndolos ambos (where routes.aeroId = aeropuertos=aeroId) antes de hacer la unión final, a ver si así te deja, por depurar el error.
Si me comentas los resultados puedo seguir ayudándote.