5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

屋内地図3次元データの作成とMapLibre GL JSとdeck.glでの屋内3Dマップの表示

5
Last updated at Posted at 2025-12-13

この記事は MapLibre Advent Calendar 2025 14日目の記事です。

はじめに

  • 本記事では、新宿駅周辺屋内地図オープンデータ(令和2年度更新版) をもとに、屋内フロア別の GeoJSON(3次元座標) を生成し、歩行空間ネットワーク(リンク)と合わせて 3D化するまでの一連のデータ処理パイプラインを紹介します。
  • さらに、作成した GeoJSON(3次元座標) を MapLibre GL JS と deck.gl を用いて、屋内3Dマップとして表示します。

使用データ

1. 新宿駅周辺屋内地図オープンデータ(令和2年度更新版)

  • 新宿駅周辺屋内地図オープンデータは、国土交通省が実施している「高精度測位社会プロジェクト」の実証実験において作成された屋内地図の 令和2年度更新版です。
  • 実証実験に用いた屋内地図のうち、通路・部屋の範囲などの基盤となる地図、歩行空間ネットワークデータ、トイレ・エレベータ等の公共設備POIデータが公開されています。
  • なお、本データは、国土地理院の「階層別屋内地理空間情報データ仕様書(案)」(平成30年3月)を基に作成されています。
  • 屋内地図データのディレクトリ構成は、大きく ShinjukuTerminal(屋内地図) と nw(歩行空間ネットワークデータ) の2つです。
新宿駅周辺屋内地図オープンデータ_統合版(Shapefile)
│  meta.xml
│
├─nw
│      Shinjuku_link.shp
│      Shinjuku_node.shp
│
└─ShinjukuTerminal
       ShinjukuTerminal_<Floor>_<Layer>.shp

屋内地図(ShinjukuTerminal ディレクトリ)

  • 屋内地図は フロア × レイヤー種別 の組み合わせで Shapefile が分割されています。
  • ファイル名のパターンは以下の通りです。
ShinjukuTerminal_<Floor>_<Layer>.(shp / dbf / prj / shx)

<Floor>:B3, B2, B1, 0, 1, 2, 2out, 3, 3out, 4, 4out
<Layer>:Drawing / Facility / Fixture / Floor / Space / Opening / TWSILine / TWSIPoint

使用データ

本記事で 3D 化の対象としたデータは、ShinjukuTerminal ディレクトリ内の以下の Shapefile です。

  • Floor(階層面)
  • Space(通路・部屋など空間)
  • Fixture(柱・設備)
  • Opening(出入口)

これらをフロアごとに読み込み、2D → 3D(Z座標付与) に変換します。
(Drawing / Facility / TWSI は今回の 3D 表示では使用しません)

歩行空間ネットワークデータ(nw ディレクトリ)

  • 歩行者ネットワークは ノード(点) と リンク(線) で構成されます。
  • ファイル名のパターンは次の通りです。
Shinjuku_<type>.(shp / dbf / prj / shx)

<type>:

  • node:ノード(交点・階段の開始点・EV乗り場などの重要地点)
  • link:リンク(ノード間の通行可能な経路)

使用データ

本記事で 3D 化に使用するネットワークデータは次の 2 つです。

  • Shinjuku_node.shp(ノード)

    • 位置(2D座標)と ordinal(階層番号)を保持
    • ordinal → フロア → Z の計算に利用
    • ノードの 3D Point を生成
  • Shinjuku_link.shp(リンク)

    • ノード間の通行可能経路
    • 起点・終点ノードの Z を参照し、線形補間で 3D LineString を生成

2. 3D都市モデル(Project PLATEAU)豊島区(2023年度) | 土地利用モデル

  • 屋内3Dマップの「平面(地表)」を表現するために、土地利用モデルを使用しています。
  • 土地利用モデルは、都市計画基礎調査の土地利用現況が出典です。
  • PLATEAU GIS Converter を用いて CityGML から GeoJSON に変換しています。
  • 変換後 GeoJSON の座標参照系は WGS 84(EPSG:4979) です。

使用するスクリプト等

使用するスクリプトやHTML、作成データ等は、以下の GitHub レポジトリに格納しています。

https://github.com/shiwaku/mlit-shinjuku-indoor-3dmap-on-maplibre

1.make_shinjuku_3d_geojson.py
2.merge_shinjuku_floor_geojson.py
4.shinjuku_network_3d_export.py
index.html

屋内地図および歩行空間ネットワークデータの3次元化

本記事で用いる Z 値は、実際の建築物の床高を再現したものではありません。
フロア構造と歩行ネットワークの立体関係を分かりやすく可視化するための 仮想的な高さ(Z値) です。

フロア別 Z 値の設定方法

まず、新宿駅周辺の地盤高を代表する値として 標高 37.5m を基準値(BASE_Z)に設定します。

