Flutterでバイナリベクトルタイルを描画

土地情報閲覧アプリ開発

FlutterのCustomPaintでバイナリベクトルタイルを描画します。

バイナリベクトルタイルを使ってみたいと思った経緯

不動産取引情報APIを見ているとバイナリベクトルタイルを返すAPIがありました。取引情報を地図上に表示することができます。GeoJSONという形式もあるようですが、バイナリベクトルタイルの方がサイズが小さくなりそうかなと思い、バイナリベクトルタイルにしました。ただし、日本地図のバイナリベクトルタイルの提供が実験中となっています。詳しくはリファレンスの国土地理院のサイトを確認してください。

次に、バイナリベクトルタイルを扱うパッケージがあるか探しました。地図を扱うパッケージでflutter_mapが有名ですが、バイナリベクトルタイルをサポートしていません。flutter_mapにバイナリベクトルタイルを扱うためのvector_map_tilesというプラグインもありますが、あまり更新されてないように見えました。

ということで、CustomPaintを使って自分で描画してみることにしました。

リファレンス

protocol buffers

バイナリベクトルタイルはプロトコルバッファで定義されます。まずはDartでプロトコルバッファを扱えるようにします。

Dartのチュートリアル

以下の公式チュートリアルに従って、チュートリアルのデータモデル addressbook.proto の書き込み/読み出しができることを確認しました。

https://protobuf.dev/getting-started/darttutorial

困ったところをメモしました。

  • addressbook.protoをDart向けにコンパイルするときに”protoc_plugin”というDartのパッケージが必要。以下のコマンドでインストールできる。
    • dart pub global activate protoc_plugin
  • addressbook.protoをコンパイルするとdartのファイルが出力されるが、コンパイルエラーが出力されている。以下の対応が必要。
    • protobufのパッケージを追加する。プロトコルバッファを扱うためのパッケージ。*.protoをコンパイルするパッケージだけじゃない。
    • addressbook.protoをコンパイルするときにgoogle/protobuf/timestamp.protoもコンパイル時のコマンドに含める。※参考記事

ベクトルタイルのprotoをコンパイル

ベクトルタイルのprotoも同じ要領で扱うことができます。

コンパイルしてテストしたコードが以下になります。

https://github.com/ohmusso/map_app/tree/main/vecmap

一つ注意点があります。以下のzigzagデコード関数で使用するxor演算がFlutter Webのjavascriptに変換されたときに正しく動作しませんでした※1。stackoverflowにあった対策コードで実装しています。Flutterでビット演算をするときは気をつける必要があります。

https://github.com/ohmusso/map_app/blob/76a4cba92d4cc58fc3e18e9b5269fa6760b384d0/vecmap/lib/vecmap.dart#L46

※1 戻り値をint型で定義したのに戻り値がUInt32で扱われてしまう。

バイナリベクトルタイルの描画

まずは一つのタイルを描画してみます。

ソースコードは以下になります。

https://github.com/ohmusso/map_app/tree/main/app_map

assets/11_1796_811.pbfに描画するタイルを置いています。京都市を表示するタイルです。

タイルの読み込み

以下のgetTileFromPbfでassetsフォルダに置いたタイルを読み込みます。将来的にhttps://cyberjapandata.gsi.go.jp/xyz/experimental_bvmap/{z}/{x}/{y}.pbfにアクセスして必要なタイルを読み込みます。

https://github.com/ohmusso/map_app/blob/76a4cba92d4cc58fc3e18e9b5269fa6760b384d0/app_map/lib/vecmap_widget.dart#L7

CustomPaintでタイルを描画

以下のコードでタイルを描画しています。

https://github.com/ohmusso/map_app/blob/76a4cba92d4cc58fc3e18e9b5269fa6760b384d0/app_map/lib/vecmap_widget.dart#L95

いろいろと未対応です。

動作確認結果

確認結果

以上