在 ServBay 中使用 pgRouting 進行地理空間路由分析
pgRouting
是一個強大的 PostgreSQL 與 PostGIS 擴充套件,專為地理空間資料提供豐富的路由與網路分析功能。有了 pgRouting
,開發者能夠針對路網資料進行進階查詢,例如尋找兩點間的最短路徑、解決旅行推銷員問題(TSP),或進行服務區分析。這些功能特別適用於地圖應用、物流規劃、交通分析等場景。
本文將詳細說明如何在 ServBay 這個本機 Web 開發環境裡輕鬆啟用 PostgreSQL 的 pgRouting
擴充套件,同時指導您完成基礎設定與路由分析。
概述
ServBay 為 macOS 開發者提供一個便利的一站式本機開發環境,已整合多款 Web 伺服器、資料庫與程式語言。ServBay 所配備的 PostgreSQL 軟體包,預先包含 pgRouting
與 PostGIS
擴充套件。這代表您無需手動下載或編譯這些套件,只要在指定資料庫簡單啟用即可使用。
前置準備
開始使用 pgRouting
前,請確認您已經符合下列條件:
- 已安裝並執行 ServBay: 若尚未安裝 ServBay,請前往 ServBay 官方網站 下載最新版本並安裝。
- 在 ServBay 已安裝並啟動 PostgreSQL 套件: 請於 ServBay 介面檢查 PostgreSQL 套件已安裝且處於「執行中」狀態。
- 具備基本的 SQL 與 PostgreSQL 操作知識: 本文假設您已了解基礎 PostgreSQL 資料庫操作與 SQL 查詢語法。
- 具備 PostGIS 基礎概念:
pgRouting
依賴PostGIS
處理地理空間資料型態及函式。確保您的資料庫已啟用PostGIS
擴充套件。ServBay 預設安裝的 PostgreSQL 通常已包含 PostGIS。
安裝與啟用 pgRouting 擴充套件
ServBay 已隨套件附帶好 pgRouting
擴充檔案,您僅需於目標資料庫中啟用即可。
連線至 PostgreSQL 資料庫:
您可透過多種方式連線 PostgreSQL,如命令列工具
psql
、圖形化管理工具 (如 pgAdmin、DBeaver),或以程式語言連接。使用 ServBay 提供的
psql
命令列工具是最直接且常見的方法。您可以於 ServBay 應用裡點選「終端機」按鈕快速啟動預設好環境變數的終端機,或手動將 ServBay 的 bin 目錄加入系統 PATH。在終端機中執行下列指令,以連線至您的目標資料庫(例如,名為
servbay_geo_db
的資料庫並使用預設servbay
用戶):bashpsql -U servbay -d servbay_geo_db
1若您的資料庫名稱、用戶名或密碼有異,請依實際狀況調整指令。
檢查並啟用 PostGIS 擴充套件(若尚未啟用):
pgRouting
需依賴PostGIS
。啟用pgRouting
前,請先確認 PostGIS 是否已啟用。於psql
提示字元輸入:sqlCREATE EXTENSION IF NOT EXISTS postgis;
1此指令會建立(或略過已存在的)
PostGIS
擴充套件。建立 pgRouting 擴充套件:
於同一資料庫連線中,執行下列 SQL 啟用
pgRouting
擴充:sqlCREATE EXTENSION pgrouting;
1若執行成功,您將見到類似
CREATE EXTENSION
訊息。驗證安裝狀態:
您可透過下列指令查詢已安裝的擴充套件並確認
pgRouting
已正常啟用:sql\dx
1您應在清單中看到
postgis
與pgrouting
及其相關資訊。
配置 pgRouting:準備路網資料並建立拓撲
pgRouting
演算法運作基礎在呈現路網結構的表格。通常會用一個存放線段(道路)的表格,每條線段需包含起點、終點及加權(如距離、時間)等欄位。為高效執行路由計算,還需利用這些線段建立一個「拓撲」結構,記錄路段之間的連結(節點)。
建立路網資料表
以下是建立 ways
路網資料表的範例。表格內容包含路段 ID、起點與終點節點 ID、正向與反向的旅行成本(cost
, reverse_cost
),以及使用 PostGIS GEOMETRY
型態存放的線段幾何。
sql
-- 建立存放路網資料的表格
CREATE TABLE ways (
id SERIAL PRIMARY KEY, -- 路段唯一識別碼
source INTEGER, -- 起始節點 ID
target INTEGER, -- 終點節點 ID
cost DOUBLE PRECISION, -- 正向通過此路段的成本(例如距離或時間)
reverse_cost DOUBLE PRECISION, -- 反向通行成本
geom GEOMETRY(LineString, 4326) -- 路段幾何,型態為LineString,SRID 4326(WGS 84 經緯度)
);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
說明:
SERIAL PRIMARY KEY
:自動產生唯一路段編號。source
,target
:分別代表拓撲中的路段起點與終點節點 ID,於建立拓撲時自動產生或對應。cost
,reverse_cost
:定義此路段的加權(如距離或通行時間)。若為單行道,可將reverse_cost
設為NULL
或極大值。geom
:以PostGIS
的GEOMETRY
型態存放線段地理資訊。LineString
表型態,4326
為常用SRID(WGS 84座標系,全球定位標準)。
插入範例資料
可於 ways
表格中插入下列範例線段:
sql
-- 插入範例路段資料
INSERT INTO ways (source, target, cost, reverse_cost, geom) VALUES
(1, 2, 1.0, 1.0, ST_SetSRID(ST_MakeLine(ST_MakePoint(116.4074, 39.9042), ST_MakePoint(116.4084, 39.9052)), 4326)),
(2, 3, 1.0, 1.0, ST_SetSRID(ST_MakeLine(ST_MakePoint(116.4084, 39.9052), ST_MakePoint(116.4094, 39.9062)), 4326)),
(3, 4, 1.0, 1.0, ST_SetSRID(ST_MakeLine(ST_MakePoint(116.4094, 39.9062), ST_MakePoint(116.4104, 39.9072)), 4326));
1
2
3
4
5
2
3
4
5
說明:
ST_MakePoint(x, y)
:以經緯度座標產生 PostGIS 點位。ST_MakeLine(point1, point2)
:用兩點產生線段資料。ST_SetSRID(geometry, srid)
:設定幾何物件的空間參考系(SRID)。- 範例資料為三條串接成的路段,加權成本皆為 1.0。經緯度為北京市區之實例座標。
建立拓撲
當路網表資料備妥,即可使用 pgr_createTopology
函數建立拓撲。此函數會自動掃描路段幾何,識別節點、填入 source
與 target
欄,並新建對應節點表(通常命名為 [your_table_name]_vertices_pgr
)。
sql
-- 為路網表格建立拓撲
-- 參數說明:
-- 'ways':欲建立拓撲的表格名稱
-- 0.00001:容差值 (tolerance),判斷相近距離內點位視為同一節點
-- 'geom':路段幾何欄位名
-- 'id':路段 ID 欄位名
SELECT pgr_createTopology('ways', 0.00001, 'geom', 'id');
1
2
3
4
5
6
7
2
3
4
5
6
7
說明:
pgr_createTopology
:pgRouting
的核心函數,用於建立網路節點-邊結構。- 容差值(tolerance)極為重要,其決定了多近的兩點會視為同一交會節點。建議根據資料精度與比例適當調整。
執行後,ways
表格的 source
與 target
欄將自動填入節點編號,並在資料庫中產生一份 ways_vertices_pgr
節點表,內含所有偵測到的節點及其座標。
使用 pgRouting 執行路由分析
拓撲建立完畢後,即可運用 pgRouting
眾多演算法進行路由分析。以下為常見演算法範例:
最短路徑分析(Dijkstra)
查詢兩點間最短路徑是最常見需求。pgRouting
內建 Dijkstra 最短路徑演算法。
sql
-- 從節點 1 到節點 4 查詢最短路徑
-- 參數說明:
-- 'SELECT id, source, target, cost FROM ways':圖形建立查詢,需包含 id, source, target, cost 欄
-- 1:起始節點 ID
-- 4:目標節點 ID
-- directed := true:指定圖為有向圖(即 cost 與 reverse_cost 是否不同)
SELECT seq, id1 AS node, id2 AS edge, cost, geom
FROM pgr_dijkstra(
'SELECT id, source, target, cost FROM ways',
1, -- 起始節點ID
4, -- 目標節點ID
directed := true -- 若需考慮反向成本,可設為 false 或省略
)
JOIN ways ON edge = ways.id; -- 與原始 ways 表 join 取得幾何資料
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
說明:
pgr_dijkstra
:執行 Dijkstra 最短路徑演算法。- 第一個參數為 SQL 查詢,必須回傳網路之邊(路段)資訊,至少有
id
,source
,target
,cost
。如需雙向考慮,需加上reverse_cost
並設 directed 為 false。 - 第二與第三參數分別為起點、終點節點 ID。
- 透過
JOIN ways ON edge = ways.id
取得原始幾何資料便於可視化。
旅行推銷員問題(Traveling Salesperson Problem, TSP)
TSP 用於尋找巡訪多個指定節點的最短或最低成本路徑。
sql
-- 解決節點 1, 2, 3, 4 的 TSP 問題,起點為1號節點
-- 參數說明:
-- 'SELECT id, x::float8 AS x, y::float8 AS y FROM ways_vertices_pgr':選取指定節點及座標
-- start_id := 1:指定起點 ID
SELECT seq, node, edge, cost
FROM pgr_tsp(
'SELECT id, ST_X(the_geom)::float8 AS x, ST_Y(the_geom)::float8 AS y FROM ways_vertices_pgr WHERE id IN (1, 2, 3, 4)', -- 要巡訪的節點及其座標
start_id := 1 -- 起點節點ID
);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
說明:
pgr_tsp
:執行 TSP 路徑優化演算法。- 第一參數 SQL 查詢返回需巡訪的節點資訊,至少須有
id
,x
,y
座標。 start_id
設定旅行起點。
服務區分析(Driving Distance / Driving Time)
服務區分析可判斷自某(多)一節點出發,在特定成本(距離或時間)能到達的所有區域或路段。
sql
-- 從節點 1 出發,搜尋成本不超過2的所有可通達路段
-- 參數說明:
-- 'SELECT id, source, target, cost FROM ways':圖形查詢
-- 1:起點節點 ID
-- 2:最大可達成本值
-- directed := true:指定圖是否為有向圖
SELECT seq, id1 AS node, id2 AS edge, cost, geom
FROM pgr_drivingDistance(
'SELECT id, source, target, cost FROM ways',
1, -- 起點節點ID
2, -- 最大可達成本
directed := true
)
JOIN ways ON edge = ways.id; -- 結合原始 ways 表取得幾何資訊
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
說明:
pgr_drivingDistance
:執行服務區分析演算法。- 第一參數與
pgr_dijkstra
相同,用於圖形建構。 - 第二參數為起點節點 ID。
- 第三參數為可容許最大成本(距離/時間)。
- 亦可 JOIN 幾何資料便於地圖視覺化。
路由結果可視化
將 pgRouting
的分析成果地圖化,對於理解及展示特定路徑極為關鍵。您可選擇桌面 GIS 軟體或於 Web 應用整合地圖 JS 函式庫來呈現。
使用桌面 GIS 工具(如 QGIS)
QGIS 是免費開源桌面 GIS 軟體,可直接連線 PostgreSQL/PostGIS 資料庫,載入並可視化包含 pgRouting
結果的空間資料。
- 啟動 QGIS。
- 點選 圖層 (Layer) > 資料來源管理員 (Data Source Manager)。
- 左側選單選擇 PostGIS。
- 按 新增 (New) 建立新資料庫連線。
- 輸入您的 ServBay PostgreSQL 連線資訊(如:主機 (Host):
localhost
,連接埠 (Port):5432
,資料庫 (Database):servbay_geo_db
,用戶 (User):servbay
,密碼 (Password):您的 PostgreSQL 密碼)。可按「測試連線」確認設定正確。 - 連線成功後,展開資料庫即可見所有表格,包含
ways
及ways_vertices_pgr
。 - 選擇欲載入的表格或查詢視圖(如最短路徑查詢結果),按 新增 (Add) 以地圖方式展示於 QGIS。
於 Web 應用中可視化(Leaflet 或 OpenLayers)
針對 Web 應用,建議於後端(如 ServBay 上運行 PHP、Node.js、Python 等)執行 pgRouting
查詢,並將結果以 GeoJSON 格式返回前端。前端則可用地圖 JS 函式庫(如 Leaflet 或 OpenLayers)呈現這些空間資料。
以下為 Leaflet 載入靜態折線的 HTML 範例。若要動態顯示查詢結果,您需:
- 後端執行
pgRouting
查詢。 - 把返回的路段幾何資料轉換成 GeoJSON。
- 提供 API 端點讓前端取得 GeoJSON。
- 於前端 JavaScript 利用 Leaflet 的
L.geoJSON
載入並顯示結果。
html
<!DOCTYPE html>
<html>
<head>
<title>ServBay pgRouting Web 視覺化範例</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<style>
#map { height: 600px; width: 100%; } /* 設定地圖容器尺寸 */
</style>
</head>
<body>
<h1>ServBay pgRouting 結果視覺化</h1>
<div id="map"></div>
<script>
// 初始化地圖,設定中心與縮放
var map = L.map('map').setView([39.906, 116.409], 14); // 置於範例資料中心
// 加入 OpenStreetMap 圖磚
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// 範例:加入自 pgRouting 查詢所得的 GeoJSON
// 實際應用中應由 AJAX 取得 geojsonData
var geojsonData = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": 1,
"cost": 1.0
},
"geometry": {
"type": "LineString",
"coordinates": [
[116.4074, 39.9042],
[116.4084, 39.9052]
]
}
},
{
"type": "Feature",
"properties": {
"id": 2,
"cost": 1.0
},
"geometry": {
"type": "LineString",
"coordinates": [
[116.4084, 39.9052],
[116.4094, 39.9062]
]
}
},
{
"type": "Feature",
"properties": {
"id": 3,
"cost": 1.0
},
"geometry": {
"type": "LineString",
"coordinates": [
[116.4094, 39.9062],
[116.4104, 39.9072]
]
}
}
]
};
// 利用 L.geoJSON 於地圖上顯示 GeoJSON
L.geoJSON(geojsonData, {
style: function (feature) {
return {color: "#ff0000", weight: 4}; // 路徑以紅色粗線呈現
}
}).addTo(map);
// 調整地圖視域以包含所有結果
if (L.geoJSON(geojsonData).getBounds().isValid()) {
map.fitBounds(L.geoJSON(geojsonData).getBounds());
}
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
請將此 HTML 檔案存於 ServBay 網站根目錄(如 /Applications/ServBay/www/pgrouting-demo/index.html
),並透過 ServBay 直接瀏覽(如 http://pgrouting-demo.servbay.demo
),即可見包含範例路徑的地圖。請注意此範例為靜態資料,主要展示 GeoJSON 載入 Leaflet 用法。
注意事項
- 資料品質:
pgRouting
計算結果極仰賴輸入路網資料品質。請確保資料正確、完整且拓撲連通。 - 效能考量: 大型路網可能計算時間較長。可考慮使用索引、精簡資料或切分區段優化效能。
- 記憶體需求: 廣域網狀架構會佔用較多記憶體,務必確保資料庫主機資源足夠。
常見問答(FAQ)
Q: 執行 CREATE EXTENSION pgrouting;
出現「擴充套件不存在」錯誤該怎麼辦? A: 請先檢查 ServBay 的 PostgreSQL 套件是否已安裝並啟動。確認所用資料庫版本支援 pgRouting
,且 ServBay 提供之 PostgreSQL 確實包含該套件(通常預裝)。仍有問題時,請查閱 ServBay 或 PostgreSQL 日誌取得詳細錯誤訊息,也請確認您以有足夠權限的用戶(如 servbay
)連線資料庫。
Q: pgr_createTopology
函式中的容差值 (tolerance) 如何選擇? A: 容差需根據您資料的地理精度決定。其定義兩頂點之間視為同一節點的最小距離。若用高精度座標(如 GPS),容差可設極小(如 0.000001)。若資料品質較低或來源多元,請適度增大容差值增加容錯。容差設太大可能導致不相干的線段錯誤連結。
Q: 要如何處理單行道或禁迴轉等交通規則? A: 對於單行道,請於 ways
表中的 reverse_cost
設為 NULL
或極大值即代表反向不可通行。禁迴轉或其他複雜交通規則則需建立更細緻的路網模型,或於路徑結果後處理;pgRouting
也提供進階功能可處理此類情境。
總結
透過 ServBay,您可於本機開發環境輕鬆部署支援 pgRouting
的 PostgreSQL。只需簡單 SQL 指令即可啟用擴充套件,準備路網資料並建立拓撲後,就能活用 pgRouting
豐富的地理空間路由演算法。結合桌面 GIS 工具或網頁地圖函式庫,您能快速將結果視覺化,為 Web 應用與空間分析/專案提供強大的資料基礎。ServBay 大幅簡化複雜環境設定,助您專注應用開發與功能創新。