總體思路是用geoserver發佈圖層,圖層爲 sql,視圖是利用存儲過程分析出的路徑結果,node
路網通常爲shp數據,若是有多個圖層,建議利用arcgis或其餘工具合併爲一個圖層,方便處理web
使用paAdmin3鏈接PostgreSQL,並執行如下語句,在新的空間數據庫裏添加空間擴展:ajax
CREATE EXTENSION postgis; CREATE EXTENSION pgrouting; CREATE EXTENSION postgis_topology; CREATE EXTENSION fuzzystrmatch; CREATE EXTENSION postgis_tiger_geocoder; CREATE EXTENSION address_standardizer;
添加路網數據,設置表名,並設置SRID爲:4326
須要使用GBK編碼,並勾選最下面一個選項。正則表達式
1.修改表結構sql
--添加起點id ALTER TABLE lproad ADD COLUMN source integer; --添加終點id ALTER TABLE lproad ADD COLUMN target integer; --添加道路權重值 ALTER TABLE lproad ADD COLUMN length double precision
2.建立拓撲結構 數據庫
--爲lproad表建立拓撲佈局,即爲source和target字段賦值 SELECT pgr_createTopology('lproad ',0.0001, 'geom', 'gid');
3.建立索引json
--爲source和target字段建立索引 CREATE INDEX source_idx ON lproad ("source"); CREATE INDEX target_idx ON lproad ("target");
4.給長度賦值瀏覽器
--爲length賦值 update lproad set length =st_length(geom); --爲lproad 表添加reverse_cost字段並用length的值賦值 ALTER TABLE lproad ADD COLUMN reverse_cost double precision; UPDATE lproad SET reverse_cost =length;
-- DROP FUNCTION public.pgr_fromatoe(double precision, double precision, double precision, double precision); CREATE OR REPLACE FUNCTION pgr_fromatoe( tbl varchar, startx double precision, starty double precision, endx double precision, endy double precision) RETURNS geometry LANGUAGE 'plpgsql' COST 100 VOLATILE STRICT 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_start_temp geometry; v_start_temp1 geometry; v_start_temp2 geometry; v_end_temp geometry; v_end_temp1 geometry; v_end_temp2 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; startpoint geometry; endpoint geometry; v_shPath1 geometry;--一次結果 v_shPath2 geometry;--二次結果 star_line geometry; --起點到最近點的線 end_line geometry; --終點到最近點的線 geoARR geometry[]; begin --查詢離起點最近的線 --4326座標系 --找起點15米範圍內的最近線 execute 'select geom, source, target from '|| tbl || ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| startx ||' ' || starty||')'',4326),3000) order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1' into v_startLine, v_startSource ,v_startTarget; raise notice '%', v_startSource; raise notice '%', v_startTarget; --查詢離終點最近的線 --找終點15米範圍內的最近線 execute 'select geom, source, target from '|| tbl || ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'',4326),3000) order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) limit 1' into v_endLine, v_endSource,v_endTarget; raise notice '%', v_endSource; raise notice '%', 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, lproad 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, lproad 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, lproad 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, lproad 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_startLine,v_res,v_endLine])) into v_res; select ST_LineLocatePoint(v_startLine, v_statpoint) into v_perStart; select ST_LineLocatePoint(v_endLine, v_endpoint) into v_perEnd; SELECT ST_Line_SubString(v_startLine,v_perStart, 1) into v_start_temp1; SELECT ST_Line_SubString(v_startLine,0,v_perStart) into v_start_temp2; SELECT ST_Line_SubString(v_endLine,v_perEnd, 1) into v_end_temp1; SELECT ST_Line_SubString(v_endLine,0,v_perEnd) into v_end_temp2; raise notice '%', v_perStart; raise notice '%', v_perEnd; raise notice '%', ST_Distance(v_res,v_start_temp1); raise notice '%', ST_Distance(v_res,v_start_temp2); raise notice '%', ST_Distance(v_res,v_end_temp2); raise notice '%', ST_Distance(v_res,v_end_temp1); v_start_temp=v_start_temp1; if(ST_Distance(v_res,v_start_temp1) > ST_Distance(v_res,v_start_temp2)) then v_start_temp=v_start_temp2; end if; v_end_temp=v_end_temp1; if(ST_Distance(v_res,v_end_temp1) > ST_Distance(v_res,v_end_temp2)) then v_end_temp=v_end_temp2; end if; --return ST_AsGeoJSON(v_res); --return v_res; -- select ST_LineLocatePoint(v_res, v_statpoint) into v_perStart; -- select ST_LineLocatePoint(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_shPath1; select st_linemerge(ST_Union(array[v_start_temp,v_res,v_end_temp])) into v_shPath1; return v_shPath1; --後續爲將起點終點與路網鏈接起來,因發佈時有點問題,暫不使用 --找線的端點 select ST_SetSRID( ST_MakePoint(startx , starty),4326 )into startpoint; select ST_SetSRID( ST_MakePoint(endx , endy),4326 )into endpoint; select ST_MakeLine( v_statpoint,startpoint) into star_line; select ST_MakeLine( v_endpoint,endpoint) into end_line; geoARR :=array[end_line,v_shPath1,star_line]; select st_union(geoARR) into v_shPath; raise notice '%', '返回數據'; --raise notice '%', ST_AsGeoJSON(v_shPath); return v_shPath; end; $BODY$;
數據準備完成後,就須要用GeoServer來進行發佈:app
啓動GeoServer,在瀏覽器中輸入,http://localhost:8080/geoserver/web/,登陸到GeoServer。函數
配置數據庫鏈接
選擇「配置新的SQL視圖」,輸入SQL語句:
SELECT * FROM pgr_fromAtoB('road_xblk', %x1%, %y1%, %x2%, %y2%)
驗證的正則表達式:^-?[d.]+$
類型:LingString
SRID:4326
點擊保存後,填入SRS,並自動計算範圍
var viewparams = [ 'x1:' + startCoord[0], 'y1:' + startCoord[1], 'x2:' + destCoord[0], 'y2:' + destCoord[1] ]; params.viewparams = viewparams.join(';'); result = new ol.layer.Image({ source: new ol.source.ImageWMS({ url: ServerUrl + '/geoserver/Routing/wms', params: params }) }); map.addLayer(result);
var vectorSource = new ol.source.Vector({ format: new ol.format.GeoJSON(), url: function (extent) { return ServerUrl + '/geoserver/wfs?service=WFS&' + 'version=1.1.0&request=GetFeature&typename=Routing:lproute&' + 'outputFormat=application/json&srsname=EPSG:4326&' + 'bbox=' + extent.join(',') + ',EPSG:4326&' + 'viewparams=' + viewparams.join(';'); }, strategy: ol.loadingstrategy.bbox }); var vector = new ol.layer.Vector({ source: vectorSource, }); map.addLayer(vector);
var wfsurl = ServerUrl + '/geoserver/wfs?service=WFS&' + 'version=1.1.0&request=GetFeature&typename=Routing:lproute&' + 'outputFormat=application/json&srsname=EPSG:4326&' + 'viewparams=' + viewparams.join(';'); $.ajax({ url: wfsurl, success: function (result) { console.log(result); } });
效果如圖: