OpenStreetMapのデータからosmiumを使って鉄道だけを抽出しPostGISに入力する方法(宇都宮周辺の鉄道データを使った例)
以前、「OpenStreetMapのデータから鉄道だけを抽出してGeoJSONで出力する方法」の記事で、OSMのデータからrailwayのデータのみを抽出してGeoJSONに書き出す手順を書きました。
ところで「「OpenStreetMapから鉄道路線データを落とせない」と愚痴っていたら、社内の人から「OSMに鉄道データ入っていますよ」と言われて、愕然とした件」に書かれているように、OSMのデータから抽出した鉄道や道路等のデータをPostGISに入力できたほうが便利なようです。
ここでは、APIサーバー等で使用するために、OSMのデータから抽出した鉄道や道路のデータを、GeoJSON等を介さず、直接PostGISに入力してみます。
宇都宮周辺だけのOSMデータの用意
先ず、日本全体のOpenStretMapのデータ(japan-latest.osm.pbf)から、宇都宮周辺に絞ったデータを抽出します。
「OpenStreetMapのデータをosmiumを使用して指定した範囲で抽出する方法」の内容に沿って、宇都宮周辺を次のようなGeoJSONで定義し、utunomiya.jsonというファイルに保存します。
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
139.77630615234375,
36.697603754877754
],
[
139.7563934326172,
36.530053615692154
],
[
139.80857849121094,
36.391993080763974
],
[
139.96925354003906,
36.38149043210595
],
[
140.16014099121094,
36.415756993900885
],
[
140.2027130126953,
36.527294814546245
],
[
140.19790649414062,
36.627100703563116
],
[
140.17730712890625,
36.721273880045004
],
[
140.01800537109375,
36.72787819497748
],
[
139.77630615234375,
36.697603754877754
]
]
]
}
}
]
}
japan-latest.osm.pbfから上のGeoJSONの範囲でOpenStreetMapを抽出するために、次のようにosmium
コマンドを実行します。
osmium extract \
--strategy complete_ways \
--set-bounds --polygon utunomiya.json \
-o utunomiya.osm.pbf \
japan-latest.osm.pbf
この結果、宇都宮周辺だけのOSMデータとして、utunomiya.osm.pbfが得られます。
Osmium-toolsを使用し宇都宮周辺のosm.pbfからの鉄道データを抽出しPostGISの形式で出力
次に、宇都宮周辺のOpenStreetMapのデータ(utunomiya.osm.pbf)から、タグがrailwayのデータだけを抽出します。
「OpenStreetMapのデータから鉄道だけを抽出してGeoJSONで出力する方法」の手順に沿って、次のようにosmium
コマンドを実行します。
osmium tags-filter utunomiya.osm.pbf \
w/railway \
-o utunomiya-railway.osm.pbf
この結果、宇都宮周辺の鉄道のデータがutunomiya-railway.osm.pbfという名前のプロトコルバッファー形式のファイルとして得られます。
このデータを、osmium
コマンドを次のように使用してPostGISに直接入力可能なファイルに変換します。
osmium export -f pg \
-o utunomiya-railway.pg \
utunomiya-railway.osm.pbf
変換後のutunomiya-railway.pgの内容は、次のようなPostGISのgeometry型とPostgreSQLのJSONB型の2カラム分の内容を1行ごとに詰めたテキストファイルとなっています。
0101000020E6100000EB1C03B2577F61400557D4BBD3504240 {"local_ref":"1","name":"宝積寺","name:en":"Hoshakuji","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E61000000458E4D70F7C61406071DD39393F4240 {"local_ref":"1","name":"雀宮","name:en":"Suzumenomiya","name:ja":"雀宮","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E61000000A6FC5B4657E6140C47762D68B5C4240 {"railway":"level_crossing"}
0101000020E6100000B0A250600B7C614074A4E9A2D73E4240 {"railway":"level_crossing"}
0101000020E61000000006DDB90B7C6140B2193B3CDF3E4240 {"railway":"switch"}
0101000020E610000035B22B2DA37E6140C9EDF208C9584240 {"railway":"level_crossing"}
0101000020E610000056B77A4EFA7E61401B88C0ECF9544240 {"railway":"level_crossing"}
0101000020E6100000EF2E617E387E61404E226706964C4240 {"local_ref":"2","name":"岡本","name:en":"Okamoto","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E6100000267F411CB57E61408242F3EFE94D4240 {"railway":"level_crossing"}
0101000020E610000002E8418BB68161404B28D8DA56554240 {"railway":"level_crossing"}
0101000020E610000079FDEEC2BB826140CB3D6E090A554240 {"railway":"level_crossing"}
0101000020E6100000D2EA9A7FEA8261404BE5ED08A7544240 {"railway":"level_crossing"}
0101000020E61000006A036674F684614009CB338A40534240 {"name":"烏山","name:en":"Karasuyama","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E6100000913BB6AF0D836140136635B808544240 {"name":"大金","name:en":"Ogane","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E610000031395A7A597F614081165CBDD4504240 {"local_ref":"3","name":"宝積寺","name:en":"Hoshakuji","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E6100000FDF50A0B6E84614057AF22A303534240 {"name":"滝","name:en":"Taki","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E6100000D99B734B468061405E00D01731534240 {"name":"下野花岡","name:en":"Shimotsuke-Hanaoka","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E61000006B96708DF48061405ABC581822544240 {"name":"仁井田","name:en":"Niita","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E610000046370C30BD836140E1EAA5CE48524240 {"name":"小塙","name:en":"Kobana","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E6100000BCF957A0A78161404F46F01A4F554240 {"name":"鴻野山","name:en":"Konoyama","public_transport":"stop_position","railway":"stop","train":"yes"}
0101000020E61000003163658FEB846140D9603CDE3F524240 {"railway":"level_crossing"}
OSMから抽出した鉄道のデータをPostGISに入力
宇都宮周辺の鉄道データをPostGISに入力できる形式で書き出したutunomiya-railway.pgファイルを、実際にPostGISに入力します。
先ず、localhostで動作しているPostGISのデータベースにpsql
コマンド使って接続します。
psql -U postgres -h localhost
次に、psql
の接続の中で、次のSQLとコマンドを実行します。
ここでは、「map」という名前のデータベースの中に「utunomiya」という名前のテーブルを作成し、その中にutunomiya-railway.pgの内容を登録しています。
create database map;
\c map
create extension postgis;
create table utunomiya (
geom geometry,
tags jsonb
);
\copy utunomiya from 'utunomiya-railway.pg'
この結果、次の図1のようにOpenStreetMapから抽出したrailwayのデータがPostGISのutunomiyaテーブルの中に登録されます。
utunomiyaテーブルのgeomカラムはPostGISのgeometry型、tagsカラムはPostgreSQLのJSONB型となっているので、一般的なPostgreSQLのSQLを使用して加工することができます。
例えば、JSONB型のtagsカラムの中からキーがrailwayとnameのものの値だけを抜き出してrailwayカラムとnameカラムとして得るには、次のようなSQLを実行します。
select geom, tags->>'railway' as railway,
tags->>'name' as name
from utunomiya;
この結果、図2のようにgeometry、railway、nameのカラムのデータが得られます。
PostGISの中の宇都宮周辺の鉄道のgeometryをQGISで表示
これまでの手順で、PostGISのmapデータベースのutunomiyaテーブルに、OpenStreetMapから抽出した鉄道のデータのgeometryとtagsが入力できました。
QGISでmapデータベースに接続し、utunomiyaテーブルのgeometryを国土地理院の淡色タイルの上に重ねて表示すると、図3のように、実際に宇都宮周辺の鉄道のデータだけを抽出できたことが確認できました。
宇都宮ライトレールのデータが表示されていることも確認できました。