在之前的二节中,我们已经准备好数据,现在可以进行路网分析了。
需要注意sroads_vertices_pgr图层保存的是道路交叉点id和几何对象。sroads中的source,target字段值来自sroads_vertices_pgr.id,在执行pgr_createTopology时生成。
要进行路网查询,首先要根据起点或终点空间位置获取相应的source和target。
1.缓冲区查询
查找半径为x距离内的要素专业术业称之为缓冲区查询。如下图
以蓝色圆点为中心点,圆半径为900米,生成一个圆,然后查找包含在圆内的几何对象。
缓冲区查询注意事项:
如果你要查找半径为x距离内的要素,不要使用ST_Distance和ST_Intersects + ST_Buffer的方式,原因如下:
– ST_DWithin可以使用空间索引,ST_Distance不能使用空间索引
– ST_Buffer只是一个缓冲区的近似值(POLYGON),而不是圆
– 同时ST_DWithin 支持geometry和geography两种几何对象
1.1 查找距离最近的道路
在本文中假设:
起点坐标为 lon:99.78987 lat:20.42609
终点坐标为 lon:101.96391 lat:5.83138
1.1.1查找起点或终点为中心点半径为1500米最近的道路
--在1500米范围内查找起点道路编号
with cte as(
select ST_SetSRID(ST_Point(99.78987,20.42609),4326) as point,
'SPHEROID["WGS84",6378137,298.257223563]'::spheroid as sphe
)select id from sroads_vertices_pgr as a,cte as b
where ST_DWithin(((a.the_geom)::geography),((b.point)::geography),1500,true)
order by ST_DistanceSpheroid(a.the_geom,b.point,b.sphe) limit 1;
--在1500米范围内查找终点道路编号
with cte as(
select ST_SetSRID(ST_Point(101.96391,5.83138),4326) as point,
'SPHEROID["WGS84",6378137,298.257223563]'::spheroid as sphe
)select id from sroads_vertices_pgr as a,cte as b
where ST_DWithin(((a.the_geom)::geography),((b.point)::geography),1500,true)
order by ST_DistanceSpheroid(a.the_geom,b.point,b.sphe) limit 1;
1.1.2 50米递增直到找到最近的道路
1.1.1节中的方法起点或终点超过1500米时,无法进行路网分析。通过改进函数来获取道路编号,改进的函数和距离无关。
drop function if exists find_short_id(float8,float8,spheroid);
create or replace function find_short_id(float8,float8,spheroid)
returns table(gid bigint,distance float8)
as $$
declare
v_point geometry;
v_grapoint geography;
v_index integer;
begin
v_point := ST_SetSRID(ST_Point($1,$2),4326);
v_grapoint := ( v_point::geography );
distance := 50; --修改这个值可增大范围
v_index := 0;
loop
select id into gid from sroads_vertices_pgr
where ST_DWithin((the_geom::geography),v_grapoint,distance,true)
order by ST_DistanceSpheroid(the_geom,v_point,$3) limit 1;
if( gid is not null ) then
exit;
else
distance := (distance + 50);
end if;
--在25000米范围内还找不到的话退出
v_index := v_index + 1;
if( v_index > 500 ) then --修改这个计数器可增大范围
exit;
end if;
end loop;
return next;
end;
$$ language plpgsql;
--使用方法
select * from find_short_id(99.78987,20.42609,'SPHEROID["WGS84",6378137,298.257223563]'::spheroid)
2.最短路径
根据第1节中的方法,现在已经获取了起始和终点道路的编号,在我这里为
– 起点:52975
– 终点:188
各人的道路编号可能不一样,请根据第1节中的方法查询获取。
select b.edge as gid, (select geom from sroads where gid=b.edge) as geom
from pgr_dijkstra('select gid as id, source, target, cost, rcost as reverse_cost FROM sroads',52975, 188) as b;
查询效果图
3.其它
3.1 设置障碍
障碍是指不能通行的道路,例如堵车、交通管制、修路、自然灾害等。因为示例数据未考虑单行、高架等因素,障碍只要将sroads中的某一线段的cost和rcost设置为-1即可。如下图不走红框内的道路:
红框的道路编号在测试机上为247(以本机为准),cost值为16643,rcost值为16643,执行以下列命令后道路永远不能通行。
update sroads set cost=-1,rcost=-1 where gid=247;
恢复通行状态
update sroads set cost=16643,rcost=16643 where gid=247;
红框中的道路为247,不能通行。
3.2 必经点
必经点可以多次执行第1节中的内容来实现。
3.3 性能优化
在生产中,由于道路全部在一个层数量非常多,严重影响分析性能。因此应该按道路等级把不同的道路提取出来,例如高速、国道、主干道、城市道路等,然后结合各个图层进行路网分析。
以高速度为例,其中高速公路数量较少(几千条),通过起点缓冲区查询获取距离最近的高速路入口,然后在城市道路和高速路入口缓冲查询城市道路数据,根据查询结果生成起点至高速路入口的最短路径,然后高速路至距离终点最近的出口,然后出口至目的地。
图中蓝色为起点,红色为高速路入口,只使用绿色框中的数据做起点-入口的最知路径分析。绿色框可根据道路自行调整半径,终点同理。
3.4 拥堵路段
顺便提一下拥堵路段,首先根据车速和相关算法计算出拥堵路段的起点和终点,然后在也是通过类似最短路径的方法生成并绘制拥堵路段。如果要避开拥堵路段,可参考3.1节。
以上就是路网分析基本原理。全文完