Versiones soportadas: latest (3.8) 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0 main dev
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]

| RETURNS TEXT

Disponibilidad

  • Versión 3.8.0

    • Not checking and not creating indexes.

    • Using pgr_separateTouching and pgr_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 es noded.

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