ArcGISベクトルタイルサーバーのベクトルタイルはどう使われているか（特にtilemapの反応について）

こんにちは。
この記事は、**ベクトルタイルの[アドベントカレンダー（2021）](https://qiita.com/advent-calendar/2021/vt)の5日目（12月5日）**の記事として書きました。11月下旬にカレンダーの空いている枠をいただきました。今にして思うと、3日目に続けての高頻度での投稿となってしまい申し訳ありませんがよろしくお願いします。

この記事の背景にある動機は、「自分で作ったベクトルタイル（あるいは地理院地図Vector（仮称）のようなものも）をArcGISオンラインでも使えるようにしたい」というものでした。特に、ArcGISではベクトルタイルのオーバーズーミングの仕組みが他のライブラリと少し違うようなので、オーバーズーミングを実現したいなぁと思いながら、まず観察から始めようということで書いた記事になります。

ちょうど昨日、ベクトルタイルの[アドベントカレンダー（2021）](https://qiita.com/advent-calendar/2021/vt) の 4 日目の記事で、@freedom-tech さんがベクトルタイルに対応しているプラットフォームを紹介してくれました。大変参考になりました。いろいろなプラットフォームでのベクトルタイルの消費方法を理解して、可能な限り、多くのプラットフォームで使ってもらえるような形でベクトルタイルを提供したいものだと個人的には考えています。


## はじめに
ArcGISサーバーからのベクトルタイルを、ArcGIS Onlieと同じ方法を使っていると思われるMap Viewでどのように消費しているのか観察してみました。具体的には、ウェブブラウザ（Google Chrome）で[Arcgis.comのVector Basemaps](https://www.arcgis.com/home/group.html?id=30de8da907d240a0bccd5ad3ff25ef4a#overview)のページを見てみました。これらのコンテンツは[Living Atlas](https://enterprise.arcgis.com/ja/portal/latest/use/what-is-living-atlas.htm)というesri社の提供する地図サービスに含まれているようで、ウェブブラウザでどのような地図なのか見ることができますから、ベクトルタイルの消費の様子を知ることができます。

#### 想定する対象読者とおことわり
この記事は、ArcGIS Onlineでどのようにベクトルタイルが消費されているのかを考えるためのメモとして作成しました。MapLibreやmapboxのベクトルタイルの消費方法と、ArcGIS Onlineでのベクトルタイル消費方法の違いや共通点を考えたい方の参考です。
なお、本記事でのtilemapはArcGIS REST APIのtilemapを指しており、ほかのところで使われているTilemapサービスのようなものではありません。

## 環境
Google Chrome (96.0.4664.45)


## ベクトルタイルのソースについて
[Arcgis.comのVector Basemaps](https://www.arcgis.com/home/group.html?id=30de8da907d240a0bccd5ad3ff25ef4a#overview)で、最近のコンテンツ（ベクトルタイル）を中心にみてみたところ、だいたい以下の2種類のベクトルタイルサーバーからのベクトルタイルを使っているようです。OSM起源のものと、esriさんの作成されたベースマップの２つがあるというイメージで理解しました。

* [https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer](https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer)
Map data (c) OpenStreetMap contributors, Microsoft, Esri Community Maps contributors, Map layer by Esri

* [https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer](https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer)
Sources: Esri, HERE, Garmin, FAO, NOAA, USGS, © OpenStreetMap contributors, and the GIS User Community

上記のURLを見てみると、両方とも空間参照系はウェブメルカトル図法（タイルだから当然ですね）、LODs（Level of detail）は0から22までとなっていて、minLODは0、maxLODは16です。

##### タイルのURL
VectorTileServerのアドレスに tile/{z}/{y}/{x}.pbf を足すとタイルのURLになります（[ArcGIS REST API](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile.htm)に書いてあるとおり）。
例えば　https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tile/1/0/0.pbf　

##### デフォルトのスタイル
デフォルトのstyleはVectorTileServerのアドレスに、resources/styles/root.jsonを足すとみられます（[ArcGIS REST API](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile.htm)に書いてあるとおり）。
例えば　https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/resources/styles/root.json

##### その他（sprite, glyphs）
そのほか、VectorTileServerのresourcesフォルダの中には、sprite（地図記号など）やglyphs（テキストフォント）が入っている場合もあります。


## Map Viewerでの観察結果
上記のなかの一つのコンテンツをウェブページで提供されているMap Viewerで見てみました。なんでもよいのですが、World_Basemap_v2のベクトルタイルを使っている[National Geographic Style (Local Language)](https://www.arcgis.com/home/item.html?id=684018c92e9b424ca8e900da8dad8b23)を見てみました。（コンテンツのページから、Map Viewerで開くをクリックします。）

(ArcGIS Onlineでも観察しましたが、見たところ同じようにベクトルタイルを消費していました。オープンな環境のものの方が書きやすいのでMap Viewerでの観察結果を報告します。)

#### 観察結果：　参照していたデータ
Google chromeでf12を押してnetworkの状況を見てみました。
ベクトルタイル（x.pbf）、テキストのフォント（0-255.pbf）、ラスタタイル（x 画像ファイル）、tilemapなどを見ています。（ベクトルタイルを見たつもりでしたが、Map Viewerではラスタタイルも参照していました。おそらく背景にある地図だと思います。）
![2021-11-22-esri-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/f80574e2-df8e-18ff-1fbc-aeec9a6c511f.png)
（↑ 図中のパスは読んだベクトルタイル）

![2021-11-22-esri-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/439f91d3-5842-43e7-507f-6c1ba0b7acf4.png)
（↑ 図中のパスは読んだtilemap）

なお、今回のタイルはLiving Atlasなので技術的にはアクセス制限はないようでしたが（注：データ利用のポリシーは別）、VectorTileServerでアクセス制限をかける場合はtokenを付けてURLを指定するようになっていたように思います。

#### 観察結果：　tilemapの働きについて
ベクトルタイル、テキストフォント、地図記号などを消費するのは他のライブラリで描いた地図も同じです。今回の観察での発見ですが、Map Viewerではtilemapも参照していることもわかります。アクセスしているファイルのうち、32?f=jsonというファイル名のものがたくさんありますが、これらは特定の場所のタイルの有無を確認するためのtilemapです。Arc GIS REST APIにある[tile mapの説明](https://developers.arcgis.com/rest/services-reference/enterprise/tile-map.htm)によれば、~~ズームレベル、leftの位置、top位置、width、heightの順~~ **ズームレベル、top位置、leftの位置、width、heightの順**でパスを指定してtilemapを得ることになっています。（注:2022.1.7順番の間違いを直しました。REST APIに書いてあるrowとcolumnはそれぞれ、topの位置とleftの位置と理解すべきでした。see below;D）。
![2022-01-07-tilemap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/86203257-b262-6c6d-e4bc-f10e46c0e3be.png)

tilemapのURLを実際にみてみると、当該の区画におけるタイルの有無がわかります。今回の観察での一番の収穫は以下の点でした。

* 発見1： ファイル名がいつも32という理由を少し考えたのですが、Map Viewerの中では、いつでも32×32のタイル範囲のtilemapを参照しているということのようです。面白いのは縦横に32もタイルが並んでいないズームレベル（ZL0-4）でも32×32の区画を指定していました。（柱：これはArcGIS Onlineでも同じでした。）

* 発見2： tilemapで参照している leftの位置、topの位置についても、32の倍数になっていることを観察しました。ZL5までは一つのtilemapなので 0と 0 でよさそうですが、ZL6からは32×32のタイルごとのtilemapを参照しているということのようです。（ArcGIS REST APIでは任意のleft, top, 範囲についてtilemapを返せるようになっていますが、実装では32×32の範囲を中心に考えればよいようです。）

表：参照されているであろうtilemapの数（ズームレベルごと）

|ZL0 | ZL1 | ZL2 | ZL3 | ZL4 | ZL5 | ZL6 | ZL7 | ZL8 | ZL9 | ZL10 | ZL11 | ... |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 1 | 1 | 4 | 16 | 64 | 256 | 1024 | 4096 | ... |


* また、tile mapは、そのバンドル（範囲）又はレベル（ズームレベル）が存在しないときはエラーコード422を返すことになっています。どこで変わるかなとおもってみたら、実験的にチェックしていた地域（15/12328/18016/10/10　と 16/24656/36032/40/40）ではZL15まではtilemapが返ってきてZL16で422が返ってきました（地物がない地域だともっと小さなZLでも422が返ってきます）。ベクトルタイルサービス概要では、MaxLODは16となっているので、どこかZL16までタイルを提供している地区があるのかもしれません。
例：
https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/tilemap/15/12328/18016/10/10?f=json
https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/tilemap/16/24656/36032/40/40?f=json

* 前述の地区において、ZL16やそれより大きい縮尺でも、tilemapを参照したあと（エラー422を得る）、ZL15のタイルを参照していたので、tilemapがデータの有無を教え、オーバーズーミングに重要な役割を果たしているのだろうなと想像します。tilemapはVectorTileServerのうちで必須の機能ではないですが、これがあることでオーバーズーミングができるようになるのではないかと考えています。

![2021-11-22-esri-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/9067bb1f-b794-07ab-0a72-cc97bae0c1b8.png)
（図の説明） tilemapではZ16のパスを参照しているが、その下のベクトルタイル(pbf)は18016となっており、ZL15であることがわかる（36032の半分）。



32×32の区画なら少しはわかりやすいのですが、全体のタイルマップを見ると量が多すぎて意味が分からないので、これを理解するまでもう少し慣れていきたいです。
https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/tilemap

## まとめ
今回の観察では、特にtilemapの反応について観察して以下のような発見がありました。これらは、今後オーバーズーミングに挑戦していく際の参考になりました。

 * ArcGSI Online (又はMap View)では、tilemapを使ってオーバーズーミングを実現している。
 * tilemapのAPIは任意の位置と範囲についてjsonを返すことができるが、実際の実装では特定の位置（32の倍数）と範囲（32×32）のjsonを使っている。

##　謝辞
今回の観察にあたっては、esriさんのLiving Atlasに掲載されているベクトルタイルを見させていただきました。感謝します。

##　References
[Arcgis.comのVector Basemaps](https://www.arcgis.com/home/group.html?id=30de8da907d240a0bccd5ad3ff25ef4a#overview)
[ArcGIS REST API (vector tile)](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-service.htm)
[National Geographic Style (Local Language)](https://www.arcgis.com/home/item.html?id=684018c92e9b424ca8e900da8dad8b23)