pgr_findCloseEdges

pgr_findCloseEdges - Encuentra las aristas cercanas a una geometría puntual.

_images/boost-inside.jpeg

Adentro: Boost Graph

Disponibilidad

  • Versión 3.4.0

Descripción

pgr_findCloseEdges - Función de utilidad que encuentra la arista más cercana a una geometría de puntos.

  • Las geometrías deben estar en el mismo sistema de coordenadas (tener el mismo SRID).

  • El código para realizar los cálculos puede obtenerse para realizar los ajustes específicos que necesite la aplicación.

  • EMTPY SET se devuelve en ejecuciones en seco

Firmas

Resumen

pgr_findCloseEdges(Edges SQL, punto, tolerancia, [options])
pgr_findCloseEdges(Edges SQL, puntos, tolerancia, [options])
opcionales: [cap, partial, dryrun]
Regresa conjunto de (edge_id, fraction, side, distance, geom, edge)
O CONJUNTO VACÍO

Un punto

pgr_findCloseEdges(Edges SQL, punto, tolerancia, [options])
opcionales: [cap, partial, dryrun]
Regresa conjunto de (edge_id, fraction, side, distance, geom, edge)
O CONJUNTO VACÍO
Ejemplo:

Con valores predeterminados

  • Por defecto: cap => 1

    • Respuesta de una fila como máximo.

  • Por defecto: partial => true

    • Con menos cálculos posibles.

  • Por defecto: dryrun => false

    • Consulta del proceso

  • Devuelve

    • valores en las columnas edge_id, fraction, side.

    • NULL en las columnas distance, geom, edge.

SELECT  *
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT geom FROM pointsOfInterest WHERE pid = 5),
  0.5);
 edge_id | fraction | side | distance | geom | edge
---------+----------+------+----------+------+------
       5 |      0.8 | l    |          |      |
(1 row)

Muchos puntos

pgr_findCloseEdges(Edges SQL, puntos, tolerancia, [options])
opcionales: [cap, partial, dryrun]
Regresa conjunto de (edge_id, fraction, side, distance, geom, edge)
O CONJUNTO VACÍO
Ejemplo:

Encuentra como máximo \(2\) aristas cercanas a todos los vértices de la tabla de puntos de interés.

Una respuesta por punto, lo más pequeña posible.

SELECT edge_id, round(fraction::numeric, 2) AS fraction, side, ST_AsText(geom) AS original_point
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT array_agg(geom) FROM pointsOfInterest),
  0.5);
 edge_id | fraction | side | original_point
---------+----------+------+----------------
       1 |     0.40 | l    | POINT(1.8 0.4)
       6 |     0.30 | r    | POINT(0.3 1.8)
      12 |     0.60 | l    | POINT(2.6 3.2)
      15 |     0.40 | r    | POINT(4.2 2.4)
       5 |     0.80 | l    | POINT(2.9 1.8)
       4 |     0.70 | r    | POINT(2.2 1.7)
(6 rows)

Las columnas edge_id, fraction, side y geom se devuelven con valores.

geom contiene la geometría de puntos original para ayudar a determinar a qué geometría de puntos pertenece la fila.

Parámetros

Parámetro

Tipo

Descripción

SQL de aristas

TEXT

SQL de aristas descritas más adelante.

punto

POINT

La geometría del punto

puntos

POINT

Una matriz de geometrías de puntos

tolerancia

FLOAT

Distancia máxima entre geometrías

Parámetros opcionales

Parámetro

Tipo

x Defecto

Descripción

cap

INTEGER

\(1\)

Limitar las filas de salida

parcial

BOOLEAN

true

  • Cuando true sólo se calculan las columnas necesarias para withPoints- Categoría.

  • Cuando false se calculan todas las columnas

dryrun

BOOLEAN

false

  • Cuando false se realizan los cálculos.

  • Cuando true los cálculos no se realizan y la consulta para hacer los cálculos se expone en un NOTICE de PostgreSQL.

Consultas Internas

SQL aristas

Columna

Tipo

Descripción

id

ENTEROS

Identificador de la arista.

geom

geometry

La geometría LINESTRING de la arista.

Columnas de resultados

Regresa conjunto de (edge_id, fraction, side, distance, geom, edge)

Columna

Tipo

Descripción

edge_id

BIGINT

Identificador de la arista.

  • Cuando \(cap = 1\), es la arista más cercana.

fraction

FLOAT

El valor entre <0,1> indica la posición relativa desde el primer punto de la arista.

side

CHAR

Valor en [r, l] que indica si el punto es:

  • A la derecha r.

  • A la izquierda l.

    • Cuando el punto está en la línea se considera que está a la derecha.

distancia

FLOAT

Distancia del punto a la arista.

  • NULL cuando cap = 1 en la firma de Un punto

geom

geometry

geometría POINT

  • Un Punto: Contiene el punto de la arista que está a fraction del punto inicial de la arista.

  • Muchos Puntos: Contiene el punto original correspondiente

edge

geometry

Geometría LINESTRING desde el punto original hasta el punto más cercano de la arista con identificador edge_id

Resultados de un punto

  • Los nodos verdes son el punto original

  • La geometría geom es un punto en la arista \(sp \rightarrow ep\).

  • La geometría edge es una línea que conecta el punto original con geom

digraph G {
  splines=false;
  subgraph cluster0 {
    point [shape=circle;style=filled;color=green];
    geom [shape=point;color=black;size=0];
    sp, ep;

    edge[weight=0];
    point -> geom [dir=none; penwidth=0, color=red];
    edge[weight=2];
    sp -> geom -> ep [dir=none;penwidth=3 ];

    {rank=same; point, geom}
  }

  subgraph cluster1 {
    point1 [shape=circle;style=filled;color=green;label=point];
    geom1 [shape=point;color=deepskyblue; xlabel="geom"; width=0.3];
    sp1 [label=sp]; ep1 [label=ep];

    edge[weight=0];
    point1 -> geom1 [weight=0, penwidth=3, color=red,
                   label="edge"];
    edge[weight=2];
    sp1 -> geom1 -> ep1 [dir=none;weight=1, penwidth=3 ];


    geom1 -> point1 [dir=none;weight=0, penwidth=0, color=red];
    {rank=same; point1, geom1}
  }
}

Resultados de muchos puntos

  • Los nodos verdes son los puntos originales

  • La geometría geom, marcada como g1 y g2 son los puntos originales

  • La geometría edge, marcada como edge1 y edge2 es una línea que conecta el punto original con el punto más cercano de la arista \(sp \rightarrow ep\).

digraph G {
  splines = false;
  subgraph cluster0 {
     p1 [shape=circle;style=filled;color=green];
     g1 [shape=point;color=black;size=0];
     g2 [shape=point;color=black;size=0];
     sp, ep;
     p2 [shape=circle;style=filled;color=green];

     sp -> g1 [dir=none;weight=1, penwidth=3 ];
     g1 -> g2 [dir=none;weight=1, penwidth=3 ];
     g2 -> ep [weight=1, penwidth=3 ];

     g2 -> p2 [dir=none;weight=0, penwidth=0, color=red, partiallen=3];
     p1 -> g1 [dir=none;weight=0, penwidth=0, color=red, partiallen=3];
     p1 -> {g1, g2} [dir=none;weight=0, penwidth=0, color=red;]

     {rank=same; p1; g1}
     {rank=same; p2; g2}
  }
  subgraph cluster1 {
     p3 [shape=circle;style=filled;color=deepskyblue;label=g1];
     g3 [shape=point;color=black;size=0];
     g4 [shape=point;color=black;size=0];
     sp1 [label=sp]; ep1 [label=ep];
     p4 [shape=circle;style=filled;color=deepskyblue;label=g2];

     sp1 -> g3 [dir=none;weight=1, penwidth=3 ];
     g3 -> g4 [dir=none;weight=1, penwidth=3,len=10];
     g4 -> ep1 [weight=1, penwidth=3, len=10];

     g4 -> p4 [dir=back;weight=0, penwidth=3, color=red, partiallen=3,
                    label="edge2"];
     p3 -> g3 [weight=0, penwidth=3, color=red, partiallen=3,
                    label="edge1"];
     p3 -> {g3, g4} [dir=none;weight=0, penwidth=0, color=red];

     {rank=same; p3; g3}
     {rank=same; p4; g4}
  }
}

Ejemplos Adicionales

Ejemplos de un punto

Como máximo dos respuestas

  • cap => 2

    • Respuesta de dos filas como máximo.

  • Por defecto: partial => true

    • Con menos cálculos posibles.

  • Por defecto: dryrun => false

    • Consulta del proceso

SELECT *
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT geom FROM pointsOfInterest WHERE pid = 5),
  0.5, cap => 2);
 edge_id |      fraction      | side |      distance       | geom | edge
---------+--------------------+------+---------------------+------+------
       5 |                0.8 | l    | 0.10000000000000009 |      |
       8 | 0.8999999999999999 | r    | 0.19999999999999996 |      |
(2 rows)

Comprendiendo el resultado

  • NULL en geom, edge

  • edge_id identificador de la arista cercana al punto original

    • Dos aristas están a menos de \(0.5\) unidades de distancia del punto original: \({5, 8}\)

  • Para la arista \(5\):

    • fraction: El punto más cercano desde el punto original está en la fracción \(0.8\) del borde \(5\).

    • side: El punto original está situado a la izquierda de la arista \(5\).

    • distance: El punto original está situado a \(0.1\) unidades de longitud de la arista \(5\).

  • Para la arista \(8\):

    • fraction: El punto más cercano desde el punto original está en la fracción \(0.89..\) del borde \(8\).

    • side: El punto original está situado a la derecha de la arista \(8\).

    • distance: El punto original se encuentra a \(0.19..\) unidades de longitud de la arista \(8\).

Una respuesta, todas las columnas

  • Por defecto: cap => 1

    • Respuesta de una fila como máximo.

  • partial => false

    • Calcular todas las columnas

  • Por defecto: dryrun => false

    • Consulta del proceso

SELECT edge_id, round(fraction::numeric, 2) AS fraction, side, round(distance::numeric, 3) AS distance,
  ST_AsText(geom) AS new_point,
  ST_AsText(edge) AS original_to_new_point
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT geom FROM pointsOfInterest WHERE pid = 5),
  0.5, partial => false);
 edge_id | fraction | side | distance |  new_point   |   original_to_new_point
---------+----------+------+----------+--------------+---------------------------
       5 |     0.80 | l    |    0.100 | POINT(3 1.8) | LINESTRING(2.9 1.8,3 1.8)
(1 row)

Comprendiendo el resultado

  • edge_id identificador de la arista más cercana al punto original

    • De todos los bordes dentro de \(0.5\) unidades de distancia desde el punto original: \({5}\) es el más cercano.

  • Para la arista \(5\):

    • fraction: El punto más cercano desde el punto original está en la fracción \(0.8\) del borde \(5\).

    • side: El punto original está situado a la izquierda de la arista \(5\).

    • distance: El punto original está situado a \(0.1\) unidades de longitud de la arista \(5\).

    • geom: Contiene la geometría del punto más cercano de la arista \(5\) desde el punto original.

    • edge: Contiene la geometría LINESTRING del punto original al punto más cercano de la arista \(5\) geom

Como máximo dos respuestas con todas las columnas

  • cap => 2

    • Respuesta de dos filas como máximo.

  • partial => false

    • Calcular todas las columnas

  • Por defecto: dryrun => false

    • Consulta del proceso

