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=" 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: ' ' 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>
最终实现效果如下: