tpc31

 TOPIC 31|PLATEAU GIS Converterを使ってコンバートしたデータをGIS分野で活用する 

PLATEAU GIS Converterは、PLATEAUのCityGML形式ファイルをさまざまなGIS形式に変換できるツールです。このトピックでは、GeoJSON形式やGeoPackage形式に変換する方法や、QGISを用いて空間結合することで道路の地面における起伏を反映させる方法を解説します。

Share

PLATEAU GIS Converterを使ってGeoJSON形式やGeoPackage形式などに変換すると、QGISなどのGISで読み込めるほか、Pythonで読み込んで分析することもできます。このトピックでは、QGISやPythonでの読み込み方法、Pythonを使って標高モデル(DEM)と組み合わせて空間演算することで道路に勾配をつける方法を解説します。また、大量のデータを変換するときに便利なコマンドラインでの実行方法や、変換の際に属性名を変更する方法など、PLATEAU GIS Converterの応用的な使い方についても解説します。

このトピックの内容は「PLATEAU GIS Converterを活用した各種形式への3D都市モデル変換」(2024年度PLATEAU Hands-onアーカイブ動画)でも利用方法をハンズオン形式で紹介しています。

【目次】

31.1  このトピックの見どころ

31.2  GeoJSON形式に変換して活用する

 31.2.1  GeoJSON形式に変換する

 31.2.2  QGISで読み込んで確認する

31.3  GeoPackage形式に変換して活用する

 31.3.1  GeoPackage形式に変換する

 31.3.2  QGISで読み込んで確認する

 31.3.3  Pythonで活用する

31.4  属性マッピングルールを使う

 31.4.1  属性マッピングファイルの形式と例

 31.4.2  属性マッピングルールを使った変換と結果

31.5  コマンドラインから変換する

 31.5.1  コマンドラインから使えるようにする

 31.5.2  コマンドラインで変換する

31.6  まとめ

31.1 _ このトピックの見どころ

PLATEAU GIS Converterは、PLATEAUの3D都市モデル(CityGML形式ファイル)をさまざまなデータ形式に変換するツールです。このトピックでは、GIS分野で活用する方法を解説します。主な見どころは以下のとおりです。

■ GeoJSON形式やGeoPackage形式への変換

PLATEAU GIS Converterを使って、GeoJSON形式やGeoPackage形式に変換し、オープンソースのGISツールであるQGISで読み込んで表示したり、属性を確認したりする方法を説明します。

■ Pythonを使ったデータの読み込み・可視化と空間分析

GeoPackage形式ファイルは、Pythonで簡単に読み込むことができます。Pythonを使って、GeoPackage形式に変換された3D都市モデルを読み込んで可視化するほか、建物と道路の高さを揃えるなどの調整を加える方法を解説します。

■ 属性マッピングの変更

PLATEAU GIS Converterでは、変換する際に、PLATEAUの属性名を別の属性名に変更できます。
その方法を解説します。

■ コマンドラインでの変換

大量のファイルを変換するときは、コマンドラインから操作すれば、ひとつひとつファイルを選択するなどの手作業が減ります。PLATEAU GIS Converterをコマンドラインで使う方法と、オプションについて解説します。

このトピックは、「TOPIC30|PLATEAU GIS Converterでコンバートして3Dで表示する」の続きです。従って以降の例では、新宿区の3D都市モデルを用います。

----------------
【3D都市モデル(Project PLATEAU)新宿区(2023年度)】

https://www.geospatial.jp/ckan/dataset/plateau-13104-shinjuku-ku-2023
----------------

31.2 _ GeoJSON形式に変換して活用する

まずは、GeoJSON形式に変換して活用する例を紹介します。変換したファイルをオープンソースGISであるQGISで開き、どのように変換されたのかを確認します。

31.2.1 _ GeoJSON形式に変換する

GeoJSON形式は、[ファイル形式]として[GeoJSON]を選択する以外は、基本的な操作は3D Tiles形式に変換する場合と同じです。異なる点は次の2点です。

・座標参照系は固定

座標参照系は、[WGS 84(EPSG:4979)]に固定です。

・テクスチャ付きの選択肢は無い

GeoJSON形式ではテクスチャを含めることができないため、[出力LODの選択]において、[テクスチャ付き最大LOD]の選択オプションはありません。

