zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    对象池使用时要注意几点
    Flash3D学习计划(一)——3D渲染的一般管线流程
    714. Best Time to Buy and Sell Stock with Transaction Fee
    712. Minimum ASCII Delete Sum for Two Strings
    647. Palindromic Substrings(马拉车算法)
    413. Arithmetic Slices
    877. Stone Game
    338. Counting Bits
    303. Range Sum Query
    198. House Robber
  • 原文地址:https://www.cnblogs.com/asdlijian/p/13514177.html
Copyright © 2011-2022 走看看