FlatGeobuf ファイルで農水省筆ポリゴン閲覧サイトを作った！

本記事は、[FOSS4G Advent Calendar 2022](https://qiita.com/advent-calendar/2022/foss4g)、１日目の記事です！

# 概要
農林水産省が公開している筆ポリゴンデータを、都道府県および全国単位で[FlatGeobuf](http://flatgeobuf.org/)形式で結合し、データの公開と閲覧をするサイト、[Fudepoly47](https://habs.rad.naro.go.jp/spatial_data/fudepoly47/)を作成しました。
元データは、[農地の区画情報（筆ポリゴン）のデータ提供・利用](https://www.maff.go.jp/j/tokei/porigon/index.html)、閲覧ページは[FlatGeobuf Leaflet Large Dataset Example ](https://flatgeobuf.org/examples/leaflet/large.html)を改変して作成しました。

全国及び都道府県選択の[カラム地図](https://github.com/tabularmaps)は、[日本カラム地図　CC BY 4.0 福野泰介](https://tabularmaps.github.io/areamap/tabularmaps_japan.html)を利用させていただきました。

サイトの名前については、[flat47](https://github.com/optgeo/flat47-r2ka)を参考にさせて頂きました。

# 今回の目的！
今回の材料は、筆ポリゴンです。筆ポリゴンは、農地の筆[^1]の区画形状と、地目、IDを含んだGISデータで、[農林水産省から公開されています](https://www.maff.go.jp/j/tokei/porigon/index.html)。公開されているデータは、市町村毎に圧縮した[GeoJSON形式](https://datatracker.ietf.org/doc/html/rfc7946)です。この筆ポリゴンをつかって、農地の情報を収集したりしています[^2]。過去の筆ポリゴンについてはベクトルタイル形式で閲覧可能にしているのですが[^3]、データが更新されたので閲覧ページを更新したいなと思っていたところ。
MVTでタイルを作り直してもいいのですが、それはそれで結構手間なので、もうちょっとさっくりする作る方法が無いかと思い、今回は[FlatGeobuf](http://flatgeobuf.org/)をつかって閲覧サイトを作ることにしました。なお、市町村毎のファイルで閲覧ページを作るとページ数が膨大になってしまうので、今回は都道府県単位で閲覧ページを作ることにしました。技術的検証目的で、全国版のページも作っています。

# 手順手順
## 基本的な流れ

以下のような流れになります。

- [筆ポリゴンダウンロードページ](https://www.maff.go.jp/j/tokei/porigon/hudeporidl.html)から、データをダウンロード。
- 都道府県ごとのzipファイルになっているので、解凍して結合。結合処理にはOSGeo4Wのogrmerge.pyを使用。使ったバッチファイルは、[都道府県別筆ポリゴン結合用BATファイル](https://github.com/wata909/fudepoly47/tree/main/scripts)で公開してます。
- 閲覧サイトをつくる。ファイルのレポジトリは[fudepolu47](https://github.com/wata909/fudepoly47)です。

以下、詳細手順です。

## 筆ポリゴンデータのダウンロードとFlatGeobuf形式への変換

ダウンロードについては説明することも無く、手作業で行いました。47都道府県分であれば、ちまちま手作業でDLしてもさほど苦ではありません（汗

さて上で記載したとおり、公開データはGeoJSON形式になります。GeoJSONについてここで改めて説明する必要は無いとおもいますが、Web上でデータ公開方法としても最近使われるようになりました。Leaflet等の地図表示ライブラリでそのまま表示できるのもいいですね。私もよく使っているのですが、少しだけ問題が。
例えば、以下のキャプチャは迅速測図のポイントデータを公開している例なのですが、データを表示するのに、GeoJSONファイルををダウンロード（ここでは約2.4MB）した上で表示していることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39797/e21f6e94-4f37-cdb0-86a1-0cb5b18d822f.png)

実際のページは[迅速測図土地利用データ](http://wata909.github.io/habs_test/5440/rapid544000.html)です。いまどき、2.5MB具であれば許容範囲かもしれませんが、ちょっともっさりしています。

これを47都道府県についてGeoJSON形式のファイルでやろうとすると、容量の最も小さい東京都でも91MB、最大の新潟県では1.12GBになります。これをブラウザで表示するのはいささか非現実的です。では市町村毎に表示ページを作るかというと、GeoJSONファイルの総数が1874、サイズも大きいもので100MB以上あり、それも難しい。ということで、今回は都道府県毎にファイルを結合し、FlatGeobuf形式に変換して表示ページを作ることにしました。

FlatGeobufについては、以下の資料に丁寧に説明されているのでそちらをご覧頂くのをお勧めします。というか、**必読です！**
- [GeoJSONをバイナリ化して圧縮するFlatGeobuf](https://gunmagisgeek.com/blog/data/7222)
- [FOSS4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動](https://docs.google.com/presentation/d/1vL-gNWlyM8W_jdG7AiUf1bsebZlvC8Nn9AXMzLs4Qoc/edit#slide=id.g10171a9a15a_0_246)

簡単に利点をまとめると、以下の点にあるかと。
- ファイルサイズが小さい
- 単ファイルであり、文字化けがない
- Webサーバで公開して、大容量データの表示が可能

ということで、実際の作業です。

- 作業環境はWindwos 64bit。10でも11でも大丈夫だとおもう
- [OSGeo4W](https://trac.osgeo.org/osgeo4w/wiki)が```C:\OSGeo4W ```にインストールされているものとする。
- ダウンロードした都道府県毎の筆ポリゴンzipファイルを、任意のフォルダにまとめて解凍する。
- さらに、[市町村別筆ポリゴン結合用BATファイル](https://github.com/wata909/fudepoly47/blob/main/scripts/merge.bat)をダウンロードして、同じフォルダに配置。以下のような感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39797/f900ba2a-2a5d-8fe4-bc11-730b190aa504.png)

- OSGeo4Wを起動し、解凍先のフォルダに移動。```merge.bat```を実行。
- ```2022_xx```フォルダ内に、```fude_2022_xx.fgb```という感じで都道府県毎のFlatGeobufファイルが生成されます！

ファイルの結合には少々お時間がかかりますが、気長にお待ちください[^4]。また、これとは別に全国版の結合ファイルも準備してあげました。

## 閲覧ページの作成

FlatGeobufを使うからといって、自動的にファイルの一部を読み込むようにはなりません。ということで、閲覧ページにつていは、[FlatGeobuf Leaflet Large Dataset Example ](https://flatgeobuf.org/examples/leaflet/large.html)をいじって作りました。
具体的なコードについては、特に解説することはないというか、よくわからず **動けばいい！** というポリシーの下で作っているので、説明できないというか（汗
あえて[fude_2022_01.html（北海道筆ポリゴンの表示ページ）](https://github.com/wata909/fudepoly47/blob/main/docs/fude_2022_01.html)を例に少し説明すると、以下のような修正を加えました。

- 7行目に[カラム地図](https://github.com/tabularmaps)表示用のスタイルシートとして以下を追加
```js
        <link rel="stylesheet" href="table.css" />
```

- 13~15行目に、地図の表示サイズを900pxで指定
```js
        <style>
            #map { height: 900px; }
        </style>
```

- 22~27行目で、地図のデフォルト表示位置を都道府県庁の位置に設定[^5]。

```js
                let map = L.map('map').setView([35.0211111111111,135.755555555556], 14);
                L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png', {
                    maxZoom: 18,
                    minZoom: 10,
                    attribution: '<a href="https://www.gsi.go.jp/development/ichiran.html#pale">地理院タイル淡色地図</a>&copy; <a href="https://www.gsi.go.jp/kikakuchousei/kikakuchousei40182.html">国土地理院</a><a href="https://www.maff.go.jp/j/tokei/porigon/index.html">筆ポリゴンデータ（2022年度公開）</a>&copy; <a href="https://www.maff.go.jp/">農林水産省</a> '
                }).addTo(map);
```

- 72~75行目で、筆ポリゴンFGBファイルの指定と、色分けを設定。

```js
                    const iter = flatgeobuf.deserialize('./fude_2022_01.fgb', fgBoundingBox());
    
                    const colorScale = ((d) => {
                        return d > 199  ? '#8b4513' :
                            d > 99 ? '#EEEE00' :
                            '#000000'
                    });
```
- 83行目で、地目（land_type）で色分けをすることを指定
```js
                            color: colorScale(feature.properties["land_type"]), 
```
- 101~103行目で、クリックしたときに表示するpopup属性を変更
```js
                        }).bindPopup(`筆ポリゴンID：${feature.properties["polygon_uuid"]}<br />
                                     地目：${feature.properties["land_type"]}<br />
                                     市町村コード：${feature.properties["local_government_cd"]}<br />`)
```
あと、いらないコードのコメントアウト等をしています。
また、他の都道府県の筆ポリゴン表示ページへのリンクとして、[カラム地図](https://github.com/tabularmaps)を使わせて頂きました。デザインは、[日本カラム地図　CC BY 4.0 福野泰介](https://tabularmaps.github.io/areamap/tabularmaps_japan.html)を利用させていただきました。

# で、実際どうなの？

## ファイル読み込みの比較
ということで、作ったサイトのトップページは[Fudepoly47](https://habs.rad.naro.go.jp/spatial_data/fudepoly47/)です。

で、実際に早くなったの？、ファイルの読み込みは効率化できたの？、の部分です。以下の図は、FlatGeobufのサイトにある[Leaflet Exampleの基本サンプル]を表示したときの画面です。```UScounties.fgb```として、14MBのファイルを読み込んでいることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39797/6897452f-333e-43a1-ba70-b8c74356a546.png)

下の図は、日本全国全体を結合したFlatGeobufファイル（約17GB！！！）を、表示したサンプルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39797/93f2d504-30a9-66a8-d5a9-bc18b74f1916.png)

最後の数行に```maff_fude_2022.fgb```とあり、ファイル全体では無く、分割して読み込んでいるようです。
さらに要求ヘッダを確認すると、例えば以下のようになっていて、指定したレンジのみを読み込んでいることが確認できました！
```
Range: bytes=211200-213759
```

ということで、でかいファイルをそのままアップロードしても、Webでの閲覧に使えることが確認できました。
なお、FlatGeobufファイルはQGIS等でも直接利用することが出来ます。これで、Web上で簡単に確認することも、DesktopGISでさっくり利用することも両方できて、とってもいいですね！

みなさん、**ShapeFileはゴミ箱に捨てて**、FlatGeobufに移行しましょう！

## Cloud Optimizedについてちょこっと。

前出の@Kanahiroさんの[資料](https://docs.google.com/presentation/d/1vL-gNWlyM8W_jdG7AiUf1bsebZlvC8Nn9AXMzLs4Qoc/edit#slide=id.g10171a9a15a_0_246)にもあるように、特別なGISサーバーを用いず、HTTP Range-request（と、いうのだそうな）を用いてデータの抽出に対応したデータ形式を**Cloud Optimized**とよび、FOSS4G界隈では、ちょっとしたトレンドになっています。代表的な例では、[Clound Optimized GeoTIFF](https://www.cogeo.org/)や、[Cloud Optimized Point Clound](https://github.com/copcio/copcio.github.io)等があります。また、[Cloud-Native Geospatial Outreach Event](https://na.eventscloud.com/website/36829/)というのも開かれたり、[STAC(SpatioTemporal Asset Catalogs)](https://stacspec.org/en/)でも、基盤技術の一つになっています。

一方で、特別なGISサーバーを用いずに空間情報を表示したり、共有したりするという点では、既存の地図タイルもCloud Optimizedに該当するのかなと、思っています。また、特別なGISサーバーを用いずに空間データの演算をクライアント側で行いというのが、Cloud Optimizedの次のステップとしてあるのかなと思っています。

そのへんのつらつらは、また別の機会に書きたいなと、思っています[^6]。



# おわりに
２日目の記事は、@kochizufan さんの「やまだこーじさんの成果を流用して論文資料図版に流用した微細地形コンタータイルサービス」です！


[^1]:普通に「田んぼ」とか、「畑」とかいった時に、区切られている単位です。
[^2]:たとえば、お宅のほ場のIDを教えてください！、ってかんじです。
[^3]:https://habs.rad.naro.go.jp/spatial_data/maff_fude_id2/
[^4]:早くする方法は、ないのかなぁ･･･・
[^5]:都道府県庁の位置は、[https://www.gsi.go.jp/KOKUJYOHO/center.htm](https://www.gsi.go.jp/KOKUJYOHO/center.htm)からダウンロードした[都道府県の庁舎及び東西南北端点の経緯度(世界測地系）](https://www.gsi.go.jp/common/000230936.pdf)より算出しました。CSVファイルは、(こちら)[https://raw.githubusercontent.com/wata909/fudepoly47/main/pref_lat_lon.csv]。位置情報は事実情報なので、著作権は生じません。ご自由にお使いください。ちなみに、いちいち計算したけど、今にして思えば、PDFのリンクに位置情報が埋め込まれていたよぉ･･･。
[^6]:が、いつになるのか･･･・