なおGeoJSONはテキスト形式であるため、ファイルサイズが大きくなりがちで、あまりに大きなファイルを変換してQGISなどのGISで読み込むと、固まってしまうことがあります。ですから、GeoJSON形式で扱うデータは、小さめ(おおよそ10MB以下)にすることを推奨します。

ここでは、比較的ファイルサイズが小さい「53394517_bldg_6697_op.gml」(新宿区の信濃町駅周辺)を変換します。変換すると、拡張子が.geojsonのファイルが作られます。

図31-1 GeoJSON形式に変換する
図31-2 ファイルサイズが小さい「53394517_bldg_6697_op_gml」を選択する
図31-3 変換されたGeoJSON形式ファイル

31.2.2 _ QGISで読み込んで確認する

変換したGeoJSON形式ファイルを確認してみましょう。ここでは、QGISで読み込んでみます。

【メモ】

QGISの基本的な使い方については、「TOPIC 5|GISで活用する[1/3]」を参照ください。

【手順】QGISでGeoJSON形式ファイルを読み込む

[1]QGISにGeoJSON形式ファイルを読み込む

QGISを起動し、GeoJSON形式ファイルをドラッグ&ドロップします。

図31-4 GeoJSON形式ファイルをドラッグ&ドロップする

[2]レイヤとして読み込まれる

レイヤ(図では「Building」レイヤ)として読み込まれます。

【メモ】

表示の拡大率によっては、地物が見えないことがあります。その場合はレイヤ(図では「Building」レイヤ)を右クリックし、[レイヤの領域にズーム]を選択すると、そのレイヤに含まれる地物全体が表示されるようにズームされます。

図31-5 レイヤとして読み込まれた

[3]属性を確認する

画面上の[属性テーブルを開く]ボタンをクリックします。すると属性テーブルのウィンドウが開き、属性一覧を確認できます。

属性一覧では、建物の用途や高さなどの情報を保持していることがわかります。GeoJSON形式では入れ子構造の列は展開されず、そのまま保持しています。例えばkeyValuePairAttributesなどはJSON文字列のまま保存されています(次に説明するGeoPackage形式では、入れ子構造は展開されます)。

図31-6 属性を確認したところ

31.3 _ GeoPackage形式に変換して活用する

もうひとつの変換例として、GeoPackage形式を解説します。いま説明したGeoJSON形式と違って、大きなファイルを変換しても問題が出にくい、異なる地物を別レイヤとして扱えるという特徴があります。

31.3.1 _ GeoPackage形式に変換する

GeoPackage形式の変換も3D Tiles形式やGeoJSON形式と同じですが、座標参照系としてさまざまな種類を選択できます。GISで扱いたい座標系に合わせて変換するとよいでしょう。

【メモ】

座標系については、「TOPIC 3|3D都市モデルデータの基本[4/4]」を参照ください。

座標系意味
WGS 84(EPSG:4979)米国が構築・維持している世界測地系。
GPSなどで使われる、経緯度座標
Web Mercator(EPSG:3857)メルカトル図法を変形したもの。
WebGISで使われるメートル座標
JGD2011/平面直角座標系Ⅰ(EPSG:6669)~JGD2011/平面直角座標系ⅩⅨ(EPSG:6687)平面直角座標系。
特定の位置を原点としたメートル座標
JGD2011/平面直角座標系Ⅰ+標高(EPSG:10162)~JGD2011/平面直角座標系ⅩⅢ(EPSG:10174)上記に対して標高を加味した座標系
表31-1 選択できる参照座標系

GeoPackage形式では、少し大きめのファイルを選択しても問題ないので、ここでは新宿区の建築物データすべてを読み込んで変換してみましょう。座標系は、WGS 84(EPSG:4979)とします。

【メモ】

図31-8では出力LODの選択で[最大LOD]を選択していますが、GISデータ形式の場合は、基本的に2次元で扱うため、最小LODで十分です。そのほうがファイルサイズは小さくなります。

図31-7 新宿区の建築物(bldgの中身すべて)を選択する
図31-8 GeoPackage形式に変換する

31.3.2 _ QGISで読み込んで確認する

GeoJSON形式のときと同様に、QGISに読み込みます。読み込み方はGeoJSON形式と同じで、QGISにドラッグ&ドロップします。GeoPackage形式の場合は、どのアイテムを読み込むかという選択画面が表示される点が異なります。

【メモ】

QGISで3D都市モデルを扱うには、PLATEAU GIS Converterを使う以外にもQGISプラグインを用いて、CityGMLファイルをインポートする方法もあります。QGISプラグインを使う方法は、QGIS単体でインポートできるので手軽ですが、PLATEAU GIS Converterを使った方法だと、大量にまとめて高速にあらかじめ変換したうえで読み込めます。用途に応じて、使い分けるとよいでしょう。

【手順】QGISでGeoPackage形式ファイルを読み込む

[1]QGISにGeoPackage形式ファイルを読み込む

QGISを起動し、GeoPackage形式ファイルをドラッグ&ドロップします。

図31-9 GeoPackage形式ファイルをドラッグ&ドロップする

[2]追加するアイテムを選択する

GeoPackage形式ファイルには、さまざまな情報が含まれています。これはPLATEAUの3D 都市モデルが、そもそも「建物の形状」以外にも、「住所」「不動産ID」「洪水浸水想定区域内」など、都市計画などに関わるさまざまな情報が含まれており、それらも変換されているためです。

分析をするときにはこうした情報が役立つことも多いですが、このトピックでは話をシンプルにするため、建物に関する基本情報である「bldg:Building」だけを選択し、[レイヤを追加]を選択します。

【メモ】

PLATEAUの3D都市モデルに含まれているデータ(これは「都市オブジェクト」と言います)については、「3D都市モデル標準製品仕様書」を参照ください。

図31-10 [bldg:Building]を選択して[レイヤを追加]をクリックする

[3]読み込まれた

レイヤ(図ではgeopackageレイヤ)として読み込まれます。新宿区全体なので、10万棟ほどの地物がありますが、GeoPackage形式であれば、この程度の数は十分表示可能です。

図31-11 レイヤとして読み込まれた

[4]地物の詳細を見る

[地物情報を表示]ボタンをクリックしてから地物をクリックすれば、地物の詳細が表示されます。この情報は、もともとのCityGML形式ファイルに格納されていたものです。

【メモ】

地物情報が表示されるのは、GeoPackage形式だけではありません。GeoJSON形式など、他のフォーマットで読み込んだ場合も表示されます。

図31-12 地物の詳細を見る

[5]属性を確認する

画面上の[属性テーブルを開く]ボタンをクリックすれば、GeoJSON形式のときと同様に属性テーブルのウィンドウが開き、属性の一覧を確認できます。

図31-13 属性を確認する

31.3.3 _ Pythonで活用する

GeoPackage形式のファイルは、Pythonで読み込んで活用することもできます。

■ Google Colaboratoryを開く

ここではPythonの実行環境として、手軽に使える「Google Colaboratory」を使います。Google Colaboratoryは、ブラウザ上でPythonのプログラムを編集したり変更したりできる環境である「Jupyter Lab」を、ログインするだけですぐに使えるように提供しているGoogleのサービスです。下記のURLにアクセスして、Googleアカウントでログインすれば、すぐに使えます。

開くと、Colaboratoryの説明ドキュメントが開くので、[ファイル]メニューから[ドライブの新しいノートブック]を選択して、新しいノートブックを作成してください。

【メモ】

本稿では、すぐに使えるGoogle Colaboratoryを使いますが、Pythonがインストールされている環境であれば、「pip install jupyterlab」というコマンドで自身のPCにインストールすることもできます(インストール後の実行は「jupyter lab」)。

----------------
【Google Colaboratory】

https://colab.research.google.com/
----------------

図31-14 新しいノートブックを作成する

ノートブック上の「セル」という入力欄にコードを入力して、左側の[▶]ボタンをクリック(または[Shift]+[Enter]キーを押す)と、そのコードが実行されます。

例として、次のコードを入力して実行した画面を示します。

print(1+2)

セルには、「コードを入力するセル」と「テキストを入力するセル」があり、どちらも、メニューから追加できます。また[↑]や[↓]のボタンで上下を入れ替えることもできます。

【メモ】

初回に限り、[▶]をクリックしたとき、実行までにしばらく時間がかかります。これはPythonの実行環境が準備されるためです。

図31-15 Pythonの簡単なプログラムを実行する

■ GISに関連するライブラリ

この節では、GISに関連するライブラリとして、次の3つのライブラリを使います。

GeoPandas

Pythonにおいて大量のデータを扱えるPandasライブラリにGISの機能を追加したライブラリです。データを読み込んだり加工したりするなどの操作をします。

② Fiona

GISに関するデータを読み込んで、その概要を取得するなどの操作ができるライブラリです。

③ Leafmap

2Dの地図表示をするライブラリです。データを可視化する際に使います。

これらのライブラリを使うため、Jupyter Labで新しいセルを作り、次のコマンドを入力して実行します。

【メモ】

先頭の「%」は、Pythonコードではなく、Pythonが実行されている実行エンジンのシェルのコマンドとして実行するための指示です。「%」からはじまるコマンドのことを「マジックコマンド」と言います。

%pip install geopandas
%pip install fiona
%pip install leafmap
図31-16 GIS関連のライブラリをインストールする

■ GeoPackage形式ファイルの内容の確認と読み込み

Pythonの実行環境の説明をしたところで、GISのプログラミングをしていきます。

【メモ】

可視化するには先ほど変換した新宿区の建築物データすべてを変換したGeoPackage形式のデータは量が多く、ローカルマシンに限らずColabであってもスペック的に扱うのがかなり厳しいため、以下では、東京都庁が含まれる3次メッシュである「53394525」に相当する「53394525_bldg_6697_op.gml」の1ファイルのみを、GeoPackage形式に変換したファイルを対象とします。変換後のファイル名が「53394525.gpkg」であるとして、解説を続けます。

【手順】GeoPackage形式ファイルを読み込んでデータを表示する

[1]GeoPackage形式ファイルをアップロードする

Google Colaboratoryにおいては、Pythonコードから使いたいファイルを、あらかじめアップロードしておきます。左側のフォルダのアイコンをクリックすると、アップロードされているファイル一覧が表示される(ここにはデフォルトで、[sample_data]が含まれています)ので、PLATEAU GIS Converterで変換しておいた、GeoPackageファイルをアップロードします。

図31-17 GeoPackage形式ファイルをアップロードする

[2]レイヤ一覧を取得する

まずは、このGeoPackage形式ファイルに含まれるレイヤ一覧を取得して表示します。次のコマンドを入力して実行します。「geopackage.gpkg」の名前は、手順[1]でアップロードしたファイル名に合わせてください。

import fiona

gpkg_path = "53394525.gpkg"
layers = fiona.listlayers(gpkg_path)
layers

JupyerLabでは、セルの最後に変数名を記述すると、その変数の内容が画面に表示されます。結果として、含まれているレイヤ一覧が表示されます。

図31-18 レイヤの一覧を表示

[3]建築物のレイヤを読み込んで確認する

GeoPandasのread_fileメソッドを使うと、該当のレイヤを読み込めます。ここでは、建物レイヤを読み込んでみます。読み込んだデータを確認するためheadメソッドで先頭10行を表示すると、建物のデータが読み込まれたことを確認できます。

import geopandas as gpd
bldg = gpd.read_file(gpkg_path, layer="bldg:Building")
bldg.head()
図31-19 建築物レイヤを読み込んだ様子

■ 2D地図で可視化する

読み込んだデータを可視化してみます。まずは、2Dで表示します。2Dで表示するライブラリはいくつかありますが、ここではLeafmapというライブラリを使います。このライブラリは、ごく簡単なコードを書くだけで地図を表示できるライブラリです。

----------------
【Leafmap】

https://leafmap.org/
----------------

次のようにすると、東京駅周辺の地図が表示されます。地図として表示されているのは、OpenStreetMapです。

【メモ】

東京駅の経緯度である35.6818,139.7629は、地理院地図で調べました。

import leafmap as lm
lm.Map(center = (35.6818, 139.7629), zoom = 16)
図31-20 東京駅周辺の地図を表示した

GepPandasで読み込んだレイヤを、この地図に重ねて表示できます。例えば次のコードを実行すると、先ほど読み込んだレイヤを重ねて表示できます(実行にはしばらく時間がかかります)。

# 中心座標を計算
bbox = bldg.total_bounds
center = [(bbox[1] + bbox[3]) / 2, (bbox[0] + bbox[2]) / 2]

map_2d = lm.Map(center = center, zoom = 16)
map_2d.add_gdf(bldg)
map_2d
図31-21 GeoPandas形式として読み込んだPLATEAUの3D都市モデルを重ねた

■ 3Dで可視化する

次に、3Dで可視化してみましょう。3Dでの可視化にはいくつかの方法がありますが、ここでは底面を高さのぶんだけ押し上げて3D表示します。こうした可視化には、PyDeckというライブラリを使うのが手軽です。次のようにしてインストールします。

%pip install pydeck

可視化するには、次のプログラムをセルに入力して実行します。

import pydeck as pdk
# PyDeckのGeoJSONLayerとして読み込む
layer = pdk.Layer(
"GeoJsonLayer",
bldg,
filled=True,
extruded=True,
get_elevation="height",
opacity=0.9,
get_fill_color=[140, 220, 100],
pickable=True,
)

# Viewを作成
view_state = pdk.ViewState(latitude=center[0], longitude=center[1], zoom=16, bearing=0, pitch=45)

# Deckを作成
r = pdk.Deck(layers=[layer], initial_view_state=view_state)
r

リスト31-1 PyDeckで可視化する

すると次のように3Dで可視化されます。示したプログラムにあるように、PyDeckで可視化するときはGeoPandasで読み込んだデータをGeoJSONレイヤとして読み込みます。ここでは読み込んだ変数をlayerという名前にしました。読み込む際には、いくつかのオプションを指定できます。例えば色を指定するget_fill_colorオプションや建物にマウスポインタを合わせると、その詳細情報がポップアップ表示されるようになるpickableオプションなどです。

可視化するには、pdk.Deckメソッドのlayersパラメータに表示したいレイヤのリストを渡します。initial_view_stateパラメータにはビュー(視点や角度などを設定したオブジェクト)を渡します。

【メモ】

PyDeckで表示している3Dは、あくまでも平面(図31-21)をそのまま計測高さのぶんだけ、立ち上げたものです(この高さはheight属性として指定しているもので、コード中ではget_elevation="height"で指定しています。計測により取得した建築物の最も低い位置から最も高い位置までの高さです)。PLATEAUの建築物モデルLOD1は建築物の上面の高さの中央値を用いて立ち上げることを原則としているため、LOD1ともLOD2とも異なる簡易的な3Dの可視化です。

【メモ】

図31-22をよく見るとわかるのですが([Shift]キーを押しながらマウスドラッグすると視点の角度を変えられるので、横から見るとわかりやすい)、ベースマップの地図から建物が浮いています。これは地面自体に起伏があるにも関わらず、ベースマップを高さ0mの地点に配置しているからです。解決する方法については、後述のコラム「ベースマップと高さをそろえる」で説明します。

図31-22 PyDeckで可視化する

■ 道路を重ねて表示する

PyDeckでは(もしくはLeafletなどほかのライブラリでも)、読み込んだレイヤを重ねて表示できます。ここでは道路などの情報が含まれている交通モデルを読み込んで重ねて表示します。

まずは、PLATEAU GIS Converterで交通モデルをGeoPackage形式に変換します。交通モデルは、PLATEAUの3D都市モデルとして配布されているフォルダにudx/tranに格納されています。ここでは、53394525_tran_6997_op.gmlファイルを使います。変換したファイル名は「53394525_trans.gpkg」とします。

図31-23 53394525_tran_6697_op.gmlをコンバートする

変換した53394525_tran_6697_op.gmlファイルをGoogle Colab上にアップロードします。アップロードしたらまずは読み込んで、含まれているレイヤを確認します。次のコードをセルに入力して実行します。

gpkg_trans_path = "53394525_trans.gpkg"
trans_layers = fiona.listlayers(gpkg_trans_path)
trans_layers

結果は次のようになります。

WARNING:fiona._err:CPLE_AppDefined:GPKG: unrecognized user_version=0x00000000 (0) on '53394525_trans.gpkg'
['tran:Road', 'uro:RoadStructureAttribute', 'uro:DataQualityAttribute']
図31-24 53394525_tran_6697_op.gmlを読み込んでレイヤを確認する

これら3つのうちのtran:Roadが道路に該当するレイヤであるため、次のように読み込んで先頭のデータを表示して確認します。すると高速道路や国道などの属性が付けられた道路の情報を確認できます。

tran= gpd.read_file(gpkg_trans_path, layer="tran:Road")
tran.head()
図31-25 tran:Roadレイヤの内容を確認したところ

この道路情報をGeoJSONレイヤとして読み込んで、PyDeckで重ねて表示します。まずは、次のようにして読み込みます。ここではtran_layer変数として読み込みました。

tran_layer = pdk.Layer(
"GeoJsonLayer",
tran,
filled=True,
extruded=True,
opacity=0.7,
get_elevation="height",
get_fill_color=[250, 140, 100],
pickable=True,
)

これを先ほど読み込んだ建物のlayer変数と重ねて表示すると、次のようになります。

r = pdk.Deck(layers=[layer, tran_layer], initial_view_state=view_state)
r
図31-26 建物と道路を重ねて表示したところ

■ 道路の高さを調整する

図31-26を見るとわかるように、道路の高さと地面の高さが合っておらず、建物が浮いているように見えます。これはPLATEAUの3D都市モデルでよく知られている事象で、道路のデータが平面であり、高さ情報を持っていないからです。これはPLATEAUの「3D都市モデル標準製品仕様書」の「交通(道路)モデルの応用スキーマ」の定義において、LOD2以下では、高さを0とするという規定があるためです。

いくつかの解決策がありますが、ここでは、同じくPLATEAUで提供されている標高モデル(起伏のデータ、DEM)と、道路のデータとを演算処理することで、道路を起伏のぶんだけ持ち上げる処理をしてみます。

その流れは、次のとおりです。

【手順】標高モデル(DEM)を使って、道路に高さを設定する

[1]標高モデルコンバートする

まずは、PLATEAUで提供されている標高モデルをGeoPackage形式に変換します。

標高モデルは、udx/demフォルダに含まれています。これは2次メッシュであるため、新宿区のPLATEAUの3D都市モデルの場合は533945_dem_6697_op.gmlという1つのファイルとして提供されています。このファイルをPLATEAU GIS Converterを使って変換します。変換後のファイル名は、「533945_dem.gpkg」とします。変換したファイルはGoogle Colabにアップロードしてください。

図31-27 533945_dem_6697_op.gmlをGeoPackage形式に変換する

[2]標高データを読み込む

アップロードした標高データ「533945_dem.gpkg」を読み込み、含まれているレイヤを確認します。

gpkg_dem_path = "533945_dem.gpkg"
dem_layers = fiona.listlayers(gpkg_dem_path)
dem_layers

結果は次のように「dem:TINRelief」というレイヤしかありません。

WARNING:fiona._err:CPLE_AppDefined:GPKG: unrecognized user_version=0x00000000 (0) on '533945_dem.gpkg'
['dem:TINRelief']

このレイヤを次のように読み込んで内容を確認します。

dem= gpd.read_file(gpkg_dem_path, layer="dem:TINRelief")
dem.head()
図31-28 標高データの確認

[3]道路のZ座標を標高モデルのZ座標で上書きする

道路に高さ情報を設定するには、①:道路のポリゴンの重心点を計算、②:標高モデルのポリゴンのZ座標の平均値を計算、③:①と②を空間結合する、④:③の値で道路のZ座標を上書きする、という一連の操作をします。

まずは①の処理として重心点を計算します。ここでは、新しくtran_centroidsというGeoDataFrameを作成します。

# 道路のポリゴンの重心点を計算して列として設定
tran["centroid"] = tran.centroid

# このtranの重心点をジオメトリとする新しいGeoDataFrameを作成
tran_centroids = gpd.GeoDataFrame(tran, geometry="centroid")

続いて②の処理です。次のように、Z座標の平均値を格納した「avg_z」という新しい属性を作ります(データが大きいため、この処理には少し時間がかかります)。

def calc_avg_z(geom):
if geom.has_z:
coords = []
for polygon in geom.geoms:
coords.extend(list(polygon.exterior.coords))
z_coords = [coord[2] for coord in coords]
return sum(z_coords) / len(z_coords)
else:
return None
dem["avg_z"] = dem["geometry"].apply(calc_avg_z)

最後に、①と②を空間結合します。

joind = gpd.sjoin(tran_centroids, dem, how="left", predicate="within")
joind

結合結果を入れた変数「joind」のavg_z列には、高さの平均が入っていることがわかります。

図31-29 結合結果のavg_zに高さの平均が格納された

これでポリゴンの平均高さがわかったので、ポリゴン自体のジオメトリのZ座標を、この値で上書きします。

#上記で計算したZ座標の平均値を道路のほうに入れる
tran["poly_avg_z"] = joind["avg_z"]

