TOPO.TW

處理 OSM 資料

osm 格式為 openstreetmap.org API 較常使用的 XML 可讀格式, 基本上所有的後續加值資料都由此衍生而來。

例如,以下的 osm 物件包含 2 個 node 和 1 個 way:

<osm version="0.6">
  <node id="2183019342" version="6" timestamp="2020-08-08T20:51:11Z" lat="23.9729809" lon="120.9261691">
    <tag k="highway" v="traffic_signals"/>
  </node>
  <node id="7797369546" version="2" timestamp="2021-02-03T14:07:03Z" lat="23.972903" lon="120.9262552">
    <tag k="highway" v="traffic_signals"/>
  </node>
  <way id="32811162" version="11" timestamp="2020-08-08T20:51:11Z">
    <nd ref="7797369546"/>
    <nd ref="369731714"/>
    <tag k="highway" v="motorway_link"/>
    <tag k="name" v="愛蘭交流道"/>
    <tag k="name:zh" v="愛蘭交流道"/>
    <tag k="oneway" v="yes"/>
  </way>
</osm>

不過考慮到網路傳輸、儲存和地理空間的處理,通常會使用其它不同的格式。 可以在 OSM 的維基頁面中,找到更多相關資訊:

以下的範例可在 Linux 系統上使用,並以 osm.pbfosmx 為主軸:

下載 OSM 台灣區切片

除了 OSM 基金會提供的主伺服器1之外,也有其它許多鏡像站可以下載全球或特定區域的原始資料:
https://wiki.openstreetmap.org/wiki/Planet.osm

這邊使用頁面中提到的 geofabrik 服務:

From Geofabrik

  • Geofabrik 台灣切片頁面: http://download.geofabrik.de/asia/taiwan.html
    • 可下載 osm.pbf 格式(無損),或 shapfile 格式(有損)
    • osm.pbf 格式較緊湊,容量較小,但搜尋上較慢。詳情可見 wiki 頁面2
      建議下載後轉換為其它格式
# 使用 curl 指令下載
curl -O http://download.geofabrik.de/asia/taiwan-latest.osm.pbf

From KCWU

# 使用 curl 指令下載
curl -O http://osm.kcwu.csie.org/download/tw-extract/recent/taiwan-latest.o5m

轉換資料格式

OSMExpress 格式在依 ID 或空間查詢時效率非常高, 雖然許多工具也可以直接查詢 osm.pbf 格式,但建議轉換為 OSMExpress 專屬的 .osmx 格式。

# 直接在 Github release 頁面下載 Linux 版本的 OSMExpress 命令行工具 
curl -LO https://github.com/protomaps/OSMExpress/releases/download/0.2.0/osmexpress-0.2.0-Linux.tgz

# 用 tar 解壓縮
tar -zxvf osmexpress-0.2.0-Linux.tgz

# 使用命令行工具將 osm.pbf 格式轉換為 osmx 格式
./osmx expand taiwan-latest.osm.pbf taiwan.osmx

自行製作切片/查詢最近的路徑

osmx 指令可以取得較小範圍的區域切片

# 使用 bounding box 產生較小的 osm.pbf (南方緯度,西側經度,北方緯度,東側經度)
./osmx extract taiwan.osmx clip.osm.pbf --bbox 24.9752,121.6431,25.0067,121.68

# 或者,輸出人類可讀的 osm 格式
./osmx extract taiwan.osmx clip2.osm --bbox 24.9752,121.6431,25.0067,121.68

或者,直接找出與某點最相鄰的 osm 物件。

以下範例使用 osmx 格式,查找座標 E121.5° N24° 的點位,最近的路徑名稱。 在筆電上耗時約 0.2 秒。

# 使用 --disc 選項可以指定地點,用 <緯度,經度,半徑(經緯度)> 的格式來取得切片
# 經緯度在台灣大致換算:
#   0.005°: 450 公尺
#   0.0001°:  8~10 公尺
# 以下命令將取得 座標 E121.5° N24° 周圍 450 公尺的所有 osm 物件
./osmx extract taiwan.osmx clip3.osm --disc 24,121.5,0.005

# 使用管道命令和 gdal 來取得 GeoJSON 格式:
#
# gdal 在解析地理資料時預設會使用故定的 layer,
# 這邊我們只指定 lines 這個 layer,也就是只包含 way 物件
#
# 因為 osmx 命令行工具目前不提供 stdout 輸出的選項
# 故這邊使用 mkfifo 創造一個 named pipe 協作
mkfifo fifo.osm
osmx extract taiwan.osmx fifo.osm --disc 24,121.5,0.0005 | \
cat fifo.osm | \
ogr2ogr -f GEOJSON -nln foo /vsistdout/ /vsistdin/ lines

# 再加入 jq 的解析命令,即可取得道路名稱
# 輸出為:
#   白葉山路線
#   七腳川山路線
mkfifo fifo.osm
osmx extract taiwan.osmx fifo.osm --disc 24,121.5,0.0005 | \
cat fifo.osm | \
ogr2ogr -f GEOJSON -nln foo /vsistdout/ /vsistdin/ lines | \
jq '.features[]|.properties.name' -r

更新 OSM 圖資

geofabrik 的台灣圖資為每日更新,基本上要使用時再下載即可。 但若要在一天內更新數次,則需使用 OSMChange (.osc) 格式的檔案進行 patch。

從不同來源下載的 OSM 原始資料,基本上都會標示Sequence Number,用以區別生成時間。 可以使用這個數字,去取得更新到最新資料所需的 osc 檔案。

例如,geofabrik 為台灣區提供的 osc 目錄,可在以下網址確認:
http://download.geofabrik.de/asia/taiwan-updates/

# 取得 osmx 內的 Sequence Number
# 若原始資料由 geofabrik 而來,則可能是 3677
osmx query taiwan.osmx | grep Sequence | grep -o '[0-9]+'

# 取得 sequence 為 3678 的 osc 檔案
curl -o 3678.osc http://download.geofabrik.de/asia/taiwan-updates/000/003/678.osc.gz

# 解壓縮
gunzip 3678.osc.gz

# 為原始資料打上 Patch
# 標識 taiwan.osmx 新的 Sequence Number 為3687,並提供時間戳記
osmx update taiwan.osmx 3678.osc 3678 `date --iso-8601` --commit