1、軟件安裝node
GeoServer下載地址:web
http://geoserver.org/download/正則表達式
PostgreSQL下載地址:算法
https://www.postgresql.org/download/sql
paAdmin3下載地址:數據庫
https://www.pgadmin.org/download/pgadmin-3-windows/windows
PostGIS下載地址:瀏覽器
http://postgis.net/windows_downloads/函數
pgRouting已經包含在安裝程序中。佈局
全部下載程序以下:
安裝過程再也不詳述。
2、數據製做
我使用的是ArcMap來繪製路網數據,也可使用其它的GIS軟件,但好像沒有這麼方便,地理座標系使用GCS_WGS_1984,編號爲:4326。
注意:全部線段鏈接的地方都須要斷開,這樣便於之後的分析。
3、數據處理
使用paAdmin3鏈接PostgreSQL,並執行如下語句,在新的空間數據庫裏添加空間擴展:
CREATE EXTENSION postgis;
CREATE EXTENSION pgrouting;
CREATE EXTENSION postgis_topology;
CREATE EXTENSION fuzzystrmatch;
CREATE EXTENSION postgis_tiger_geocoder;
CREATE EXTENSION address_standardizer;
製做完路網數據後,須要使用 來把路網數據導入到PostgreSQL中去。
點擊「View connection details....」在彈出的窗口中填入PostgreSQL的帳號和密碼,以及Database。
鏈接成功後,須要設置一下「Optionns...」
須要使用GBK編碼,並勾選最下面一個選項。
添加路網數據,並設置SRID爲:4326
導入完成後,會在數據庫中建立一個對應的表:
在查詢表中分別執行下列SQL,對錶結構進行修改:
1.修改表結構
--添加起點id
ALTER TABLE public.road_xblk ADD COLUMN source integer;
--添加終點id
ALTER TABLE public.road_xblk ADD COLUMN target integer;
--添加道路權重值
ALTER TABLE public.road_xblk ADD COLUMN length double precis
2.建立拓撲結構
--爲sampledata表建立拓撲佈局,即爲source和target字段賦值
SELECT pgr_createTopology('public.road_xblk',0.0001, 'geom', 'gid');
3.建立索引
--爲source和target字段建立索引
CREATE INDEX source_idx ON road_xblk("source");
CREATE INDEX target_idx ON road_xblk("target");
4.給長度賦值
--爲length賦值
update road_xblk set length =st_length(geom);
--爲road_xblk表添加reverse_cost字段並用length的值賦值
ALTER TABLE road_xblk ADD COLUMN reverse_cost double precision;
UPDATE road_xblk SET reverse_cost =length;
5.建立最短路徑函數
---建立查詢隨意兩點以前的最短路徑的函數
1 DROP FUNCTION pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float); 2 3 CREATE OR REPLACE function pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float) 4 5 returns geometry as 6 7 $body$ 8 9 declare 10 11 v_startLine geometry;--離起點最近的線 12 13 v_endLine geometry;--離終點最近的線 14 15 16 17 v_startTarget integer;--距離起點最近線的終點 18 19 v_startSource integer; 20 21 v_endSource integer;--距離終點最近線的起點 22 23 v_endTarget integer; 24 25 26 27 v_statpoint geometry;--在v_startLine上距離起點最近的點 28 29 v_endpoint geometry;--在v_endLine上距離終點最近的點 30 31 32 33 v_res geometry;--最短路徑分析結果 34 35 v_res_a geometry; 36 37 v_res_b geometry; 38 39 v_res_c geometry; 40 41 v_res_d geometry; 42 43 44 45 v_perStart float;--v_statpoint在v_res上的百分比 46 47 v_perEnd float;--v_endpoint在v_res上的百分比 48 49 50 51 v_shPath_se geometry;--開始到結束 52 53 v_shPath_es geometry;--結束到開始 54 55 v_shPath geometry;--最終結果 56 57 tempnode float; 58 59 begin 60 61 --查詢離起點最近的線 62 63 execute 'select geom, source, target from ' ||tbl|| 64 65 ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| startx ||' ' || starty||')'',4326),15) 66 67 order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1' 68 69 into v_startLine, v_startSource ,v_startTarget; 70 71 72 73 --查詢離終點最近的線 74 75 execute 'select geom, source, target from ' ||tbl|| 76 77 ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'',4326),15) 78 79 order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) limit 1' 80 81 into v_endLine, v_endSource,v_endTarget; 82 83 84 85 --若是沒找到最近的線,就返回null 86 87 if (v_startLine is null) or (v_endLine is null) then 88 89 return null; 90 91 end if ; 92 93 94 95 select ST_ClosestPoint(v_startLine, ST_Geometryfromtext('point('|| startx ||' ' || starty ||')',4326)) into v_statpoint; 96 97 select ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')',4326)) into v_endpoint; 98 99 100 101 -- ST_Distance 102 103 104 105 --從開始的起點到結束的起點最短路徑 106 107 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 108 109 'FROM pgr_kdijkstraPath( 110 111 ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 112 113 ||v_startSource || ', ' ||'array['||v_endSource||'] , false, false 114 115 ) a, ' 116 117 || tbl || ' b 118 119 WHERE a.id3=b.gid 120 121 GROUP by id1 122 123 ORDER by id1' into v_res ; 124 125 126 127 --從開始的終點到結束的起點最短路徑 128 129 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 130 131 'FROM pgr_kdijkstraPath( 132 133 ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 134 135 ||v_startTarget || ', ' ||'array['||v_endSource||'] , false, false 136 137 ) a, ' 138 139 || tbl || ' b 140 141 WHERE a.id3=b.gid 142 143 GROUP by id1 144 145 ORDER by id1' into v_res_b ; 146 147 148 149 --從開始的起點到結束的終點最短路徑 150 151 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 152 153 'FROM pgr_kdijkstraPath( 154 155 ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 156 157 ||v_startSource || ', ' ||'array['||v_endTarget||'] , false, false 158 159 ) a, ' 160 161 || tbl || ' b 162 163 WHERE a.id3=b.gid 164 165 GROUP by id1 166 167 ORDER by id1' into v_res_c ; 168 169 170 171 --從開始的終點到結束的終點最短路徑 172 173 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 174 175 'FROM pgr_kdijkstraPath( 176 177 ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 178 179 ||v_startTarget || ', ' ||'array['||v_endTarget||'] , false, false 180 181 ) a, ' 182 183 || tbl || ' b 184 185 WHERE a.id3=b.gid 186 187 GROUP by id1 188 189 ORDER by id1' into v_res_d ; 190 191 192 193 if(ST_Length(v_res) > ST_Length(v_res_b)) then 194 195 v_res = v_res_b; 196 197 end if; 198 199 200 201 if(ST_Length(v_res) > ST_Length(v_res_c)) then 202 203 v_res = v_res_c; 204 205 end if; 206 207 208 209 if(ST_Length(v_res) > ST_Length(v_res_d)) then 210 211 v_res = v_res_d; 212 213 end if; 214 215 216 217 218 219 --若是找不到最短路徑,就返回null 220 221 --if(v_res is null) then 222 223 -- return null; 224 225 --end if; 226 227 228 229 --將v_res,v_startLine,v_endLine進行拼接 230 231 select st_linemerge(ST_Union(array[v_res,v_startLine,v_endLine])) into v_res; 232 233 234 235 select ST_Line_Locate_Point(v_res, v_statpoint) into v_perStart; 236 237 select ST_Line_Locate_Point(v_res, v_endpoint) into v_perEnd; 238 239 240 241 if(v_perStart > v_perEnd) then 242 243 tempnode = v_perStart; 244 245 v_perStart = v_perEnd; 246 247 v_perEnd = tempnode; 248 249 end if; 250 251 252 253 --截取v_res 254 255 SELECT ST_Line_SubString(v_res,v_perStart, v_perEnd) into v_shPath; 256 257 258 259 return v_shPath; 260 261 262 263 end; 264 265 $body$ 266 267 LANGUAGE plpgsql VOLATILE STRICT;
4、數據發佈
數據準備完成後,就須要用GeoServer來進行發佈:
啓動GeoServer,在瀏覽器中輸入,http://localhost:8080/geoserver/web/,登陸到GeoServer。
1.建立工做區
添加xblk名稱的工做區。
2.添加數據存儲:
填入對應的鏈接信息:
3.添加圖層:
注意紅框中的內容。
4.添加路徑查詢服務,添加圖層,選擇「配置新的SQL視圖」:
視圖名稱:navigation
SQL語句:
SELECT * FROM pgr_fromAtoB('road_xblk', %x1%, %y1%, %x2%, %y2%)
驗證的正則表達式:^-?[\d.]+$
類型:LingString
SRID:4326
點擊保存後,填入SRS,並自動計算範圍:
5、結果展現
使用OpenLayer進行結果展現,代碼請直接下載,結果以下:
說明:這個最短路徑的算法有必定的問題,在特定的條件下,查找的不必定是最短的路徑,須要對數據進行再處理,或者對算法進行優化。