PostgreSQL PostGIS pgrouting 泰国(thailand)全国路网分析(3)路网分析


在之前的二节中,我们已经准备好数据,现在可以进行路网分析了。
需要注意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节。

以上就是路网分析基本原理。全文完

转载自:https://blog.csdn.net/kmblack1/article/details/78930128

You may also like...