BASE_Z = 37.5  # 新宿駅の基準標高(可視化用)

次に、各フロアに対して BASE_Z からの 相対オフセットを定義し、地下階は負、地上階は正の値にします。

FLOOR_OFFSETS = {
    "B3": -35.0,
    "B2": -25.0,
    "B1": -15.0,
    "0F":   0.0,
    "1F": +15.0,
    "2F": +25.0,  "2out": +25.0,
    "3F": +35.0,  "3out": +35.0,
    "4F": +45.0,  "4out": +45.0,
}

各フロアの Z 値は次の式で決定します。

Z = BASE_Z + FLOOR_OFFSETS[floor_label]

ここで設定しているオフセット値は、実際の階高(数 m)を正確に表現するものではなく、次を優先して 意図的に誇張しています。

  • フロア同士が 3D 空間上で重ならないこと
  • MapLibre / deck.gl 等の Web地図 表示で視認しやすいこと

また、2out や 3out などの屋外通路は、対応する屋内フロアと同じ高さに設定しています。
この Z 値定義は屋内地図データと歩行空間ネットワークデータで共通に使用し、フロア形状とネットワークが 3D 空間上で正しく対応することを保証します。

1. Shapefile からフロア別 GeoJSON(3次元座標)を生成

使用するスクリプト: 1.make_shinjuku_3d_geojson.py

処理フロー

屋内地図 Shapefile 群を読み込み、以下を行います。

  1. ./shape 配下のすべての Shapefile を走査
  2. ファイル名からフロアラベルを推定(例:_b2, _1, _2out → B2, 1F, 2out)
  3. フロアラベルに応じて Z を決定(Z = BASE_Z + FLOOR_OFFSETS[floor])
  4. ジオメトリを 3D 化([x, y] → [x, y, z])
  5. メタ情報を付与(__floor, __z_abs)
  6. *.3d.geojson として出力

フロア推定の例

filename = "shinjuku_b2_polygon.shp"
floor = "B2"  # 正規表現で抽出
Z = BASE_Z + FLOOR_OFFSETS[floor]

ジオメトリ3D化のイメージ

new_coords = [(x, y, z) for (x, y) in original_coords]
  • Point / LineString / Polygon / MultiPolygon / MultiLineString に対応
  • shapely の make_valid() で壊れたジオメトリを救済
  • 必要に応じて WGS84(EPSG:4326)へ変換可能

ポイント

  • ファイル名でフロアを推定することで、Shapefile 側にフロア属性が無くても扱える
  • 3D化時にメタデータを付与し、可視化・解析で使いやすくする

2. フロア別 × ジオメトリタイプ別に GeoJSON(3次元座標)をマージ

使用するスクリプト: 2.merge_shinjuku_floor_geojson.py

目的

クライアント側で扱いやすいよう、次の粒度で GeoJSON をマージします。

  • フロア別(B3, B2, B1, 0F, 1F, 2F, 2out…)
  • ジオメトリ種別別(points / lines / polygons)

処理フロー

  1. ./geojson 配下の 3D GeoJSON を読み込み

  2. ファイル名から

    • フロアラベルの推定
    • 空間種別(Space / Floor / Fixture…)の推定
  3. MERGE_MODE = "per_floor_by_geom" を利用

  4. Feature のジオメトリタイプで分類

    • Point → points
    • Line → lines
    • Polygon → polygons
  5. 次のような出力を得ます。

Shinjuku_B1.polygons.geojson
Shinjuku_B1.lines.geojson
Shinjuku_B1.points.geojson
...

メタ情報の保持

Feature に __source_file を付与し、「どの Shapefile → どの Feature か」 を追跡できるようにしています。

3. 歩行者ネットワーク(node / link)の3D化

使用するスクリプト: 4.shinjuku_network_3d_export.py

3.1 node の3D化

  1. Shinjuku_node.shp を読み込み
  2. ordinal(階層番号)→ floor_label(B3, B2, B1, 0F, 1F…)へ変換
  3. Z = BASE_Z + FLOOR_OFFSETS[floor_label] で高さ決定
  4. 3D Point として GeoJSON 化

ordinal → floor の一例

ordinal floor_label
-3 B3
-2 B2
-1 B1
0 0F
1 1F

3.2 link の3D化(線形補間)

  1. link の start_id / end_id から node の高さを join
  2. LineString の各頂点に対して Z を線形補間して付与
  3. MultiLineString にも対応
  4. shinjuku_link_3d.geojson を出力

線形補間の式

Z(t) = z_start + (z_end - z_start) * (dist(t) / dist_total)

階段やスロープ等のリンクも、自然な 3D ラインとして可視化できます。

4. Web地図で可視化(MapLibre GL JS / deck.gl)

使用する HTML: index.html

前章までで生成したフロア別 GeoJSON(3次元座標)と 3D 歩行者ネットワークを、MapLibre GL JS + deck.gl で重ね合わせて表示します。実装は index.html にまとめています。

