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.

    • edge: Contains the LINESTRING geometry of the original point to the closest point on on edge \(8\) geom

One point dry run execution

  • Returns EMPTY SET.

  • partial => true

    • Is ignored

    • Because it is a dry run excecution, the code for all calculations are shown on the PostgreSQL NOTICE.

  • dryrun => true

    • Do not process query

    • Generate a PostgreSQL NOTICE with the code used to calculate all columns

      • cap and original point are used in the code

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)

Many points examples

At most two answers per point

  • 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 on edge

  • edge_id identifier of the edge close to a original point (geom)

    • Two edges at most withing \(0.5\) distance units from each of the original points:

      • For POINT(1.8 0.4) and POINT(0.3 1.8) only one edge was found.

      • For the rest of the points two edges were found.

  • For point POINT(2.9 1.8)

    • Edge \(5\) is before \(8\) therefore edge \(5\) has the shortest distance to 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\).

One answer per point, all columns

  • 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.

  • For the original point POINT(2.9 1.8)

    • Edge \(5\) is the closest edge to the original point

    • 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: Contains the geometry of the original point POINT(2.9 1.8)

    • edge: Contains the LINESTRING geometry of the original point (geom) to the closest point on on edge.

Many points dry run execution

  • Returns EMPTY SET.

  • partial => true

    • Is ignored

    • Because it is a dry run excecution, the code for all calculations are shown on the PostgreSQL NOTICE.

  • dryrun => true

    • Do not process query

    • Generate a PostgreSQL NOTICE with the code used to calculate all columns

      • cap and original point are used in the code

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)

Find at most two routes to a given point

Using 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)

A point of interest table

Handling points outside the graph.

Puntos de interés

Some times the applications work «on the fly» starting from a location that is not a vertex in the graph. Those locations, in pgRrouting are called points of interest.

The information needed in the points of interest is pid, edge_id, side, fraction.

On this documentation there will be some 6 fixed points of interest and they will be stored on a table.

Columna

Descripción

pid

A unique identifier.

edge_id

Identifier of the edge nearest edge that allows an arrival to the point.

side

Is it on the left, right or both sides of the segment edge_id

fraction

Where in the segment is the point located.

geom

The geometry of the points.

newPoint

The geometry of the points moved on top of the segment.

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