SELECT edge_id, round(fraction::numeric, 2) AS fraction, side, round(distance::numeric, 3) AS distance,
  ST_AsText(geom) AS new_point,
  ST_AsText(edge) AS original_to_new_point
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT geom FROM pointsOfInterest WHERE pid = 5),
  0.5, cap => 2, partial => false);
 edge_id | fraction | side | distance |  new_point   |   original_to_new_point
---------+----------+------+----------+--------------+---------------------------
       5 |     0.80 | l    |    0.100 | POINT(3 1.8) | LINESTRING(2.9 1.8,3 1.8)
       8 |     0.90 | r    |    0.200 | POINT(2.9 2) | LINESTRING(2.9 1.8,2.9 2)
(2 rows)

Comprender el resultado:

  • edge_id identificador de la arista cercana al punto original

    • Dos aristas están a menos de \(0.5\) unidades de distancia del punto original: \({5, 8}\)

  • Para la arista \(5\):

    • fraction: El punto más cercano desde el punto original está en la fracción \(0.8\) del borde \(5\).

    • side: El punto original está situado a la izquierda de la arista \(5\).

    • distance: El punto original está situado a \(0.1\) unidades de longitud de la arista \(5\).

    • geom: Contiene la geometría del punto más cercano de la arista \(5\) desde el punto original.

    • edge: Contiene la geometría LINESTRING del punto original al punto más cercano de la arista \(5\) geom

  • Para la arista \(8\):

    • fraction: El punto más cercano desde el punto original está en la fracción \(0.89..\) del borde \(8\).

    • side: El punto original está situado a la derecha de la arista \(8\).

    • distance: El punto original se encuentra a \(0.19..\) unidades de longitud de la arista \(8\).

    • geom: Contiene la geometría del punto más cercano de la arista \(8\) desde el punto original.

    • borde: Contiene la geometría LINESTRING del punto original al punto más cercano de la arista \(8\) geom

Ejecución en seco de un punto

  • Devuelve CONJUNTO VACÍO.

  • partial => true

    • Se ignora

    • Dado que se trata de una ejecución dry run, el código de todos los cálculos se muestra en el NOTICE de PostgreSQL.

  • dryrun => true

    • No procesar la consulta

    • Generar un NOTICE de PostgreSQL con el código utilizado para calcular todas las columnas

      • cap y punto original se utilizan en el código

SELECT *
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT geom FROM pointsOfInterest WHERE pid = 5),
  0.5,
  dryrun => true);
NOTICE:
    WITH
    edges_sql AS (SELECT id, geom FROM edges),
    point_sql AS (SELECT '01010000003333333333330740CDCCCCCCCCCCFC3F'::geometry AS point)

    SELECT
      id::BIGINT AS edge_id,
      ST_LineLocatePoint(geom, point) AS fraction,
      CASE WHEN ST_Intersects(ST_Buffer(geom, 0.5, 'side=right endcap=flat'), point)
           THEN 'r'
           ELSE 'l' END::CHAR AS side,

        geom <-> point AS distance,
        ST_ClosestPoint(geom, point) AS new_point,
        ST_MakeLine(point, ST_ClosestPoint(geom, point)) AS new_line

    FROM  edges_sql, point_sql
    WHERE ST_DWithin(geom,  point, 0.5)
    ORDER BY geom <-> point LIMIT 1

 edge_id | fraction | side | distance | geom | edge
---------+----------+------+----------+------+------
(0 rows)

Ejemplos de muchos puntos

Un máximo de dos respuestas por punto

  • cap => 2

    • Respuesta de dos filas como máximo.

  • Por defecto: partial => true

    • Con menos cálculos posibles.

  • Por defecto: dryrun => false

    • Consulta del proceso

SELECT edge_id, round(fraction::numeric, 2) AS fraction, side, round(distance::numeric, 3) AS distance,
  ST_AsText(geom) AS geom_is_original, edge
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT array_agg(geom) FROM pointsOfInterest),
  0.5, cap => 2);
 edge_id | fraction | side | distance | geom_is_original | edge
