最短路径实现
主要工具
QGIS建立拓撲關(guān)系
使用v.clean運行,并用DBManager即可以建立拓撲關(guān)系并導(dǎo)入數(shù)據(jù)庫。
注意
QGIS2.16有數(shù)據(jù)溢出問題,使用QGIS2.14可以解決這個問題
Postgres存儲數(shù)據(jù)表
導(dǎo)入wuhan_road_topo后可以進行相應(yīng)處理
drop table if exists tmp_pts_topo; create table tmp_pts_topo as select osm_id ,(st_dump(geom)).geom as geom ,st_startpoint((st_dump(geom)).geom) ,st_endpoint((st_dump(geom)).geom) ,st_length((st_dump(geom)).geom)*110 as dis from wuhan_road_topo;alter table tmp_pts_topo add column id serial; select * from tmp_pts_topo limit 10;drop table if exists tmp_pts; create table tmp_pts(geom geometry);insert into tmp_pts select geom from ( select st_startpoint as geom from tmp_pts_topo union all select st_endpoint as geom from tmp_pts_topo )x group by geom;alter table tmp_pts add column id serial; select * from tmp_pts limit 10; select * from tmp_pts_topo limit 10; alter table tmp_pts_topo add column start_point int; alter table tmp_pts_topo add column end_point int;create index indx_geom_tmp_pts on tmp_pts using gist(geom);create index indx_geom_tmp_pts_1 on tmp_pts_topo using gist(st_startpoint);create index indx_geom_tmp_pts_2 on tmp_pts_topo using gist(st_endpoint);select * from tmp_pts limit 10; select * from tmp_pts_topo limit 10;update tmp_pts_topo t1 set start_point=t2.id from tmp_pts t2 where st_dwithin(t1.st_startpoint,t2.geom,0);update tmp_pts_topo t1 set end_point=t2.id from tmp_pts t2 where st_dwithin(t1.st_endpoint,t2.geom,0);insert into tmp_pts(geom) select st_startpoint from tmp_pts_topo where start_point is null union select st_endpoint from tmp_pts_topo where end_point is null;update tmp_pts_topo t1 set start_point=t2.id from tmp_pts t2 where st_dwithin(t1.st_startpoint,t2.geom,0) and start_point is null;update tmp_pts_topo t1 set end_point=t2.id from tmp_pts t2 where st_dwithin(t1.st_endpoint,t2.geom,0) and end_point is null;delete from tmp_pts_topo where id in ( select id from( select id,row_number() over(partition by start_point,end_point order by dis) from tmp_pts_topo where (start_point,end_point) in ( select start_point,end_point from tmp_pts_topo group by start_point,end_point having count(*)>1 ) )x where row_number>1 );select * from tmp_pts_topo where start_point=1138 and end_point=1143;select count(*) from tmp_pts_topo;select * from tmp_pts_topo limit 1;select * from tmp_pts_topo where start_point=10997;delete from tmp_pts_topo where start_point is null or end_point is null;注意
要刪除空白點,不然無法正常運行
測試查詢
選定一個起點與終點,測試有沒有結(jié)果
Geoserver發(fā)布相關(guān)服務(wù)
使用Geoserver連接postgres并發(fā)布wuhan_road_topo,并配置新的SQL視圖,SQL視圖可以接收參數(shù)返回相應(yīng)的視圖
可參見:GeoServer的SQL Views詳解
將SQL語句修改為
with start_point as ( select st_setsrid( st_makepoint(%startLon%,%startLat%) ,4326) as p ) ,end_point as ( select st_setsrid(st_makepoint(%endLon%,%endLat%),4326) as p ) select t2.seq,(t1.geom) from ( SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_dijkstra(' SELECT id, start_point as source, end_point as target, dis AS cost FROM tmp_pts_topo', ( select id from tmp_pts where st_dwithin( (select p from start_point) ,geom,0.05) order by st_distance( (select p from start_point) ,geom) limit 1 ) , ( select id from tmp_pts where st_dwithin( (select p from end_point) ,geom,0.05) order by st_distance( (select p from end_point) ,geom) limit 1 ), false, false) )t2 left join tmp_pts_topo t1 on t1.id=t2.edge where t2.edge>0 order by t2.seq發(fā)布成功后可以通過修改參數(shù),如http://localhost:8080/geoserver/wuhanwork/wms?service=WMS&version=1.1.0&request=GetMap&view&layers=wuhan:tt&styles=&bbox=114.22769686949,30.559729927104,114.246243846172,30.5719569775606&width=512&height=337&srs=EPSG:4326&format=application/openlayers&viewparams=startLon:114.25;startLat:30.57;endLon:114.39;endLat:30.70 來訪問
即可通過輸入起點與終點,返回最短路徑
客戶端實現(xiàn)
<!DOCTYPE html> <html lang="zh-cmn-Hans"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=Edge"><meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width"><!-- 新 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css"><!-- 可選的Bootstrap主題文件(一般不用引入) --><link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css"><link rel="stylesheet" href="./css/prism.css" type="text/css"><link rel="stylesheet" href="./css/ol.css" type="text/css"><link rel="stylesheet" href="./css/layout.css" type="text/css"><link rel="stylesheet" href="./css/popup.css"><link rel="stylesheet" type="text/css" href="./css/main.css"><script src="js/ol-debug.js"></script><script src="js/ol-deps.js"></script><script src="js/ol.js"></script><title>HomeWork</title> </head><body><div class="mycontainer"><div class="row" id="header"><h1>Digital engineering practice</h1></div></div><div class="container-fluid"><div class="row-fluid"><div class="span12"><div id="map" class="map"></div><div id="popup" class="ol-popup"><a href="#" id="popup-closer" class="ol-popup-closer"></a><div id="popup-content"></div></div><!--鼠標點擊--><div class="buttonlay"><button type="button" id="btStart" onclick="btStart_click()" data-original-title="Click" class="btn btn-lg btn-default btn-check mybutton"><span>Click to input start point</span></button><button type="button" id="btEnd" onclick="btEnd_click()" data-original-title="Click" class="btn btn-lg btn-default btn-check mybutton"><span>Click to input end point</span> </button><button type="button" id="selectShort" onclick="select_click()" data-original-title="Click" class="btn btn-lg btn-default btn-check mybutton"> <span>Click to slect shortest way</span></button></div></div></div></div> </body> <script type="text/javascript"> /*** Elements that make up the popup.*/ var container = document.getElementById('popup'); var content = document.getElementById('popup-content'); var closer = document.getElementById('popup-closer');//記錄按鈕動作 var ableSt = false; var ableEd = false;//起點經(jīng)度,起點維度,終點經(jīng)度,終點緯度 var st_lon, st_lat, ed_lon, ed_lat;/*** Create an overlay to anchor the popup to the map.*/ var overlay = new ol.Overlay( /** @type {olx.OverlayOptions} */ ({element: container,autoPan: true,autoPanAnimation: {duration: 250} }));/*** 加載瓦片圖層**/ var source = new ol.source.XYZ({url: 'http://localhost:8080/tilemill/{z}/{x}/{y}.png' });var center = ol.proj.transform([114.2207, 30.5960], 'EPSG:4326', 'EPSG:3857'); var map = new ol.Map({logo: false,layers: [new ol.layer.Tile({source: source})],overlays: [overlay],target: 'map',view: new ol.View({maxZoom: 18,center: center,zoom: 10}) });/*** Add a click handler to hide the popup.* @return {boolean} Don't follow the href.*/ closer.onclick = function() {overlay.setPosition(undefined);closer.blur();return false; };/*** Add a click handler to the map to render the popup.*/ map.on('singleclick', function(evt) {var coordinate = evt.coordinate;var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(coordinate, 'EPSG:3857', 'EPSG:4326'));var xy = ol.proj.transform(coordinate, 'EPSG:3857', 'EPSG:4326').toString();var lon_string = xy.split(",")[0];var lat_string = xy.split(",")[1];var lon_number = new Number(lon_string);var lat_number = new Number(lat_string);if (ableSt) {st_lon = lon_number.toFixed(4);st_lat = lat_number.toFixed(4);content.innerHTML = '<p>You put start point here:</p><code>' + hdms + '</code>';ableSt = false;} else {if (ableEd) {ed_lon = lon_number.toFixed(4);ed_lat = lat_number.toFixed(4);content.innerHTML = '<p>You put end point here:</p><code>' + hdms + '</code>';ableEd = false;} else {content.innerHTML = '<p>You clicked here:</p><code>' + hdms + '</code>';}}overlay.setPosition(coordinate); });/***按鈕相應(yīng)事件**/ function btStart_click() {ableSt = true; }function btEnd_click() {ableEd = true; }//最短路徑按鈕 function select_click() {overlay.setPosition(undefined);closer.blur();var getwayurl = 'http://localhost:8080/geoserver/wuhan/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=wuhan:wuhan&maxFeatures=50&outputFormat=application/json&viewparams=' + 'st_lon:' + st_lon + ';st_lat:' + st_lat + ';ed_lon:' + ed_lon + ';ed_lat:' + ed_lat;var getMywayurl = 'http://localhost:8080/geoserver/wuhanwork/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=wuhanwork:tt&maxFeatures=50&outputFormat=application/json&viewparams=' + 'startLon:' + st_lon + ';startLat:' + st_lat + ';endLon:' + ed_lon + ';endLat:' + ed_lat;var roadsource = new ol.layer.Vector({source: new ol.source.Vector({ url: getMywayurl,format: new ol.format.GeoJSON({extractStyles: true}),style: new ol.style.Style({stroke: new ol.style.Stroke({color: [255, 255, 255, 1],width: 30})})})});map.addLayer(roadsource); } </script></html>源代碼:SourceCode
總結(jié)
- 上一篇: 8.MySQL 数据操作 DML
- 下一篇: NFS服务器原理、搭建、配置