博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于pgrouting的任意两点间的最短路径查询函数二
阅读量:5942 次
发布时间:2019-06-19

本文共 5965 字,大约阅读时间需要 19 分钟。

    在前面的博文中写过一篇查询任意两点间最短路径的函数,当时对pgrouting不熟悉,功能很low。现在对该函数进行扩展,支持用户自己输入查询的数据库表,这一点看似简单,其实意义很大,在做室内导航的时候当用户所在的楼层变化的时候最短路径函数查询的数据表名称也会发生变化,不可能一栋大楼里的道路都是一样的吧,另外进行跨楼层的最短路径规划时,需要查询从A到楼梯口的最短路径和楼梯口到B的最短路径,这些都需要进行最短路径规划的时候能够自己选择数据表。

    先解释一下最短路径规划的处理步骤,首先要确定用户的出发点和目的地所在的道路,再在相应的道路上确定道路的节点,查找这两个节点之间的最短路径,最后再处理出发点和目的地到道路节点之间的路段。具体过程为:

    (1)查找距离用户出发点最近的道路和该道路的终点T。

    (2)查找距离用户目的地最近的道路和该道路的起点S。

    (3)计算前两步找出的两点之间的最短路径。

    (4)处理出发点和道路终点T以及目的去和道路起点S之间的路段。