---------+----------+------+----------+------------------+------
       1 |     0.40 | l    |    0.200 | POINT(1.8 0.4)   |
       6 |     0.30 | r    |    0.200 | POINT(0.3 1.8)   |
      12 |     0.60 | l    |    0.200 | POINT(2.6 3.2)   |
      11 |     1.00 | l    |    0.447 | POINT(2.6 3.2)   |
      15 |     0.40 | r    |    0.200 | POINT(4.2 2.4)   |
       9 |     1.00 | l    |    0.447 | POINT(4.2 2.4)   |
       5 |     0.80 | l    |    0.100 | POINT(2.9 1.8)   |
       8 |     0.90 | r    |    0.200 | POINT(2.9 1.8)   |
       4 |     0.70 | r    |    0.200 | POINT(2.2 1.7)   |
       8 |     0.20 | r    |    0.300 | POINT(2.2 1.7)   |
(10 rows)

Comprendiendo el resultado

  • NULL en edge

  • edge_id identificador de la arista cercana a un punto original (geom)

    • Dos aristas a un máximo de \(0.5\) unidades de distancia de cada uno de los puntos originales:

      • Para POINT(1.8 0.4) y POINT(0.3 1.8) sólo se encontró una arista.

      • Para el resto de los puntos se encontraron dos aristas.

  • Para el punto POINT(2.9 1.8)

    • La arista \(5\) está antes que la arista \(8\) por lo tanto la arista \(5\) tiene la distancia más corta a POINT(2.9 1.8).

    • Para la arista \(5\):

      • fraction: El punto más cercano desde el punto original está en la fracción \(0.8\) del borde \(5\).

      • side: El punto original está situado a la izquierda de la arista \(5\).

      • distance: El punto original está situado a \(0.1\) unidades de longitud de la arista \(5\).

    • Para la arista \(8\):

      • fraction: El punto más cercano desde el punto original está en la fracción \(0.89..\) del borde \(8\).

      • side: El punto original está situado a la derecha de la arista \(8\).

      • distance: El punto original se encuentra a \(0.19..\) unidades de longitud de la arista \(8\).

Una respuesta por punto, todas las columnas

  • Por defecto: cap => 1

    • Respuesta de una fila como máximo.

  • partial => false

    • Calcular todas las columnas

  • Por defecto: dryrun => false

    • Consulta del proceso

SELECT edge_id, round(fraction::numeric, 2) AS fraction, side, round(distance::numeric, 3) AS distance,
  ST_AsText(geom) AS geom_is_original,
  ST_AsText(edge) AS original_to_new_point
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT array_agg(geom) FROM pointsOfInterest),
  0.5, partial => false);
 edge_id | fraction | side | distance | geom_is_original |   original_to_new_point
---------+----------+------+----------+------------------+---------------------------
       1 |     0.40 | l    |    0.200 | POINT(1.8 0.4)   | LINESTRING(1.8 0.4,2 0.4)
       6 |     0.30 | r    |    0.200 | POINT(0.3 1.8)   | LINESTRING(0.3 1.8,0.3 2)
      12 |     0.60 | l    |    0.200 | POINT(2.6 3.2)   | LINESTRING(2.6 3.2,2.6 3)
      15 |     0.40 | r    |    0.200 | POINT(4.2 2.4)   | LINESTRING(4.2 2.4,4 2.4)
       5 |     0.80 | l    |    0.100 | POINT(2.9 1.8)   | LINESTRING(2.9 1.8,3 1.8)
       4 |     0.70 | r    |    0.200 | POINT(2.2 1.7)   | LINESTRING(2.2 1.7,2 1.7)
(6 rows)

