基于pgrouting的任意两点间的最短路径查询函数二 - cytggit/Map-openlayers GitHub Wiki
前一篇查询任意两点间最短路径的函数,功能不完善。现在对该函数进行扩展,支持用户自己输入查询的数据库表,另外进行跨楼层的最短路径规划时,需要查询从A到楼梯口的最短路径和楼梯口到B的最短路径,这些都需要进行最短路径规划的时候能够自己选择数据表。
最短路径规划的处理步骤,首先要确定用户的出发点和目的地所在的道路,再在相应的道路上确定道路的节点,查找这两个节点之间的最短路径,最后再处理出发点和目的地到道路节点之间的路段。具体过程为:
(1)查找距离用户出发点最近的道路和该道路的终点T。
(2)查找距离用户目的地最近的道路和该道路的起点S。
(3)计算前两步找出的两点之间的最短路径。
(4)处理出发点和道路终点T以及目的去和道路起点S之间的路段。
代码如下(已经过调整和测试!):
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||') '',4326),15)
order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1'
into v_startLine ,v_startTarget;
--查询离终点最近的线
execute 'select geom,source from ' ||tbl||
' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||') '',4326),15)
order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) 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 ||')',4326)) into v_statpoint;
select ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')',4326)) into v_endpoint;
--最短路径
execute 'SELECT st_linemerge(st_union(st_astext(b.geom))) ' ||
'FROM pgr_kdijkstraPath(
''SELECT id as id, source, target, length as cost FROM ' || tbl ||''','
||v_startTarget || ', ' ||'array['||v_endSource||'] , false, false
) a, '
|| tbl || ' b
WHERE a.id3=b.id
GROUP by id1
ORDER by id1' into v_res ;
select st_setsrid(st_astext(v_res), 4326) into v_res ;
--如果v_res已包含 v_startLine或 v_endLine,不做拼接
if(v_res is null) or (ST_Distance(v_res,v_statpoint) > 0.000000001) then
--将v_res,v_startLine进行拼接
select st_linemerge(ST_Union(array[st_astext(v_res),st_astext(v_startLine)])) into v_res;
select st_setsrid(st_astext(v_res), 4326) into v_res ;
end if;
if(v_res is null) or (ST_Distance(v_res,v_endpoint) > 0.000000001) then
--将v_res,v_endLine进行拼接
select st_linemerge(ST_Union(array[st_astext(v_res),st_astext(v_endLine)])) into v_res;
select st_setsrid(st_astext(v_res), 4326) into v_res ;
end if;
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;
SQL如下(已经过调整和测试!):
-- Function: public.pgr_fromatob(character varying, double precision, double precision, double precision, double precision)
-- DROP FUNCTION public.pgr_fromatob(character varying, double precision, double precision, double precision, double precision);
CREATE OR REPLACE FUNCTION public.pgr_fromatob(tbl character varying, startx double precision, starty double precision, endx double precision, endy double precision)
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||') '',4326),15)
order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1'
into v_startLine ,v_startTarget;
--查询离终点最近的线
execute 'select geom,source from ' ||tbl||
' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||') '',4326),15)
order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) 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 ||')',4326)) into v_statpoint;
select ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')',4326)) into v_endpoint;
--最短路径
execute 'SELECT st_linemerge(st_union(st_astext(b.geom))) ' ||
'FROM pgr_kdijkstraPath(
''SELECT id as id, source, target, length as cost FROM ' || tbl ||''','
||v_startTarget || ', ' ||'array['||v_endSource||'] , false, false
) a, '
|| tbl || ' b
WHERE a.id3=b.id
GROUP by id1
ORDER by id1' into v_res ;
select st_setsrid(st_astext(v_res), 4326) into v_res ;
--如果v_res已包含 v_startLine或 v_endLine,不做拼接
if(v_res is null) or (ST_Distance(v_res,v_statpoint) > 0.000000001) then
--将v_res,v_startLine进行拼接
select st_linemerge(ST_Union(array[st_astext(v_res),st_astext(v_startLine)])) into v_res;
select st_setsrid(st_astext(v_res), 4326) into v_res ;
end if;
if(v_res is null) or (ST_Distance(v_res,v_endpoint) > 0.000000001) then
--将v_res,v_endLine进行拼接
select st_linemerge(ST_Union(array[st_astext(v_res),st_astext(v_endLine)])) into v_res;
select st_setsrid(st_astext(v_res), 4326) into v_res ;
end if;
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
COST 100;
ALTER FUNCTION public.pgr_fromatob(character varying, double precision, double precision, double precision, double precision)
OWNER TO postgres;
GEOSERVER的SQL视图:
SELECT ST_MakeLine(route.geom) FROM (
SELECT geom FROM pgr_fromatob('ways', %x1%, %y1%, %x2%, %y2%
)as geom )AS route
正则表达式输入:^-?[\d.]+$