二 路径分析—PostgreSQL+GeoServer+Openlayers

路径分析—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;

推荐阅读