Comprendiendo el resultado

  • edge_id identificador de la arista más cercana al punto original

    • De todos los bordes dentro de \(0.5\) unidades de distancia desde el punto original: \({5}\) es el más cercano.

  • Para el punto original POINT(2.9 1.8)

    • La arista \(5\) es la más cercana al punto original

    • fraction: El punto más cercano desde el punto original está en la fracción \(0.8\) del borde \(5\).

    • side: El punto original está situado a la izquierda de la arista \(5\).

    • distance: El punto original está situado a \(0.1\) unidades de longitud de la arista \(5\).

    • geom: Contiene la geometría del punto original POINT(2.9 1.8)

    • edge: Contiene la geometría LINESTRING del punto original (geom) al punto más cercano en el borde.

Ejecución en seco de muchos puntos

  • Devuelve CONJUNTO VACÍO.

  • partial => true

    • Se ignora

    • Dado que se trata de una ejecución dry run, el código de todos los cálculos se muestra en el NOTICE de PostgreSQL.

  • dryrun => true

    • No procesar la consulta

    • Generar un NOTICE de PostgreSQL con el código utilizado para calcular todas las columnas

      • cap y punto original se utilizan en el código

SELECT *
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges$$,
  (SELECT array_agg(geom) FROM pointsOfInterest),
  0.5,
  dryrun => true);
NOTICE:
WITH
edges_sql AS (SELECT id, geom FROM edges),
point_sql AS (SELECT unnest('{0101000000CDCCCCCCCCCCFC3F9A9999999999D93F:0101000000CDCCCCCCCCCC10403333333333330340:0101000000CDCCCCCCCCCC04409A99999999990940:0101000000333333333333D33FCDCCCCCCCCCCFC3F:01010000003333333333330740CDCCCCCCCCCCFC3F:01010000009A99999999990140333333333333FB3F}'::geometry[]) AS point),
results AS (
  SELECT
    id::BIGINT AS edge_id,
    ST_LineLocatePoint(geom, point) AS fraction,
    CASE WHEN ST_Intersects(ST_Buffer(geom, 0.5, 'side=right endcap=flat'), point)
         THEN 'r'
         ELSE 'l' END::CHAR AS side,
    geom <-> point AS distance,
    point,
    ST_MakeLine(point, ST_ClosestPoint(geom, point)) AS new_line
  FROM  edges_sql, point_sql
  WHERE ST_DWithin(geom, point, 0.5)
  ORDER BY geom <-> point),
prepare_cap AS (
  SELECT row_number() OVER (PARTITION BY point ORDER BY point, distance) AS rn, *
  FROM results)
SELECT edge_id, fraction, side, distance, point, new_line
FROM prepare_cap
WHERE rn <= 1

 edge_id | fraction | side | distance | geom | edge
---------+----------+------+----------+------+------
(0 rows)

Encontrar como máximo dos rutas a un punto dado

Usando pgr_withPoints - Propuesto

SELECT * FROM pgr_withPoints(
  $e$ SELECT * FROM edges $e$,
  $p$ SELECT edge_id, round(fraction::numeric, 2) AS fraction, side
      FROM pgr_findCloseEdges(
        $$SELECT id, geom FROM edges$$,
        (SELECT geom FROM pointsOfInterest WHERE pid = 5),
        0.5, cap => 2)
  $p$,
  1, ARRAY[-1, -2]);
 seq | path_seq | end_pid | node | edge | cost | agg_cost
-----+----------+---------+------+------+------+----------
   1 |        1 |      -2 |    1 |    6 |    1 |        0
   2 |        2 |      -2 |    3 |    7 |    1 |        1
   3 |        3 |      -2 |    7 |    8 |  0.9 |        2
   4 |        4 |      -2 |   -2 |   -1 |    0 |      2.9
   5 |        1 |      -1 |    1 |    6 |    1 |        0
   6 |        2 |      -1 |    3 |    7 |    1 |        1
   7 |        3 |      -1 |    7 |    8 |    1 |        2
   8 |        4 |      -1 |   11 |    9 |    1 |        3
   9 |        5 |      -1 |   16 |   16 |    1 |        4
  10 |        6 |      -1 |   15 |    3 |    1 |        5
  11 |        7 |      -1 |   10 |    5 |  0.8 |        6
  12 |        8 |      -1 |   -1 |   -1 |    0 |      6.8
