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

  • 相关阅读:
    Unity3D-实现连续点击两次返回键退出游戏(安卓/IOS)
    Unity3D插件-自制小插件、简化代码便于使用(新手至高手进阶必经之路)
    Unity3D安卓程序中提示窗与常用静态方法封装
    Unity插件-NGUI使用教程
    Unity 3D游戏-塔防类游戏源码:重要方法和功能的实现
    Unity 3D编辑器扩展介绍、教程(二) —— 创建窗口
    Unity 3D编辑器扩展介绍、教程(一) —— 创建菜单项
    Unity 3D换装系统教程/Demo
    Unity3D游戏-愤怒的小鸟游戏源码和教程(二)
    WebApi接口测试
  • 原文地址:https://www.cnblogs.com/asdlijian/p/13514177.html
Copyright © 2011-2022 走看看