ベクトルタイルの進捗と展望

これは [FOSS4G アドベントカレンダー 2018](https://qiita.com/advent-calendar/2018/foss4g) の 21 日目の記事です。

ベクトルタイルの進捗と展望について、主に私が関わっているプロジェクトの観点からお話ししたいと思います。

# 背景
**性能**が良く**相互運用性**があるベクトルタイルの生産と消費を支援するために、2018年12月3日の FOSS4G Asia 2018 の基調講演で[国連ベクトルタイルツールキット](https://github.com/un-vector-tile-toolkit)を[リリース](https://speakerdeck.com/hfu/collaboration-of-geospatial-information-communities-through-the-un-open-gis-initiative?slide=17)しました。詳細な経緯は[地理文化講演会の資料](https://speakerdeck.com/hfu/jmc-lecture-2018-12-07)で説明しています。

今回の記事は、国連ベクトルタイルツールキットの構造と構成を踏まえていますので、まずはそれを簡単に説明してみたいと思います。

## 国連ベクトルタイルツールキットの構造
国連ベクトルタイルツールキットは、ベクトル形式の**多様な**ソースデータを、**性能**が良くて**相互運用性**のあるベクトルタイルに変換し、実際にスタイルづけをして公開することができる主体を増やすことを目的としています。

この目的のために、インポート（import）、生産（produce）、ホスト（host）、スタイル（style）、最適化（optimize）の各要素について、ツールを選定又は開発し、実際にそれらツールを複数のデータで使っていくことによってベストプラクティスを形成し、文書化をすることを目指しています。

<img width="710" alt="国連ベクトルタイルツールキットの構造" src="https://qiita-image-store.s3.amazonaws.com/0/102082/e6a976d9-657d-5254-a74b-747d83535258.png">

**インポート**は、様々な既存のベクトルデータを、ベクトルタイル生産のためのツール用に整える要素です。データフォーマットの変換と、ベクトルタイル特有の設計属性である「最大ズーム、最小ズーム、レイヤ名」の追加等を行います。

**生産**は、ベクトルデータをベクトルタイルパッケージに変換する作業です。ベクトルデータの更新に応じて、バッチ処理で**連続自動更新（continuous and automatic update）**ができるようにすることに留意しています。

**ホスト**は、生産されたベクトルタイルパッケージを、ウェブブラウザで消費可能な形でサーバに置く作業です。

**スタイル**は、ウェブブラウザで消費可能になったベクトルタイルに、適切な描画スタイルを定義する作業です。

**最適化**は、国連ベクトルタイルツールキットにおいて最も特徴的な要素です。国連ベクトルタイルツールキットにオリジナリティがあるとすれば、データの特性を客観的に計測していわゆるベクトルタイルスキーマを調整する、この最適化の要素を加えたことです。具体的には、ホストできる状態まで持ってきたベクトルタイルパッケージを用いて、ベクトルタイルのサイズ分布を計測し、ベクトルタイルのサイズが現実的なものになるようにいわゆるベクトルタイルスキーマを調整する機会を提供します。

## 国連ベクトルタイルツールキットの構成
国連ベクトルタイルツールキットの、実装上の構成についてもう少し詳しく解説すると、次の通りです。

<img width="726" alt="国連ベクトルタイルツールキットの構成" src="https://qiita-image-store.s3.amazonaws.com/0/102082/df1e3064-612d-626d-81cc-98b1ae692896.png">

### インポート
**インポート**は、多様なソースデータに対して柔軟に対応することを目指すことから、カスタムスクリプトを作成し、それをオープンソースで公開することによりベストプラクティスを共有するというアプローチをしています。

いわゆる**ベクトルタイルスキーマ**は、インポートの段階で形成されます。ベクトルタイルスキーマをコードの詳細から分離するために、modify.js というアプローチを考案しています。また、モジュールアプローチを採用しています。これらのアプローチについては、下記進捗の節で改めて説明します。

### 生産
上記のインポート作業により設計属性を加えたベクトルデータをベクトルタイルパッケージに変換するツールとして、[Tippecanoe](https://github.com/mapbox/tippecanoe) を採用しています。

Tippecanoe は C++ で実装されたベクトルタイルへのコンバータで、古くからあるものですが、日々開発が進捗しているように見えています。2項目BSDライセンスによるオープンソースソフトウェアです。

### ホスト
ベクトルタイルをホストするソフトウェアは色々ありますが、モジュール化された多様な内容のベクトルタイルを、マスターデータベースから切り離した環境で簡単にホストする方法をカスタムスクリプトで実現しました。

### スタイル
ベクトルタイルに適用するスタイルを編集するツールとして [Maputnik](https://github.com/maputnik/editor) を採用しています。

### 最適化
ベクトルタイルのサイズの最適化を支援するツールとして [vt-optimizer](https://github.com/ibesora/vt-optimizer) を採用しています。

# 国連ベクトルタイルツールキットの進捗
上記で説明した各要素ごとに、国連ベクトルタイルツールキットの進捗を整理してみると、次のようになると思います。

## インポート
PostGIS, Shapefile, osm.pbf からフレキシブルにベクトルデータをインポートできる技術を特定することができており、現在のところ、取り立てて新しく開発すべき要素はないと考えています。

### モジュール
効率的なベクトルタイル生産につなげるため、データセットを適当なズームレベルのタイルの区画で分割し、それをモジュールと呼び、そのモジュールごとにベクトルタイル変換を行うことにしています。モジュールごとに生産したベクトルタイルパッケージは、ファイルシステム上で接合することなくそのままホストすることにしています。

モジュールのサイズは、ベクトルタイル変換の入力となるところの GeoJSON Text Sequences 形式で、最大数 GB 程度が理想的であると考えています。

OSM データを地球規模で変換する事例では、モジュールの単位に z=6 を採用しました。これは、全体を 4096 個に分割することに相当します。また、別のデータでは、モジュールの単位に z=10 を採用しました。稠密な部分を含むデータの場合には、モジュールのサイズを z=10 くらいにする必要もある、と思っています。

### modify.js
「最大ズーム、最小ズーム、レイヤ名」の設計属性を加え、余計な属性を外し、さらには地物の面積等に応じて設計属性を変えるといったことを行うにあたり、これらの処理をフォーマット変換の細部から切り離すため、[modify-spec](https://github.com/hfu/modify-spec) という規約を考えました。これは、地物を引数にとって、修正後の地物を返すという関数のかたちを定める規約です。

modify.js が、実質上、いわゆるベクトルタイルスキーマを定義します。modify.js を差し替え可能にすることにより、一つのデータソースからいくつもの種類のベクトルタイルを試作してみることもできるようになりました。

## 生産
生産については、本当に Tippecanoe の速度に感謝するばかりで、なんらの問題も発生していないと認識しています。

今後、より多種のデータを生産に加えて、クライアントの要求を完全に満たすベクトルタイルを生産していく必要があります。

このために、いわゆるベクトルタイルスキーマや、変換時に使用した特殊な処理をわかりやすく文書化する必要があると考えています。その第一弾として、表形式でいわゆるベクトルタイルスキーマを表現する試みを [spinel-schema](https://github.com/un-vector-tile-toolkit/spinel-schema) で試行することができています。

## ホスト
モジュール方式で生産されたベクトルタイルをホストする方式を確立することができました。

また、ArcGIS Server のベクトルタイルサービスに対応したアプリケーションとの相互運用についても、[pietra](https://github.com/hfu/pietra) で実証することができています。

この pietra のコードに、the OSGeo.JP Workshop for the UN Vector Tile Toolkit のために作成した [spinel](https://github.com/un-vetor-tile-toolkit/spinel) で施した改良を反映していく必要があります。

また、自動的・連続的に更新される、モジュール式のベクトルタイルパッケージを hot-swap する手順をコード化する必要もあるでしょう。

また、より高度なプロトタイプの生産に成功した後、配備へのゴーサインが出れば、配備環境に合わせた作り込みも必要になってくると考えています。

モジュール式のベクトルタイルパッケージは、一個あたりおおむね 200MB 程度です。このことを利用すれば、ベクトルタイルサーバは、より現場に近い環境に逐次進出させることが可能なのではないかと考えています。この「進出可能なベクトルタイルサーバ」の概念は、通信インフラが十分ではない環境でベクトルタイルを活用していくために、必要な技術になるかもしれません。この概念の実現についても、時間を見つけて考えていければと思っています。

なお、モジュール式のベクトルタイルパッケージをホストするという国連ベクトルタイルツールキットのアイディアと似たアイディアを、[Tapalcatl](https://github.com/tilezen/tapalcatl) が持っているようで、[解説記事](https://medium.com/@mojodna/tapalcatl-cloud-optimized-tile-archives-1db8d4577d92) と [その第二弾](https://medium.com/@mojodna/tapalcatl-2-updates-8eb827d969c1) を、ワクワクしながら読み進めているところです。

## スタイル
ベクトルタイルのスタイルづけについては、今のところは Maputnik に頼って、経験によって作り込みを行なっています。

これら作り込みの中で得た知見を活かしつつ、より多様なデータを加えて生産された、より本格的なベクトルタイルにスタイルづけをしていく必要があります。

スタイルづけのツールについては、オープンソースではないツールのほうに良いものがあるという状況であり、また、Mapbox Style の文法自体にも進展があるので、やや明るい展望が見えづらい状況かもしれません。

良好なスタイルを実現するため作り込んだ結果、スタイル記述が重くなりすぎて、ベクトルタイル表示について必要な性能が出なくなる懸念もあります。

## 最適化
最適化の基準を確立することができており、最適化のためのツールについても十分な選択肢を持ち得る状況になっています。

なお、最適の基準は、私は「タイルあたり最大 128KB まで」としています。他方で、 vt-optimizer の作者である ibesora は「平均 50KB 以下」としていたように記憶しています。概ね、そういうところでしょう。

## 文書化
the OSGeo.JP Workshop for the UN Vector Tile Toolkit のハンズオン資料作成が、文書化を始めるにあたっての良い機会となりました。

現在、[国連ベクトルタイルツールキットのウェブサイト](https://un-vector-tile-toolkit.github.io) を置くこともできており、２０１８年１２月の時点で、公開型のチャンネルを一応開設できた、という状況にあります。

今後、プロダクトができてくるに沿ってドキュメントを整備することは必須ですし、国連ベクトルタイルツールキットがコミュニティベースで持続可能になるための戦略を立てた上で、その戦略に沿ったドキュメント化を進めていく必要があると考えています。

引き続き、助言をいただければと考えています。

# 展望
今後、多様なデータを追加した上でのベクトルタイル生産を行い、より完成度の高いスタイルを準備した段階で、テスト及び評価を受けることになります。評価の結果が良好であれば、配備の作業を行い、文書化を行うことになります。

# 補足
## 他のツールとの関係
国連ベクトルタイルツールキットは、基本図ベクトルタイルの生産と消費の支援を主眼においています。変換が必要なベクトルデータの量が 10GB を超えるような場合への対応が重要視されています。

変換が必要なデータが少ない場合、例えば 3GB を超えないような場合には、国連ベクトルタイルツールキットのアプローチをお調べいただく前に、例えば [NYCPlanning の geojson2mvt](https://github.com/NYCPlanning/labs-geojson2mvt) をお調べになるのも良いかもしれません。

## ローカル言語の必要性と重要性
このエントリが日本語で書かれていることに関連して、FOSS4G Asia 2018 の基調講演で提示したスライドを一枚紹介させてください。

<img width="714" alt="ローカル言語の重要性" src="https://qiita-image-store.s3.amazonaws.com/0/102082/be364145-0c67-1d98-4519-35d75a4c6c19.png">

私の能力と経験では、いきなり外国語で考えを形式化するよりも、いちど自分の母語で考えをざっとでも書き出し、それを読んだ上で外国語を書いた方が、良い外国語の文書が得られます。

もちろん、外国語が流暢であるということは良いことですが、それに加えて、母語の存在を利点に変える努力も必要であると私は考えます。

スライドの右下に書いてみましたが、ローカル言語を使って考えを形式化していく作業は、（１）あなたのアイディアをオーガナイズ（整理）するのにも良いし、（２）あなたのローカルコミュニティをオーガナイズ（組成）するのにもよいと思います。

外国語で話が進んでから母語に翻訳するのではなく、話を進める段階で母語・外国語の両方を使って考えを練る、ということを私もやりたいと思いますし、他の母語を持つ方々にも試してもらえればと思っています。もしかしたら、Ruby における英語と日本語の扱いに似せるようなやり方かもしれません。英語以外を母語とする方々の能力を最大限に発揮するためには、そうしたマルチリンガリズムをソフトウェア開発コミュニティでも積極的に試していく必要がある気がします。