ArcGISベクトルタイルサーバを観察する

# はじめに
ArcGIS Onlineからベクトルタイルを配信したいのですが、まずは同じような環境であると考えられるArcGISサーバのベクトルタイルを観察して、どのように表示されているのかを見てみます。[こちらの記事](https://qiita.com/T-ubu/items/6360252ece6c792732c7)を参考にさせていただいています。記事にする必要がないかもしれませんが、自身で整理するとより理解が深まるため、このように記載しています。

# 環境
Google chromeバージョン: 131.0.6778.265

# ArcGIS Server と ArcGIS Online 
上記２つが何なのかよく分からなかったので、調べました。
ArcGIS Serverは ArcGIS Enterprise に含まれます。ArcGIS Enterpriseはでオンプレミスまたはプライベートクラウド向けで、ArcGIS OnlineはクラウドベースのSaaS (Software-as-a-service)です。
[Esriページ](https://enterprise.arcgis.com/ja/portal/latest/administer/linux/choosing-between-an-arcgis-online-subscription-and-portal-for-arcgis.htm)に説明があります。

参照記事には[Arcgis.comのVector Basemaps](https://www.arcgis.com/home/group.html?id=30de8da907d240a0bccd5ad3ff25ef4a#overview)はArcGISサーバーからのベクトルタイルであることが記載されていますが、それがArcGISサーバのベクトルタイルなのか、ArcGIS Onlineのベクトルタイルなのかはよく分かりませんでした。

# ベクトルタイルのソースについて
参照記事に記載の通り、[Arcgis.comのVector Basemaps](https://www.arcgis.com/home/group.html?id=30de8da907d240a0bccd5ad3ff25ef4a#overview)には、大まかにOSM(OpenStreetMap)起源のものとEsriさん作成起源のものがあるようです。

### [OSM起源](https://www.arcgis.com/home/item.html?id=3e1a00aeae81496587988075fe529f71)
・https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/
Map data © OpenStreetMap contributors, Microsoft, Facebook, Google, Esri Community Maps contributors, Map layer by Esri

### [Esriさん起源](https://www.arcgis.com/home/item.html?id=6d188135dc814d4ea254440a3dd844df)
・https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer
Sources: Esri, TomTom, Garmin, FAO, NOAA, USGS, © OpenStreetMap contributors, and the GIS User Community

上記URLを見ると以下のような記載があります。
  "capabilities": "TilesOnly,Tilemap",
  "type": "indexedVector",
  "tileMap": "tilemap",
この書き方を踏襲すれば、ArcGIS Onlineでベクトルタイルを表示出来そうです。


### タイルのURL
VectorTileServerに「/tile/\<level>/\<row>/\<column>.pbf」を追加すると、ベクトルタイルのURLとなります。[Esriドキュメント](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile/)に記載のある通りです。
例としては以下です。
https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tile/5/12/28.pbf

:::note info
[coesite3](https://github.com/unvt/coesite3/blob/main/routes/esriIF.js)では、/tile/を含むパスは利用されていません。 index.jsonの"tiles"で定義されています。
[こちらの記事](https://qiita.com/k96mz/items/4afa683a7fe3b293bafd)では、/tile/を含むパスが利用されており、ContentのNew itemから保存することなどが出来ています。
:::

### スタイル
VectorTileServerに「resources/styles/root.json」を追加すると、スタイルのURLとなります。[Esriドキュメント](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-style/)に記載のある通りです。「style」ではなく、「styles」であることに注意が必要です。
例としては以下です。
https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/resources/styles/root.json

spriteとglyphs（フォント）は以下のようにスタイルファイルの中に記載されています。
	"sprite" : "../sprites/sprite",
	"glyphs" : "../fonts/{fontstack}/{range}.pbf",


# Map Viewerでの観察
上記で見たOSM起源の地図をMap Viewerを使用して[こちら](https://www.arcgis.com/apps/mapviewer/index.html?layers=3e1a00aeae81496587988075fe529f71)から見てみます。

参照しているデータは、背景地図にあるラスタタイル関連を除くと、ベクトルタイル(x.pbf)、フォント（6144-6399.pbfなど）、tilemap(32?f=json)です。

それぞれのキャプチャは以下のとおりです。

ベクトルタイル
![スクリーンショット 2025-01-15 17.16.51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/c67f620c-6951-7d73-8d22-fe2f7ad7a458.jpeg)

フォント
![スクリーンショット 2025-01-15 17.17.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/1b69daab-8b93-be60-c4d4-f987249aa782.jpeg)

tilemap
![スクリーンショット 2025-01-15 17.18.38.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/6eae9aca-f3c7-f6d2-517e-e7708de22ffd.jpeg)


tilemapはあるズームレベルでタイルの有無を確認するために使用され、不必要な通信をなくしパフォーマンスを向上させます。

## [Esriの説明](https://developers.arcgis.com/rest/services-reference/enterprise/tile-map/)（tilemap)

### リクエスト

・以下の形式がリクエスト時に使用されます。

```
https://map-image-vectorservice-url>/tilemap/<level>/<row>/<column>/<width>/<height>
```
それぞれ以下を示します。
level：ズームレベル
row, column：左上のタイル位置
width, height：リクエストされたエリアのサイズ

・リクエストパラメータ
f：レスポンスフォーマットをhtml or jsonで指定します。デフォルトはhtmlです。ArcGIS onlineではjsonを指定しています。

tilemapのリクエストURL例は以下の通りです。
https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tilemap/2/0/0/32/32?f=json

### レスポンス

・レスポンスプロパティ
レスポンスのtopとleftの座標は、リクエストのrowとcolumnに必ず一致します。

レスポンス例は以下のとおりです。
```json
{
	 "adjusted": false,
	 "location": {
		  "left": 0,
		  "top": 0,
		  "width": 32,
		  "height": 32
	 },
	 "data": [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,…]
}
```

adjusted：リクエストした領域がバンドル（小さなブロック）の境界を跨ぐ場合には、trueとなります。基本はfalseだと思います。

left、top：左上のタイル位置（バンドル内での位置ということだと思います。ズームレベル６以上だと0以外が現れます。top、leftの順番にした方が、リクエストのrow, columnの順番と整合します。

width、height：レスポンスされたエリアのサイズですが、リクエストのサイズと異なることもあるようです。しかし、実際は32しか見たことありません。

data：配列のサイズはwidth * height(32 * 32 = 1024)です。データがあれば1、なければ0が格納されます。

リクエストされたバンドルがない、もしくは対応するズームレベルでない場合は、以下のとおり422を返します。
```json
{
  "error": {
    "code": 422,
    "message": "No tile available for the specified boundary.",
    "details": null
  }
}
```

## 観察結果

リクエストのwidth, height、レスポンスのwidth、heightは、ズームレベルに関わらず常に32です。

・ズームレベル0~5まで
リクエストのrow, column、レスポンスのtop、leftは常に0です。

・ズームレベル6
リクエストのrow, columnとそれに対応するレスポンスのtop、leftは以下の４つです。つまりtilemapファイルは４つあります。
・row:0, column:0   //  top:0, left:0
・row:32, column:0  //  top:32, left:0
・row:0, column:32  //  top:0, left:32
・row:32, column:32  //  top:32, left:32

分かりづらいですが、リクエストのrowがレスポンスのtopに、リクエストのcolumnがレスポンスのleftに対応します。

例えば、リクエストが以下だとします。
https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tilemap/6/0/32/32/32?f=json

その場合のレスポンスは以下です。
top: 0, left: 32, width: 32, height: 32


・ズームレベル7
同様に考えてズームレベル7ではタイルマップファイルは16個あります。
以下が例です。
https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tilemap/7/32/96/32/32?f=json


各ズームレベルにおけるタイル数とtilemap数（8以降は省略）


| ズームレベル       | 0  | 1  | 2  | 3   | 4   | 5    | 6    | 7     | ...  |
|:---------------:|:--:|:--:|:--:|:---:|:---:|:----:|:----:|:-----:| :-----:|
| 横方向タイル数     | 1  | 2  | 4  | 8   | 16  | 32   | 64   | 128   | ... |
| 全体タイル数       | 1  | 4  | 16 | 64  | 256 | 1024 | 4096 | 16384 | ... |
| tilemapファイル数| 1  | 1  | 1 | 1  | 1 | 1 | 4 | 16 | ... |
| tilemapのdata数| 1024 | 1024 | 1024 | 1024 | 1024 | 1024 | 4096 | 16384 | ... |


ズームレベル0~4までは、全体タイル数が1024より小さいにも関わらず、「tilemapのdata数」で32×32 = 1024の区画を指定しています。最初は、ひとつのタイルに対して複数のtilemapの値が割り当てられているかと思っていました。しかしそうではなく、tilemapの一つの大きさは一つのタイルの大きさと等しく、例えばズームレベル0のときは、その横方向と縦方向に、さらに31個のtilemapがはみ出しているイメージなのではないかと思います。
ズームレベル5以降は、ひとつにタイルに対して一つのtilemapのdata値が対応しており、タイルが存在するかどうかを示します。

リクエストのrow, columnと、対応するレスポンスのtop、leftは、ズームレベル6以降は常に32の倍数を取ります。tilemapが左上にあるときは0となるイメージです。

・ズームレベル15
ズームレベル15のリクエスト例です。
https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tilemap/15/12896/29088/32/32?f=json

この場合は、以下のレスポンスが返ります。
top: 12896, left: 29088, width: 32, height: 32


・ズームレベル16
ズームレベル16のリクエスト例です。dataの値である0と1が不規則に並んでいることが分かります。
https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tilemap/16/25792/58176/32/32?f=json

この場合は、以下のレスポンスが返ります。
top: 25792, left: 58176, width: 32, height: 32

参照記事ではズームレベル16だと422が返ってくるとありましたが、実際はきちんとレスポンスが返ってきました。OSMだと返ってくるのかもしれないと考え、Esriさん起源のベクトルタイルについても調べたところ、こちらもズームレベル16でもきちんとレスポンスが返ってきました。

参照記事ではズームレベル16の場合では、ズームレベル15のベクトルタイルが返ってくるとありましたが、私が確認したところ、ズームレベル16のベクトルタイルが返ってきました。


# まとめ
ArcGISベクトルタイルサーバーで使用されているベクトルタイルの動きを観察しました。tilemapの動きが興味深いです。オーバーズーミングについては、引き続き勉強していきます。

# Reference
https://qiita.com/T-ubu/items/6360252ece6c792732c7

https://developers.arcgis.com/rest/services-reference/enterprise/tile-map/