QGIS(3.28.2)で 利用できる ベクトルタイルのスタイル表現について

# はじめに
2022年の年末から2023年の年始にかけて、QGISで使えるベクトルタイルスタイル表現（Mapbox/MapLibreスタイル仕様の中から）をいくつか確認しました。

数年前にベクトルタイルをQGISで表示したときに、うまく表示できない表現があったので、今回改めて整理したいと思って実験したものの記録です。

年末年始で思ったように作業ができず、ラフなメモになってしまいますが、記録としてメモしておきたいと思います。


## 確認したかったこと
QGISでベクトルタイルとそのスタイルを読みこむにあたり、、
* background レイヤを読めるか？
* 色の表現はどれでも大丈夫か？（index color, rgb color, rgba color, etc.）
* filterの表現はどれでも大丈夫か？（matchつかえる？）
* 進んだ表現に対応可能か？
* glyphs フォントを参照できている？（以前はシステムのフォントだった）
* 複数のベクトルタイルソースに対応できる？
* レイヤ数をたくさん読んでも大丈夫？

などを確認しておきたいと思いました。


# 環境

* QGIS version 3.28.2 Firenze （自宅のWindows 10 PC）
* QGIS version 3.16.6 （職場のWindows 10 PC）
    * デフォルトでの読み込みに加えて、Vector Tiles Reader というプラグインも試してみました。
* Github page


QGISは2022年12月末現在で、最新のものをインストールし直しました！ 下のインストーラーでは失敗しましたので、こちらの方法（[別の記事](https://qiita.com/T-ubu/items/af64e06e432d18887abb)）でやりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/f213df6f-322e-c60a-6a59-96372d1193ce.png)


# QGISでベクトルタイルをどのように読み込むか
## QGISでのベクトルタイルサポート
QGISは2020年6月にリリースされたversion 3.14 からベクトルタイルのネイティブ・ローディングをサポートしました。2022年12月末現在、最新のQGISはversion 3.28.2となっていますが、今回の実験でもQGISに備え付けられているベクトルタイル読み込み機能を使って実験していきたいと思います。

**今回は、自宅パソコンでQGIS 3.28.2 を試し、職場パソコンでQGIS 3.16.6 を試しました。**

ベクトルタイルとスタイルの読み込みは簡単で、ブラウザパネルのVector Tilesから選んでもいいですし、レイヤ ＞ レイヤを追加　＞　ベクタタイルレイヤを追加　と選んでいってもよさそうです。

↓ブラウザパネルから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/763cf559-311a-1e96-2a70-d8e2a86084c7.png)

↓レイヤメニューから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/ded1c4fa-5935-5655-595d-4810c1f9c0af.png)

触ってみて感じた点は以下の通りです：
* ベクトルタイル情報の入力にあたっては、直接ベクトルタイルのURLを指定する形（zxyのpbf形式）になっています。Tilejsonを指定する形でないところが、プラグインのVector Tiles Readerとの違いの一つです。また、ここで指定できるソースURLは一つということなので、一つのスタイルjsonの中で複数のソースを参照させるということができるMapLibre GL JSやMapbox GL JSのスタイリングとは基本的な考え方が違うのだと感じます。
* スタイルはオプショナルになっていますが指定することができます。スタイルJSONのURLを指定すれば、スタイルをある程度指定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/3c0b7c80-ae84-65e0-b1e6-1aae36820b2d.png)

ということで、今回の実験ではQGISにもともとついているVector Tileの読み込み機能を使います。

注意が必要だと感じた点：
MapLibre GL JS　や　Mapbox GL JSだと、スタイルJSONに記載されたソースURL（またはタイルJSONのURL）を読みに行ってベクトルタイルを使うようになっています。QGISではベクトルタイルのURLを（1つだけ）指定する形ですから、前提にある考え方が少し違うかもしれません。

ーーー私の勝手なイメージーーー
QGIS：　１つのソースURLに格納されているベクトルタイルを表示する。その際に、スタイリングが可能ならスタイル付けする。（QGISの別なレイヤとして、複数のベクトルタイルを同時に追加することは可能のようです。）
MapLibre GL JSなど：　複数のソース（ベクトルタイル、ラスタタイル、etc）からのレイヤをスタイル付けしてウェブ地図を作る。
ーーーーーーーーーーーーーーー

