上一篇的室内地图算法,在新版本的PostgreSQL中,无法使用,提示函数过时,因此修改了以下算法
DROP FUNCTION pgr_floor(tbl varchar,startx float, starty float,endx float,endy float,fnumber integer);
--tbl路网表名
--startx起点经度
--starty起点纬度
--endx终点经度
--endy终点纬度
--fnumber楼层
CREATE OR REPLACE function pgr_floor(tbl varchar,startx float, starty float,endx float,endy float,fnumber integer)
--限制返回类型
returns geometry as
$body$
declare
fmin integer;
fmax integer;
v_startLine geometry;--离起点最近的线
v_endLine geometry;--离终点最近的线
v_startTarget integer;--距离起点最近线的终点
v_startSource integer;
v_endSource integer;--距离终点最近线的起点
v_endTarget integer;
v_statpoint geometry;--在v_startLine上距离起点最近的点
v_endpoint geometry;--在v_endLine上距离终点最近的点
v_res geometry;--最短路径分析结果
v_res_a geometry;
v_res_b geometry;
v_res_c geometry;
v_res_d geometry;
v_perStart float;--v_statpoint在v_res上的百分比
v_perEnd float;--v_endpoint在v_res上的百分比
v_shPath_se geometry;--开始到结束
v_shPath_es geometry;--结束到开始
v_shPath geometry;--最终结果
tempnode float;
begin
raise notice '%','开始运行';
fmin=fnumber*1000;
fmax=fmin+1000;
raise notice '%', fmin;
raise notice '%', fmax;
--查询离起点最近的线
--4326坐标系
--找起点15米范围内的最近线
execute 'select geom, source, target from ' ||tbl||
' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| startx ||' ' || starty||')'',4326),15)
and source between '||fmin||' and '||fmax||' order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1'
into v_startLine, v_startSource ,v_startTarget;
raise notice '%', v_startSource;
raise notice '%', v_startTarget;
--查询离终点最近的线
--找终点15米范围内的最近线
execute 'select geom, source, target from ' ||tbl||
' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'',4326),15)
and source between '||fmin||' and '||fmax||'
order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) limit 1'
into v_endLine, v_endSource,v_endTarget;
raise notice '%', v_endSource;
raise notice '%', v_endTarget;
--如果没找到最近的线,就返回null
if (v_startLine is null) or (v_endLine is null) then
return null;
raise notice '%', 'null1';
end if ;
raise notice '%', '已找到最近线';
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;
raise notice '%', '已找到最近点';
-- ST_Distance
--从开始的起点到结束的起点最短路径
execute 'SELECT st_linemerge(st_union(ad.geom)) FROM (SELECT geom FROM road_line where gid in (SELECT id2 AS gid FROM pgr_dijkstra(''
SELECT gid AS id,
source::integer,
target::integer,
length::double precision AS cost
FROM ' || tbl ||''',
' ||v_startSource|| ', ' ||v_endSource||' , false, false))) ad' into v_res ;
raise notice '%', '融合1';
--从开始的终点到结束的起点最短路径
execute 'SELECT st_linemerge(st_union(ad.geom)) FROM (SELECT geom FROM road_line where gid in (SELECT id2 AS gid FROM pgr_dijkstra(''
SELECT gid AS id,
source::integer,
target::integer,
length::double precision AS cost
FROM ' || tbl ||''',
' ||v_startTarget|| ', ' ||v_endSource||' , false, false))) ad' into v_res_b ;
raise notice '%', '融合2';
--从开始的起点到结束的终点最短路径
execute 'SELECT st_linemerge(st_union(ad.geom)) FROM (SELECT geom FROM road_line where gid in (SELECT id2 AS gid FROM pgr_dijkstra(''
SELECT gid AS id,
source::integer,
target::integer,
length::double precision AS cost
FROM ' || tbl ||''',
' ||v_startSource|| ', ' ||v_endTarget||' , false, false))) ad' into v_res_c ;
raise notice '%', '融合3';
--从开始的终点到结束的终点最短路径
execute 'SELECT st_linemerge(st_union(ad.geom)) FROM (SELECT geom FROM road_line where gid in (SELECT id2 AS gid FROM pgr_dijkstra(''
SELECT gid AS id,
source::integer,
target::integer,
length::double precision AS cost
FROM ' || tbl ||''',
' ||v_startTarget|| ', ' ||v_endTarget||' , false, false))) ad' into v_res_d ;
raise notice '%', '融合4';
if(ST_Length(v_res) > ST_Length(v_res_b)) then
v_res = v_res_b;
end if;
if(ST_Length(v_res) > ST_Length(v_res_c)) then
v_res = v_res_c;
end if;
if(ST_Length(v_res) > ST_Length(v_res_d)) then
v_res = v_res_d;
end if;
--如果找不到最短路径,就返回null
if(v_res is null) then
return null;
raise notice '%', 'null2';
end if;
raise notice '%', '找到最短路径';
--将v_res,v_startLine,v_endLine进行拼接
select st_linemerge(ST_Union(array[v_res,v_startLine,v_endLine])) into v_res;
select ST_LineLocatePoint(v_res, v_statpoint) into v_perStart;
select ST_LineLocatePoint(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;
raise notice '%', '返回数据';
return v_shPath;
end;
$body$
LANGUAGE plpgsql VOLATILE STRICT;