• #leaflet
  • #openstreetmap
  • #overpass-api
  • #gpx
  • #geojson
  • #tokyo-soundscape
開発tokyo-onkeiメモ

OSM建物オーバーレイとGPXトレース修正

音声プレイヤーの地図に建物の輪郭とPOI(ポイント・オブ・インタレスト)を重ねる機能を実装した。GPXデータの分析から始まり、トレース修正、建物データ取得、オーバーレイ描画、POI表示まで一日で一気に進めた。

GPXデータの分析と問題発見

プレイヤーで使っているGPXファイルを調べたところ、2つの<trk>要素が入っていた。

  • トラック1: 移動経路全体
  • トラック2: 浅草寺境内での録音区間

プレイヤーは tracks[tracks.length - 1] で最後のトラックを取得していたため、トラック2(録音区間)が使われていた。これ自体は意図通り。

問題は、トラック2のポイント183番から195番が本堂の建物内を突き抜けていたこと。GPSの精度限界で、実際には本堂の南側を歩いていたのにトラックが建物の中を通過している状態だった。

GPXトレース修正

修正方針として「建物の外を迂回させる」ではなく「本堂の南半分に実際に入っていたので、建物内部に制限する」を選んだ。南側の境界線(lat <= 35.71475)にクリッピングする方式。

Pythonスクリプト fix_gpx_v2.py で13ポイントの緯度を修正した。建物ポリゴンの南端に沿わせる形で、大きく逸脱していたポイントを南側境界に揃えた。

OSM建物データの取得

Overpass APIで浅草寺周辺の建物データを取得した。

[out:json][timeout:25];
way["building"](around:500, 35.7148, 139.7967);
out body; >; out skel qt;

約1,400棟の建物が返ってきた。全部表示すると重いので、2段階に分けた。

  • ランドマーク建物: 本堂、五重塔、宝蔵門、雷門、影向堂など11棟を手動で選別
  • 一般建物: 残りの建物(薄い白枠で控えめに表示)

選別では病院・幼稚園・交番といった寺社と無関係な施設を除外し、影向堂・薬師堂・淡島堂など境内の堂宇を追加した。出力はGeoJSON形式。

Player.client.vueへの建物オーバーレイ

地図の右下にBLDGトグルボタンを追加して、建物ポリゴンの表示/非表示を切り替えられるようにした。

  • ランドマーク建物: アクセントカラー(#4ECDC4)の枠線、名前をtooltipで常時表示
  • 一般建物: 薄い白枠、tooltipなし

ランドマークは目立たせたいが地図を邪魔しない程度に、というバランス。fillOpacityを低くして建物の形だけわかるようにした。

POIの追加

建物だけだと地図が物足りないので、Overpassクエリを拡張してPOIも取得した。

追加したノードの種類:

  • 彫像・モニュメント(阿形・吽形の仁王像、沙竭羅龍王像など)
  • 灯籠、時計(平和の時計)
  • 仲見世通りの店舗ノード

結果として仲見世通りの店舗が236件、寺社関連のPOIが176件。ランドマークPOIはpermanent tooltipで名前を常時表示し、店舗はホバー時にのみtooltipを出す方式にした。

ラベル重複問題

permanent tooltipが104個になり、ラベルが盛大に重なった。仲見世通りの店舗名が密集するエリアでは完全に読めない状態。

ズームレベルに応じた表示制御や、ラベルの厳選が必要だとわかったが、対応は明日以降に持ち越した。計画だけ先に作成しておいた。

conceptサイトへの機能追加

フィールドワークマップ機能をconceptサイト側にも追加した。8コンポーネントとページを新規作成し、ビルドが通ることを確認した(11,732ルート)。

その他、カレンダーデータの復元(site側からconcept側へのコピー)と、spotsページのconcept側への追加も実施した。

ふりかえり

OSMのデータはOverpass APIで簡単に取れるが、取れたデータをそのまま表示するとノイズが多い。「何を見せて何を見せないか」の選別が地図UIの肝だと感じた。

GPXの建物内通過問題は、GPS精度を考えれば当然起きる話で、建物ポリゴンと照合してクリッピングするのは妥当なアプローチだった。ただし手動で境界値を決めたので、汎用化するなら建物ポリゴンとの交差判定を自動化したい。

ラベル重複は「たくさん情報を出せばいいわけではない」という地図デザインの基本に立ち返る問題。ズームレベル連動の表示制御は次の課題。