## （参考）Vector Tiles Reader について
2019年12月のversion3.2.2で開発が止まっていますが、[Vector Tiles Reader](https://plugins.qgis.org/plugins/vector_tiles_reader/)というQGISのプラグインもあります。

このプラグインでも自分で作ったベクトルタイルが見られますので、私は数年前はこれを使っていました。 Layer → Add Layers→Add Vector Tiles Layerと選んでいきました（Layersタブからもいけます）。Add Layerのメニューをよく見ると、プラグインの『Add Vector Tiles Layer...』というのと、『Add Vector Tile Layer』というのがあるのがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/f7397cb1-9b81-d2ea-1cb1-6e80a275fd4c.png)

こちらだと、タイルJSONとベクトルタイルでURLを指定してから使うレイヤを指定する形になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/387c6753-f789-3b7c-949d-4e5aadb8d9b4.png)


# 実験の準備
## レポジトリの作成
今回の作業用のレポジトリを作成しました。　https://github.com/ubukawa/qgis-style


ここに、実験のため、3つのタイルJSON（つまり３つのベクトルタイルソース）を準備しておきます。
QGISのベクトルタイルサポートではタイルJSONではなくて、直接タイルURLを読む形ですが、昔のプラグインはタイルJSONを参照させていたので準備しておきます。

* https://ubukawa.github.io/qgis-style/tilejson01.json
* https://ubukawa.github.io/qgis-style/tilejson02.json
* https://ubukawa.github.io/qgis-style/tilejson03.json

そして、以下の24通りのスタイルを準備しておきます。それぞれの目的は後で説明します。
* https://ubukawa.github.io/qgis-style/style01.json
* https://ubukawa.github.io/qgis-style/style02.json
* https://ubukawa.github.io/qgis-style/style03.json
* https://ubukawa.github.io/qgis-style/style04.json
* https://ubukawa.github.io/qgis-style/style05.json
* https://ubukawa.github.io/qgis-style/style06.json
* https://ubukawa.github.io/qgis-style/style07.json
* https://ubukawa.github.io/qgis-style/style08.json
* https://ubukawa.github.io/qgis-style/style09.json
* https://ubukawa.github.io/qgis-style/style10.json
* https://ubukawa.github.io/qgis-style/style11.json
* https://ubukawa.github.io/qgis-style/style12.json
* https://ubukawa.github.io/qgis-style/style13.json
* https://ubukawa.github.io/qgis-style/style14.json
* https://ubukawa.github.io/qgis-style/style15.json
* https://ubukawa.github.io/qgis-style/style16.json
* https://ubukawa.github.io/qgis-style/style17.json
* https://ubukawa.github.io/qgis-style/style18.json
* https://ubukawa.github.io/qgis-style/style19.json
* https://ubukawa.github.io/qgis-style/style20.json
* https://ubukawa.github.io/qgis-style/style21.json
* https://ubukawa.github.io/qgis-style/style22.json
* https://ubukawa.github.io/qgis-style/style23.json
* https://ubukawa.github.io/qgis-style/style24.json

# 結果
私が試した範囲での実験の結果は以下の通りでした。

|スタイルファイル |参照したベクトルタイル |テーマ |確認事項 |QGIS 3.28.2 |QGIS 3.16.6 |Plug-in(ver 3.2.2 on QGIS 3.16.6) |
|---|---|---|---|---|---|---|
|[style01.json](https://ubukawa.github.io/qgis-style/style01.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |背景 |背景の表示（indexカラー） |〇 |× |〇 |
|[style02.json](https://ubukawa.github.io/qgis-style/style02.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |背景 |背景の表示（RGBカラー） |〇 |× |〇 |
|[style03.json](https://ubukawa.github.io/qgis-style/style03.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |色の表現 |線色・indexカラー |〇 |〇 |〇 |
|[style04.json](https://ubukawa.github.io/qgis-style/style04.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |色の表現 |線色・RGBカラー |〇 |〇 |〇 |
|[style05.json](https://ubukawa.github.io/qgis-style/style05.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |色の表現 |線色・RGBAカラー |〇 |〇 |〇 |
|[style06.json](https://ubukawa.github.io/qgis-style/style06.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |色の表現 |線色・線の名前（例：blue） |〇 |〇 |× |
|[style07.json](https://ubukawa.github.io/qgis-style/style07.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |フィルタ |["==", "bdytyp", 0] のようなフィルタ |〇 |〇 |〇 |
|[style08.json](https://ubukawa.github.io/qgis-style/style08.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |フィルタ |["==", ["get", "bdytyp"], 0] のようなフィルタ |〇 |〇 |× |
|[style09.json](https://ubukawa.github.io/qgis-style/style09.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |フィルタ |["any", ["==", ["get", "bdytyp"], 0],["==", ["get", "bdytyp"], 1]]のようなフィルタ |〇 |〇 |〇 |
|[style10.json](https://ubukawa.github.io/qgis-style/style10.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |フィルタ |matchを使ったフィルタ |〇 |〇 |× |
|[style11.json](https://ubukawa.github.io/qgis-style/style11.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |表現 |line-colorにmatchを使って色分け |×　(getが動いていない） |× |× |
|[style12.json](https://ubukawa.github.io/qgis-style/style12.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |表現 |stopsを使ってズームレベルで線色を変える（ArcGIS、Maputnikでよく使われる方法） |〇 |〇 |〇 |
|[style13.json](https://ubukawa.github.io/qgis-style/style13.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |表現 |step、zoomを使いズームレベルで線色を変える |× |× |× |
|[style14.json](https://ubukawa.github.io/qgis-style/style14.json) |[tilejson01](https://ubukawa.github.io/qgis-style/tilejson01.json) |表現 |interpolate、linearを使いズームレベルで線幅を変える |〇 |〇 |× |
|[style15.json](https://ubukawa.github.io/qgis-style/style15.json) |[tilejson02](https://ubukawa.github.io/qgis-style/tilejson02.json) |シンボルの確認・ケース１ |Fill と Lineのみ |× (タイルへのアクセスが遅いのが原因） |〇 |キャッシュがおかしくて確認できず |
|[style16.json](https://ubukawa.github.io/qgis-style/style16.json) |[tilejson02](https://ubukawa.github.io/qgis-style/tilejson02.json) |シンボルの確認・ケース１ |sprite  |× (タイルへのアクセスが遅いのが原因） |〇 |キャッシュがおかしくて確認できず |
|[style17.json](https://ubukawa.github.io/qgis-style/style17.json) |[tilejson02](https://ubukawa.github.io/qgis-style/tilejson02.json) |シンボルの確認・ケース１ |ラベル（glyphsのリンク先のフォント） |× (タイルへのアクセスが遅いのが原因） |no (font not available) |キャッシュがおかしくて確認できず |
|[style18.json](https://ubukawa.github.io/qgis-style/style18.json) |[tilejson02](https://ubukawa.github.io/qgis-style/tilejson02.json) |シンボルの確認・ケース１ |ラベル（QGISのフォント） |× (タイルへのアクセスが遅いのが原因） |〇 |キャッシュがおかしくて確認できず |
|[style19.json](https://ubukawa.github.io/qgis-style/style19.json) |[tilejson02](https://ubukawa.github.io/qgis-style/tilejson02.json) |シンボルの確認・ケース１ |ラベルとspriteを同時（glyphsのリンク先のフォント） |× (タイルへのアクセスが遅いのが原因） |no (font not available) |キャッシュがおかしくて確認できず |
|[style20.json](https://ubukawa.github.io/qgis-style/style20.json) |[tilejson02](https://ubukawa.github.io/qgis-style/tilejson02.json) |シンボルの確認・ケース１ |ラベルとspriteを同時（QGISのフォント） |× (タイルへのアクセスが遅いのが原因） |〇 |キャッシュがおかしくて確認できず |
|[style21.json](https://ubukawa.github.io/qgis-style/style21.json) |[tilejson03](https://ubukawa.github.io/qgis-style/tilejson03.json) |シンボルの確認・ケース２ |Fill と Lineのみ |〇 |〇 |〇 |
|[style22.json](https://ubukawa.github.io/qgis-style/style22.json) |[tilejson03](https://ubukawa.github.io/qgis-style/tilejson03.json) |シンボルの確認・ケース２ |sprite  |〇 |〇 |×（シンボルでない） |
|[style23.json](https://ubukawa.github.io/qgis-style/style23.json) |[tilejson03](https://ubukawa.github.io/qgis-style/tilejson03.json) |シンボルの確認・ケース２ |ラベルとspriteを同時（glyphsのリンク先のフォント） |〇 |× |× （シンボルでない、ラベル1つだけ） |
|[style24.json](https://ubukawa.github.io/qgis-style/style24.json) |[tilejson03](https://ubukawa.github.io/qgis-style/tilejson03.json) |シンボルの確認・ケース２ |ラベルとspriteを同時（QGISのフォント） |〇 |〇 |× （シンボルでない、ラベル1つだけ） |


## 発見
* 古いQGIS（例えば3.16.6）ではbackgroundレイヤが表示できなかったが、最新のQGISでは表示できる。
* 色の表現は、index、rgb、rgba、色名での指定等、どれでも大丈夫そう。（プラグインは少し制限あり）
* フィルタについてはArcGISやMaputnikでよく使われている表現（Mapbox,MapLibre非奨励）ならばだいたい表示できる。matchなどのexpressionでも大丈夫（プラグインは×）。
* ただし、レイアウトやペイントのなかでexpressionを使っていくと対応していないことがある。
* シンボル、ラベルの表現の対応については、QGISのバージョンの違いでずいぶん差がある。プラグインは困難が多い。QGISではシステムフォントを参照していたが、最新バージョンではglyphsフォントにも対応している可能性がある。（少なくともフォントがなくてもだいたいフォントで表示してくれている様子。）
* タイルへのアクセスが遅いとQGISは表示してくれない。
* （レイヤ数が表示に及ぼす影響は今回は試せていません。）


## イメージ集

**style06（色の名前で指定してみる）：**
Plugin のときは、blue と指定したのが違う色になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/4bfeb4fb-c04d-f338-f5cd-afb1b7c684af.png)

3.28.2だと"blue"を解釈してくれる大丈夫！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/83de724f-e442-59a5-d488-a8a64d90a999.png)

**フィルターのかけかた**
Plugin のときは、filterで['==', bdytyp, 0]は働く（style07）が、['==', ［"get", "bdytyp"], 0]は働かない（style08）。プラグインはスタイルを読めないと、ベクトルタイルだけ読み込まれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/4afd4f32-8090-f932-1fa7-7b39df53a8c5.png)

3.28.2だとフィルターが適切に動いている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/dfe5e82e-4736-2e8c-7107-8221ab7ba3f5.png)

Style11で、matchを使って色を変えてみようとしてみたがダメ。おそらく、matchの中のgetが働いていない（エラーメッセージが出なくて、すべてのラインが条件falseの時のカラーになっているから）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/cc623706-6156-f5fd-495c-47fe4ea29a8a.png)


**style13:**
step、zoomは3.28.2でも理解してもらえない。エラーメッセージあり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/9d966e9f-b4a8-60bc-326c-6de4c9d48d70.png)



**シンボルの実験**
自宅ネットワークからだと、タイルURLへのアクセスに時間がかかりすぎてエラーになりました（style16～20）。
なので、別のデータセットでも実験しました（style21～24）。

古いQGISだと、glyphsのフォントは参照せず、QGISのシステムフォントを参照しています。
例、style17: フォントが出るが、指定フォントは参照できない（glyphsが参照できていないということ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/c5723fb0-e40e-9168-18bf-debad4893421.png)
 
ただし、新しいQGISだと、glyphsのフォントを参照しているかもしれません。（あるいは単にシステムフォントの中にnotosansファミリーが追加されたか。。）

例：スタイル23
↓スタイル23をversion 3.28.2でよんだ例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/fe46e70a-34e8-9369-222c-fa67723a246d.png)
↓スタイル23をversion 3.16.6でよんだ例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/1ef2e375-3b4c-69c4-1c8c-50298af37963.png)
↓スタイル23をプラグインでよんだ例（シンボルも出ないし、ラベルはなぜか１つしかでない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/3999c170-cdc2-3dfd-e4b9-3314be3723ea.png)


# まとめ
今回、QGISでのスタイル表現をいくつか調べてみました。

* ベクトルタイルのスタイル表現への対応は、最新のQGISの方がよい。自分が使うときは、最新のQGISを使いたい。一方で、スタイルを提供する立場になれば、旧バージョンのQGIS用のスタイルも少し意識した方がよいかもしれない。
* フィルタには高度なexpressionを使っても大丈夫そうだが、レイアウトやペイントの中での利用については慎重に考えた方がよい。
* Maputnikで使われているようなスタイル表現はQGISのベクトルタイル読み込みに親和性が高いようなので、それを真似して書くのも一案。

このツールは随時進歩しているようなので、今後も定期的に見ていきたいと思います。


# 参考

https://qgis.org/en/site/forusers/visualchangelog314/#

https://wanderingcartographer.wordpress.com/2021/01/09/qgis-3-and-vector-map-tiles/


https://plugins.qgis.org/plugins/vector_tiles_reader/