国土地理院のベクトルタイルから道路中心線をぶっこ抜いた話

## はじめに
![スクリーンショット 2020-02-11 15.32.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73197/8b36b48a-fc5e-4a2e-b8b0-75921b875ad7.png)

国土地理院は、2019年7月から「ベクトルタイル提供実験」を実施しています。
[gsi-cyberjapan/gsimaps-vector-experiment](https://github.com/gsi-cyberjapan/gsimaps-vector-experiment)

[地理院地図Vector](https://maps.gsi.go.jp/vector/)でのデータ配信が本旨でしょうが、自分のサイトのMapbox GL JSに表示してみたいなんて気持ちになったりもします。また、地理院のベクトルタイルには「道路中心線」データが含まれており、これは今までオープンデータになった事はないはずです（確か有償提供）。じゃあその道路中心線、ゲットしたいな、という事で本記事ではその過程を示します。

なお本記事ではベクトルタイルとはなんぞや、という説明は省きます。

## 目標
以下の画像のようにQGISで地理院ベクトルタイルを表示する事を目標とします。
こうなれば外部ファイルへの出力など、煮るなり焼くなり好きに出来ますね。
![スクリーンショット 2020-02-11 16.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73197/3c49682e-b256-1a10-2afa-82d2998de9c8.png)

## ベクトルタイル提供実験
データの使用条件などは以下のとおりです。
> 提供の位置づけ
国土地理院ベクトルタイル提供実験におけるデータの提供の位置づけは次のとおりです。
本提供実験は、ベクトルタイル提供における技術的・施策的課題を国土地理院が把握するとともに、外部からの技術的な提案を受け取り、外部との技術的な議論を通じてベクトルタイルの適切な提供方法を研究開発することを目的とするものです。
本提供実験の期間は、2019年7月29日から本提供実験終了までとなります。
本提供実験のデータは、国土地理院コンテンツ利用規約に従って利用できます。データを利用する際は、「国土地理院ベクトルタイル提供実験」と、出典の明示を行ってください。
本提供実験のベクトルタイルは基本測量成果と位置付けているものではありませんが、基本測量成果としての提供を検討するにあたって、提供を行うものです。
本提供実験の利用により生じた損失及び損害等について、国土地理院はいかなる責任も負わないものとします。

## 地理院ベクトルタイルについて
リポジトリより、地理院ベクトルタイルのデータソースは以下のURLである事がわかります。

```
https://cyberjapandata.gsi.go.jp/xyz/experimental_bvmap/{z}/{x}/{y}.pbf
```

しかしラスタータイルと異なり、多くのソフト・フレームワークでは、このURLをただ指定するだけでは表示してくれません。
ではまず、Mapbox GL JSで表示する手順を追ってみます。

## Mapboxで表示する
https://kanahiro.github.io/experiment-gsi-bvmap/dist/
上記は表示したサンプルサイトです（うっすらとOSMを表示しています）。
Mapbox GL JSで地理院ベクトルタイルのうち道路中心線を表示するコードは以下のとおりです。

```javascript
let map = new mapboxgl.Map({
    'container':'mapPane',
    'style':{
        'version':8,
        'sources':{
            'gsi-bvmap':{
                'type':'vector',
                'tiles':[
                    'https://cyberjapandata.gsi.go.jp/xyz/experimental_bvmap/{z}/{x}/{y}.pbf'
                ],
            }
        },
        'layers':[
            {
                'id':'road',
                'type':'line',
                'source':'gsi-bvmap',
                'source-layer':'road',
                'paint':{
                    'line-color':'#990000',
                    'line-width':3
                }
            }
        ]
    },
    center: [139.7, 35.6],
    zoom: 9
})
```

①source:「ベクトルタイルのURL（.pbf）」をtilesという配列にセットする。
②layer:sourceとそれに含まれるデータ（source-layer）を指定して、「好きなスタイルで」追加してやる。

source-layerの名前は、バイナリデータ内で定義されているため、事前にデータ名を把握しておいた方が良いです。
今回はリポジトリに定義一覧があるので、そこで道路中心線のデータ名は「road」である事がわかります。
※多分デコードしてsource-layerの名前を取得する事も不可能じゃないと思いますが調べていません

「好きなスタイルで」というのが、ベクトルタイルの大きな利点です。
同一のデータから、利用者の望むスタイル（色・太さ・透明度など）で表示する事が出来る訳ですね。

当然、道路データ以外もlayersで定義してやれば同時に表示する事が可能です。

## QGISで読み込む
QGISでベクトルタイルを表示する手順は[昨日の投稿した記事](https://qiita.com/Kanahiro/items/88d15b19b1f2ed4d45c1)のとおりです。
しかしここまでの説明で行けば、明らかに足りないものがあります。tiles.jsonです。

#### 無からtiles.jsonを錬成する
他のベクトルタイルのtiles.jsonを眺めてみると、.pbfタイルのURLがわかれば、tiles.jsonは自前で作成出来る事がわかりました。
というわけで今回作成したtiles.jsonの構造は以下のとおりです。
※どのkeyがoptionalでどれが必須なのかわからない中作成していますので、無駄なkeyがあるかもしれません
<b>※追記：tiles.jsonの仕様について以下のリポジトリで定義されています</b>
https://github.com/mapbox/tilejson-spec

```javascript:tiles.json
{
	"tilejson": "2.0.0",
	"id": "gsi-bvmap",
	"name": "GSI-BinaryVectorMap",
	"format": "pbf",
	"maxzoom": 17,
	"minzoom": 5,
	"attribution": "国土地理院",
	"description": "GSI Experiment",
	"vector_layers": [
		{
			"id": "road",
			"fields": {
				"motorway": "String"
			},
			"maxzoom": 14,
			"minzoom": 0,
			"description": ""
		}
	],
	"crs": "EPSG:3857",
	"crs_wkt": "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs\"],AUTHORITY[\"EPSG\",\"3857\"]]",
	"tile_grid": "mercator",
	"tiles": [
		"https://cyberjapandata.gsi.go.jp/xyz/experimental_bvmap/{z}/{x}/{y}.pbf"
	]
}
```

今回はroadレイヤーのみ欲しいので、それ以外のデータは定義していません（が、プラグインは何も問題なく動きます（後述））。
本当なら、すべてのsource-layerをvector_layersで網羅してあげるべきです。

#### Vector Tiles Readerで表示する
上記のtiles.jsonを適当にホスティングして、そのURLをプラグインに与えてConnect→Addすれば、無事にQGISで地理院ベクトルタイルが表示されます（ある程度、日本列島の領域に拡大してからAddしてください）。なお、vector_layersに定義していないはずのroad以外のデータも（おそらくはpbfをデコードして自動的に）追加されます。
ちなみに[私のGitHub pages](https://kanahiro.github.io/experiment-gsi-bvmap/dist/tiles.json)にも上記のtiles.jsonをアップしてあります。

なお、QGIS上の表示領域内の地物のみがレイヤーのデータとなるため、たとえばデータを外部ファイルに出力したいとき、狙いの地物が完全に表示領域内となっている必要があります。

そんなわけで道路中心線（北海道の主要道路のみ）をぶっこ抜けました。
そのデータを用いたネットワーク解析によるポケモンマンホール最適経路分析はまた別の記事で。