(12 rows)

Una tabla de puntos de interés

Manejo de puntos fuera del gráfico.

Puntos de interés

Algunas veces las aplicaciones trabajan «sobre la marcha» comenzando desde una localización que no es un vértice en el grafo. Esas localizaciones, en pgRrouting se llaman puntos de interés.

La información necesaria en los puntos de interés es pid, edge_id, side, fraction.

En esta documentación habrá unos 6 puntos de interés fijos y se almacenarán en una tabla.

Columna

Descripción

pid

Un identificador único.

edge_id

Identificador de la arista más cercana que permite una llegada al punto.

side

Está a la izquierda, a la derecha o a ambos lados del segmento edge_id

fraction

En qué parte del segmento se encuentra el punto.

geom

La geometría de los puntos.

newPoint

La geometría de los puntos desplazados sobre el segmento.

CREATE TABLE pointsOfInterest(
    pid BIGSERIAL PRIMARY KEY,
    edge_id BIGINT,
    side CHAR,
    fraction FLOAT,
    geom geometry);
CREATE TABLE

LLenado de puntos de interés

INSERT INTO pointsOfInterest (edge_id, side, fraction, geom) VALUES
(1, 'l' , 0.4, ST_POINT(1.8, 0.4)),
(15, 'r' , 0.4, ST_POINT(4.2, 2.4)),
(12, 'l' , 0.6, ST_POINT(2.6, 3.2)),
(6, 'r' , 0.3, ST_POINT(0.3, 1.8)),
(5, 'l' , 0.8, ST_POINT(2.9, 1.8)),
(4, 'b' , 0.7, ST_POINT(2.2, 1.7));
INSERT 0 6

Conectando componentes desconectados

Para obtener la conectividad del grafo:

SELECT * FROM pgr_connectedComponents(
  'SELECT id, source, target, cost, reverse_cost FROM edges'
);
 seq | component | node
-----+-----------+------
   1 |         1 |    1
   2 |         1 |    3
   3 |         1 |    5
   4 |         1 |    6
   5 |         1 |    7
   6 |         1 |    8
   7 |         1 |    9
   8 |         1 |   10
   9 |         1 |   11
  10 |         1 |   12
  11 |         1 |   13
  12 |         1 |   14
  13 |         1 |   15
  14 |         1 |   16
  15 |         1 |   17
  16 |         1 |   18
  17 |         2 |    2
  18 |         2 |    4
(18 rows)

En este ejemplo, el componente \(2\) está formado por vértices \(\{2, 4\}\) y ambos vértices también forman parte del conjunto de resultados sin salida.

Este grafo debe estar conectado.

Nota

Con el grafo original de esta documentación, habría 3 componentes, ya que la arista de cruce en este grafo es un componente diferente.

Preparar el almacenamiento de la información de conexión

ALTER TABLE vertices ADD COLUMN component BIGINT;
ALTER TABLE
ALTER TABLE edges ADD COLUMN component BIGINT;
ALTER TABLE

Guardar la información de conexión de los vértices

UPDATE vertices SET component = c.component
FROM (SELECT * FROM pgr_connectedComponents(
  'SELECT id, source, target, cost, reverse_cost FROM edges'
)) AS c
WHERE id = node;
UPDATE 18

Guardar la información de conexión de las aristas

UPDATE edges SET component = v.component
FROM (SELECT id, component FROM vertices) AS v
WHERE source = v.id;
UPDATE 20

Obtener el vértice más cercano

Usando pgr_findCloseEdges el vértice más cercano al componente \(1\) es el vértice \(4\). Y la arista más cercana al vértice \(4\) es la arista \(14\).

