漂泊雪狼的博客

思考,讨论,分享C#,JavaScript,.NET,Oracle,SQL Server……技术
posts - 159, comments - 284, trackbacks - 9, articles - 10

导航

公告

使用pgrouting进行最短路径搜索

Posted on 2018-01-13 18:59 漂泊雪狼 阅读(...) 评论(...) 编辑 收藏
   PgRouting是基于开源空间数据库PostGIS用于网络分析的扩展模块,最初它被称作pgDijkstra,因为它只是利用Dijkstra算法实现最短路径搜索,之后慢慢添加了其他的路径分析算法,如A算法,双向A算法,Dijkstra算法,双向Dijkstra算法,tsp货郎担算法等,然后被更名为pgRouting。该扩展库依托PostGIS自身的gist索引,丰富的坐标系与图形类型,强大的几何处理能力,如空间查询,空间处理,线性参考等优势,能保障在较大数据级别下的网络分析效果更快更好。
最新源码见:
1、环境搭建
需要先安装PostgreSQL9.6,再安装PostGIS,注意版本号PostGIS2.4后已经集成了pgRouting,无需单独安装
PostGIS 官网 http://www.postgis.org/
pgRouting官网http://pgrouting.org/documentation.html
2、启用pgRouting功能,连接到对应postgres数据库后执行下面的sql语句
CREATE EXTENSION postgis;
CREATE EXTENSION pgrouting;

 

3、路网数据处理
由于路网分析的特殊性,只支持LineString类型,不支持MultiLineString类型,如果路网数据为MultiLineString类型导入前需加工处理,可使用arcgis在交叉点处使用打断相交线来分割线,参见
http://resources.arcgis.com/zh-cn/help/main/10.1/index.html#//01m8,最终可用的数据必须为路网不自相交,导入时选择简单的线类型,否则网络拓扑计算数据会错误
 
4、路网拓扑数据计算处理,执行成功后,执行成功后会生产一个**_vertices_pgr的表,里面包含路网相交点的空间数据
 alter table road add column source int;

alter table road add column target int;

create index road_source_idx on road("source");
create index road_target_idx on road("target");


ALTER TABLE road  ADD COLUMN length double precision;  


SELECT pgr_createTopology('road',0.00001, 'geom', 'gid');  

update road set length =st_length(geom); 


5、查询最短路径sql语句

SELECT seq, id1 AS node, id2 AS edge, cost,geom  FROM pgr_dijkstra('  
SELECT gid AS id,                      
source::integer,                         
target::integer,                        
length::double precision AS cost  
FROM xmpark_road',  
1, 10, false, false) as di  
join xmpark_road pt  
on di.id2 = pt.gid

6、参数化的查询sql语句,可以用下面的语句,在geoserver中使用发布sql视图图层来显示导航搜索图层,见下图

SELECT seq, id1 AS node, id2 AS edge, cost,geom  FROM pgr_dijkstra('  
SELECT gid AS id,                      
source::integer,                         
target::integer,                        
length::double precision AS cost  
FROM xmpark_road',  
%a%, %b%, false, false) as di  
join xmpark_road pt  
on di.id2 = pt.gid

 7、在ol中使用上面发布的搜索图层使用起止交叉点来显示导航路径,源码如下
  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  5     <title></title>
  6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7     <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
  8     <link rel="stylesheet" href="ol/ol.css" type="text/css">
  9     <script src="ol/ol-debug.js"></script>
 10     <script src="ol/proj4.js"></script>
 11     <script src="js/jquery-1.8.0.min.js"></script>
 12     <meta charset="utf-8" />
 13 </head>
 14 <body>
 15     <div id="map" style="width: 100%;height:800px;border:solid 1px red" class="map">
 16         <div>
 17             id1: <input id="id1" value="30" />
 18             id2: <input id="id2" value="66" />
 19             <input type="button" value="query" onclick="queryRoute()" />
 20         </div>
 21     </div>
 22 </body>
 23 </html>
 24 
 25 
 26 <script type="text/javascript">
 27     var format = 'image/png';
 28     var bounds = [501369.9375, 2494100.25,
 29         502073, 2495256.25];
 30     var mousePositionControl = new ol.control.MousePosition({
 31         className: 'custom-mouse-position',
 32         target: document.getElementById('location'),
 33         coordinateFormat: ol.coordinate.createStringXY(5),
 34         undefinedHTML: '&nbsp;'
 35     });
 36     var tiled = new ol.layer.Tile({
 37         visible: true,
 38         source: new ol.source.TileWMS({
 39             url: 'http://localhost:8080/geoserver/pg_ws/wms',
 40             params: {
 41                 'FORMAT': format,
 42                 'VERSION': '1.1.1',
 43                 tiled: true,
 44                 STYLES: '',
 45                 LAYERS: 'pg_ws:xmpark_road',
 46             }
 47         })
 48     });
 49 
 50     var cross_tiled = new ol.layer.Tile({
 51         //visible: true,
 52         source: new ol.source.TileWMS({
 53             url: 'http://localhost:8080/geoserver/pg_ws/wms',
 54             params: {
 55                 'FORMAT': format,
 56                 'VERSION': '1.1.1',
 57                 tiled: true,
 58                 STYLES: '',
 59                 LAYERS: 'pg_ws:xmpark_road_vertices_pgr',
 60             }
 61         })
 62     });
 63 
 64     var projection = new ol.proj.Projection({
 65         code: 'EPSG:3857',
 66         units: 'm',
 67         axisOrientation: 'neu',
 68         global: true
 69     });
 70     var map = new ol.Map({
 71         controls: ol.control.defaults({
 72             attribution: false
 73         }).extend([mousePositionControl]),
 74         target: 'map',
 75         layers: [
 76             tiled, cross_tiled
 77         ],
 78         view: new ol.View({
 79             projection: projection
 80         })
 81     });
 82    
 83    
 84     map.getView().fit(bounds, map.getSize());
 85 
 86     var routeLayer = null;
 87 
 88     function queryRoute() {
 89         if (routeLayer != null) {
 90             map.removeLayer(routeLayer);
 91         }
 92 
 93         var val1 = $("#id1").val();
 94         var val2 = $("#id2").val();
 95          routeLayer = new ol.layer.Tile({
 96             visible: true,
 97             source: new ol.source.TileWMS({
 98                 url: 'http://localhost:8080/geoserver/pg_ws/wms',
 99                 params: {
100                     'FORMAT': format,
101                     'VERSION': '1.1.1',
102                     tiled: true,
103                     STYLES: '',
104                     LAYERS: 'pg_ws:xmpark_road_route',
105                     'viewparams': 'a:' + val1 + ';b:' + val2
106                 }
107             })
108         });
109 
110         map.addLayer(routeLayer);
111     }
112 </script>
导航图层搜索


最终实现效果如下: