Postgresql+Geoserver+Openlayers+pgRouting学习1

 

pgRouting 学习 最短路径算法

1、数据预处理

数据的投影需要定义,空间数据库中矢量图层的数据投影需要定义,而且需要同geoserver以及openlayer中投影定义一致,我使用的是EPSG:4326

编辑矢量图层数据

最短路径使用的 Dijkstra算法,了解这个算法对于数据的要求是矢量数据要是一张图,意味着如果相邻的两个节点之间连接的线段是独立的,就是说如果有一条街道和别的街道相交就需要把它拆分。

将矢量数据导入postgresql

postgresql处理线表

--ShortestPath为表名
--source为线表起点字段名称
--target为线表终点字段名称
--source和target可以在导入数据库前直接先自己定义
--如果不自己定义起点终点,则自动生成起点和终点点号
ALTER TABLE shortestpath ADD COLUMN "source" integer;
ALTER TABLE shortestpath ADD COLUMN "target" integer;
--创建拓扑
SELECT pgr_createTopology('shortestpath', 0.00001, 'geom', 'id');
--为起点号终点号加空间索引
CREATE INDEX source_idx ON ShortestPath("source");
CREATE INDEX target_idx ON ShortestPath("target");
--添加长度字段、并计算赋值
ALTER TABLE shortestpath ADD COLUMN length double precis;
update shortestpath set length =st_length(geom);
--将长度值赋给reverse_cost,作为路线选择标准
ALTER TABLE shortestpath ADD COLUMN reverse_cost double precision;
UPDATE shortestpath SET reverse_cost = length;

构建路径函数

--删除已存在的函数
DROP FUNCTION pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float);
--tbl路网表名
--startx起点经度
--starty起点纬度
--endx终点经度
--endy终点纬度
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_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
    --查询离起点最近的线 
    --4326坐标系
    --找起点15米范围内的最近线
    execute 'select geom, source, 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_startSource ,v_startTarget; 
     
    --查询离终点最近的线 
    --找终点15米范围内的最近线
    execute 'select geom, source, target 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,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; 
   
   -- ST_Distance 
     
    --从开始的起点到结束的起点最短路径
    execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
    'FROM pgr_kdijkstraPath( 
    ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 
    ||v_startSource || ', ' ||'array['||v_endSource||'] , false, false 
    ) a, ' 
    || tbl || ' b 
    WHERE a.id3=b.gid   
    GROUP by id1   
    ORDER by id1' into v_res ;
   
    --从开始的终点到结束的起点最短路径
    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_b ;
 
    --从开始的起点到结束的终点最短路径
    execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
    'FROM pgr_kdijkstraPath( 
    ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 
    ||v_startSource || ', ' ||'array['||v_endTarget||'] , false, false 
    ) a, ' 
    || tbl || ' b 
    WHERE a.id3=b.gid   
    GROUP by id1   
    ORDER by id1' into v_res_c ;
 
    --从开始的终点到结束的终点最短路径
    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_endTarget||'] , false, false 
    ) a, ' 
    || tbl || ' b 
    WHERE a.id3=b.gid   
    GROUP by id1   
    ORDER by id1' 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_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;

2、geoserver 发布图层

geoserver可以发布矢量图层作为地图,sql视图图层作为分析图层

SELECT * FROM pgr_fromAtoB('shortestpath', %x1%, %y1%, %x2%, %y2%)

从sql语句来看,实则调用空间数据库pgr_fromAtoB函数,将起点和终点坐标作为参数。

3、前端调用

测试可使用url测试,如返回图片则成功;如果出现错误,则在geoserver控制台查看错误信息,我遇到的错误有:

  • 混合投影

    解决办法:定义空间数据库表格投影

  • 数据格式不一致

    解决办法:修改空间数据库表格类型

http://localhost:8082/geoserver/jinmen/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=jinmen%3AShortest%20Path&viewparams=x1%3A120.53052%3By1%3A30.637777%3Bx2%3A120.55427%3By2%3A30.62243&CRS=EPSG%3A4326&STYLES=&FORMAT_OPTIONS=dpi%3A124&WIDTH=789&HEIGHT=616&BBOX=30.61324977874755%2C120.52187555486509%2C30.65170192718505%2C120.5711267644709

posted @ 2020-01-01 11:42  mangata  阅读(363)  评论(0编辑  收藏  举报