Versiones no soportadas:2.6 2.5 2.4 2.3 2.2 2.1 2.0
pgr_nodeNetwork
¶
pgr_nodeNetwork
- Crea los nodos de una tabla de aristas de la red.
- Autor:
Nicolas Ribot
- Derechos de autor:
Nicolas Ribot, el código fuente está liberado bajo la licencia MIT-X.
La función carga los bordes de una tabla que no tiene los nodos en las intersecciones y reescribe los bordes con los nodos en una nueva tabla.
| pgr_nodenetwork(edge_table, tolerance, [options]) | options:[id, text the_geom, table_ending, rows_where, outall]
| RETURNSTEXT
Disponibilidad
Versión 3.8.0
Not checking and not creating indexes.
Using
pgr_separateTouching
andpgr_separateCrossing
.Created table with
BIGINT
.
Versión 2.0.0
Función oficial.
Descripción¶
Las principales características son:
Un problema común asociado con la incorporación de datos SIG en pgRouting es el hecho de que los datos a menudo no están correctamente referenciados con nodos. Esto provoca topologías no válidas, que resultan en rutas que son incorrectas.
Que los bordes estén indicados como anudados significa que, en cada intersección de la red de caminos, las aristas se descompondrán en segmentos separados . Los casos como una intersección por puente o túnel donde no existe conexión vial no son detectados por esta función.
Esta función lee la tabla edge_table
, que tiene una columna de clave principal id
y columna de la geometría llamada the_geom
, y verifica la intersección de todos los segmentos contra todos los demás segmentos creando una tabla de salida edge_table_noded
. Usa la tolerancia tolerance
para decidir cuáles nodos son considerados como mismo nodo.
Parámetros¶
- edge_table:
text
La tabla de la red. (puede contener el nombre del esquema)- tolerancia:
float8
tolerancia para puntos de coincidencia (en la unidad de proyección)- id:
text``Nombre de la columna de la clave principal de la tabla de red. Valor por defecto es ``id
”.- the_geom:
text
nombre de la columna de la geometría en la tabla de la red. El valor por defecto es the_geom`.- table_ending:
text
sufijo para la nueva tabla. El valor predeterminado esnoded
.
La tabla de salida que tendrá para edge_table_noded
- id:
bigint
identificador único del vértice- old_id:
bigint
Identificador de la arista en la tabla original- sub_id:
integer
número del segmento del borde original- source:
bigint
Empty source column- target:
bigint
Empty target column- la geom:
geometry
Columna de geometría de la red discontínua
Ejemplos¶
Crear la topología para los datos en Datos Muestra
SELECT * INTO vertices
FROM pgr_extractVertices('SELECT id, geom FROM edges ORDER BY id');
SELECT 17
/* -- set the source information */
UPDATE edges AS e
SET source = v.id, x1 = x, y1 = y
FROM vertices AS v
WHERE ST_StartPoint(e.geom) = v.geom;
UPDATE 18
/* -- set the target information */
UPDATE edges AS e
SET target = v.id, x2 = x, y2 = y
FROM vertices AS v
WHERE ST_EndPoint(e.geom) = v.geom;
UPDATE 18
Analyze the network for intersections.
SELECT e1.id id1, e2.id id2, ST_ASTEXT(ST_Intersection(e1.geom, e2.geom)) AS point
FROM edges e1, edges e2
WHERE e1.id < e2.id AND ST_Crosses(e1.geom, e2.geom);
id1 | id2 | point
-----+-----+--------------
13 | 18 | POINT(3.5 3)
(1 row)
Analizar la red por espacios.
WITH
data AS (
SELECT id, geom, (in_edges || out_edges)[1] as inhere
FROM vertices where array_length(in_edges || out_edges, 1) = 1
),
results AS (
SELECT d.id, d.inhere,
(pgr_findCloseEdges('SELECT id, geom FROM edges WHERE id != ' || inhere , geom, 0.001)).*
FROM data d
)
SELECT
id, inhere, edge_id, fraction,
ST_AsText(geom) AS geom, ST_AsText(edge) AS edge
FROM results;
id | inhere | edge_id | fraction | geom | edge
----+--------+---------+----------+---------------------------+--------------------------------------
4 | 17 | 14 | 0.5 | POINT(1.999999999999 3.5) | LINESTRING(1.999999999999 3.5,2 3.5)
(1 row)
El análisis dice que la red tiene un hueco y una intersección.
Arreglando una intersección¶
Almacenando las intersecciones.
SELECT e1.id id1, e2.id id2, st_intersection(e1.geom, e2.geom) AS point
INTO intersections
FROM edges e1, edges e2
WHERE e1.id < e2.id AND st_crosses(e1.geom, e2.geom);
SELECT 1
Llamando a pgr_nodeNetwork
.
SELECT pgr_nodeNetwork('edges', 0.001, the_geom => 'geom', rows_where=>'id in ('||id1||','||id2||')')
FROM intersections;
NOTICE: PROCESSING:
NOTICE: id: id
NOTICE: the_geom: geom
NOTICE: table_ending: noded
NOTICE: rows_where: id in (13,18)
NOTICE: outall: f
NOTICE: pgr_nodeNetwork('edges', 0.001, 'id', 'geom', 'noded', 'id in (13,18)', f)
NOTICE: Performing checks, please wait .....
NOTICE: Processing, please wait .....
NOTICE: Split Edges: 2
NOTICE: Untouched Edges: 0
NOTICE: Total original Edges: 2
NOTICE: Edges generated: 4
NOTICE: Untouched Edges: 0
NOTICE: Total New segments: 4
NOTICE: New Table: public.edges_noded
NOTICE: ----------------------------------
pgr_nodenetwork
-----------------
OK
(1 row)
Inspeccionar la tabla generada, podemos ver que las aristas 13 y 18 ha sido segmentados.
SELECT old_id, ST_AsText(geom) FROM edges_noded ORDER BY old_id, sub_id;
old_id | st_astext
--------+---------------------------
13 | LINESTRING(3 3,3.5 3)
13 | LINESTRING(3.5 3,4 3)
18 | LINESTRING(3.5 2.3,3.5 3)
18 | LINESTRING(3.5 3,3.5 4)
(4 rows)
Actualizar la topología
Agregar segmentos a la tabla de aristas.
INSERT INTO edges (cost, reverse_cost, geom)
WITH
the_fractions AS (
SELECT e1.id id, st_lineLocatePoint(e1.geom, point) AS fraction
FROM intersections, edges e1, edges e2 WHERE e1.id = id1 AND e2.id = id2
UNION
SELECT e2.id, st_lineLocatePoint(e2.geom, point)
FROM intersections, edges e1, edges e2 WHERE e1.id = id1 AND e2.id = id2
)
SELECT
CASE WHEN sub_id = 1
THEN cost*fraction ELSE cost*(1-fraction) END as cost,
CASE WHEN sub_id = 1
THEN reverse_cost*(1-fraction) ELSE reverse_cost*(fraction) END AS reverse_cost,
segments.geom
FROM edges as edges
JOIN edges_noded as segments ON (edges.id = segments.old_id)
JOIN the_fractions f ON (segments.old_id = f.id);
INSERT 0 4
Insertar las intersecciones como nuevos vértices.
INSERT INTO vertices (id, geom)
SELECT row_number() over() + 100, point
FROM intersections;
INSERT 0 1
Actualizar la salida y el destino en la tabla de aristas.
UPDATE edges e SET source = v.id FROM
vertices v where source IS NULL AND (st_startPoint(e.geom) = v.geom);
UPDATE 4
UPDATE edges e SET target = v.id FROM
vertices v where target IS NULL AND (st_endPoint(e.geom) = v.geom);
UPDATE 4
Eliminar la arista original original.
DELETE FROM edges
WHERE id IN (
SELECT id1 FROM intersections
UNION
SELECT id2 FROM intersections);
DELETE 2
Actualizar la topología de vértices
WITH data AS (
select p.id, p.in_edges, p.out_edges
FROM pgr_extractVertices('select id, source, target from edges') p)
UPDATE vertices v
SET (in_edges,out_edges) = (d.in_edges,d.out_edges)
FROM data d where d.id = v.id;
UPDATE 18
Analyze the network for intersections.
SELECT e1.id, e2.id
FROM edges_noded e1, edges e2
WHERE e1.id < e2.id AND st_crosses(e1.geom, e2.geom);
id | id
----+----
(0 rows)
Fixing a gap¶
Almacenar los callejones sin salida
WITH
data AS (
SELECT id, geom, (in_edges || out_edges)[1] as inhere
FROM vertices where array_length(in_edges || out_edges, 1) = 1)
SELECT
d.id, d.inhere,
(pgr_findCloseEdges('SELECT id, geom FROM edges WHERE id != ' || inhere , geom, 0.001)).*
INTO deadends
FROM data d;
SELECT 1
Llamando a pgr_nodeNetwork
.
SELECT pgr_nodeNetwork('edges', 0.001, the_geom => 'geom', rows_where=>'id in ('||inhere||','||edge_id||')')
FROM deadends;
NOTICE: PROCESSING:
NOTICE: id: id
NOTICE: the_geom: geom
NOTICE: table_ending: noded
NOTICE: rows_where: id in (17,14)
NOTICE: outall: f
NOTICE: pgr_nodeNetwork('edges', 0.001, 'id', 'geom', 'noded', 'id in (17,14)', f)
NOTICE: Performing checks, please wait .....
NOTICE: Processing, please wait .....
NOTICE: Split Edges: 1
NOTICE: Untouched Edges: 1
NOTICE: Total original Edges: 2
NOTICE: Edges generated: 2
NOTICE: Untouched Edges: 1
NOTICE: Total New segments: 3
NOTICE: New Table: public.edges_noded
NOTICE: ----------------------------------
pgr_nodenetwork
-----------------
OK
(1 row)
Inspeccionar la tabla generada, podemos ver que la arista 14 ha sido segmentado.
SELECT old_id, ST_AsText(geom) FROM edges_noded ORDER BY old_id, sub_id;
old_id | st_astext
--------+----------------------------------------
14 | LINESTRING(2 3,1.999999999999 3.5)
14 | LINESTRING(1.999999999999 3.5,2 4)
17 | LINESTRING(0.5 3.5,1.999999999999 3.5)
(3 rows)
Actualizar la topología
Agregar segmentos a la tabla de aristas.
INSERT INTO edges (cost, reverse_cost, geom)
SELECT
CASE WHEN sub_id = 1 THEN cost*fraction ELSE cost*(1-fraction) END as cost,
CASE WHEN sub_id = 1 THEN reverse_cost*(1-fraction) ELSE reverse_cost*(fraction) END as reverse_cost, en.geom
FROM deadends r JOIN edges_noded en ON (old_id = edge_id) JOIN edges e ON (old_id = e.id)
UNION
SELECT 0,0,edge FROM deadends;
INSERT 0 3
Insertar las intersecciones como nuevos vértices.
/* Update the vertices table */
INSERT INTO vertices (id, geom)
select row_number() over() + 200, st_endpoint(edge) FROM deadends;
INSERT 0 1
Actualizar la salida y el destino en la tabla de aristas.
UPDATE edges e SET source = v.id FROM
vertices v where source IS NULL AND (st_startPoint(e.geom) = v.geom);
UPDATE 3
UPDATE edges e SET target = v.id FROM
vertices v where target IS NULL AND (st_endPoint(e.geom) = v.geom);
UPDATE 3
Eliminar la arista original original.
DELETE FROM edges WHERE id IN (SELECT edge_id FROM deadends);
DELETE 1
Actualizar la topología de vértices
WITH data AS (
select p.id, p.in_edges, p.out_edges
FROM pgr_extractVertices('select id, source, target from edges') p)
UPDATE vertices v
SET (in_edges,out_edges) = (d.in_edges,d.out_edges)
FROM data d where d.id = v.id;
UPDATE 19
Analizar la red por espacios.
WITH
data AS (
SELECT id, geom, (in_edges || out_edges)[1] as inhere
FROM vertices where array_length(in_edges || out_edges, 1) = 1),
results AS (
SELECT (pgr_findCloseEdges(
'SELECT id, geom FROM edges WHERE id != ' || inhere , geom, 0.001)).*,
d.id, d.inhere
FROM data d
)
SELECT * FROM results;
edge_id | fraction | side | distance | geom | edge | id | inhere
---------+----------+------+-----------------------+--------------------------------------------+------------------------------------------------------------------------------------+-----+--------
17 | 1 | l | 1.000088900582341e-12 | 010100000000000000000000400000000000000C40 | 01020000000200000000000000000000400000000000000C4068EEFFFFFFFFFF3F0000000000000C40 | 201 | 25
(1 row)
Ver también¶
Topología - Familia de Funciones para una visión general de una topología para algoritmos de enrutamiento.
Índices y tablas