ArcGIS Onlineで外部のベクトルタイルを表示する

# はじめに
本記事では、ArcGIS onlineのMap viewer classic及びMap viewer において、外部にて作成したベクトルタイルを表示したいと思います。
[こちらの記事](https://qiita.com/T-ubu/items/ac4c1aef293e4b253111)を参考にさせていただいています。

# 使用した素材

使用するベクトルタイルとスタイルは[こちらの記事](https://qiita.com/k96mz/items/318e915097bfbaa435b9)で作成したものです。

![スクリーンショット 2025-01-14 14.48.19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/944240a6-47a4-3821-45b6-a18e9846e445.jpeg)

以前に作成した地図は[こちら](https://k96mz.github.io/20240830symbol/index.html)から見られます。

# 参考記事の解説

参照記事において、さらに参考とされている記事は[こちら](https://support.woolpert.io/hc/en-us/articles/360047005294-Vector-Tiles-on-Google-Cloud-Storage-Web-Clients)です。

概要は以下のとおりです。
・VectorTileServerというフォルダの下にタイル情報を記載したindex.jsonを置くこと
・スタイルファイルはMapboxの仕様に従い、
/VectorTileServer/resources/styles/root.jsonに置かれる必要があること
・ArcGIS Online (AGOL)もしくは Portal に"tile layer"として登録すること。[こちら](https://woolpertinc.maps.arcgis.com/home/item.html?id=616e74fda7c64fe28dbace32c43d5d6b)が例です。
・Esriの標準ベースマップと該当ベクトルタイルレイヤを組み合わせたWeb地図も作成できること。[こちら](https://woolpertinc.maps.arcgis.com/home/item.html?id=740f61767a1e4e7bb66c68b244192a8b)が例です。
・ArcGIS Online (AGOL)に"tile layer"を登録する方法は、new web mapをクリックし、「Add > Add Layer from Web」として、「ArcGIS Server Web Service」を選び、URLにVectorTileServerフォルダのURLを記載する。
・ArcGIS Online (AGOL)に"tile layer"をitemとして追加するためには、Save Layerとする。
・ArcGIS Online (AGOL)にベクトルタイルレイヤをitemとして直接加えることは出来ない。なぜなら、GeoServices REST API specに不備があるから。
・tile layer　と web map のitemがコンテンツセクションに表示される。（Web mapも作成出来るとのことですが、私が試したところできませんでした。なぜだか不明です。）

# ArcGIS REST API（ArcGIS ServerのAPI）
ArcGIS Online (AGOL)はベクトルタイルをそのまま参照出来ないため、ArcGIS REST APIを使用する必要があります。後述されるように、ArcGIS Onlineは、ArcGIS Server でホストされたサービスと通信します。

VectorTileServerを返すサーバを作成します。

関連する文書の概要以下のとおりです。

### [Vector Tile Service](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-service/)

VectorTileServerの下にindex.jsonを置きます。タイル情報、空間参照、範囲などを記載します。

### [Vector Tile](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile/)

URLは以下の通りです。
VectorTileServer/tile/\<level>/\<row>/\<column>.pbf
levelはz、rowはx（東方向）、columnはy（南方向）に対応します。
タイルが見つからない場合は、404 (Not found)を返します。

:::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から保存することなどが出来ています。
:::

### [Vector Tile Style](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-style/)

VectorTileServer/resources/styleにファイルを置きます。Mapbox version8のスタイルを返します。sprite と glyphs(フォント)の相対パスを含むとありますが、絶対パスでも大丈夫なようです。

### [Vector Tile Font](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-font/)

以下にフォントファイルを置きます。
VectorTileServer/resources/fonts/\<fontstack>/\<range>.pbf
実際にはstyleファイルでパスを定義しているのだと思います。

### [Vector Tile Sprite](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-sprite/)

以下にspriteファイルを置きます。
VectorTileServer/resources/sprites/sprite.json
こちらも実際にはstyleファイルでパスを定義しているのだと思います。

### [Vector Tile Resource Info](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-resource-info/)

VectorTileServer/resources/info
でリソースの場所を返します。参照ページではfontとspriteのパスをリストしていますが、なくても良いようです。

### [Vector Tilemap](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tilemap/)

サーバに存在しないタイルのリクエストを避けるためのものです。
[\<node>,\<node>,\<node>,\<node>]の形式で順序は NW, NE, SW, SE  です。
•1: 子ノードを持たないタイル（リーフタイルと呼ばれる）。
•0: タイルが存在しない
•2: 異なるインデックスファイルで定義されたサブツリー（インデックスが大きくなりすぎるのを防ぐため）。
2は良く分かりません。

{"index":[[1,0,1,1],0,0,0]}
これはLOD1を表します。
[1,0,1,1]が北西(NW)、その他の0はNE, SW, SEを表します。
[1,0,1,1]はLOD2の北西 (NW)、北東 (NE)、南西 (SW)、南東 (SE) を表します。

この情報により、クライアントは存在しないタイル（０のノード）をリクエストせず、無駄なデータ転送を回避できます。


# コードの解説
[こちらのコード](https://github.com/ubukawa/VTtest3/tree/main)を参考にさせていただいています。自身で修正したコードは[こちら](https://github.com/k96mz/20250114VTtest3)です。また、重要なファイルは以下の2つです。

## index.json
[Esriのページ](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-service/)に記載がある通り、「VectorTileServer」のパスにファイルを置きます。タイル情報、空間参照、範囲などを記載します。

```json: index.json
{
  "currentVersion": 10.9,
  "name": "VT Test 3",
  "capabilities": "TilesOnly",
  "copyrightText": "SymbolタイプのMaputnikでの表示",
  "type": "indexedFlat",
  "defaultStyles": "resources/styles",
  "tiles": [
    "https://k96mz.github.io/20240830symbol/Data/VTpractice/{z}/{x}/{y}.pbf"
  ],
  "exportTilesAllowed": false,
  "initialExtent": {
    "xmin": -2.0037507842788246e7,
    "ymin": -2.0037508342787e7,
    "xmax": 2.0037507842788246e7,
    "ymax": 2.0037508342787e7,
    "spatialReference": {
      "wkid": 102100,
      "latestWkid": 3857
    }
  },
  "fullExtent": {
    "xmin": -2.0037507842788246e7,
    "ymin": -2.0037508342787e7,
    "xmax": 2.0037507842788246e7,
    "ymax": 2.0037508342787e7,
    "spatialReference": {
      "wkid": 102100,
      "latestWkid": 3857
    }
  },
  "minScale": 2.958287637957775e8,
  "maxScale": 4513.9887055,
  "tileInfo": {
    "rows": 512,
    "cols": 512,
    "dpi": 96,
    "format": "pbf",
    "origin": {
      "x": -2.0037508342787e7,
      "y": 2.0037508342787e7
    },
    "spatialReference": {
      "wkid": 102100,
      "latestWkid": 3857
    },
    "lods": [
      {
        "level": 0,
        "resolution": 78271.516964,
        "scale": 2.958287637957775e8
      },
      {
        "level": 1,
        "resolution": 39135.75848199995,
        "scale": 1.479143818978885e8
      },
      {
        "level": 2,
        "resolution": 19567.87924100005,
        "scale": 7.39571909489445e7
      },
      {
        "level": 3,
        "resolution": 9783.93962049995,
        "scale": 3.6978595474472e7
      },
      {
        "level": 4,
        "resolution": 4891.96981024998,
        "scale": 1.8489297737236e7
      },
      {
        "level": 5,
        "resolution": 2445.98490512499,
        "scale": 9244648.868618
      },
      {
        "level": 6,
        "resolution": 1222.992452562495,
        "scale": 4622324.434309
      },
      {
        "level": 7,
        "resolution": 611.496226281245,
        "scale": 2311162.2171545
      },
      {
        "level": 8,
        "resolution": 305.74811314069,
        "scale": 1155581.1085775
      },
      {
        "level": 9,
        "resolution": 152.874056570279,
        "scale": 577790.5542885
      },
      {
        "level": 10,
        "resolution": 76.4370282852055,
        "scale": 288895.2771445
      },
      {
        "level": 11,
        "resolution": 38.2185141425366,
        "scale": 144447.638572
      },
      {
        "level": 12,
        "resolution": 19.1092570712683,
        "scale": 72223.819286
      },
      {
        "level": 13,
        "resolution": 9.55462853563415,
        "scale": 36111.909643
      },
      {
        "level": 14,
        "resolution": 4.777314267817075,
        "scale": 18055.9548215
      },
      {
        "level": 15,
        "resolution": 2.388657133974685,
        "scale": 9027.977411
      },
      {
        "level": 16,
        "resolution": 1.19432856698734,
        "scale": 4513.9887055
      }
    ]
  },
  "maxzoom": 16,
  "resourceInfo": {
    "styleVersion": 8,
    "tileCompression": "gzip",
    "cacheInfo": {
      "storageInfo": {
        "packetSize": 128,
        "storageFormat": "compactV2"
      }
    }
  },
  "minLOD": 0,
  "maxLOD": 5,
  "maxExportTilesCount": 100000,
  "supportedExtensions": ""
}
```

:::note info
・  "currentVersion": 10.9,
このバージョンはArcGIS Serverのバージョンです。10.4 のリリースで、初めて「ベクター タイル サービスを公開する機能」が含まれるようになりました。
[こちらのサイト](https://support.esri.com/ja-jp/products/arcgis-enterprise/life-cycle?utm_source=chatgpt.com)にバージョンに関する記載があります。ArcGIS Serverのバージョンが11以上だとArcGIS Onlineと完全な互換性を持つそうです。Map viewerでうまく表示が出来ないときはこのバージョンを上げるとうまくいくかもしれません。
:::


・  "type": "indexedFlat",
"indexedVector" と "indexedFlat" は、ベクタタイルデータの構造と配信方法に関連する設定を示しています。chatGPTによると違いは以下のとおりです。

![スクリーンショット 2025-01-15 10.57.45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/b06c2e0f-92ad-0e65-a58a-40d421b2dafd.jpeg)

:::note info
これを見ると、indexedVectorの方が良さそうに見えるので、今後はそのように設定してもいいかもしれません。
:::

出来たファイルはGitHubにアップして、GitHubページから公開しました。以下のどのURLにアクセスしても同じファイルがみられます。

https://k96mz.github.io/20250114VTtest3/VectorTileServer/index.json
https://k96mz.github.io/20250114VTtest3/VectorTileServer
https://k96mz.github.io/20250114VTtest3/VectorTileServer?f=pjson
https://k96mz.github.io/20250114VTtest3/VectorTileServer?f=json

## root.json
こちらも[Esriのページ](https://developers.arcgis.com/rest/services-reference/enterprise/vector-tile-style/)に記載がある通り、「VectorTileServer/resources/styles」のパスにファイルを置きます（Esriページではstyleとなっていますが、stylesとしています）。Mapbox version8のスタイルを返します。 sprite と glyphs の情報も含みます。

```json: root.json
{
  "version": 8,
  "name": "Empty Style",
  "metadata": { "maputnik:renderer": "mlgljs" },
  "sources": {
    "v": {
      "type": "vector",
      "url": "https://k96mz.github.io/20250114VTtest3/VectorTileServer",
      "minzoom": 0,
      "maxzoom": 3
    }
  },
  "sprite": "https://k96mz.github.io/20240830symbol/sprite/sprite",
  "glyphs": "https://k96mz.github.io/20240830symbol/font/{fontstack}/{range}.pbf",
  "layers": [
    {
      "id": "bg",
      "type": "background",
      "maxzoom": 3,
      "paint": { "background-color": "rgba(147, 154, 255, 1)" }
    },
    {
      "id": "landmass",
      "type": "fill",
      "source": "v",
      "source-layer": "landmass",
      "maxzoom": 3,
      "paint": { "fill-color": "rgba(137, 243, 195, 1)" }
    },
    {
      "id": "coastl",
      "type": "line",
      "source": "v",
      "source-layer": "coastl",
      "maxzoom": 3
    },
    {
      "id": "bndl",
      "type": "line",
      "source": "v",
      "source-layer": "bndl",
      "maxzoom": 3
    },
    {
      "id": "popp",
      "type": "circle",
      "source": "v",
      "source-layer": "popp",
      "maxzoom": 3,
      "paint": { "circle-color": "rgba(203, 140, 140, 1)" }
    },
    {
      "id": "loc",
      "type": "symbol",
      "source": "v",
      "source-layer": "loc",
      "maxzoom": 3,
      "layout": {
        "icon-image": "public_building",
        "text-field": "{name}",
        "text-font": ["sans"]
      }
    }
  ],
  "_ssl": true
}

```

"sources"の中の"url"には、index.jsonを返すエンドポイントを記載します。
"https://k96mz.github.io/20250114VTtest3/VectorTileServer"
最後にスラッシュがあるとエラーが出るそうなので、なくしています

sslの記載は標準的な Mapbox Style Specification や MapLibre GL JS の仕様には含まれていないカスタム設定です。そのため、必要かどうか不明です。削除してもいいかもしれません。


# ArcGIS Onlineで読み込む

該当コードを自身のGithubにアップロードします。
職場のアカウントで、ArgGIS Onlineを開き確認します。

## Map viewer classic
Map viewer classicで、以下のURLを入力します。
 https://k96mz.github.io/20250114VTtest3/VectorTileServer

以下の通り、レイヤが読み込まれています。

![スクリーンショット 2025-01-15 13.10.37.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/c6bc505f-13d3-c83b-b41d-f28b702b53bb.jpeg)

レイヤを保存します。
そうすると、以下のように追加したレイヤのページを表示することが出来ます。

![スクリーンショット 2025-01-15 13.14.36.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/f90c93fc-d916-4d02-5e2f-368348f8cb6c.jpeg)


上記画像では見えませんが、右下の方のURLには、先程指定したURLが表示されます。
https://k96mz.github.io/20250114VTtest3/VectorTileServer/

右上のOpen in Map Viewerをクリックすると、Map Viewerでも地図が以下のように見られました。


![スクリーンショット 2025-01-15 13.18.50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3684675/aeac6558-2ba8-43b6-e5dc-40b8a2454ec5.jpeg)

# まとめ
本記事では、ArcGIS onlineのMap viewer classic及びMap viewer において、外部にて作成したベクトルタイルを表示する方法を記載しました。tilemapの構成等まだまだ分かっていない部分があるので、今後勉強していきます。

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

https://qiita.com/k96mz/items/318e915097bfbaa435b9

https://support.woolpert.io/hc/en-us/articles/360047005294-Vector-Tiles-on-Google-Cloud-Storage-Web-Clients

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