PLATEAUのデータを必要な範囲だけダウンロードして表示する方法（仮）

## はじめに

:::note info
この記事は、「[3D都市モデル Project PLATEAU Advent Calendar 2024](https://qiita.com/advent-calendar/2024/plateau)」の21日目の記事です。
:::

[Project PLATEAU](https://www.mlit.go.jp/plateau/)で公開されている3D都市モデルをダウンロードする時、どのように行っていますでしょうか？  
[Unity](https://project-plateau.github.io/PLATEAU-SDK-for-Unity/)で扱う場合はSDKが開発されたため、比較的楽にダウンロードできるようになったかなと思います。一方で、GISで扱う場合はG空間情報センターの[3D都市モデル（Project PLATEAU）ポータルサイト](https://www.geospatial.jp/ckan/dataset/plateau)から使用したい自治体のCityGMLのZIPファイルをダウンロードし、[PLATEAU GIS Converter](https://github.com/Project-PLATEAU/PLATEAU-GIS-Converter)などでGISにて読み込める形式に変換している方が多いと思います。  
このとき、以下のような課題を感じていました。  
- 実際に使用したい範囲は自治体の一部地域であるが、自治体全体のデータをダウンロードしないといけない
- 範囲が複数自治体にまたがる場合は、それぞれの自治体分ダウンロードしないといけない

上のようなことから、本当に使いたいところは一部地域なのに使用しない範囲もダウンロードしていて、**ストレージがひっ迫**するようなこともしばしばありました。。。
そこで、使いたい範囲のデータのみをダウンロードすることができないかチャレンジしてみました。  


## この記事の目標
今回は、静岡県浜松市の浜松駅周辺の建物データを、使いたい範囲のみダウンロードしQGISで表示することを目標とします。  
理由としては
1. [浜松アクトタワー](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%82%AF%E3%83%88%E3%82%B7%E3%83%86%E3%82%A3%E6%B5%9C%E6%9D%BE)という高い建物があり、最終的にQGISで表示できたときに映えそうなので
2. [浜松市のデータ](https://www.geospatial.jp/ckan/dataset/plateau-22130-hamamatsu-shi-2023/resource/4f92750f-561d-4678-b22b-7a51139500aa)をダウンロードすると、ZIP圧縮した状態で**251GB**のデータをダウンロードしないといけないため（相変わらず、すごい容量ですね）  
    
    ![大容量のzipファイル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/e1db56b3-5dc4-373d-9caa-70b03c949def.png)


という達成感がありそうなところを選んでみました。


## 方針
任意の範囲のみをダウンロードするということで、以下の通りの処理を実装できるように考えていきます。
1. 使いたい範囲のポリゴンを用意する
2. 1. のポリゴンと交差する3次メッシュを特定する
（PLATEAUの建物データは、3次メッシュごとに公開されているため）
3. 2.で特定した3次メッシュ範囲のCityGMLのみをダウンロードする


## 準備するもの
### 1. 使いたい範囲のポリゴン
GISを用いて用意しました。今回は、以下の画像における赤枠の範囲とします。

![ダウンロードする範囲.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/cee57ecc-7163-28e8-24b6-66cb7962656e.png)

### 2. 3次メッシュのポリゴン
使いたい範囲の3次メッシュを用意します。ポリゴンの座標から計算して3次メッシュコードを求めても良かったのですが面倒であったので、今回はG空間情報センターにて環境省自然環境局生物多様性センターが公開している[3次メッシュのポリゴンデータ](https://www.geospatial.jp/ckan/dataset/biodic-mesh/resource/38bd3651-120e-480f-99cf-7bb89cad7a05)を用います。  


## 手順
### 建物データの取得方法
まず、3次メッシュ単位の建物データをQGISで表示する方法を考えていきます。  
普通に考えると、G空間情報センターから自治体全体のCityGMLをダウンロードしないといけないですが、ストレージの事情も考えると、一時的にでも251GBのZIPファイルをダウンロードするのは厳しいです。  

そこで、地理空間情報を扱うライブラリであるGDALの[仮想ファイルシステム](https://gdal.org/en/stable/user/virtual_file_systems.html)を使用していきます。これは、ローカルファイル以外にも特殊なプレフィックスを使用することで、圧縮されたデータやWeb上で公開されているデータなど様々なデータにアクセスできるという大変便利な仕組みです。この仕組みを用いることで、圧縮されたデータの処理を解凍せずに扱えたり、Web上にあるデータをダウンロードせずに扱えたりします。  

#### 例1) ZIP圧縮された画像の情報を調べたいとき  
`/vsizip/`というプレフィックスを使用することで、ZIP圧縮されたデータにアクセスすることができます。  
`gdalinfo` コマンドを用いて、example.zipの中にあるimage.tifの情報を調べたいときに、以下のように行えます。  
```shell
$ gdalinfo /vsizip/example.zip/image.tif
```

#### 例2) Web上にあるGeoJSONの情報を調べたいとき  
`/vsicurl/`というプレフィックスを使用することで、ZIP圧縮されたデータにアクセスすることができます。  
`ogrinfo` コマンドを用いて、`http://localhost:8080`上で公開されているsample.geojsonの情報を調べたいときに、以下のように行えます。  
```shell
$ ogrinfo /vsicurl/http://localhost:8080/sample.geojson
```

#### 例3) Web上にあるZIP圧縮されたGMLの情報を調べたいとき
今まで使用した`/vsizip/`と`/vsicurl/`は組み合わせて使用することも可能です。  
`ogrinfo` コマンドを用いて、`http://localhost:8080`上で公開されているsample.zipの中に含まれるbuilding.gmlの情報を調べたいときに、以下のように行えます。  
```shell
$ ogrinfo /vsizip//vsicurl/http://localhost:8080/sample.zip/building.gml
```

### GDALのファイルシステムを用いたPLATEAUの建物データへのアクセス
ここからは、例3を応用してPLATEAUの建物データへのアクセスを試していきます。

#### 1. G空間情報センター上にあるZIPファイルのURLを調べる
今回の目標である浜松市のデータのURLは、G空間情報センターのCityGMLを実際にダウンロードするページから調べることができます。Google Chromeの場合、ダウンロードボタンを右クリックし、「リンクのアドレスをコピー」からZIPのURLをコピーできます。  

![URLの調べ方.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/b83e5493-5f1d-e189-6fb3-021e3fd6414f.png)

#### 2. ZIPファイルの中身のフォルダ構成
続いて、公開されているZIPファイルの中身のフォルダ構成ですが、[Project PLATEAU公式サイトのLearning](https://www.mlit.go.jp/plateau/learning/tpc03-1/)にて記載されているように、しっかりと決まっています。  

**フォルダ構成の例 （[PLATEAUのLearningサイトより引用](https://www.mlit.go.jp/plateau/learning/tpc03-1/)）**  
```
01100_sapporo-shi_2020_citygml_3_op
├─01100_indexmap_op.pdf
├─codelists
├─metadata
├─specification
└─udx
    ├─bldg
    │  ├─64414267_bldg_6697_appearance
    │  ├─…略…
    ├─dem
    ├─fld
    │  ├─natl
    │  │  ├─ishikarigawa_atsubetsugawa
    │  │  ├─…略…
    │  └─pref
    │      ├─hoshiokigawa_hoshiokigawa
    │      ├─…略…
    ├─lsld
    ├─luse
    ├─tnm
    │  └─01_1
    ├─tran
    └─urf
```

そのため、今回ダウンロードしたい建物の場合は、多くが`udx/bldg`の下に格納されています。  

#### 3. 建物のCityGMLの命名規則
フォルダまで特定ができたので、あとはダウンロードしたい範囲のCityGMLのファイル名が分かれば、アクセスができます。  
ファイル名についても、[3D都市モデル標準製品仕様書](https://www.mlit.go.jp/plateaudocument/#toc7)に記載がある通り、しっかりと決まっています。  
例えば、建物の場合は以下のように命名されます。 
`[メッシュコード]_bldg_6697_[オプション].gml`  
また、オプションはさらに分割したい場合やデータの更新などがあったときに区別を行えるように付与されていますが、建物の場合はほとんど使用されていないので、多くの場合は以下のように命名されています。  
`[メッシュコード]_bldg_6697_op.gml`

#### 4. 特定の3次メッシュの建物データへのアクセス
`ogrinfo` コマンドでアクセスできるか試していきます。  
ここまでの話をまとめると、ZIPフォルダに含まれているの建物のCityGMLは以下のような命名規則になっています。  
`[ZIPファイルのURL]/udx/bldg/[3次メッシュコード]_bldg_6697_op.gml` 

また、浜松市の最新のCityGMLは以下の通りです。  
`https://assets.cms.plateau.reearth.io/assets/02/5cfd50-fa54-42a3-9618-708f4972b412/22130_hamamatsu-shi_city_2023_citygml_1_op.zip`  

さらに、最初の方で準備した3次メッシュポリゴンと今回表示したい範囲のポリゴンをGISで重ねて表示すると、ダウンロードしたい範囲の3次メッシュは、「52370548」と「52370549」であることが分かります。

![3次メッシュとaoiを重ねて表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/b9bf9931-3118-a8fd-a920-55462b80023f.png)

そのため、「52370548」の部分の建物データに関する情報は、以下にアクセスすることで得ることができそうです。
`/vsizip//vsicurl/https://assets.cms.plateau.reearth.io/assets/02/5cfd50-fa54-42a3-9618-708f4972b412/22130_hamamatsu-shi_city_2023_citygml_1_op.zip//udx/bldg/52370548_bldg_6697_op.gml`

実際に、`ogrinfo`コマンドを試してみると、以下のように情報が取得できたため、アクセスできたことが分かります。  

```shell
$ ogrinfo /vsizip//vsicurl/https://assets.cms.plateau.reearth.io/assets/02/5cfd50-fa54-42a3-9618-708f4972b412/22130_hamamatsu-shi_city_2023_citygml_1_op.zip/udx/bldg/52370548_bldg_6697_op.gml
INFO: Open of `/vsizip//vsicurl/https://assets.cms.plateau.reearth.io/assets/02/5cfd50-fa54-42a3-9618-708f4972b412/22130_hamamatsu-shi_city_2023_citygml_1_op.zip/udx/bldg/52370548_bldg_6697_op.gml'
      using driver `GML' successful.
1: Building (3D PolyhedralSurface)
```

## QGISで表示
PLATEAUのCityGMLをQGISで表示するときは、なるべく最新版の使用をオススメします。  
（そうしないと、[色々苦しむ](https://qiita.com/Yfuruchin/items/aa3a847db26c7f378d6e)ことになります。）  
また、Windows版のQGISは新しめのGDALが入っているのですが、Mac版やLinux版だと、まだ対応していないこともあります。  
この記事では、比較的最近リリースされたバージョンである`3.34`のWindows版を使用していきます。  

QGISで[データソースマネージャ]を開き、[ベクタ]を選んだ状態で、ベクタデータセットに先ほどアクセスできたパスを入力します。（画像中の文字が小さいので、クリックして表示すると見やすいです。）  

![qgis_ベクタマネージャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/0eb630dc-32f9-596c-6bc3-f08ab0528852.png)

[追加]ボタンを押すと、以下のようにQGIS上に建物ポリゴンが表示されました！  
（紫色のポリゴンが、表示された建物ポリゴン）  

![データ表示_gfs無.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/5351a4b9-1662-2237-2b44-9d046b9238b8.png)

表示は出来ているようですが、明らかに建物の数が足りません。  
どうやら、LOD2が整備されている建物のデータが表示されていないみたいです。  
色々調べていくうちに、[GDALを用いてCityGMLから2Dのデータに変換する記事](https://qiita.com/tkhrmeme/items/bdacd335494c125f3496)を見つけ、**GFS_TEMPLATE** オプションに`gfs`という拡張子のファイルを指定することで、どのLOD要素を使用するか指定できることが分かりました。    
この記事を参考に、LOD2の建物が表示できるように`gfs`ファイルを作成しました。  
実際に作成したものは、以下のリンクからアクセスできます。  
- [LOD1の建物を表示するときに指定したgfs](https://gist.github.com/raokiey/2957dc6f9eed06b4e40bfe5596072cf9)
- [LOD2の建物を表示するときに指定したgfs](https://gist.github.com/raokiey/2caeee1d93915ca2436f1e271bf25151)

`LOD2の建物を表示するときに指定したgfs`をダウンロードし、そのパスを[データソースマネージャ]にある`GFS_TEMPLATE`の欄に入力して表示すると

![LOD1とLOD2合わせて表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/8d1b6277-6f3b-026c-d595-21e9f0753ecd.png)

無事に、「52370548」の範囲の建物が表示されました。 

あとは、残りの「52370549」も表示し、マージして、空間検索などで使いたい範囲内のポリゴンのみを抽出すれば、大容量のZIPファイルをダウンロードせずにGISで扱える対象範囲のPLATEAUの建物データが手に入りました！！

![最終的にダウンロードされた建物データ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/fb6140b8-f74d-7435-d1bc-a583b2ab66da.png)

gfsにLOD2の要素を指定しているので、3Dで表示するとこんな感じになります。  

![最終的にダウンロードされた建物3Dデータ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/06646d08-c64d-4489-b07e-deedd145f5fc.png)


## 課題
今回試した方法は、現在分かっている範囲で以下のような課題があります。
- 道路など建物以外の公開されているデータでも行えるか不明
    → まだ試していないため  
- LOD0のジオメトリ情報を取得できない？
    → LOD0の要素をgfsに指定して、表示してみたが表示できなかった
- LOD1、LOD2の両方の要素を使用しても表示されない建物がある ~~（例: 東京タワー）~~
    → 東京タワーなども表示できることを確認しました。まだ全国分のデータを試していませんが、ほとんどの建物は取得、表示できると思います。  


## おわりに
この記事では、G空間情報センターにて公開されているPLATEAUの大容量のZIPファイルをダウンロードせずに、特定の範囲の建物データを取得することを試しました。建物以外で対応しているのか、この方法では取得できない建物があるなど課題はまだまだありますが、皆様のお役に立てれば幸いです。  
また、今回はQGISベースであったので、プログラム化してWebGIS上でポリゴンを描き、その範囲を自動でダウンロードできるようにしたいなと思っています。