#tranのマルチポリゴンを上書きする
from shapely import Polygon, Point, MultiPolygon
def add_z_to_multipolygon(geom, z_value):
polygons = []
for polygon in geom.geoms:
new_exterior = [(x, y, z_value) for x, y, _ in polygon.exterior.coords]
new_interiors = [
[(x, y, z_value) for x, y, _ in interior.coords]
for interior in polygon.interiors
]
new_polygon = Polygon(new_exterior, new_interiors)
polygons.append(new_polygon)
return MultiPolygon(polygons)

tran["geometry"] = tran.apply(
lambda x: add_z_to_multipolygon(x.geometry, x.poly_avg_z), axis = 1
)

#計算に使ったcentroidを削除
tran = tran.drop(columns="centroid")

リスト31-2 道路情報tranの高さを標高モデルのポリゴンの平均高さで上書きする

以上で道路情報tranの高さが、標高モデルの平均値で更新されました。

[4]PyDeckで再度、可視化する

再度、PyDeckで可視化すると、道路に高さが設定され、建物とそろうことがわかります。

r = pdk.Deck(layers=[layer, tran_layer], initial_view_state=view_state)
r
図31-30 高さの調整前(上)と調整後(下)
コラム:ベースマップと高さをそろえる

建物と道路はこれでそろうのですが、ベースマップ(背面に表示している地図)からは浮いています。これは道路も建物も、地面が標高を基準とした高さ(東京近郊ではおよそ36m)であるのに対して、ベースマップは高さ0メートルの位置に配置されているからです。これはベースマップと重ねて表示する際の表示上の問題です。

もしベースマップにピッタリとそろえたいのであれば、道路の高さを設定した方法と似た方法で、建物や道路を0mに位置まで強制的に下げる(標高の分だけ下げる)ようにします。

■ エクスポートして他でも利用できるようにする

このように変換した道路は、エクスポートすれば、他のソフトウェアで利用できます。例えばUnityなどで表示するときには、変換した情報を使えば建物の高さと道路の高さとをそろえられます。エクスポートすると、Google Colabの左側にファイルができるので、右クリックして[ダウンロード]からダウンロードできます。

tran.to_file("53394525_tran_update_z.gpkg", driver="GPKG")
図31- 31 変換後のデータをエクスポートする

31.4 _ 属性マッピングルールを使う

CityGMLにはたくさんの属性が含まれていますが、その属性はデフォルトの「属性マッピングルール」に基づいて変換されます。

デフォルトの属性マッピングルールの設定は、基本的に、もとの属性名と同じ名前に変換するように構成されています。ただし、ファイル形式によって、そのまま変換すると属性名が重複したり、長さ制限や使えない文字が含まれる場合には、この限りではありません。ファイル形式ごとに設定が異なるので、詳しくは、下記のリンクを参照してください。

----------------
【属性マッピングルール】

https://project-plateau.github.io/PLATEAU-GIS-Converter/manual/mapping_rules/index.html
----------------

属性マッピングルールを設定することで、変換の際のマッピングを変更できます。例えば、英語の名前ではなく日本語の名前に変更することもできます。

31.4.1 _ 属性マッピングファイルの形式と例

属性マッピングファイルはJSON形式のファイルで、次の書式で定義します。

{
"rename" : {
"CityGMLの属性名" : "変更先の属性名",
・・・
}
}

例えばリスト31-3に示すrules.jsonを作るとします(ファイル名は任意名です)。

{
"rename" : {
"gml:name" : "名前",
"bldg:address" : "住所",
"gml:description": "説明",
"core:creationDate":"作成日",
"bldg:class": "種類",
"bldg:usage": "用途"
}
}

リスト31-3 マッピングファイルの例(rules.json)

31.4.2 _ 属性マッピングルールを使った変換と結果

PLATEAU GIS Converterで変換する際、[属性マッピング]の項目でリスト31-3のファイルを選択します。そして変換してQGISで開いてみると、属性名が日本語に変わっていることがわかります。

データ解析で、あらかじめ属性名を変更したい場合には、こうした属性マッピングルールを適用して変換すると良いでしょう。そうすれば、読み込んだ後に、改めて属性名を変更しなくて済みます。

図31-32 属性マッピングルールを適用して変換する
図31-33 一部の属性が指定に基づき、日本語に変更された

