pgr_findCloseEdges
¶
pgr_findCloseEdges
- Encuentra las aristas cercanas a una geometría puntual.
![_images/boost-inside.jpeg](_images/boost-inside.jpeg)
Adentro: Boost Graph¶
Disponibilidad
Versión 3.4.0
Nuevas firmas propuestas:
pgr_findCloseEdges
(Un punto)pgr_findCloseEdges
(Muchos puntos)
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
[cap, partial, dryrun]
(edge_id, fraction, side, distance, geom, edge)
Un punto¶
[cap, partial, dryrun]
(edge_id, fraction, side, distance, geom, edge)
- 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 columnasdistance
,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¶
[cap, partial, dryrun]
(edge_id, fraction, side, distance, geom, edge)
- 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 descritas más adelante. |
|
punto |
|
La geometría del punto |
puntos |
|
Una matriz de geometrías de puntos |
tolerancia |
|
Distancia máxima entre geometrías |
Parámetros opcionales¶
Parámetro |
Tipo |
x Defecto |
Descripción |
---|---|---|---|
|
|
\(1\) |
Limitar las filas de salida |
|
|
|
|
|
|
|
|
Consultas Internas¶
SQL aristas¶
Columna |
Tipo |
Descripción |
---|---|---|
|
ENTEROS |
Identificador de la arista. |
|
|
La geometría |
Columnas de resultados¶
Regresa conjunto de (edge_id, fraction, side, distance, geom, edge)
Columna |
Tipo |
Descripción |
---|---|---|
|
|
Identificador de la arista.
|
|
|
El valor entre <0,1> indica la posición relativa desde el primer punto de la arista. |
|
|
Valor en
|
|
|
Distancia del punto a la arista.
|
|
|
geometría
|
|
|
Geometría |
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 congeom
![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}
}
}](_images/graphviz-f095009bc5e25b0759561a55f4bc2634d170824b.png)
Resultados de muchos puntos
Los nodos verdes son los puntos originales
La geometría
geom
, marcada como g1 y g2 son los puntos originalesLa 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}
}
}](_images/graphviz-c1aa13dbbbf1cb5c2eff7da689f0cf61b8653ab4.png)
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
engeom
,edge
edge_id
identificador de la arista cercana al punto originalDos 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 originalDe 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íaLINESTRING
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 originalDos 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íaLINESTRING
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 theLINESTRING
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 columnscap
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
onedge
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)
andPOINT(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 originalDe 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 pointPOINT(2.9 1.8)
edge
: Contains theLINESTRING
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 columnscap
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 |
---|---|
|
A unique identifier. |
|
Identifier of the edge nearest edge that allows an arrival to the point. |
|
Is it on the left, right or both sides of the segment |
|
Where in the segment is the point located. |
|
The geometry of the points. |
|
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