DROP FUNCTION pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float);CREATE OR REPLACE function pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float)   returns  geometry as  $body$  declare      v_startLine geometry;--离起点最近的线      v_endLine geometry;--离终点最近的线            v_startTarget integer;--距离起点最近线的终点      v_endSource integer;--距离终点最近线的起点        v_statpoint geometry;--在v_startLine上距离起点最近的点      v_endpoint geometry;--在v_endLine上距离终点最近的点            v_res geometry;--最短路径分析结果          v_perStart float;--v_statpoint在v_res上的百分比      v_perEnd float;--v_endpoint在v_res上的百分比        v_shPath geometry;--最终结果    tempnode float;	begin                   --查询离起点最近的线      execute 'select geom ,target  from ' ||tbl||			' where 			ST_DWithin(geom,ST_Geometryfromtext(''point('||	startx ||' ' || starty||')''),15) 			order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')''))  limit 1' 			into v_startLine ,v_startTarget;            --查询离终点最近的线      execute 'select geom,source  from ' ||tbl||			' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')''),15) 			order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')''))  limit 1' 			into v_endLine,v_endSource;        --如果没找到最近的线,就返回null      if (v_startLine is null) or (v_endLine is null) then          return null;      end if ;        select  ST_ClosestPoint(v_startLine, ST_Geometryfromtext('point('|| startx ||' ' || starty ||')')) into v_statpoint;      select  ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')')) into v_endpoint;              --最短路径      execute 'SELECT st_linemerge(st_union(b.geom)) ' ||     'FROM pgr_kdijkstraPath(      ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''','      ||v_startTarget || ', ' ||'array['||v_endSource||'] , false, false      ) a, '      || tbl || ' b      WHERE a.id3=b.gid      GROUP by id1      ORDER by id1' into v_res;        --如果找不到最短路径,就返回null      if(v_res is null) then          return null;      end if;            --将v_res,v_startLine,v_endLine进行拼接      select  st_linemerge(ST_Union(array[v_res,v_startLine,v_endLine])) into v_res;            select  ST_Line_Locate_Point(v_res, v_statpoint) into v_perStart;      select  ST_Line_Locate_Point(v_res, v_endpoint) into v_perEnd;  		if(v_perStart > v_perEnd) then          tempnode =  v_perStart;		v_perStart = v_perEnd;		v_perEnd = tempnode;    end if;	    --截取v_res      SELECT ST_Line_SubString(v_res,v_perStart, v_perEnd) into v_shPath;             return v_shPath;                end;  $body$  LANGUAGE plpgsql VOLATILE STRICT

使用这个最短路径规划函数进行路径规划一般不会出现问题,但是有的时候会出现这样的问题,因为函数的查找思路是查找距离起点最近的线和改线的终点,查找离目的地最近的线和该线的起点,这样有可能会出现这样的情况,就是起点和终点对应的线段是相连接的,这时查找的距离起点最近线的终点和距离目的地最近线上的起点就是同一个点,这样的话这两点直接就没有最短距离。

所以需要对上述代码第59到61行进行修改,修改后的代码如下:

DROP FUNCTION pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float);CREATE OR REPLACE function pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float)   returns  geometry as  $body$  declare      v_startLine geometry;--离起点最近的线      v_endLine geometry;--离终点最近的线            v_startTarget integer;--距离起点最近线的终点      v_endSource integer;--距离终点最近线的起点        v_statpoint geometry;--在v_startLine上距离起点最近的点      v_endpoint geometry;--在v_endLine上距离终点最近的点            v_res geometry;--最短路径分析结果          v_perStart float;--v_statpoint在v_res上的百分比      v_perEnd float;--v_endpoint在v_res上的百分比        v_shPath geometry;--最终结果    tempnode float;	begin                   --查询离起点最近的线      execute 'select geom ,target  from ' ||tbl||			' where 			ST_DWithin(geom,ST_Geometryfromtext(''point('||	startx ||' ' || starty||')''),15) 			order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')''))  limit 1' 			into v_startLine ,v_startTarget;            --查询离终点最近的线      execute 'select geom,source  from ' ||tbl||			' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')''),15) 			order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')''))  limit 1' 			into v_endLine,v_endSource;        --如果没找到最近的线,就返回null      if (v_startLine is null) or (v_endLine is null) then          return null;      end if ;        select  ST_ClosestPoint(v_startLine, ST_Geometryfromtext('point('|| startx ||' ' || starty ||')')) into v_statpoint;      select  ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')')) into v_endpoint;              --最短路径      execute 'SELECT st_linemerge(st_union(b.geom)) ' ||     'FROM pgr_kdijkstraPath(      ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''','      ||v_startTarget || ', ' ||'array['||v_endSource||'] , false, false      ) a, '      || tbl || ' b      WHERE a.id3=b.gid      GROUP by id1      ORDER by id1' into v_res ;        --如果找不到最短路径,就返回null      --if(v_res is null) then      --    return null;      --end if;            --将v_res,v_startLine,v_endLine进行拼接      select  st_linemerge(ST_Union(array[v_res,v_startLine,v_endLine])) into v_res;            select  ST_Line_Locate_Point(v_res, v_statpoint) into v_perStart;      select  ST_Line_Locate_Point(v_res, v_endpoint) into v_perEnd;  		if(v_perStart > v_perEnd) then          tempnode =  v_perStart;		v_perStart = v_perEnd;		v_perEnd = tempnode;    end if;	    --截取v_res      SELECT ST_Line_SubString(v_res,v_perStart, v_perEnd) into v_shPath;             return v_shPath;                end;  $body$  LANGUAGE plpgsql VOLATILE STRICT

你可能感兴趣的文章
Android图片处理
查看>>
2015年第21本:万万没想到,用理工科思维理解世界
查看>>
大家谈谈公司里的项目经理角色及职责都是干什么的?
查看>>
剑指offer
查看>>
Velocity魔法堂系列二:VTL语法详解
查看>>
NopCommerce架构分析之八------多语言
查看>>
转:Eclipse自动补全功能轻松设置
查看>>
ES6新特性:Javascript中的Reflect对象
查看>>
hibernate逆向工程生成的实体映射需要修改
查看>>
mysql update操作
查看>>
Robots.txt - 禁止爬虫(转)
查看>>
MySQL数据库
查看>>
项目分析_xxoo-master
查看>>
SQLServer2012自增列值跳跃的问题
查看>>
ViewBag对象的更改
查看>>
Mysql 监视工具
查看>>
hdu1025 Constructing Roads In JGShining's Kingdom(二分+dp)
查看>>
Android PullToRefreshListView和ViewPager的结合使用
查看>>
禅修笔记——硅谷最受欢迎的情商课
查看>>
struts2入门(搭建环境、配置、示例)
查看>>