31.5 _ コマンドラインから変換する

これまで説明してきたように、PLATEAU GIS ConverterはGUIのツールですが、コマンドラインから使うこともできます。サーバー上でファイル変換したいときや大量のファイルを変換したいときなどには、コマンドラインからの実行を検討するとよいでしょう。

31.5.1 _ コマンドラインから使えるようにする

PLATEAU GIS Converterは、Rust言語を使って構築されたツールです。コマンドラインから使えるようにするには、Rustをインストールした後にソースファイルからセットアップします。

【メモ】

コマンドラインでの利用方法については、公式マニュアルも参照してください。

【手順】コマンドラインから使えるようにする

[1]Rustをインストールする

Rustをインストールします。詳細は、Rustの公式サイトのインストール方法も参照してください。

・macOSまたはLinux

以下のコマンドを実行してインストールします。

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

・Windows

公式サイトからインストーラをダウンロードして実行します。

[2]リポジトリをクローンする

GitHubのリポジトリから、ソースコード一式をクローンします。git pullコマンドを使っても、ZIP形式でダウンロードしてもかまいません。

----------------
【PLATEAU-GIS-Converter】

https://github.com/Project-PLATEAU/PLATEAU-GIS-Converter
----------------

31.5.2 _ コマンドラインで変換する

PLATEAU GIS Converterの本体は、nusamaiフォルダ(これはPLATEAU GIS Converterの開発コード名です)のcargoという実行ファイルです。

cd ./nusamai

次のいずれかの方法で実行できます。

① デバッグモード

最適化せずに実行します。実行までの時間は速いですが、変換処理に時間がかかります。

cargo run -- ~/path/to/PLATEAU/15100_niigata-shi_2022_citygml_1_op/udx/bldg/*.gml --sink geojson --output foobar.geojson

② 通常モード

最適化コンパイルをしたうえで実行します。一般的な利用では、この方法を使ってください。

cargo run --release -- ~/path/to/PLATEAU/15100_niigata-shi_2022_citygml_1_op/udx/bldg/*.gml --sink geojson --output foobar.geojson

③ LTO有効プロダクションビルド

LTOを有効にしてビルドします。実行までの時間が遅いですが、変換処理は最高速です。

cargo run --profile release-lto -- ~/path/to/PLATEAU/15100_niigata-shi_2022_citygml_1_op/udx/bldg/*.gml --sink geojson --output foobar.geojson

実行時のオプションの詳細は、次のとおりです。

-- : 以降の引数はファイル名として解釈されます。*を使って複数ファイルを指定できます。
--sink : 出力形式を指定します。以下のように指定可能です。
3dtiles : 3D Tiles
gpkg : GeoPackage
mvt : Mapbox Vector Tiles
geojson : GeoJSON
czml : CZML
gltf : glTF
kml : KML
ply : PLY
minecraft : Minecraft Java World Data
obj: Wavefront OBJ
shapefile : Shapefile
--output : 出力先を指定します。拡張子なども指定してください。
-t: 利用するLODを指定可能です。利用可能なオプションはGUIと同様です。
use_lod
max_lod: 最大LODを抽出する
min_lod: 最小LODを抽出する
textured_max_lod: テクスチャ付きの最大LODを抽出し、テクスチャがない場合は最大のLODを抽出する
-o: 出力ファイル形式固有のオプションを設定します。
split: OBJ形式専用です。オブジェクト分割についてbool値で設定します。
limit_texture_resolution: 3D形式専用です。距離(メートル)あたりのテクスチャ解像度を制限します。有効にすると、小さな地物の過剰に高解像度なテクスチャを適切に調整し、全体的なパフォーマンスを向上させます。

リスト31-4 実行時のオプション

31.6 _ まとめ

このトピックでは、主にGeoPackage形式に変換して、それをPythonから読み込んで空間演算する方法を紹介しました。道路の高さを標高モデルに合わせるために空間結合という手法を使いましたが、Pythonではほかにも「特定の範囲内に含まれるすべての地物を検索する」「最も近い地物を探す」など、さまざまな空間演算ができます。GeoPackag形式に変換したデータをGeoPandasで読み込んで、さまざまな活用をしてみてください。QGISを使った空間分析の方法については、例えばQGIS LABなどが参考になります。

【文】

西尾 悟(MIERUNE)

【協力】

大澤文孝