關於最短路徑查詢計劃分爲三篇文章來記錄。
本篇:主要來記錄在這個方案中,要如何去準備數據及相關的數據庫操作
Geoserver篇:主要記錄在Geoserver中如何去創建最短路徑分析圖層服務。
Openlayers篇:主要記錄在前端使用Openlayers如何去調用最短路徑服務。
一、軟件基礎
- 安裝PostgreSQL數據庫
- 安裝Geoserver地圖服務器
- 安裝PostGIS數據庫插件
相信做地圖開發的對這幾個軟件的安裝都不陌生,沒安裝過也不要害怕,因爲安裝極其簡單。
二、準備工作
-
首先,準備要用作路徑分析的數據源,幾何類型一定要是線類型。如道路中心線,文件格式:.shp
-
如果你的分析結果要考慮方向,請添加通行方向字段(建議添加)。
通行情況可以分爲四種情況:
1:雙向通行,值:空;
2:正向通行(即實際通行方向與矢量數據的方向一致),值:FT;
3:反向通行(即實際通行方向與矢量數據的方向相反),值:TF;
4:禁止通行,值:N。
當然取值你也可以使用其它內容來標識。
可以在ArcGIS或QGIS中查看線的矢量方向,然後根據實際情況去設置值。如果嫌麻煩,只是爲測試,可以均設置爲正向。 -
線線相交處打斷線(不要忘)
這一步操作,可以藉助ArcGIS工具箱中的要素轉線來完成。 -
在PostgreSQL中創建數據庫
-
添加postgis、pgrouting及相關的拓展
-
將線文件導入數據庫
使用PostGIS自帶的pgsql2shp工具,將shp文件導入數據庫。注意座標系,選擇多線轉單線。
三、數據操作(重點)
假設導入後的數據表名:road
1.添加字段:source、target、length、rev_length等字段
alter table road add column source int;
alter table road add column target int;
alter table road add column length double precision;
alter table road add column rev_length double precision;
2.爲了提高查詢效率,給source、target字段創建索引
create index source_idx on road ("source");
create index target_idx on road ("target");
3.創建拓撲
select pgr_createTopology('road ',0.0001, 'geom', 'gid');
創建拓撲後會在數據庫中生成以 vertices_pgr 結尾的表,用於記錄線文件中所有交叉點和端點。
4.更新length 、rev_length字段
update road set length=ST_Length(ST_TransForm(geom,4326),true),rev_length=ST_Length(ST_TransForm(geom,4326),true) where oneway is null;
update road set length=st_length(ST_TransForm(geom,4326),true),rev_length=99999999999 where oneway='FT';
update road set length=99999999999,rev_length=st_length(ST_TransForm(geom,4326),true) where oneway='TF';
update road set length=99999999999,rev_length=99999999999 where oneway='N';
因爲我們要查詢的是最短路徑,因此路段的長度實際上就是我們要評估權重的參數。這一段的意義,可以理解爲:
- 如果道路是雙向通行,則將正反向的路段長度設置爲實際長度;
- 如果是正向單向通行,則正向通行設置爲實際長度,反向通行距離設置爲99999999999(距離過大,不可取);
- 如果是反向單向通行,則與正向單向相反;
- 如果是禁止通行,則正反向長度均99999999999。
5.上面這些操作完成了以後,就可以進行最短路徑查詢了
查詢最短路徑
如果忽略方向問題,則
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 road ',
7,12,false,false) as di
join road pt
on di.id2 = pt.gid
如果查詢結果要考慮方向,則
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,
rev_length::double precision as reverse_cost
from road ',
7,12,true,true) as di
join road pt
on di.id2 = pt.gid
其中,7,12分別是你要查詢的起點和終點的gid編號。
本文參考:
https://www.jianshu.com/p/34c8378c3da9
https://blog.csdn.net/GISuuser/article/details/78625246
http://www.cnblogs.com/weiweictgu/p/8280285.html