路徑分析—QGIS+PostgreSQL+PostGIS+pgRouting(一)

2022-10-11 15:01:26

前言

因業務需求,需要做最短路徑分析。最近幾天查詢資料,並自己動手,實現了簡單的路徑分析。

下面就介紹具體的實現過程。

本篇文章最終結果是在 PostgreSQL 資料庫中實現的,後續的視覺化展示會跟進。

一、道路資料處理

如果你已經有了道路資料,那就直接使用。

由於當前並沒有較好的道路資料,這裡我自己用 QGIS 造了些資料以供使用。

為了效果較好,在建立道路資料時是疊加了影像圖的。並且要開啟「捕捉工具」,這樣在後續的拓撲分析中更好。

在完成道路資料的建立後,我直接進行了後續的工作,但是最終發現有問題,分析時發現:道路的資料在每個相交的點處要進行打斷,否則無法進行路徑分析。

於是在這裡對道路資料做了處理。使用「線相交」工具,輸入、相交圖層選當前道路圖層:

如下圖:

這三段本是一條道路,但是為了拓撲分析,需要進行在和別的道路相交點進行打斷。

 

此處部分要注意:

  1、編輯時開啟「捕捉工具」

  2、完成道路後進行線的打斷

 

二、資料入庫

資料庫這一塊,因為 PostgreSQL  有強大的空間資料處理擴充套件外掛(PostGIS),並且也有路徑分析的外掛(pgRouting),所以選用該資料庫。

1)、PostgreSQL 資料安裝

  1、windows 下,直接在官網下載安裝包即可,安裝完成資料庫後,會有 stackbuilder 安裝嚮導,可以安裝對應的一些外掛等,比較方便;

  2、Ubuntu下(我用的伺服器),在 18.04 及以上,可以使用 PostgreSQL Apt Repository ,這樣可以安裝需要的版本;

    2.1、PostgreSQL Apt Repository 使用

  3、安裝及設定參考

2)、PostGIS

  這部分有兩塊,一個是 PostgreSQL 的擴充套件,一個是 PostGIS的GUI(需要單獨安裝,主要用於匯入空間資料)。

3)、資料匯入

  1、建立資料庫,建立完成後需要進行對資料庫新增空間擴充套件

-- 提供如下空間資訊服務功能:空間物件、空間索引、空間操作函數和空間操作符
CREATE EXTENSION postgis;
-- 用於網路分析的擴充套件模組
CREATE EXTENSION pgrouting;
-- gis 拓撲
CREATE EXTENSION postgis_topology;
-- 提供了幾個函數來確定字串之間的相似性和距離
CREATE EXTENSION fuzzystrmatch;
CREATE EXTENSION postgis_tiger_geocoder;
CREATE EXTENSION address_standardizer;

  2、使用工具匯入空間資料,最新版本在Windows下名字比較長,如下圖:

 

 

 

 

到這裡就完成了空間資料的匯入,在這個過程中會遇到一些問題,可以參考:PostgreSQL 與 PostGIS 安裝使用注意坑

三、構建拓撲

這一塊主要是在資料庫中使用 SQL 完成,建立對應的 source、target、length、reverse_cost 欄位並賦值。

建立拓撲函數的使用

-- 新增起點id
ALTER TABLE public.roads ADD COLUMN source integer;

-- 新增終點id
ALTER TABLE public.roads ADD COLUMN target integer;

-- 新增道路權重值
ALTER TABLE public.roads ADD COLUMN length double precision;


-- 建立拓撲結構                  
-- 為roads表建立拓撲佈局,即為source和target欄位賦值
SELECT pgr_createTopology('roads',0.00001, 'geom','id');


-- 建立索引
-- 為source和target欄位建立索引
CREATE INDEX source_idx ON roads ("source");
CREATE INDEX target_idx ON roads ("target");


-- 為length賦值,這裡在計算的時候用 ST_Transform 進行了轉換
UPDATE roads SET length =st_length(ST_Transform(geom,3857));

-- 為 roads 表新增 reverse_cost 欄位並用length的值賦值
ALTER TABLE roads ADD COLUMN reverse_cost double precision;
UPDATE roads SET reverse_cost =length;

四、路徑分析

pgRouting 提供的最佳路徑演演算法比較多,具體可以參考:pgRouting 最短路徑演演算法查詢

這裡用 Shortest Path Dijkstra(狄克斯特拉)演演算法進行計算。

最新的 pgr_dijkstra 演演算法,支援多種方式,一對一、一對多、多對一、多對多等。

1)、用例分析

pgr_dijkstra(Edges SQL, start vid, end vid , [directed])
pgr_dijkstra(Edges SQL, start vid, end vids , [directed])
pgr_dijkstra(Edges SQL, start vids, end vid , [directed])
pgr_dijkstra(Edges SQL, start vids, end vids , [directed])
pgr_dijkstra(Edges SQL, Combinations SQL , [directed])
RETURNS SET OF (seq, path_seq, [start_vid], [end_vid], node, edge, cost, agg_cost)
OR EMPTY SET

傳入的引數:

  1、Edges SQL

    a、id,建立拓撲的標識,名稱不同用 as

    b、source,邊起點識別符號,拓撲後新增的欄位

    c、target,邊終點識別符號,拓撲後新增的欄位

    d、cost,邊權重(長度)

    e、reverse_cost,回程權重

  2、start vid:路徑起始點標識

  3、end vid:路徑終點標識

  4、directed:ture 時,圖被認為是有向的

返回引數:

  1、seq:查詢結果排序值

  2、path_seq:一個路徑下的排序值,新的路徑重新從1開始

  3、start_vid:多對一、多對,有這個欄位,路徑的起始點標識

  4、end_vid:一對多、多對多,有這個欄位,路徑的終點標識

  5、node:路徑中個個邊連線點的標識(上一個邊的 end,下一個邊的 start)

  6、edge:路徑中邊的標識

  7、cost:當前邊的成本(長度)

  8、reverse_cost:總成本(總長度)

2)、具體使用

-- 最短路徑分析
-- 直接使用,返回的是演演算法預設資料
SELECT * from  public.pgr_dijkstra(
    'SELECT
    id,
    source::integer,
    target::integer,
    length::double precision AS cost,
    reverse_cost
    FROM roads', 
    1, 
    20, 
    false
);


-- edge 是建立拓撲時的 id 標識欄位,所以可以通過這個在 roads 中篩選,並通過資料庫自帶的視覺化檢視結果
SELECT * from roads where "id" in
(
    SELECT edge from  public.pgr_dijkstra(
        'SELECT
        id,
        source::integer,
        target::integer,
        length::double precision AS cost,
        reverse_cost
        FROM roads', 
        1, 
        20, 
        false
    )
);

第二個SQL效果如下: