# 地図タイルについて (2022 Remix) この記事は[Smart Maps Advent Calander 2022](https://qiita.com/advent-calendar/2022/smart-maps)の2022/12/18のものです。 今回は2015年に書いた「[地図タイルについて](https://smellman.hatenablog.com/entry/2015/12/26/054520)」を元に現在の理解に合わせたものになります。 なお、2015年に書いた記事は糞長いため、一旦忘れてください。 > [TOC] ## 地図「タイル」とは何か 現在一般的に使われている多くの地図アプリケーションでは背景地図に地図タイルの仕組みが使われています。 地図タイル自体が一般的に知られるようになったのはGoogle Mapが採用した事によるものと理解しています。 ただし、地図タイルという仕組み自体は古くから実装があり、そこらへんはNetflix オリジナルドラマのビリオンダラーコードという作品を見ると良いかも知れません。 まぁ、昔話なので今の話をします。 で、じゃ地図タイルって何なのかというと、「EPSG:3857で定義された座標系に沿って地図をズームレベルごとにタイル状に分割したもの」が現在の地図タイルの定義です。 突然、EPSGという単語が出てきたのですが、これは座標系を定義する数字を表すもので、座標系の変換するための関数などをデータベース化したものとなります。 例えば、旧日本測地系から現在の日本測地系に変換するためにはそれぞれの定義の関数が必要ですが、EPSGのデータベースがあれば、EPSG:4301(旧日本測地系)からEPSG:6668(測地成果2011)への変換というコードを書くだけとなります。 なお、この仕組みを提供しているのが[PROJ](https://proj.org/)というOSSになりますが、話が脱線するので割愛します。 で、EPSG:3857で定義された座標系というのはどういうものかというと、約北緯85度、約南緯85度の間だけをカットしてメルカトル図法で世界全体を表したものとなります。 これをWeb Mercator(ウェブメルカトル)と呼んでいます。 ウェブメルカトルでは北極及び南極を示すことはできないのですが、その代わりにズームレベル0で地球全体を一枚の正方形の絵として表示することができます。 ここでズームレベルという概念が出てきたので、ズームレベルとは何かを説明します。 一般的な地図アプリケーションではズームイン(拡大)、ズームアウト(縮小)が出来ます。 ズームレベルとは現在表示している地図がどれぐらいの縮尺かで定義されています。 先ほど、「地球全体を一枚の正方形の絵」で表示した縮尺がズームレベル0と定義してあり、ズームレベルが1つ上がるごとに解像度が倍になっていくという仕組みになります。 この解像度が倍になる仕組みこそ、「タイル」が実現するものとなります。 わかりやすいように国土地理院が公開している絵を紹介します。 ![Tile Num](https://maps.gsi.go.jp/help/image/tileNum.png) 上記のようにズームレベルに合わせて解像度が上がっていくようにタイルを生成することで、地図タイルという仕組みが完成します。 もう一つ絵を紹介します。 ![](https://i.imgur.com/cNvZvmS.png) これはタイルがどのような命名規則になっているかを紹介しているプレゼンの一部です。 タイルは通常 `{ズームレベル}/{x 座標}/{y 座標}.{拡張子}` というアクセスになります。 また、X座標、Y座標は左上から始まります。 左上とは「コンピュータの座標」と同じ並びになります。 なお、Y座標を逆にすることで「数学の座標」と同じにすることもでき、そういう仕様もありますが、割愛します。 で、座標は0からスタートします。 これは多くのプログラミング言語で配列は0からカウントするのと同じ考え方です。 基本的にこの仕組みを命名規則に沿って`zxyタイル`という表現をしたりします。 ## 地図タイルが実現するもの 地図タイルという仕組みを使うと以下のものが実現できます。 - ズームイン、ズームアウト - 画面上のスクロール ズームイン、ズームアウトについては前述通り、縮尺が変わるという仕組みですが、このとき重要なのは「必要な部分だけを取り込む」という仕組みです。 例えば、地球全体を見ている時にズームイン、つまり拡大を繰り返していくと地球の一部のみを見る事になります。 そのときに「一部」しか見てないのに「地球全体」は必要無いはずです。 拡大していくと、拡大したところ以外は「いまのところ不必要」です。 タイルという仕組み自体はそれを提供します。 さて、拡大したときに「右の方にスクロールしたい」となったときにどうなるでしょう? であれば、スクロールした先のタイルのみ、つまり今表示している部分から右にあるタイルのみを取得すれば良いという流れになります。 これがタイルが実現する「画面上のスクロール」の仕組みです。 ## 地図タイルの種類 ここまで地図タイル自体の説明をしましたが、地図タイルには用途によっていくつかの種類に分けることができます。 - ラスタタイル - 背景地図、航空写真など - 標高タイルなど - ベクタータイル ### ラスタタイルとは ラスタタイルとは画像形式で配布される地図タイルを指します。 ラスタタイルの特徴としては、画像形式なので多くのクライアントが対応しているという点が上げられます。 #### 背景地図、航空、衛星写真 背景地図は地図の基本となるもので、基本的には「サーバサイドでレンタリングしたものを画像として配布」となります。 例えば[OpenStreetMap.org](https://openstreetmap.org)では標準の地図以外に[CyclMap](https://www.cyclosm.org)、サイクリングマップなどいくつかのレイヤーを提供していますが、いずれもサーバサイドでレンタリングされたものを画像として提供しています。 [地理院地図](https://maps.gsi.go.jp)も標準地図、淡色地図なども同様です。 航空写真は飛行機から、衛星写真は衛星から撮った画像を指します。 最近ではドローンによる空撮もありますが、いずれも画像として提供されます。 背景地図と航空、衛星写真の大きな違いは拡張子です。 背景地図の多くはPNG形式で配布されているのに対して、航空、衛星写真はJPEG形式で配布されています。 #### 標高タイルなど ラスタタイルは画像として出力されたものですが、その中で画像の色を数値として表現しているものがあります。 よく例で上げられるのが標高タイルです。 例えば、MapboxやMapLibreで使われる標高タイルは以下の数式に基づいています。 $$ height = -10000 + ((R * 256 * 256 + G * 256 + B) * 0.1) $$ また、国土地理院が整備している標高タイルは[別の計算式に基づいています](https://maps.gsi.go.jp/development/demtile.html)。 他にも雨量や浸水時の表現など、画像でありながら数値を提供する例はたくさんあります。 ### ベクタータイルとは ベクタータイルとはベクターデータを格納した地図データとして配布される地図タイルを指します。 ベクターデータなので、レンタリング自体はクライアント側で行う必要があります。 そのため、地図の表現するためのスタイルと合わせて利用する必要があります。 ベクタータイルのフォーマットとしては[Mapbox Vector Tile](https://docs.mapbox.com/data/tilesets/guides/vector-tiles-standards/)が現在多く使われています。 スタイルとしてはMapbox Style Specificationが多く使われています。 ただし、Mapboxはプロプライエタリなソフトウェアとなってしまったため、現在ではコミュニティによるforkである[MapLibre Style Specification](https://maplibre.org/maplibre-gl-js-docs/style-spec/)が一般的になっています。 (注1: Mapbox自体はソースコードは公開されているもののライセンスがプロプライエタリなものになっているのと、Mapbox Style Specification自体が独自の実装が追加されているため、互換性が無くなってきています) (注2: 個人的にはMapboxはもう追わなくなってしまったので、何が追加されてるかなどは正直知らないという立場を取っています。) ベクタータイルとスタイルの関係はHTMLとCSSに似ています。 データそのものを提供するのがHTMLで、CSSでデザインを行ってWebsiteが成り立ってるのと同じような仕組みと考えてください。 ## タイルの大きさ タイル自体は解像度が上がっても同じ大きさのタイルを配信するのが基本です。 ラスタタイルでは縦256px横256pxのファイルが基本となります。 ただし、512pxにしたいという場合は`{z}/{x}/{y}@2x.{ext}`という風にretinaディスプレイ向けのアクセスと同じ仕組みを使います。 しかしながら、256pxが基本的で、`@2x`はあまり提供しているところは無いと思われます。 Mapbox Vector Tileでは大きさはベクターデータによって変わります(extentされる)。 そのため、決まった大きさはemptyの場合だけですが、データを詰め込みすぎるとファイルが大きくなるため、Mapbox Vector Tileを作るプログラムにはだいたいファイルを大きさでアラートを出したりとか、処理を停止するなどの仕組みが入っています。 ### ラスタタイルとベクタータイルの大きさの違い ラスタタイルとベクタータイルはファイルの大きさに多くの違いがあります。 ラスタタイルはズームレベルが上がってもファイルの大きさはある程度一定です。 それに対して、ベクタータイルはズームレベルごとに地物の配置を決める事ができるため、タイルの作成方法によっては極端にファイルが大きくなる事があります。 例えば、1タイルに2MBのデータを入れるとします。 そんなデータがたくさんあっても困りますが、これがスタイルとの組み合わせを使う事でうまく回すことができます。 上記の2MBのタイルがズームレベル10のもので、スタイル自体はズームレベルに関係なく使う事ができます。 つまり、ズームレベル17などで表示をしている場合では、かなりの範囲がズームレベル10のものでまかなえるため、1タイルで多くの領域をカバーする事ができ、結果としてファイルの転送量がラスタタイルに比べて小さくなるという事がよく起きるという事になります。 # まとめ 数年ぶりにタイルについて改めてまとめてみました。 タイルは仕組みを知るだけでだいぶ面白いものとなります。 是非、地理院地図を眺めながらHTTPリクエストを見てニヤニヤしてみてください。