PLATEAUの地形と向き合う
PLATEAU 3D都市モデル利活用のための Python ライブラリ PlateauKit を開発している @ozekik です。突然ですが、PLATEAUというと「建物の3Dモデル」というイメージが一般的には強いのではないでしょうか。実際に建築物の3Dモデルが主役的な立ち位置にあることは間違いないと思いますが、各都市のPLATEAUのデータセットには建物以外のデータも含まれています。
- ただし、どのようなデータが含まれているかは都市によって異なります。(今回取り上げる地形データも含まれていない都市があります)
データの内容に関して言えば、建築物や橋梁のデータの目新しさに比べると、その他の災害関連データや地形データのデータは以前から何らかの形で公開はされていたものも多いのではないかと思います。しかしながら、(1) タイル配信のような形態ではなく完全にダウンロード可能なのでサーバー負荷等を気にせず使える、(2) 共通のオープンなライセンスで利用可能、また (3) CityGMLという統一フォーマットで整備されているといった点で非常に価値があります。
PlateauKit では、3D建物だけでなく、PLATEAUデータセットのすべての種類のデータを扱えるようにすることを目指しています。その中でも地形データは、単純な「2D地図 + 3D建物」との差別化を図り、視覚的にも活用的にも「デジタルツイン感」を高めるために重要だと考えています。そこで今回はPLATEAUの地形データの利用や内容、処理について簡単にまとめてみます。
地形データの扱いに関しては、PLATEAU VIEW等の開発に関わっているEukarya社 (のRe:Earthというプロダクト) のエンジニアリングブログで分かりやすく興味深い記事がつい先日公開されていたので、そちらもぜひご覧ください。
PLATEAUの地形データを使ってみよう
PLATEAUの地形データを何らかの方法で使おうとした場合、現状手近なところでは以下のような方法があるかと思います。(他にもいい方法があればぜひ教えてください。)
PLATEAU VIEW
https://plateauview.mlit.go.jp/
- PLATEAU VIEWではデフォルトで起伏が立体表示され、陰影もつきます。(逆に、無効にする方法はなさそう?)
- PLATEAUの道路データ自体には高さの情報はないのですが、道路も起伏に合わせて表示 (ドレープ?) されます。
- 次に述べるPLATEAU配信サービスの説明を見るに、内部的にはPLATEAU配信サービスと同じものが使われていると思われます。
PLATEAU配信サービス
PLATEAU-Terrain 配信チュートリアル (plateau-streaming-tutorial/terrain/plateau-terrain-streaming.md)
- あらかじめホスティングされていてありがたいのですが、使用にあたっては実質的に CesiumJS での利用が前提になっており (Cesium ion のアカウント、トークンも作成する必要がある)、その点で Cesium 以外の環境で使うにはハードルが高くなっています。
- 同じPLATEAU配信サービスでも、建築物データのほうは特に登録は不要で、3D Tiles形式で配信されているので、Deck.gl などでも読み込むことができます。
- また、上記URLの説明によれば、この配信サービスの地形データは実はPLATEAUのデータを使って作成されているわけではなく、国土地理院の基盤地図情報数値標高モデル5mメッシュ/10mメッシュから直接作成されているようです。したがって、利用に際しては国土地理院の承認番号を記載する必要があるなど、PLATEAUのデータセットとは利用条件が異なることに注意が必要です。(PLATEAUの地形データの元データもおそらく同じ数値標高モデルなので、中身に関しては違いはないと思いますが)
- PLATEAUのデータである必要がなければ、地形データは産総研のシームレス標高タイルなどの形でも提供されています。
PLATEAU GIS Converter
PLATEAU公式 : https://github.com/Project-PLATEAU/PLATEAU-GIS-Converter
開発版 (MIERUNE社) : https://github.com/MIERUNE/plateau-gis-converter
- CityGMLをGeoJSONや3D Tiles, MVT, glTF, OBJ等の形式に変換可能で、地形のデータにも対応しています。
PLATEAU QGIS Plugin
「PLATEAU 地形モデルをメッシュとして読み込む」実行手順 (plateau-qgis-plugin/docs/manual.md)
- PLATEAU QGIS Plugin を使うことで、CityGMLの地形データをQGISのメッシュレイヤーとして読み込むことができます。ここからさらにQGISの機能でラスタータイルに変換することもできるようです。
PLATEAU SDK for Unity/Unreal Engine
https://github.com/Project-PLATEAU/PLATEAU-SDK-for-Unity
https://github.com/Project-PLATEAU/PLATEAU-SDK-for-Unreal
- Unity/Unreal Engineにインポートすることができます。ここからさらにFBXなどにエクスポートすることで、Blenderなどでも扱えるはずです。
PLATEAUの地形データの中身を見る
PLATEAUの地形 (起伏) データは、配布サイト (geospatial.jp) からダウンロードできる各都市のデータセットの /udx/dem/
以下に配置されています。
PLATEAU の CityGML の仕様 (巨大なHTMLなので注意) によると、LOD1以上の地形データ (地形モデル) では、
- MassPointRelief (地形表面の点群)
- TINRelief (Triangulated Irregular Network, 地形の三角形ポリゴンのメッシュ)
の2種類と、上記の要素の集まりである ReliefFeature の、全部で3種類の要素 (地物型) が使えることになっています。また、LOD1〜3のレベルは地形の表現の細かさ (格子間隔) に応じて決まることになっています。
ただ、2024年3月時点のデータセットの属性等の統計 (データセット配布サイト内の「整備都市の属性リスト」) によると、現在公開されているPLATEAUデータセットの地形モデルはすべて TINRelief (とそのReliefFeature) で、MassPointRelief が使われている都市は1都市もありません。また、TINRelief を用いるのはLOD1以上なので、LOD0のデータも現状存在していないことになります。
- ただし、(本家仕様と同じなのか独自なのかは把握していないのですが) LOD0の仕様自体は策定されていて、LOD1以上とはまったく違う表現方法になっていておもしろいのでぜひ見てみてください。(https://www.mlit.go.jp/plateaudocument/#toc4_18_01)
TINRelief の場合、形状を表す部分自体は建築物などに比べるとシンプルで、メッシュの頂点座標 (緯度・軽度・標高) の数値列になっています。以下は箱根町の地形データの例 (抜粋) です。
<dem:ReliefFeature gml:id="dem_e58e5935-3e2b-4499-8398-4ce2f11388aa">
<gml:name>52396035</gml:name>
<dem:lod>1</dem:lod>
<dem:reliefComponent>
<dem:TINRelief gml:id="dem_9e4af167-63dc-11ed-9ab6-989096d73cb5">
<gml:name>52396035</gml:name>
<dem:lod>1</dem:lod>
<dem:tin>
<gml:TriangulatedSurface>
<gml:trianglePatches>
<gml:Triangle>
<gml:exterior>
<gml:LinearRing>
<gml:posList>35.191666671644704 139.06259722912046 940.2299760052546 35.19166667234952 139.06261111640185 939.6634189626074 35.1916944447754 139.0626388888888 940.02001953125 35.191666671644704 139.06259722912046 940.2299760052546</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Triangle>
...
</gml:trianglePatches>
</gml:TriangulatedSurface>
</dem:tin>
</dem:TINRelief>
</dem:reliefComponent>
</dem:ReliefFeature>
(出典: 3D都市モデル(Project PLATEAU)箱根町(2020年度) (国土交通省) CC-BY-4.0)
PLATEAUの地形データを処理する
PLATEAUの地形データを使うには上記で紹介したような方法もありますが、PlateauKit でも地形データを活用したデータ処理や可視化、アプリケーション開発を可能にするため、地形に関してまずは以下のような機能を実装したいと考えています。
(もし他に便利そうな使い方があればぜひ教えてください。)
- 地形データの前処理 (事前ビルド)
- 地形データのCityJSONへの変換
- JupyterLab/Notebook での表示 (可視化)
- 指定した地点の標高の取得
- 道路に高さ情報を付加/地形に合わせて表示
現在はこのうちいくつかの実装を実験的に進めています。
地形データの前処理 (事前ビルド)
今のところ他のデータとほぼ同様に、内部的に GeoParquet に変換しています。ただ、地形というものの性質上、建築物などと異なり基本的には都市の面積にほぼ比例してデータが大きくなるので、圧縮効率の高い GeoParquet であってもどうしてもデータサイズが大きくなってしまいます。そこで、事前ビルド時に精度を指定して頂点削減/圧縮できるようにしたいと考えています。
また、地形に関しては GeoParquet ではなくquantized-meshのような形式でデータを持ったほうが効率的かもしれないのですが、まだ検討段階です。
地形データのCityJSONへの変換
CityGMLとCityJSONはほぼ互換性があるので、基本的には仕様通りに変換するだけです。PlateauKit の場合、すでに建築物や棟梁等の変換には対応しているので、既存の実装を拡張して地形にも対応させています。
CityJSON は、CityJSON Ninja などでWebブラウザからプレビューできるほか、Three.js に読み込んで使うこともできます。
エクスポートした地形のCityJSONのプレビュー (頂点削減の手法の関係で湖岸線が怪しい?)
建築物とセットでエクスポートした結果
JupyterLab/Notebook での表示 (可視化)
PlateauKit では、3D都市モデルをJupyterLab/Notebook で表示する方法として、
の2つの表示エンジンを実装しています。上記の通りCityJSONへの変換が実装できているので、Three.jsベースの表示エンジンではそれをそのまま表示することができそうです。
一方で、MapLibre/Deck.gl ベースの表示エンジンで地形を反映するにはいくつかの方法があります。
現状ではどちらかというと MapLibre の3D地形機能のほうがいろいろと便利そうという印象です。ただ、MapLibre のほうは基本的にはデータソースとして標高タイル、しかもラスタータイルを想定している雰囲気なので、その点でPython側でのデータ処理と連携させるには一手間ありそうです。データの形式については Deck.gl のほうが柔軟性があるかもしれません (データ読み込みはquantized-meshにも対応しているようです)。
指定した地点の標高の取得
データ構造やアルゴリズムを工夫する余地と必要がありそうですが、まだ最適な方法が分かっていません。今のところナイーブな実装として、
- メッシュを持ち、レイキャスティングしてポリゴンを取得、高さを計算
- ラスタータイル (的なもの) を持ち、指定した地点の近傍の高さを取得
のいずれかを考えています。
道路に高さ情報を付加/地形に合わせて表示
未実装ですが、指定した地点の標高の取得ができれば道路のメッシュの各頂点に高さを割り当てることができそうです。
また、地形に合わせて表示するだけであれば、MapLibre の3D地形機能などを使って描画時にドレープ処理できるかもしれません。
結びと課題
- アドベントカレンダーには公開が間に合いませんでしたが、近日中に一部の機能を追加したバージョンの PlateauKit をリリース予定です。
- ジオイドの考慮ができていないので、今後実装に反映したいと思います。
Discussion