pgr_findCloseEdges
¶
pgr_findCloseEdges
-查找点几何图形的闭合边。
可用性
描述¶
pgr_findCloseEdges
- 一个用于找到离点几何最近的边的实用函数。
几何图形必须位于同一坐标系中(具有相同的 SRID)。
可以获取计算代码,以便根据应用需要进行进一步的具体调整。
空运行执行时返回
EMTPY SET
签名¶
总结
[cap, partial, dryrun]
(edge_id, fraction, side, distance, geom, edge)
一个点¶
[cap, partial, dryrun]
(edge_id, fraction, side, distance, geom, edge)
- 示例:
有默认值
默认:
cap => 1
最多回答一行。
默认:
partial => true
尽可能减少计算。
默认:
dryrun => false
过程查询
返回
edge_id
,fraction
,side
列的值。distance
,geom
,edge``列上为``NULL
。
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)
多点¶
[cap, partial, dryrun]
(edge_id, fraction, side, distance, geom, edge)
- 示例:
最多找出 \(2\) 接近兴趣点表上所有顶点的边。
每点一个答案,越小越好。
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)
返回了带有值的列 edge_id
, fraction
, side
和 geom
。
geom
包含原始的点几何信息,以帮助确定该行属于哪个点几何。
参数¶
参数 |
类型 |
描述 |
---|---|---|
|
Edges SQL 如下所述。 |
|
point |
|
点几何 |
points |
|
点几何数组 |
tolerance |
|
几何图形之间的最大距离 |
可选参数¶
参数 |
类型 |
默认 |
描述 |
---|---|---|---|
|
|
\(1\) |
限制输出行数 |
|
|
|
|
|
|
|
|
内部查询¶
Edges SQL¶
列 |
类型 |
描述 |
---|---|---|
|
ANY-INTEGER |
边的标识符。 |
|
|
边的 |
结果列¶
返回集合 (edge_id, fraction, side, distance, geom, edge)
列 |
类型 |
描述 |
---|---|---|
|
|
边的标识符。
|
|
|
在 <0,1> 范围内的值,表示相对于边的第一个端点的相对位置。 |
|
|
|
|
|
点到边缘的距离。
|
|
|
|
|
|
从 原始点 到具有标识符 |
单一点的结果
绿色节点是 原始点
几何
geom
是 \(sp \rightarrow ep\) 边上的一个点。几何
edge
是连接 original point 和geom
的线
多点成果
绿色节点为 原始点
标为 g1 和 g2 的几何体
geom
是 原始点标为 edge1 和 edge2 的几何图形
edge
是一条连接 ** 原始点** 和 \(sp \rightarrow ep\) 边上最近点的线。
其他示例¶
单点示例¶
最多两个答案¶
cap => 2
最多回答两行。
默认:
partial => true
尽可能减少计算。
默认:
dryrun => false
过程查询
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)
了解结果
NULL
在geom
,edge
上edge_id
靠近 原始点 的边的标识符有两条边与 原始点 : \({5, 8}\) 的距离在 \(0.5\) 单位范围内
对于边 \(5\):
fraction
:离 原始点 最近的点位于边 \(5\) 处的 \(0.8\) 分数位置。side
: 原始点 位于边 \(5\) 的左侧。distance
: 原始点 位于边 \(5\) 的 \(0.1\) 长度单位处。
对于边 \(8\):
fraction
:离 原始点 最近的点位于边 \(8\) 的 \(0.89..\) 分数位置。side
: 原始点 位于边 \(8\) 的右侧。distance
: 原始点 距离边 \(8\) 有 \(0.19..\) 长度单位。
一个答案,所有列¶
默认:
cap => 1
最多回答一行。
partial => false
计算所有列
默认:
dryrun => false
过程查询
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)
了解结果
edge_id
与 原始点 最 接近 的边的标识符从距离 原始点 不超过 \(0.5\) 距离单位的所有边中,边 \({5}\) 是最近的一条。
对于边 \(5\):
fraction
:离 原始点 最近的点位于边 \(5\) 处的 \(0.8\) 分数位置。side
: 原始点 位于边 \(5\) 的左侧。distance
: 原始点 位于边 \(5\) 的 \(0.1\) 长度单位处。geom
:包含了从 原始点 到边 \(5\) 上最近点的几何形状。edge
:包含了从 原始点 到边 \(5\)geom
上最近点的LINESTRING
几何形状
所有列最多有两个答案¶
cap => 2
最多回答两行。
partial => false
计算所有列
默认:
dryrun => false
过程查询
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)
了解结果:
edge_id
靠近 原始点 的边的标识符有两条边与 原始点 : \({5, 8}\) 的距离在 \(0.5\) 单位范围内
对于边 \(5\):
fraction
:离 原始点 最近的点位于边 \(5\) 处的 \(0.8\) 分数位置。side
: 原始点 位于边 \(5\) 的左侧。distance
: 原始点 位于边 \(5\) 的 \(0.1\) 长度单位处。geom
:包含了从 原始点 到边 \(5\) 上最近点的几何形状。edge
:包含了从 原始点 到边 \(5\)geom
上最近点的LINESTRING
几何形状
对于边 \(8\):
fraction
:离 原始点 最近的点位于边 \(8\) 的 \(0.89..\) 分数位置。side
: 原始点 位于边 \(8\) 的右侧。distance
: 原始点 距离边 \(8\) 有 \(0.19..\) 长度单位。geom
:包含了从 原始点 到边 \(8\) 上最近点的几何形状。edge
:包含了从 原始点 到边 \(8\)geom
上最近点的LINESTRING
几何形状
单点模拟执行¶
返回
EMPTY SET
。partial => true
被忽略
由于这是一次 模拟 执行,所有计算的代码都显示在 PostgreSQL 的
NOTICE
中。
dryrun => true
不处理查询
生成一个包含用于计算所有列的代码的 PostgreSQL
NOTICE
代码中使用了
cap
和 原始点
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)
多点示例¶
每个点最多两个答案¶
cap => 2
最多回答两行。
默认:
partial => true
尽可能减少计算。
默认:
dryrun => false
过程查询
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)
了解结果
edge``为``NULL
edge_id``是与一个 **原始点** (``geom
)靠近的边的标识符每个 原始点 中,最多有两条边位于距离不超过 \(0.5\) 距离单位的范围内:
对于
POINT(1.8 0.4)
和POINT(0.3 1.8)
,只找到一条边。其余的点有两条边。
对于点
POINT(2.9 1.8)
边 \(5\) 在 \(8\) 之前,因此边 \(5\) 到
POINT(2.9 1.8)
的距离最短。对于边 \(5\):
fraction
:离 原始点 最近的点位于边 \(5\) 处的 \(0.8\) 分数位置。side
: 原始点 位于边 \(5\) 的左侧。distance
: 原始点 位于边 \(5\) 的 \(0.1\) 长度单位处。
对于边 \(8\):
fraction
:离 原始点 最近的点位于边 \(8\) 的 \(0.89..\) 分数位置。side
: 原始点 位于边 \(8\) 的右侧。distance
: 原始点 距离边 \(8\) 有 \(0.19..\) 长度单位。
每点一个答案,所有列¶
默认:
cap => 1
最多回答一行。
partial => false
计算所有列
默认:
dryrun => false
过程查询
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)
了解结果
edge_id
与 原始点 最 接近 的边的标识符从距离 原始点 不超过 \(0.5\) 距离单位的所有边中,边 \({5}\) 是最近的一条。
对于 原始点
POINT(2.9 1.8)
边 \(5\) 是距离 原始点 最近的边
fraction
:离 原始点 最近的点位于边 \(5\) 处的 \(0.8\) 分数位置。side
: 原始点 位于边 \(5\) 的左侧。distance
: 原始点 位于边 \(5\) 的 \(0.1\) 长度单位处。geom
:包含了 原始点 的几何形状,即POINT(2.9 1.8)
edge
:包含了 原始点 (geom
)到最接近的边上的LINESTRING
几何形状。
多点模拟执行¶
返回
EMPTY SET
。partial => true
被忽略
由于这是一次 模拟 执行,所有计算的代码都显示在 PostgreSQL 的
NOTICE
中。
dryrun => true
不处理查询
生成一个包含用于计算所有列的代码的 PostgreSQL
NOTICE
代码中使用了
cap
和 原始点
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)
最多找到两条到达给定点的路线¶
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)
兴趣点表¶
处理图外的点。
兴趣点¶
有时应用程序会“即时执行”,从不是图中顶点的位置开始。在pgRouting中,这些位置被称为兴趣点。
兴趣点所需的信息包括 pid
, edge_id
, side
, fraction
。
在这份文档中,将有6个固定的兴趣点,并且它们将被存储在一个表中。
列 |
描述 |
---|---|
|
唯一标识符。 |
|
允许到达该点的最近边的标识符。 |
|
它位于边 |
|
该点位于边的哪个位置。 |
|
点的几何形状。 |
|
在线段顶部移动的点的几何形状。 |
CREATE TABLE pointsOfInterest(
pid BIGSERIAL PRIMARY KEY,
edge_id BIGINT,
side CHAR,
fraction FLOAT,
geom geometry);
CREATE TABLE
兴趣点填充¶
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
连接不连通的组件¶
要获取图的连通性:
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)
在此示例中,组件 \(2`由顶点 :math:\){2, 4}` 组成,并且两个顶点也是死端结果集的一部分。
这个图需要连接起来。
Note
对于本文档的原始图,将有 3 个组件,因为该图中的交叉边是不同的组件。
为连接信息准备存储¶
ALTER TABLE vertices ADD COLUMN component BIGINT;
ALTER TABLE
ALTER TABLE edges ADD COLUMN component BIGINT;
ALTER TABLE
保存顶点连接信息¶
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
保存边连接信息¶
UPDATE edges SET component = v.component
FROM (SELECT id, component FROM vertices) AS v
WHERE source = v.id;
UPDATE 20
获取最近的顶点¶
使用 pgr_findCloseEdges 距离组件 \(1\) 最近的顶点是顶点 \(4\)。 距离顶点 \(4\) 最近的边是 边 \(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)
edge``可用于连接组件,利用边 :math:`14` 的``fraction
信息来分割连接边。
连接组件¶
连接组件有三种基本方法
从顶点到边的起点
从顶点到边的终点
从边上的顶点到最近的顶点
该解决方案需要将边缘分割。
以下查询显示了连接组件的三种方式:
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
检查组件¶
忽略需要进一步工作的边缘。 该图现在已完全连接,因为只有一个组件。
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)
另请参阅¶
索引和表格