SELECT edge_id, fraction, ST_AsText(edge) AS edge, id AS closest_vertex
FROM pgr_findCloseEdges(
  $$SELECT id, geom FROM edges WHERE component = 1$$,
  (SELECT array_agg(geom) FROM vertices WHERE component = 2),
  2, partial => false) JOIN vertices USING (geom) ORDER BY distance LIMIT 1;
 edge_id | fraction |                 edge                 | closest_vertex
---------+----------+--------------------------------------+----------------
      14 |      0.5 | LINESTRING(1.999999999999 3.5,2 3.5) |              4
(1 row)

La arista edge se puede utilizar para conectar los componentes, utilizando la información fraction sobre la arista \(14\) para dividir la arista de conexión.

Conectando componentes

Existen tres formas básicas de conectar los componentes

  • Del vértice al punto inicial de la arista

  • Desde el vértice hasta el punto final de la arista

  • Del vértice al vértice más cercano de la arista

    • Esta solución requiere dividir el borde.

La siguiente consulta muestra las tres formas de conectar los componentes:

WITH
info AS (
  SELECT
    edge_id, fraction, side, distance, ce.geom, edge, v.id AS closest,
    source, target, capacity, reverse_capacity, e.geom AS e_geom
  FROM pgr_findCloseEdges(
    $$SELECT id, geom FROM edges WHERE component = 1$$,
    (SELECT array_agg(geom) FROM vertices WHERE component = 2),
    2, partial => false) AS ce
  JOIN vertices AS v USING (geom)
  JOIN edges AS e ON (edge_id = e.id)
  ORDER BY distance LIMIT 1),
three_options AS (
  SELECT
    closest AS source, target, 0 AS cost, 0 AS reverse_cost,
    capacity, reverse_capacity,
    ST_X(geom) AS x1, ST_Y(geom) AS y1,
    ST_X(ST_EndPoint(e_geom)) AS x2, ST_Y(ST_EndPoint(e_geom)) AS y2,
    ST_MakeLine(geom, ST_EndPoint(e_geom)) AS geom
  FROM info
  UNION
  SELECT closest, source, 0, 0, capacity, reverse_capacity,
    ST_X(geom) AS x1, ST_Y(geom) AS y1,
    ST_X(ST_StartPoint(e_geom)) AS x2, ST_Y(ST_StartPoint(e_geom)) AS y2,
    ST_MakeLine(info.geom, ST_StartPoint(e_geom))
  FROM info
  /*
  UNION
  -- This option requires splitting the edge
  SELECT closest, NULL, 0, 0, capacity, reverse_capacity,
    ST_X(geom) AS x1, ST_Y(geom) AS y1,
    ST_X(ST_EndPoint(edge)) AS x2, ST_Y(ST_EndPoint(edge)) AS y2,
    edge
  FROM info */
  )
INSERT INTO edges
  (source, target,
    cost, reverse_cost,
    capacity, reverse_capacity,
    x1, y1, x2, y2,
    geom)
(SELECT
    source, target, cost, reverse_cost, capacity, reverse_capacity,
    x1, y1, x2, y2, geom
  FROM three_options);
INSERT 0 2

Revisando componentes

Ignorando la arista que requiere más trabajo. El grafo está ahora totalmente conectado, ya que sólo hay un componente.

SELECT * FROM pgr_connectedComponents(
  'SELECT id, source, target, cost, reverse_cost FROM edges'
);
 seq | component | node
-----+-----------+------
   1 |         1 |    1
   2 |         1 |    2
   3 |         1 |    3
   4 |         1 |    4
   5 |         1 |    5
   6 |         1 |    6
   7 |         1 |    7
   8 |         1 |    8
   9 |         1 |    9
  10 |         1 |   10
  11 |         1 |   11
  12 |         1 |   12
  13 |         1 |   13
  14 |         1 |   14
  15 |         1 |   15
  16 |         1 |   16
  17 |         1 |   17
  18 |         1 |   18
(18 rows)

Ver también

Índices y tablas