地図のレンダリングを実現するまでの流れはどうなっているのか？

:::note info
これは [MIERUNE AdventCalendar 2023](https://qiita.com/advent-calendar/2023/mierune)…7日目の記事です。
昨日は @Yfuruchin さんによる [チーム「shpファイル」のメンバーが足りません](https://qiita.com/Yfuruchin/items/9995b178ba2bb97a4c39) でした。
:::

# はじめに
地図作成がアナログからデジタルに進化していく過程で、それまでは「職人芸」だった地図作成は、とりわけここ10年以内の急激な発展により、今や誰でもプロと何ら遜色の無いものを作れるようになっています。

[Mapbox](https://www.mapbox.jp)や[MapTiler](https://maptiler.jp)などのクラウドサービスでは、地図のスタイリングをGUIで比較的簡単に行える機能を提供しています。

https://www.mapbox.jp

https://maptiler.jp

また、クラウドサービスの利用規約に適合しない地図サービスを構築したい場合、例えば[MapTiler](https://maptiler.jp)が提供するOpenMapTilesを利用することで、開発者はスタイルファイルの記述を自ら行うことで地図サービスを構築できます。

https://openmaptiles.org

このOpenMapTilesを使って実際に作成したのが、MIERUNEマップです。

https://qiita.com/moritoru/items/193f6d9bfd4b6bccea46

さらに、地図描画だけではなく、日本で利用可能なPOI検索、住所検索、ルート検索などの機能も必要であれば、例えば[HERE](https://www.here.com/jp/platform/developer)などの企業から提供されています。

https://www.here.com/jp/platform/developer


## この記事では
さて、この記事は、こうしたサービスの利用方法では無くて、地図のレンダリングを実現するまでの流れはどうなっているのか？という簡単な解説します。なお、地図画面自体の提供以外の、POI検索、住所検索、ルート検索などの機能については、本記事では含まず、地図画面自体の提供に絞ります。

## 良い地図サービスとは
良い地図サービスは、**用途に最適な表示要素が、表示されるべきズームレベルで、適切な表現で提供される**状態を言います。

「なんだ、当たり前じゃないか」、と感じられるかも知れません。しかし、様々にある地図データのカテゴリーを、ズームレベル毎に整理統合して、それぞれに表示のためのスタイルを記述していくプロセスには大変な労力がかかります。

これをざっくりと整理するとこんな感じです。
|目的|用途に最適な表示要素が|表示されるべきズームレベルで|適切な表現で提供される|
|:-:|:-:|:-:|:-:|
|プロセス|ソースデータの調達と統合|レンダリング用タイルデータの生成|スタイリングとレンダリング|


一つ一つ解説します。

### 1．ソースデータの調達と統合
地図作りの原材料と言うべき地図データ。これを必要十分な精度と網羅度で調達できているかが、その地図の内容を決定する出発点となります。
- 世界はシングルソースではありません。国や地域による言語、文化、規制などによって、地図データ自体はモザイクの様相を呈します。従って、異なる地域の地図データの仕様を合わせる「ローミング」が必要となります。
- 同じ地域であっても、異なるデータ提供者から、それぞれのデータ格納仕様で、複数のフォーマット（shp, PostGIS, GeoJson, GeoTiff, CSVなど）や異なる測地系（JGD2011, WGS84, 平面直角座標系など）で提供されることもあります。このため、そうした違いも吸収する必要があります。
- それぞれのデータは、必ずしも精度、粒度、情報日付が一致しないため、必要に応じてデータの精度を失わない形でマージや切り捨て処理を行う必要があります。
- これらのデータ処理においては、品質の低いもの取り扱いには注意が必要です。データクレンジングなどを行ったとしても、元の精度や粒度を超えるものを得ることは困難ですので、あまり期待しすぎないようにしましょう。

### 2．レンダリング用のタイル作成
統合された地図データを、パソコンやスマホのデバイス側でレンダリングしやすいようにタイルデータを生成します。
- 近年の地図サービスでは、ズームレベル単位（紙地図的な用語では「縮尺」にあたります）で格子状に区切られたデータ（タイルデータ）をサーバー側からクライアント側に配信し、クライアント側でレンダリングを行うことが一般的です。
- ベクトルタイルのフォーマットは、[MVT形式](https://github.com/mapbox/vector-tile-spec)が採用されることが多いです。
- MVT形式のタイルデータの生成には[tippecanoe](https://github.com/felt/tippecanoe)がよく使われます。
- ズームレベルは0から24など多段階に分かれていて、それぞれのズームレベルを構成するタイルデータに、表示すべき要素を格納します。
- 低いズームレベルでは、大陸や地域などの概要を表す情報を格納し、中間のズームレベルでは、都市や道路網などの位置関係がわかる情報を格納します。そして高いズームベルでは、詳細な交通網や建物、土地利用、施設情報、行政境界線（北米などではstreet name）などを格納します。
- 日本の地図の場合は、ズームレベルが15を超えたあたりからが本領発揮で、高密度の情報が格納される傾向があります。
- 一方、北米などに見られるような、都市部でもあまり密集度の高くない地域では、ズームレベルが15を超えても、格納される情報があまり増えない傾向があります。
- タイルデータにリッチな情報を盛り込めば、地図のレンダリングでの様々な選択肢が得られるのですが、クライアント側へのタイルデータのダウンロード時間を短縮するために、データサイズを少なくする必要があるという、トレードオフの関係です。

ベクトルタイルの仕様はいわばノウハウの塊で、ソースデータの構成を理解して顧客からの要請を満たしつつ軽量なタイルデータを生成するための様々な工夫が施されています。
ベクトルタイルの仕様が実際にどのようなものなのか、例えばOpenMapTilesとHERE VectorTileAPIをご覧いただければと思います。読めば読む程味わいが深いです。

https://openmaptiles.org/schema/

https://jp.developer.here.com/documentation/vector-tiles-api/dev_guide/index.html

HEREの方がOpenMapTilesに比べると圧倒的に複雑な仕様ですが、これは様々な業務用途に対応するために拡張を続けた結果です。ちなみにHEREのVectorTileAPIは[Amazon Location Service](https://aws.amazon.com/jp/location/)でも採用されています。

### 3．スタイリングとレンダリング
さて、ようやくこれでスタイリングを行えます。クライアント側（例えばWebブラウザ）がスタイルファイルの記述に従って地図描画を実行します。
- MVT形式のベクトルタイルであれば、[MapLibre GL JS](https://maplibre.org/maplibre-gl-js/docs/)がよく使われます。
- スタイルファイルの記述は、テキストエディタのみでは作業効率が上がらないため、例えば[Maputnik](https://maputnik.github.io)を使うことで、実際の表現を確認しながら記述することができます。
- スタイルファイルは一万行を超えるボリュームになることが多く、特にグローバルの地図に加えて、日本の地図データも扱うような場合には、数万行規模になることすらあります。
- 従って、地図サービスを展開している事業者は、スタイルファイルの記述をゼロから書かせるのでは無く、利用者の多いと思われる数パターンの地図スタイルを作成し、利用者が用途に適切なスタイルを選択する方法を推奨しています。
- 1例ですが、HEREが日本向けに提供する様々なスタイルについての解説記事です。これらのスタイルを利用することで、ユーザーは0からスタイルを書くとんでもない苦労をせずに済みます。

https://qiita.com/moritoru/items/45c4b51fc5ea0db9ba94

- 数万行規模の「巨大」なスタイルファイルの実行スピードは、デバイス側の性能向上、MapLibre GL JSなどのレンダリングエンジンの性能向上のため、瞬時に行われ、もたつくことは滅多にありません。
- タイルデータをデバイス側にダウンロード（全部では無くて表示したいエリアとその周辺のみ）する必要があるため、ネットワーク帯域が限られている場合に、少し時間がかかる場合があります。
- 多層のレイヤー、複雑な描画方法は、地図表現に豊かさをもたらしますが、一方でタイルデータの増大や、描画の際に使用されるデバイス側のCPU/GPU、メモリなどリソース消費の増加をもたらします。結果としてバッテリー消費も進みます。

以下は、少し古い記事になりますが、スタイルファイルの作成に関して説明しています。参考になさってください。

https://qiita.com/moritoru/items/c6fc303bf9925de0a3a7

https://qiita.com/moritoru/items/434783e50345a35d9d45

# おわりに
あるズームレベルでの地図にレンダリングしたい項目があっても、それが前工程のタイルデータに適切な属性を付与されて格納されていなければ表示できません。さらに、そもそもソースデータを調達して、それが利用可能な状態に統合されていなければ、タイルデータすら作成できません。

普段はあまりこうした「縁の下の力持ち」的なプロセスは触れられることは無いかと思いますが、実はそこはとても大切な部分です。

:::note info
明日は@darshuさんです！お楽しみにー
:::