基於PostGIS+PgRouting的最短路徑查詢的實現(一):數據庫篇

關於最短路徑查詢計劃分爲三篇文章來記錄。
本篇:主要來記錄在這個方案中,要如何去準備數據及相關的數據庫操作
Geoserver篇:主要記錄在Geoserver中如何去創建最短路徑分析圖層服務。
Openlayers篇:主要記錄在前端使用Openlayers如何去調用最短路徑服務。

一、軟件基礎

  • 安裝PostgreSQL數據庫
  • 安裝Geoserver地圖服務器
  • 安裝PostGIS數據庫插件

相信做地圖開發的對這幾個軟件的安裝都不陌生,沒安裝過也不要害怕,因爲安裝極其簡單。

二、準備工作

  1. 首先,準備要用作路徑分析的數據源,幾何類型一定要是線類型。如道路中心線,文件格式:.shp

  2. 如果你的分析結果要考慮方向,請添加通行方向字段(建議添加)。
    通行情況可以分爲四種情況:
    1:雙向通行,值:空;
    2:正向通行(即實際通行方向與矢量數據的方向一致),值:FT;
    3:反向通行(即實際通行方向與矢量數據的方向相反),值:TF;
    4:禁止通行,值:N。
    當然取值你也可以使用其它內容來標識。
    可以在ArcGIS或QGIS中查看線的矢量方向,然後根據實際情況去設置值。如果嫌麻煩,只是爲測試,可以均設置爲正向。

  3. 線線相交處打斷線(不要忘)
    這一步操作,可以藉助ArcGIS工具箱中的要素轉線來完成。

  4. 在PostgreSQL中創建數據庫

  5. 添加postgis、pgrouting及相關的拓展

  6. 將線文件導入數據庫
    使用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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章