Análisis de rutas geoespaciales con pgRouting en ServBay
pgRouting
es un potente módulo de extensión para bases de datos PostgreSQL y PostGIS, diseñado específicamente para ofrecer amplias capacidades de análisis de rutas y redes sobre datos geográficos. Usando pgRouting
, los desarrolladores pueden realizar consultas complejas sobre datos viales, como encontrar la ruta más corta entre dos puntos, resolver el problema del viajante (TSP) o realizar análisis de áreas de servicio. Estas funciones resultan especialmente útiles en aplicaciones de mapas, planificación logística, análisis de tráfico y otros escenarios similares.
Este artículo detalla cómo habilitar fácilmente la extensión pgRouting
en una base de datos PostgreSQL dentro del entorno de desarrollo web local de ServBay, así como su configuración y análisis básicos de rutas.
Visión general
ServBay proporciona a los desarrolladores en macOS un entorno local unificado y fácil de usar, con servidores web, bases de datos y varios lenguajes de programación preinstalados. El paquete de PostgreSQL brindado por ServBay ya incluye las extensiones pgRouting
y PostGIS
. Esto significa que no tienes que descargar ni compilar manualmente estas extensiones: solo necesitas habilitarlas en tu base de datos para empezar a utilizarlas.
Requisitos previos
Antes de utilizar pgRouting
, asegúrate de cumplir los siguientes requisitos:
- ServBay instalado y funcionando: Si aún no tienes ServBay, visita el sitio oficial de ServBay para descargar e instalar la versión más reciente.
- El paquete de PostgreSQL está instalado y ejecutándose en ServBay: En la interfaz de ServBay, asegúrate de que el paquete de PostgreSQL esté instalado y en estado "ejecutándose".
- Conocimientos básicos de SQL y manipulación de PostgreSQL: Se supone que tienes experiencia básica con bases de datos PostgreSQL y consultas SQL.
- Bases de PostGIS:
pgRouting
depende dePostGIS
para manejar tipos de datos y funciones espaciales. Asegúrate de tener habilitada la extensiónPostGIS
en tu base de datos. El paquete PostgreSQL de ServBay comúnmente incluye PostGIS preinstalado.
Instalación y habilitación de la extensión pgRouting
ServBay ya tiene listos los archivos de extensión de pgRouting
, por lo que solo necesitas habilitar la extensión en la base de datos donde la quieras usar.
Conéctate a la base de datos PostgreSQL:
Puedes conectarte a PostgreSQL a través de múltiples vías: utilizando la herramienta de línea de comandos
psql
, herramientas gráficas (como pgAdmin, DBeaver) o bibliotecas de cliente desde tu lenguaje de programación preferido.Usar la consola
psql
que ServBay proporciona es una de las maneras más directas y habituales. Puedes usar el botón "Terminal" en la interfaz de ServBay para abrir una terminal ya configurada, o bien añadir manualmente el directoriobin
de ServBay a tu PATH del sistema.En la terminal, conecta a tu base de datos objetivo (por ejemplo, una llamada
servbay_geo_db
usando el usuario predeterminadoservbay
) mediante:bashpsql -U servbay -d servbay_geo_db
1Si tu base de datos, usuario o contraseña son diferentes, modifica el comando acorde.
Verifica y habilita la extensión PostGIS (si aún no está habilitada):
pgRouting
necesita quePostGIS
esté activo. Antes de activarpgRouting
, verifica o habilitaPostGIS
en el prompt depsql
:sqlCREATE EXTENSION IF NOT EXISTS postgis;
1Este comando crea la extensión si aún no existe, o la omite si ya está instalada.
Crea la extensión pgRouting:
En la misma conexión de base de datos, ejecuta:
sqlCREATE EXTENSION pgrouting;
1Si el comando es exitoso, verás una salida similar a
CREATE EXTENSION
.Verifica la instalación:
Puedes listar las extensiones instaladas para verificar que
pgRouting
está activa:sql\dx
1Deberías ver
postgis
ypgrouting
junto con detalles relacionados en la lista.
Configuración de pgRouting: preparación de datos viales y creación de topología
Los algoritmos de pgRouting
requieren trabajar sobre una tabla que represente la red vial. Generalmente, esta tabla contiene segmentos (tramos de caminos) con un nodo de inicio, un nodo final y un peso (por ejemplo, distancia o tiempo). Para un cálculo eficiente de rutas, es necesario transformar estos datos en una estructura topológica, es decir, identificar y relacionar correctamente los nodos de los segmentos.
Creación de la tabla de red vial
El siguiente es un ejemplo básico de cómo crear una tabla ways
para almacenar los datos de los caminos. La tabla incluye un ID de segmento, IDs de nodo origen y destino, coste en ambos sentidos (cost
, reverse_cost
), y la geometría del segmento como tipo PostGIS GEOMETRY
.
-- Crea una tabla para almacenar la red vial
CREATE TABLE ways (
id SERIAL PRIMARY KEY, -- Identificador único del tramo
source INTEGER, -- ID del nodo de inicio
target INTEGER, -- ID del nodo final
cost DOUBLE PRECISION, -- Coste para recorrer este tramo en sentido de origen a destino (distancia, tiempo, etc)
reverse_cost DOUBLE PRECISION, -- Coste en sentido inverso
geom GEOMETRY(LineString, 4326) -- Geometría del tramo, tipo LineString y SRID 4326 (WGS 84)
);
2
3
4
5
6
7
8
9
Explicaciones:
SERIAL PRIMARY KEY
: genera automáticamente un ID único para cada segmento.source
,target
: representan el nodo de inicio y final en la topología. Estos se rellenan manualmente o durante la creación de la topología.cost
,reverse_cost
: el peso para cada sentido. Para calles de sentido único,reverse_cost
puede serNULL
o un valor muy alto.geom
: almacena la información geográfica de cada segmento.LineString
indica que es una línea, y4326
corresponde al sistema de coordenadas WGS 84 (lat/lon).
Inserción de datos de ejemplo
Puedes añadir algunos segmentos de ejemplo a la tabla ways
así:
-- Inserta segmentos viales de ejemplo
INSERT INTO ways (source, target, cost, reverse_cost, geom) VALUES
(1, 2, 1.0, 1.0, ST_SetSRID(ST_MakeLine(ST_MakePoint(116.4074, 39.9042), ST_MakePoint(116.4084, 39.9052)), 4326)),
(2, 3, 1.0, 1.0, ST_SetSRID(ST_MakeLine(ST_MakePoint(116.4084, 39.9052), ST_MakePoint(116.4094, 39.9062)), 4326)),
(3, 4, 1.0, 1.0, ST_SetSRID(ST_MakeLine(ST_MakePoint(116.4094, 39.9062), ST_MakePoint(116.4104, 39.9072)), 4326));
2
3
4
5
Explicaciones:
ST_MakePoint(x, y)
: crea un punto PostGIS a partir de latitud y longitud.ST_MakeLine(point1, point2)
: genera una línea PostGIS a partir de dos puntos.ST_SetSRID(geometry, srid)
: asigna el sistema de referencia espacial.- Estos ejemplos representan tres caminos conectados, con coste 1.0 cada uno, usando coordenadas en Beijing como referencia.
Creación de la topología
Con la tabla de red formada, utiliza la función pgr_createTopology
para construir la topología. Esta función analiza la geometría de los segmentos, identifica nodos de conexión y rellena las columnas source
y target
, además de crear una tabla de nodos asociada (usualmente de nombre [nombre_tabla]_vertices_pgr
).
-- Crea la topología para los segmentos viales
-- Parámetros:
-- 'ways': nombre de la tabla
-- 0.00001: tolerancia para considerar qué puntos son el mismo nodo
-- 'geom': columna que almacena la geometría
-- 'id': columna con el ID de segmento
SELECT pgr_createTopology('ways', 0.00001, 'geom', 'id');
2
3
4
5
6
7
Explicaciones:
pgr_createTopology
: función clave depgRouting
para construir el modelo nodo-arista de la red.- La tolerancia define cuán próximos deben estar dos puntos para ser considerados el mismo nodo —ajústala según la precisión de tus datos—.
Después de este proceso, las columnas source
y target
tendrán valores asignados y se creará una tabla ways_vertices_pgr
con la información de los nodos.
Análisis de rutas usando pgRouting
Una vez creada la topología, puedes usar diversas funciones de pgRouting
para analizar rutas y redes. A continuación se muestran ejemplos de los algoritmos más habituales.
Análisis de la ruta más corta (Dijkstra)
Encontrar la ruta más corta entre dos nodos es la necesidad más común. pgRouting
incluye el algoritmo de Dijkstra para estos casos.
-- Encuentra la ruta más corta del nodo 1 al nodo 4
-- Parámetros:
-- 'SELECT id, source, target, cost FROM ways': consulta para construir el grafo
-- 1: ID del nodo inicial
-- 4: ID del nodo destino
-- directed := true: indica si el grafo es dirigido (si cost y reverse_cost difieren)
SELECT seq, id1 AS node, id2 AS edge, cost, geom
FROM pgr_dijkstra(
'SELECT id, source, target, cost FROM ways',
1, -- ID nodo inicial
4, -- ID nodo final
directed := true -- Establece en false si consideras reverse_cost o rutas bidireccionales
)
JOIN ways ON edge = ways.id; -- Une resultados con la tabla ways para obtener la geometría
2
3
4
5
6
7
8
9
10
11
12
13
14
Explicaciones:
pgr_dijkstra
: ejecuta el algoritmo de Dijkstra sobre el grafo.- El primer parámetro debe ser una consulta SQL que incluya al menos las columnas
id
,source
,target
,cost
. Si necesitas rutas en ambos sentidos, incluye tambiénreverse_cost
y pondirected := false
. - El resultado se une con
ways
para visualizar la geometría de los tramos.
Problema del viajante (Traveling Salesperson Problem - TSP)
El TSP busca el recorrido más corto para visitar un grupo de nodos y regresar al punto de inicio.
-- Resuelve el TSP para visitar los nodos 1, 2, 3, 4 desde el nodo 1
-- Parámetros:
-- 'SELECT id, x::float8 AS x, y::float8 AS y FROM ways_vertices_pgr': nodos y coordenadas
-- start_id := 1: nodo inicial
SELECT seq, node, edge, cost
FROM pgr_tsp(
'SELECT id, ST_X(the_geom)::float8 AS x, ST_Y(the_geom)::float8 AS y FROM ways_vertices_pgr WHERE id IN (1, 2, 3, 4)', -- nodos a visitar
start_id := 1 -- nodo de inicio
);
2
3
4
5
6
7
8
9
Explicaciones:
pgr_tsp
: ejecuta el algoritmo TSP.- El parámetro SQL debe incluir
id
,x
yy
(coordenadas), habitualmente desdeways_vertices_pgr
. - Indica el nodo inicial con
start_id
.
Análisis de áreas de servicio (Driving Distance / Driving Time)
Este análisis determina los caminos o regiones accesibles desde uno o más puntos bajo cierto coste (distancia o tiempo).
-- Desde el nodo 1, obtiene segmentos accesibles con coste máximo de 2 unidades
-- Parámetros:
-- 'SELECT id, source, target, cost FROM ways': consulta para el grafo
-- 1: nodo de inicio
-- 2: coste máximo permitido
-- directed := true: indica si el grafo es dirigido
SELECT seq, id1 AS node, id2 AS edge, cost, geom
FROM pgr_drivingDistance(
'SELECT id, source, target, cost FROM ways',
1, -- nodo inicial
2, -- coste máximo
directed := true
)
JOIN ways ON edge = ways.id; -- Obtiene la geometría
2
3
4
5
6
7
8
9
10
11
12
13
14
Explicaciones:
pgr_drivingDistance
: eficiencia de área de servicio.- Parámetros y consultas iguales a los ejemplos anteriores.
- La consulta retorna las aristas accesibles y sus geometrías.
Visualización de resultados de pgRouting
Visualizar los resultados de pgRouting
es clave para comprender y mostrar los análisis de rutas. Puedes hacerlo con software SIG de escritorio o integrando mapas en aplicaciones web.
Usando herramientas SIG de escritorio (por ejemplo, QGIS)
QGIS es una aplicación SIG gratuita y de código abierto capaz de conectarse directamente a bases de datos PostgreSQL/PostGIS y visualizar datos espaciales, incluidos los procedentes de pgRouting
.
- Abre QGIS.
- Ve a Capa (Layer) > Administrador de fuentes de datos (Data Source Manager).
- En el menú izquierdo selecciona PostGIS.
- Haz clic en Nuevo (New) para crear una nueva conexión.
- Ingresa los detalles de la conexión PostgreSQL de ServBay (Host:
localhost
, Puerto:5432
, Base de datos:servbay_geo_db
, Usuario:servbay
, Contraseña: tu clave de PostgreSQL). Puedes probar la conexión con el botón correspondiente. - Al conectarte, expande la base y verás las tablas incluidas
ways
yways_vertices_pgr
. - Selecciona la tabla o vista de consulta que desees cargar (por ejemplo, una vista con la ruta más corta) y haz clic en Añadir (Add) para visualizarla en QGIS.
Visualización web (Leaflet u OpenLayers)
Para aplicaciones web, necesitas un backend (por ejemplo, PHP, Node.js, Python corriendo sobre ServBay) que ejecute consultas pgRouting
y devuelva resultados —usualmente en formato GeoJSON— al frontend. Este último utiliza una biblioteca de mapas (como Leaflet u OpenLayers) para mostrarlos.
Aquí tienes un ejemplo básico de estructura HTML para mostrar una línea estática en Leaflet. Para mostrar rutas generadas dinámicamente:
- El backend ejecuta la consulta
pgRouting
. - Convierte los resultados geométricos a GeoJSON.
- Provee los datos al frontend mediante una API.
- El frontend usa Leaflet y el método
L.geoJSON
para cargar y mostrar los datos.
<!DOCTYPE html>
<html>
<head>
<title>Ejemplo de visualización web con ServBay y pgRouting</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<style>
#map { height: 600px; width: 100%; } /* Tamaño del contenedor de mapa */
</style>
</head>
<body>
<h1>Visualización de resultados de pgRouting en ServBay</h1>
<div id="map"></div>
<script>
// Inicializa el mapa y establece el centro y zoom
var map = L.map('map').setView([39.906, 116.409], 14); // Centrado en los ejemplos
// Capa base de OpenStreetMap
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Ejemplo: agrega datos GeoJSON estáticos convertidos desde un resultado de pgRouting
// Para datos dinámicos, geojsonData debe cargarse vía AJAX desde el servidor
var geojsonData = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": 1,
"cost": 1.0
},
"geometry": {
"type": "LineString",
"coordinates": [
[116.4074, 39.9042],
[116.4084, 39.9052]
]
}
},
{
"type": "Feature",
"properties": {
"id": 2,
"cost": 1.0
},
"geometry": {
"type": "LineString",
"coordinates": [
[116.4084, 39.9052],
[116.4094, 39.9062]
]
}
},
{
"type": "Feature",
"properties": {
"id": 3,
"cost": 1.0
},
"geometry": {
"type": "LineString",
"coordinates": [
[116.4094, 39.9062],
[116.4104, 39.9072]
]
}
}
]
};
// Agrega los datos GeoJSON al mapa con estilo personalizado
L.geoJSON(geojsonData, {
style: function (feature) {
return {color: "#ff0000", weight: 4}; // Rutas en rojo y gruesas
}
}).addTo(map);
// Ajusta el encuadre del mapa para mostrar todos los elementos
if (L.geoJSON(geojsonData).getBounds().isValid()) {
map.fitBounds(L.geoJSON(geojsonData).getBounds());
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
Guarda este archivo HTML bajo el directorio raíz de tu sitio ServBay (por ejemplo /Applications/ServBay/www/pgrouting-demo/index.html
) y accede a través del navegador (por ejemplo http://pgrouting-demo.servbay.demo
). Verás en el mapa la ruta de ejemplo representada como líneas. Recuerda: esto es un ejemplo estático; para casos reales deberás implementar la obtención dinámica y renderizado de los resultados de pgRouting
.
Consideraciones
- Calidad de los datos: Los resultados de
pgRouting
dependen en gran medida de la precisión y topología de tus datos viales. Asegúrate de que sean precisos y correctos. - Rendimiento: En redes viales grandes, los cálculos de rutas pueden ser costosos. Usa índices, simplificación del grafo y algoritmos más eficientes según sea necesario.
- Memoria: Redes y topologías extensas requerirán mayor memoria disponible en el servidor.
Preguntas frecuentes (FAQ)
P: Recibo un error de “extensión no existe” al ejecutar CREATE EXTENSION pgrouting;
. ¿Qué hago?
R: Comprueba primero que el paquete PostgreSQL de ServBay está instalado y en funcionamiento. Verifica además la versión de tu base de datos y que la extensión pgRouting
viene incluida en ServBay (algo común). Si el problema persiste, revisa los logs de ServBay/PostgreSQL para más detalles. Recuerda conectarte con un usuario que tenga permisos suficientes, como el usuario servbay
.
P: ¿Cómo elijo el valor de tolerancia (tolerance) en pgr_createTopology
?
R: Depende de la precisión de tus datos espaciales. Define la distancia máxima entre dos vértices para considerarlos el mismo nodo. Si tus datos son muy precisos (p.ej. coordenadas GPS), usa tolerancias bajas (ejemplo: 0.000001). Si los datos son menos precisos o provienen de varias fuentes, elige un poco más alto para asegurar la conectividad. No exageres para evitar unir segmentos incorrectamente.
P: ¿Cómo modelar calles de sentido único o restricciones de giro/retorno?
R: Las columnas cost
y reverse_cost
de la tabla ways
sirven para esto. Para calles de un solo sentido, pon reverse_cost
a NULL
o un valor muy alto. Para restricciones de giro, puede requerir modelado adicional o tratamiento posterior, aunque pgRouting
incluye algunas funciones avanzadas para estas situaciones.
Resumen
ServBay hace sencillo montar un entorno local con PostgreSQL y soporte para pgRouting
. Con unos pocos comandos SQL activas las extensiones, preparas tus datos de red y creas la topología para aprovechar los potentes algoritmos geoespaciales de rutas de pgRouting
. Combinando herramientas SIG de escritorio o bibliotecas de mapas web, puedes visualizar fácilmente resultados y dotar a tus aplicaciones web o proyectos espaciales de potentes funcionalidades de análisis de rutas. ServBay elimina la complejidad de la configuración, permitiéndote centrarte en la lógica y las funciones de tu aplicación.