4.1 使用ライブラリと構成

  • MapLibre GL JS:ベース地図
  • deck.gl(MapboxOverlay):GeoJSON(3次元座標)(屋内フロア / 歩行者ネットワーク)を 3次元表示

4.2 deck.gl を MapLibre に重畳(MapboxOverlay)

map.on("load", ...) で MapboxOverlay を追加し、deck.gl のレイヤー群を MapLibre 上に重ねます。

const overlay = new deck.MapboxOverlay({
  interleaved: true,
  layers: [ /* deck.GeoJsonLayer */ ],
});
map.addControl(overlay);

4.3 フロア別 GeoJSON(polygons/lines/points)を一括レイヤー化

フロア一覧と色定義

const FLOORS = ["B3","B2","B1","0F","1F","2F","2out","3F","3out","4F","4out"];

const FLOOR_COLORS = {
  B3: [255, 0, 255, 230],
  B2: [127, 0, 255, 230],
  // ...
  "4out": [255, 0, 0, 170],
};

4.4 GeoJSON ファイル命名則に合わせた URL 生成

前処理で出力した命名則(Shinjuku_<floor>.<type>.geojson)に合わせて、URL を組み立てています。

function urlFor(floor, type) {
  return `./geojson_merged/Shinjuku_${floor}.${type}.geojson`;
}

4.5 レイヤー生成関数(GeoJsonLayer)

buildLayer(floor, type) で、フロア×ジオメトリ種別の deck.gl レイヤー(GeoJsonLayer)を作ります。

GeoJsonLayer
GeoJSONの座標には、高度または標高を、オプションの3番目の値として含めることができる(GeoJSON 仕様 RFC 7946 ではオプショナル)。 deck.gl の GeoJsonLayer は 、GeoJSON の高さパラメータをきちんと解釈して 3D 空間に GeoJSON の要素を配置してくれるため、データを用意するだけで3D表示できる。

function buildLayer(floor, type) {
  const color = FLOOR_COLORS[floor] || [200,200,200,160];
  const id = `Shinjuku_${floor}.${type}`;

  if (type === "polygons") {
    return new deck.GeoJsonLayer({
      id,
      data: urlFor(floor, type),
      extruded: true,
      wireframe: true,
      filled: true,
      stroked: true,
      lineWidthUnits: "meters",
      getLineWidth: 0.8,
      getLineColor: color,
      getFillColor: [color[0], color[1], color[2], 30], // 塗りは薄め
      getElevation: 5,
      pickable: true,
    });
  }

  // lines / points も同様に type に応じて GeoJsonLayer を返す(実装は省略)
}

4.6 3D 歩行者ネットワーク(リンク)を重ねる

shinjuku_link_3d.geojson を 1 本の GeoJsonLayer として描画します。

特徴:

  • parameters: { depthTest: false } で常に前面表示(ポリゴンに埋もれにくい)
  • blending: "additive" で発光っぽい見た目に寄せる
new deck.GeoJsonLayer({
  id: "shinjuku_link_3d",
  data: "./shinjuku_link_3d.geojson",
  stroked: true,
  filled: false,
  lineWidthUnits: "meters",
  getLineWidth: 1,
  getLineColor: [0, 255, 255, 80],
  parameters: { depthTest: false },
  blending: "additive",
});

4.7 デモサイト: 新宿駅周辺屋内3Dマップ

https://shiwaku.github.io/mlit-shinjuku-indoor-3dmap-on-maplibre/

image.png

5. 全体の処理パイプラインまとめ

Shapefile群
   ↓
1. フロア推定 + 3D化(make_shinjuku_3d_geojson.py)
   ↓
2. フロア別 × ジオメトリ別に整理(merge_shinjuku_floor_geojson.py)
   ↓
3. 歩行者ネットワークの3D化(shinjuku_network_3d_export.py)
   ↓
4. Web地図で可視化(MapLibre GL JS / deck.gl)

6. 屋内3Dマップの利用が想定されるシーン

  • 駅構内や地下通路等ナビゲーションの 3D 可視化
  • 駅構内や地下通路等シミュレーション(歩行者流動、導線評価)
  • フロア別レイヤ切替 UI
  • 3D 経路探索
  • パーティクル可視化(deck.gl の ParticleLayer 等)との組み合わせ

7. まとめ

本記事では、屋内地図データをフロア別に 3D 化し、歩行者ネットワークも含めて立体的に扱えるデータ処理パイプラインを解説しました。

  • フロア推定 → 固定Z付与で 3D 化
  • ジオメトリ別に整理して Web 表示に最適化
  • node/link の線形補間により滑らかな 3D ネットワークを生成

一連の処理をスクリプト化しておくと、実務でも応用しやすくなります。ぜひ似た案件で活用してみてください。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?