公開Shapefileをちょっと触って、駅を歩く
- 6 分で読めます - 2825 文字きっかけは、「歩ける3D空間に、メッセージ性のある表示を出せないか」と考えたことだった。
国土交通省が公開している新宿駅周辺と東京駅周辺の屋内地図を使い、床や通路を階ごとに重ねてブラウザへ表示してみた。 施設名を検索でき、出発地と目的地を選べば経路が出る。 一人称視点へ切り替えると、その経路に沿って駅構内を移動することもできる。
Pythonで座標と属性を整理し、描画用の形状、経路探索用のグラフ、検索用の施設情報をJSONへまとめ、ブラウザだけで描画している。

Station Layersの全体画面。デモ用データを使い、施設と階層構造を立体表示している。
元データには、駅の形以外も入っていた
使用したのは、国土交通省の「高精度測位社会プロジェクト」で整備された駅周辺屋内地図オープンデータである。 複数の鉄道会社、民間ビル、公共施設にまたがる通路を、ひと続きの屋内地図として扱うために作られている。
Shapefileは、点、線、面と、それぞれにひも付く属性を保存できるGIS向けのファイル形式である。
名前は単数形だが、形状の.shp、属性の.dbf、インデックスの.shxなど、実際には複数のファイルで一つのレイヤーを構成する。
今回の公開データには、床や通路の形だけでなく、歩行空間ネットワークデータと施設情報も含まれている。
| 元データ | アプリでの使い道 |
|---|---|
| 床、通路、部屋などの面 | 各フロアの描画 |
| 接続点と、それらを結ぶ線 | 経路探索 |
| トイレ、改札、出口、エレベーターなどの施設情報 | 検索と位置表示 |
床の形だけなら、立体的に眺めるところまでは作れる。 どこを歩けるか、何がどこにあるかという情報も含めて公開されていたので、経路探索と施設検索へ進めた。
公開データをブラウザ向けに変換する
公開データから画面が表示されるまでの流れは、次のようになっている。
flowchart TD
subgraph SHP["公開Shapefile"]
direction TB
B[床・通路・部屋などの面]
C[歩行空間ネットワーク]
D[施設情報]
end
SHP -->|Pythonで変換| E[描画用メッシュ<br/>経路探索用グラフ<br/>検索用施設情報]
E -->|JSON| F[WebGL 2.0で描画]
変換にはGeoPandas、Shapely、pyprojを使った。 元データのJGD2011に基づく座標を、駅周辺をメートル単位で扱える平面座標へ投影し、駅の中心を原点とするローカル座標へ変換した。
階どうしの間隔は表示用に調整できる。 見た目の高さは実際の建物の高さではなく、各階の床形状を設定した高さへ配置したものだ。 3Dモデルを作ったというより、感覚としては2.5Dに近い。

階層表示の例。階層間隔を広げると、地下から地上までの積み重なりが見える。
線を経路へ、点を行き先へ変える
床を作っただけでは、駅の中の歩行ルートは分からない。
歩行空間ネットワークデータの接続点と線を読み込み、経路探索に使うグラフへ変換する。 線の属性から階段、エスカレーター、エレベーター、スロープなどを判定し、移動条件に応じて経路の選び方を変えている。
施設情報は、名称や施設コードを手掛かりに、トイレ、出口、改札、エレベーター、店舗などへ分類する。 そのうえで最寄りの接続点と関連付け、検索した施設を経路の出発地や目的地にできるようにした。
見た目を作る処理と、歩ける場所を決める処理は別である。 床がそこに描かれていても、歩行空間ネットワークの線がつながっていなければ、経路探索では通れない。
立体表示が動いたので、欲を出す
最初は、地下と地上のフロアを重ねて表示できれば十分だと思っていた。 動いたので、欲が出た。
「階層間隔」スライダーを動かすと、各フロアが上下に離れ、駅の積み重なりを確認できる。 真上から見る2D表示、単一フロア表示、歩行空間ネットワークと施設名の表示切り替えも加えた。
施設情報を選ぶと、その場所へ視点を移動できる。 出発地と目的地を選ぶと経路を計算し、3D空間内へ線で表示する。
「段差を避ける」設定では、階段とエスカレーターを避け、エレベーターやスロープを優先するように経路計算の条件を変える。 経路を一人称視点で追うほか、WASDキーや矢印キーで自由に移動する操作も用意した。

新宿駅周辺の変換データ上で、2Fのエレベーターから地上階段までの経路を表示。

計算した経路を一人称視点で再生。画面下部から再生速度や進行方向を操作できる。
描画にはThree.jsやBabylon.jsを使わず、WebGL 2.0を直接使っている。 メッシュ、ライン、ポイント用のシェーダーを分け、カメラ、照明、霧も描画コード側で処理した。
周辺の開発環境やGISライブラリは使いやすくなったが、WebGL 2.0の書き方まで簡単になったわけではない。 普通に大変なので、このあたりは素直にThree.jsやBabylon.jsを使った方がいいですね。
難しかったのは、形より属性の意味だった
ここまでの処理は、制作全体から見ると素直だった。 時間がかかったのは、元データの図形と属性をアプリの挙動へ結び付ける作業である。
この面は床なのか、設備の範囲なのか
この線は通常の通路なのか、階段なのか
この施設はどの階に属しているのか
この経路は選択した移動条件で使えるのか同じように見える列でも、配布データによって名前や値の入り方が少し違う。 属性が欠けている箇所もあり、変換処理だけで決めきれない部分は、元の地図と変換後の表示を見比べて確認した。
見た目は3Dだが、制作中に一番よく見ていたのは属性テーブルだった。
立体表現のハードルは下がった
公開Shapefileを入力にして、立体表示だけでなく、施設の検索と駅構内の移動まで作れた。 形状だけでなく、歩行空間ネットワークと施設情報がそろっていたからである。
一方で、どの面を床として扱い、どの線を歩ける経路にするかは、アプリ側で決めなければならない。 公開データは完成した3Dモデルではないが、別の体験へ組み替えるための材料としてはかなり強い。
今回は駅を使ったが、同じようなデータがあれば、地下街、商業施設、空港、スタジアムでも試せる。
公開データを見つけたら、とりあえず少し触ってみる。 それくらいの軽さで立体表示を試せるようになったのは、なかなか面白い。
複雑な空間を分かりやすく見せ、認知負荷を下げる手段として、今後さまざまな分野で使われていくだろうと感じた。