路径分析—QGIS+PostgreSQL+PostGIS+pgRouting(一)
路径分析—PostgreSQL+GeoServer+Openlayers(二)
前言上一篇文章中实现数据库层面的路径分析了,可以在数据库里面通过 SQL 查询到结果 。
本篇文章实现了从前端页面直接可视化操作点选起点、终点,并返回最短路径进行展示 。
一、数据库函数在 PostgreSQL 数据库中创建函数,该函数实现的功能是:传入表名、起点、终点经纬度、距离等参数,返回对应的最短距离 geometry 。
创建的函数具体如下:
-- 删除已经存在的函数(可能会报错,报错的话注释)DROP FUNCTION pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float);-- tbl路网表名-- startx起点经度-- starty起点纬度-- endx终点经度-- endy终点纬度-- diatance 起点、终点到路径查询的距离CREATE OR REPLACE function pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float, distance float)--限制返回类型returns geometry as $body$declare v_startLine geometry; -- 离起点最近的线 v_endLine geometry; -- 离终点最近的线 v_startSource integer; -- 距离起点最近线的起点 v_startTarget 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_ss geometry; --起点到最近距离点的线 v_shPath_ee geometry; --终点到最近距离点的线 v_shPath geometry; --最终结果 tempnode float;begin -- 4326坐标系 -- 查询离起点最近的线 -- 找起点15米范围内的最近线 execute 'select geom, source, target from ' ||tbl|| ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| startx || ' ' || starty||')'',4326),'|| distance ||') order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1' into v_startLine, v_startSource ,v_startTarget; -- 查询离终点最近的线 -- 找终点15米范围内的最近线 execute 'select geom, source, target from ' ||tbl|| ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'',4326),'|| distance ||') order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) limit 1' into v_endLine, v_endSource,v_endTarget; -- 如果没找到最近的线,就返回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_Union(b.geom) ' || 'FROM pgr_dijkstra( ''SELECT id, source, target, length as cost FROM ' || tbl ||''',' || v_startSource || ', ' || v_endSource || ' , false ) a LEFT JOIN ' || tbl || ' b ON a.edge=b.id' into v_res ; --从开始的终点到结束的起点最短路径 execute 'SELECT ST_Union(b.geom) ' || 'FROM pgr_dijkstra( ''SELECT id, source, target, length as cost FROM ' || tbl ||''',' || v_startTarget || ', ' || v_endSource || ' , false ) a LEFT JOIN ' || tbl || ' b ON a.edge=b.id' into v_res_b ; --从开始的起点到结束的终点最短路径 execute 'SELECT ST_Union(b.geom) ' || 'FROM pgr_dijkstra( ''SELECT id, source, target, length as cost FROM ' || tbl ||''',' || v_startSource || ', ' || v_endTarget || ' , false ) a LEFT JOIN ' || tbl || ' b ON a.edge=b.id' into v_res_c ; --从开始的终点到结束的终点最短路径 execute 'SELECT ST_Union(b.geom) ' || 'FROM pgr_dijkstra( ''SELECT id, source, target, length as cost FROM ' || tbl ||''',' || v_startTarget || ', ' || v_endTarget || ' , false ) a LEFT JOIN ' || tbl || ' b ON a.edge=b.id' into v_res_d ; 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;-- 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_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_LineSubstring(v_res,v_perStart, v_perEnd) into v_shPath; SELECT ST_MakeLine(ST_SetSRID(ST_Point( startx, starty),4326),v_statpoint) into v_shPath_ss; SELECT ST_MakeLine(ST_SetSRID(ST_Point( endx, endy),4326),v_endpoint) into v_shPath_ee; -- 将 v_shPath、v_shPath_ss、v_shPath_ee 拼接 select ST_LineMerge(ST_Union(array[v_shPath,v_shPath_ss,v_shPath_ee])) into v_shPath; return v_shPath;end;$body$ LANGUAGE plpgsql VOLATILE STRICT;
推荐阅读
- 电锯人第二集在哪可以看
- 二 SpringBoot - 核心配置文件
- Redis高可用之主从复制原理演进分析
- .NET 采用 SkiaSharp 生成二维码和图形验证码及图片进行指定区域截取方法实现
- 【算法训练营day1】LeetCode704. 二分查找 LeetCode27. 移除元素
- AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。
- 记一次 .NET 某电子病历 CPU 爆高分析
- 军棋的暗棋怎么玩要详细(二人军棋暗棋翻棋方法)
- 一 路径分析—QGIS+PostgreSQL+PostGIS+pgRouting
- 记一次某制造业ERP系统 CPU打爆事故分析