3
14
2026
QGIS上で国土地理院のベクタータイルのスタイルを変更してみる
QGISを用いて地理院のベクタータイルのスタイルを編集してみる
QGISで国土地理院のベクタータイル地図のスタイルをカスタマイズしている様子
以前の記事で地理院のベクタータイルの表示スタイルを編集する方法について簡単に紹介したが、一般の人たちが自分でWEBイトを立ち上げてMapbox GL JSなどのフレームワークを利用して自分専用のWEBマップシステムを作ることは非現実的な話だろう.
地図データを業務で活用する場合にはArcGISなどの市販の専用GISツールを使うのが一般的だが、個人レベルで簡単に手が出せるような値段ではないので、貧乏組織や個人の趣味レベルでGISツールを利用しようとすると、QGISなどのオープンソースベースのGISツールを選択することになる.
QGISについては既に多くの人達がWEB等を通じて使い方などを解説しているので、ここでは使い方については触れない(多機能すぎてとても簡単に解説できるような代物ではない)が、国土地理院のベクタータイルを読み込んで、簡単に地図の表示スタイルを編集ことが可能だ.
QGISはインターネット上の地図データだけではなく、手元のPC上のデータも扱うことが可能なのでオフラインの地図編集ツールとしても活用可能なので、外部には出せないような機密データを用いた門外不出の地図データを作成するような用途にも向いている.
今回の記事は、国土地理院のベクタータイルをQGISで取り扱うための基本的な事項について紹介することにする.現時点ではQGISそのものを有効活用するための知識や経験が無いので、もう少しQGISの扱いにに慣れてきたら、QGISの活用方法についても紹介して行きたいと思う.
QGISを自分のPCにインストールするには自分の環境(Linux, Maoc, Windows)に合わせたインストーラーを入手する必要があるが、なるべく最新の安定版を入手するようにして欲しい.重要な業務で使用する場合は、LTR版と呼ばれている長期のサポート期間が設定されているバージョンを入手して欲しい.
QGISのダウンロードページ: https://qgis.org/download/ から簡単にダウンロードできるので、LTR版か最新Stable版、のいずれかをインストールする.
現時点では、Mac版についてはLTR版は用意されておらず、最新のStable版3.44の利用が推奨されている.3.44.8版がLTR版としてリリースされる予定らしい.尚、2026年3月6日付けで最新版の4.0版がリリースされたようだが、もう少し様子を見てから導入したほうが良いだろう.
QGISのドキュメントは ”Resources” > “Documentation” に用意されており、日本語を含めた各国語版が用意されているようだが、私の環境ではWEBホスト側で言語環境を判定して強制的にオリジナルの英語版のページにリダイレクトされてしまうので、実際の日本語ドキュメントの内容や翻訳の質については不明だ.(最近ユーザ側のブラウザの言語設定に合わせて勝手に強制リダイレクトしてしまうサイトが多くて困ったものだ)
QGISで国土地理院のベクタータイルを読み込んでみる
QGISアプリ本体をダブルクリックで起動すると初期のプロジェクト画面が表示されるので、左端の上部にある”Browser”ペインの各項目から “Vector Tiles” を選択した状態で、マウスの右クリックでメニューを表示させ、”New Generic Connection…” を呼び出す.
同じ操作をメインメニューからの操作で行う場合は、”Layer” > “Add Layer…” > “Add Vector Tile Layer…”を選択し、”Data Source Manager”ダイアログから地理院ベクタータイルデータセットの設定を行う.
QGISを最初に起動した際の初期画面
QGISでデフォルトフォントとして利用されている ”Open Sans” というフォントがQGISシステムにインストールされた旨の通知が出ているが、国土地理院のベクタータイル提供実験では、”NotoSansCJKjp-Regular” というフォントが使用されているが、QGIS環境ではこの国土地理院がタイルサーバで配布している”NotoSansCJKjp-Regular”に上手くアクセスできない.
QGISでの代替フォントとして、”Noto Sans CJK JP”というAdobeとGoogleが共同開発したライセンスフリーのWEB用フォントをOSシステムにインストールして、QGISで使えるようにする方法については後ほど説明することにする.
ベクタータイルセットを追加する(マウスの右クリックで直接追加する場合)
ベクタータイルセットを追加する(メインメニュー経由で追加する場合)
国土地理院のベクタータイル提供実験のタイルのURLとズームレベルの設定を行う
“Vector Tiles Connection”ダイアログが現れるので、”Name”欄に適切な名前を設定し、その2つ下に有る”Source URL”に国土地理院のベクタータイル提供実験用のURL、
https://cyberjapandata.gsi.go.jp/xyz/experimental_bvmap/{z}/{x}/{y}.pbf
を記載する.
“Min Zoom Level” と “Max Zoom Level” の項目に、国土地理院のベクタータイルで利用可能な数値を設定する.”Min Zoom Level” = 4, “Max Zoom Level” = 17 を設定しておく.
その下に ”Authentication” の設定があるが、国土地理院のタイルは認証なしに誰でもアクセス可能な公開データなので、認証に関する項目の設定は不要だ.
“Name”と”Source URL”の間に、”Style URL” という項目があるが、ここはオプション項目なので特に指定しなくてもベクタータイルを読み込んでQGISの画面に表示することは可能だ.但し、QGIS側でデフォルトの最低限のスタイルが勝手に適用(線や地物の配色はランダム)されて表示されてしまうので、とりあえずタイルの内容を確認する程度の用途にしか使えないので、実際には用途に合わせたスタイルデータを用意しておかないと実用にならない.
“Layer”メニューの”Data Source Manager”を呼び出して”Data Source Manager”ダイアログから “Add” を行うかまたは画面左の”Browser”ペーンの”Vector Tile”の項目に先ほど登録した”GSI Vector Tile – Pale” という項目が追加されているので、その項目をダブルクリックすると”Browser”ペーンの下にある、”Layers”ペーンに “GSI Vector Tile – Pale” が追加される.
画面中央の地図描画ペーンには何やら日本列島らしき小さなオブジェクトが表示されている
中央のプロジェクト画面に何となく日本列島の形をしたような地図らしきデータが小さく表示されていることだろう.
スクロールホイールでズームアップしていくとだんだん地図っぽくなってきた
1/25000レベルまで縮尺を変えてみる
QGISのデフォルトのスタイルではポリゴンとライン、ポイントの地物データは全て描画されてしまう
QGISのデフォルトの初期スタイルでは、地物のタイプがポリゴン、ライン、ポイントであればQGISがランダムに設定したスタイルで地物の描画を行うようになっている.地理院のベクタータイルセットは多くの地物データを含んでいる巨大なベクタータイルセットなので、データセットに含まれている全ての地物がこのデフォルトスタイルに従って表示されてしまう.
上記の画面の様子から分かるように、描画されている地物の数が多すぎて何が何だか分からない状態だ.ユーザによるスタイル定義が為されていないと全く使い物にならないことが分かるだろう.
QGISのユーザ定義スタイルの設定方法
先の例では、ベクタータイルセットの指定とズームレベルの設定しか登録していなかったので、地図のスタイルに関する情報が何も設定されていない状態だ.このような場合、QGIS側で勝手にデフォルトの簡略スタイルが適用されてしまうが、ユーザ定義のスタイルをここで設定すれば最初からユーザ指定のスタイルで地図が描画されるようになる.
“Vector Tiles Connection” ダイアログの設定で、”Style URL”というオプション項目があり、この”Style URL”に自分で設定したスタイル定義データファイルのURLを記載することができる.スタイル定義ファイルが置かれている場所のURLを指定すれば良い.一般的なURLのスキーム “https” 以外に “file” でもアクセス可能なので、手元のPC上に置かれたローカルファイルも指定可能だ.
自分のWEBサイトや外部のWEBサイトにスタイルファイルが置かれている場合は、”https://y2tech.net/MapTest/JSGIVectorMaps/oldstyle/pale_modified.json” のようなスタイルファイルを指定すれば良い.手元のPC上のローカルファイルであれば、 “file://[PC上のローカルスタイルファイルへのパス]/pale.json” というような記述になるだろう.
WEBサイト上のスタイルファイルをHTTPで読み込む場合の設定
手元のPC上のローカルファイルを読み込む場合の設定例
“Vector Tiles Connection” ダイアログで設定する以外にも、”Layer Properties” ダイアログ(メインメニューから “Layer” > “Layer Properties” または、”Layers”ペーンの項目を直接ダブルクリックで呼び出し)の下部にある “Style” プルダウンメニューから、手元のPC上に置かれたスタイルファイルを直接読み込んでスタイルを変更することが可能だ.
“Layer Properties” ダイアログの”Style”プルダウンメニューでスタイルファイルを読み込むことも可能
手元に置いたスタイルファイルを直接読み込んでみる
地図のスタイルが “blank”(白地図)に変更された
国土地理院が公開しているGitHubサイトのスタイルファイルのURL(”https://github.com/gsi-cyberjapan/gsivectortile-mapbox-gl-js/blob/master/pale.json” など)を直接指定しても問題ないはずなのだが、何故かQGISからはスタイルデータ上手く読み込んでくれななかった.
GitHub上ではなく手元のWEBサーバ上に置いたスタイルファイルを指定した場合は問題なく、QGISから読み込みできているので、レスポンスの遅いGitHubサーバだとタイムアウト等を起こしてQGIS側でスタイルファイルの読み込みを断念しているのかもしれない.
とりあえず今回は、GitHubサイトのスタイルファイルを一旦手元のPC上にダウンロードして、ローカルファイルデータとしてQGISに取り込む方法を用いることにする.
QGIS上に国土地理院のベクタータイルを読み込んでみる
ここでは、国土地理院の淡色表示スタイル定義ファイル”pale.json” を用いて、前回の記事『MapboxでカスタムWebmap作りに挑戦 #3(地理院のベクタータイルを表示する)』で行ったスタイルファイルのカスタマイズと同じことをQGIS上で行ってみることにする.
国土地理院の淡色表示スタイル定義ファイル”pale.json” を用いてQGIS上に地図を表示させると、次のようなエラーメッセージが表示される.このエラーの大部分は、スタイル定義ファイル”pale.json”で指定している文字フォント “NotoSansCJKjp-Regular” がシステム上で使うことができないというエラーメッセージとテキストを描画する際の文字の回転角度などの計算式でエラーが発生しているという内容だった.
エラーメッセージの大半はフォントの欠落とサポートされていない演算子が用いられているという内容だ
The following warnings were generated while converting the vector tile style:
gsibv-vectortile-layer-1583: Referenced font NotoSansCJKjp-Regular is not available on system
gsibv-vectortile-layer-1601: Referenced font NotoSansCJKjp-Regular is not available on system
...
gsibv-vectortile-layer-2102: Could not retrieve sprite '電波塔'
...
gsibv-vectortile-layer-2138: Skipping unsupported expression "*"
gsibv-vectortile-layer-2139: Referenced font NotoSansCJKjp-Regular is not available on system
...
“NotoSansCJKjp-Regular”フォントがシステム上に無いということなので、”NotoSansCJKjp-Regular”フォントをOSシステム(今回はMac OS)にインストールすることにする.エラーメッセージ中の”System”の定義がOSのことなのか、QGISのことなのかハッキリしなかったが、とりあえずOS側に”NotoSansCJKjp-Regular”フォントをインストールしてみることにする.
ちなみに、QGISのワークディレクトリやシステム設定等のファイルは、Mac OS の場合、個人のホームディレクトリの下に置かれており、”~/Library/Application Support/QGIS/QGIS3/profiles/default/”配下に置かれており、その中に”fonts”というフォルダが存在する.このフォルダの中に、一番最初の起動時に”OpenSans”フォントがインストールされた旨の表示がなされていたが、どうやらQGISはこのフォルダをフォントのキャッシュとして利用しているようだ.
フォントの世界のことは詳しくないので、とりあえず”NotoSansCJKjp-Regular”というフォント名のウェイト(太さ)を除いたフォント名 ”NotoSansCJKjp” で検索を掛けたら、AdobeとGoogleのサイトに “Noto Sans CJK JP”というフォント名が見つかった.
“Noto Sans CJK JP”フォントはAdobeとGoogleが共同で開発し配布している、可読性を考慮したフリーのゴシック体フォントの名前で、日本語、韓国語、中国語の文字を含んだレギュラー書体(標準的な太さ)のフォントだ.Apache License 2.0 で配布されていて、AdobeのサイトかGoogleのサイトを通じて無償で入手可能だ.
ダウンロードした “Noto_Sans_JP.zip” を解凍すると、”Noto_Sans_JP”というフォルダとその配下に”static”フォルダとREADME.txt, OFL.txt, NotoSansJP-VariableFont_wght.ttf が置かれている.”static”フォルダの配下には、ウェイトが異なる9つのフォントが置かれている.
“NotoSansJP-VariableFont_wght.ttf” はバリアブルフォントと呼ばれる比較的新しい形式のフォントで、1つのフォントファイル内に、様々なウェイト(太さ)の情報を詰め込んであり、WEBで使用する場合はCSSの指定でフォントのウェイトを簡単に設定することが可能なようだ.
staticフォルダ内の “NotoSansJP-xxxxx.ttf” フォントは固定ウェイトのフォントで、従来型のフォントと言うことようだ.地理院のスタイル定義で指定されているフォントは “NotoSansCJKjp-Regular” とのことなので、”NotoSansJP-Regular.ttf” をPCシステム側にインストールしてみた.
私の環境はMacなので、とりあえず”NotoSansCJKjp-Regular”をダブルクリックして、Macの標準フォント管理ツールである “FontBook”を起動しこのフォントをインストールしてみた.この方法でインストールすると、個人のホームディレクトリ配下(~/Library/Fonts/)にインストールしたフォントが置かれていた.
残念ながらOS”Noto Sans CJK JP”フォントをインストールしただけでは、フォントが見つからないというエラーは解消されなかった.
国土地理院のMapbox形式のスタイル定義ファイル”pale.json” では、スタイルファイルのヘッダ部分で、スタイルファイルで使用するフォントに関する Glyphs のURLが指定されており、国土地理院のタイル配信サーバ上に置かれたPBF形式のフォントセットから拾ってくる仕様になっている.
Mapbox GLではこのGlyphsを参照して国土地理院のサーバから”NotoSansCJKjp-Regular”を参照できているが、QGISこのGlyphsのURLにアクセスして”NotoSansCJKjp-Regular”フォントを参照できていないようだ..
エラーを起こしている箇所を幾つか拾ってみる.
{
"version": 8,
"glyphs": "https://maps.gsi.go.jp/xyz/noto-jp/{fontstack}/{range}.pbf",
"sources": {
"gsibv-vectortile-source-1-4-16": {
"type": "vector",
"tiles": [
"https://cyberjapandata.gsi.go.jp/xyz/experimental_bvmap/{z}/{x}/{y}.pbf"
],
"minzoom": 4,
"maxzoom": 16,
"attribution": "地理院地図Vector(仮称)"
}
},
"layers": [
...
{
"id": "gsibv-vectortile-layer-1616",
"type": "symbol",
"source": "gsibv-vectortile-source-1-4-16",
"source-layer": "symbol",
"metadata": {
"layer-id": "layer-1473",
"title": "田",
"path": "記号-田",
"added": 1
},
"minzoom": 13, "maxzoom": 14,
"filter": [ "all", [ "in", "ftCode", 6311 ]
],
"layout": {
"icon-size": { "stops": [ [ 13, 0.5 ], [ 14, 0.6 ] ] },
"icon-image": "田-20",
"icon-pitch-alignment": "viewport",
"icon-rotation-alignment": "viewport",
"text-font": [ "NotoSansCJKjp-Regular" ], <=== フォントが無い
"symbol-placement": "point",
"icon-allow-overlap": true,
"text-keep-upright": true,
"text-allow-overlap": false,
"symbol-z-order": "auto",
"text-max-width": 100,
"visibility": "visible"
}
},
...
{
"id": "gsibv-vectortile-layer-2102",
"type": "symbol",
"source": "gsibv-vectortile-source-1-4-16",
"source-layer": "symbol",
"metadata": {
"layer-id": "layer-1501",
"title": "電波塔",
"path": "記号-電波塔",
"added": 1
},
"minzoom": 14, "maxzoom": 17,
"filter": [ "all", [ "in", "ftCode", 8105 ] ],
"layout": {
"icon-size": {
"stops": [ [ 14, 0.4 ], [ 15, 0.8 ], [ 16, 1 ], [ 17, 1 ] ]
},
"icon-image": "電波塔", <=== spriteファイル中にこのアイコンが無い
"icon-pitch-alignment": "viewport",
"icon-rotation-alignment": "viewport",
"text-font": [ "NotoSansCJKjp-Regular" ], <=== フォントが無い
"symbol-placement": "point",
"icon-allow-overlap": true,
"text-keep-upright": true,
"text-allow-overlap": false,
"symbol-z-order": "auto",
"text-max-width": 100,
"visibility": "visible"
}
},
...
{
"id": "gsibv-vectortile-layer-2169",
"type": "symbol",
"source": "gsibv-vectortile-source-1-4-16",
"source-layer": "label",
"metadata": {
"layer-id": "layer-1529",
"title": "警察",
"path": "注記-警察",
"added": 1
},
"minzoom": 17,
"maxzoom": 18,
"filter": [ "all", [ "in", "ftCode", 100 ],
[ "==", "annoCtg", 883 ]
],
"layout": {
"text-size": 24,
"text-allow-overlap": true,
"text-rotate": [ "case", [ "==", [ "get", "arrng" ], 2 ],
[ "*", [ "+", [ "to-number", [ "get", "arrngAgl" ] ], 90 ], -1 ],
[ "*", [ "to-number", [ "get", "arrngAgl" ] ], -1 ]
],
"text-anchor": [ "case", [ "==", [ "get", "arrng" ], 2 ],
[ "case", [ "==", [ "get", "dspPos" ], "LT" ], "top-right",
[ "==", [ "get", "dspPos" ], "CT" ], "right",
[ "==", [ "get", "dspPos" ], "RT" ], "bottom-right",
[ "==", [ "get", "dspPos" ], "LC" ], "top",
[ "==", [ "get", "dspPos" ], "CC" ], "center",
[ "==", [ "get", "dspPos" ], "RC" ], "bottom",
[ "==", [ "get", "dspPos" ], "LB" ], "top-left",
[ "==", [ "get", "dspPos" ], "CB" ], "left",
[ "==", [ "get", "dspPos" ], "RB" ], "bottom-left",
"center"
],
[ "case", [ "==", [ "get", "dspPos" ], "LT" ], "top-left",
[ "==", [ "get", "dspPos" ], "CT" ], "top",
[ "==", [ "get", "dspPos" ], "RT" ], "top-right",
[ "==", [ "get", "dspPos" ], "LC" ], "left",
[ "==", [ "get", "dspPos" ], "CC" ], "center",
[ "==", [ "get", "dspPos" ], "RC" ], "right",
[ "==", [ "get", "dspPos" ], "LB" ], "bottom-left",
[ "==", [ "get", "dspPos" ], "CB" ], "bottom",
[ "==", [ "get", "dspPos" ], "RB" ], "bottom-right",
"center"
]
],
"text-pitch-alignment": "viewport",
"text-rotation-alignment": "viewport",
"icon-pitch-alignment": "auto",
"icon-rotation-alignment": "auto",
"text-offset": [ "case", [ "==", [ "get", "arrng" ], 2 ],
[ "case", [ "any", [ "==", [ "get", "dspPos" ], "CB" ],
[ "==", [ "get", "dspPos" ], "RB" ],
[ "==", [ "get", "dspPos" ], "LB" ]
],
[ "literal", [ 0.5, 0 ] ],
[ "any", [ "==", [ "get", "dspPos" ], "CT" ],
[ "==", [ "get", "dspPos" ], "RT" ],
[ "==", [ "get", "dspPos" ], "LT" ]
],
[ "literal", [ -0.5, 0 ] ],
[ "any", [ "==", [ "get", "dspPos" ], "LC" ] ],
[ "literal", [ 0, 0.5 ] ],
[ "any", [ "==", [ "get", "dspPos" ], "RC" ] ],
[ "literal", [ 0, -0.5 ] ],
[ "literal", [ 0, 0 ] ]
],
[ "case", [ "any", [ "==", [ "get", "dspPos" ], "LT" ],
[ "==", [ "get", "dspPos" ], "LC" ],
[ "==", [ "get", "dspPos" ], "LB" ]
],
[ "literal", [ 0.5, 0 ] ],
[ "any", [ "==", [ "get", "dspPos" ], "RT" ],
[ "==", [ "get", "dspPos" ], "RC" ],
[ "==", [ "get", "dspPos" ], "RB" ]
],
[ "literal", [ -0.5, 0 ] ],
[ "any", [ "==", [ "get", "dspPos" ], "CT" ] ],
[ "literal", [ 0, 0.5 ] ],
[ "any", [ "==", [ "get", "dspPos" ], "CB" ] ],
[ "literal", [ 0, -0.5 ] ],
[ "literal", [ 0, 0 ] ]
],
],
"text-field": [ "get", "knj" ],
"text-font": [ "NotoSansCJKjp-Regular" ],
"symbol-placement": "point",
"icon-allow-overlap": true,
"text-keep-upright": true,
"symbol-z-order": "auto",
"text-max-width": 100,
"visibility": "visible"
},
"paint": {
"text-color": "rgba(0,0,0,1)",
"text-halo-color": "rgba(255,255,255,1)",
"text-halo-width": 2
}
}
],
"sprite":"https://gsi-cyberjapan.github.io/gsivectortile-mapbox-gl-js/sprite/pale", <=== GitHubホストの場合に問題が発生している
"metadata": {
"gsimaps-vector-url": "https://maps.gsi.go.jp/vector/#7/36.104611/140.084556/&ls=&disp=&d=l",
"center": { "lng":140.084556, "lat":36.104611 },
"zl": 7
}
}
指定されたフォントが無いというエラーに関してはQGIS側が代替フォント(OpenSans ?)で表示してくれているので、とりあえず無視して先へ進めても問題なさそうだ.
"NotoSansCJKjp-Regular"というフォント名は国土地理院のタイル配信サーバに置かれたPBFフォントに付けられた固有の名称のようなので、Mac OS側にインストールされている "Noto Sans CJK JP" とフォント名が異なっているので"NotoSansCJKjp-Regular"フォントが見つからないというエラーになるのだと思われる.
スタイルファイル "pale.json" のフォント指定部分 "text-font": [ "NotoSansCJKjp-Regular" ] を、Mac OSの "FontBook"アプリの表示名(フォントファミリー名?)である "text-font": [ "Noto Sans CJK JP" ] に変更してみたところ、QGISはMac OS側にインストールされている"Noto Sans CJK JP"がQGISのフォントとして取り込まれたようで、フォントが見つからないというエラーを解消することができた
Macの"FontBook"アプリで "Noto Sans CJK JP" という名称が正式なフォント名であることを確認
"Noto Sans CJK JP"フォントがQGIS上で使えるようになった
フォントが見つからないというエラーは解消された
spriteデータの"電波塔" に関するエラーは国土地理院が提供しているスプライトイメージ(アイコンセットの一種)のインデクスデータ "https://gsi-cyberjapan.github.io/gsivectortile-mapbox-gl-js/sprite/pale.json" 中に定義されている、"電波塔" の文字列が何故か文字列として認識されていないことが原因のようだ.
"https://gsi-cyberjapan.github.io/gsivectortile-mapbox-gl-js/sprite/pale.json"をWEBブラウザで表示して中身を確認すると、次のように "empty" となってしまう.
spriteファイルがGitHubでホストされていると"電波塔"が"empty"になっている
spriteのホストサーバをこのサーバに切り替えるときちんと"電波塔"の文字が見えている
GitHub上に置かれた"pale.json"ファイルをコピーして手元のWEBサーバ経由(”https://y2tech.net/MapTest/JSGIVectorMaps/sprite/pale.json")で提供した場合には、問題なく"電波塔" と表示されているので、GitHubのサーバが返すデータの文字エンコードに原因がありそうだ.
とりあえずスタイルファイル "pale.json" のspriteのURLを、手元のWEBサーバ経由に切り替えたところ、"電波塔"のアイコンイメージが見つからないというエラーは解消された.
スタイルファイルのspriteの指定を "sprite":"file://[ローカルパス]/sprite/pale"のような形で指定できれば、自分のWEBサーバが無くても手元のPC上に置いておくこことができるのだが、残念ながらQGISはこのようなローカルファイル形式ののsprite URLを処理できないので、スプライトのアイコン表示はすべてエラーとなってしまった.
国土地理院のスタイルファイル"pale.json"で用いられているspriteイメージ
" gsibv-vectortile-layer-2138: Skipping unsupported expression "*" " というエラーメッセージは文字をレンダリングする際の回転角度の計算で、式中の演算子"*" をサポートしていないとのことなので、QGISはこの式を評価することができないようだこのエラーに関しては回避策がなさそうなので、とりあえず無視して先へ進めることにする.
上記のスタイルファイル "pale.json" の警察署の文字表記方法に関する複雑な式を見て分かるように、国土地理院の地図での文字表記に関する拘りの強さが感じられるのではないだろうか.
QGISが扱うことのできるスタイル情報について
QGIS上に国土地理院のベクタータイルを読み込んで、Mapbox形式のスタイルファイルを適用することでQGIS上でもWEBマップ上の地理院地図と同じようなイメージでベクター地図を取り扱うことが可能であることがお分かりいただけたことと思う.
QGIS上ではMapbox形式のスタイルファイルを読み込むことが可能だが、QGISの内部ではQGIS独自のスタイル情報定義を行っているようで、QGIS上で編集したスタイル情報はQGIS独自の形式でしか外部に書き出せないようだ.
QGISのスタイル情報は "Layer Property"ダイアログの"Style"プルダウンメニューの "Save Style..." を通じてファイルに書き出すことが可能だが、残念ながら QGIS独自の形式(QML形式)なので、Mapbox GLなどのWEBマップシステムで活用するには専用の変換ツールが必要だろう.
QML形式でQGISのスタイル情報を書き出すことが可能
QGISのスタイルファイルの中身
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis minScale="1e+08" styleCategories="AllStyleCategories" maxScale="0" hasScaleBasedVisibilityFlag="0" autoRefreshMode="Disabled" autoRefreshTime="0" version="3.44.7-Solothurn">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<customproperties>
<Option/>
</customproperties>
<renderer type="basic">
<styles>
<style max-zoom="16" enabled="1" layer="structurel" geometry="1" name="gsibv-vectortile-layer-1539" expression="("ftCode" IS 4202)" min-zoom="14">
<symbols>
<symbol alpha="1" type="line" is_animated="0" force_rhr="0" name="0" clip_to_extent="1" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data_defined_properties>
<layer pass="0" enabled="1" id="{e1347f47-5379-4987-bd17-47833f3fd80b}" locked="0" class="SimpleLine">
<Option type="Map">
<Option type="QString" value="0" name="align_dash_pattern"/>
<Option type="QString" value="square" name="capstyle"/>
<Option type="QString" value="5;2" name="customdash"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="customdash_map_unit_scale"/>
<Option type="QString" value="MM" name="customdash_unit"/>
<Option type="QString" value="0" name="dash_pattern_offset"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="dash_pattern_offset_map_unit_scale"/>
<Option type="QString" value="MM" name="dash_pattern_offset_unit"/>
<Option type="QString" value="0" name="draw_inside_polygon"/>
...
<style max-zoom="13" enabled="1" layer="river" geometry="1" name="gsibv-vectortile-layer-1540" expression="("ftCode" IS 5322)" min-zoom="11">
<symbols>
<symbol alpha="1" type="line" is_animated="0" force_rhr="0" name="0" clip_to_extent="1" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data_defined_properties>
<layer pass="0" enabled="1" id="{b8345609-c847-490b-bc15-13d340e349b3}" locked="0" class="SimpleLine">
<Option type="Map">
<Option type="QString" value="0" name="align_dash_pattern"/>
<Option type="QString" value="square" name="capstyle"/>
<Option type="QString" value="0.529167;0.529167" name="customdash"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="customdash_map_unit_scale"/>
<Option type="QString" value="MM" name="customdash_unit"/>
<Option type="QString" value="0" name="dash_pattern_offset"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="dash_pattern_offset_map_unit_scale"/>
<Option type="QString" value="MM" name="dash_pattern_offset_unit"/>
...
<Option type="double" value="0" name="minLength"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="minLengthMapUnitScale"/>
<Option type="QString" value="MM" name="minLengthUnit"/>
<Option type="double" value="0" name="offsetFromAnchor"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="offsetFromAnchorMapUnitScale"/>
<Option type="QString" value="MM" name="offsetFromAnchorUnit"/>
<Option type="double" value="0" name="offsetFromLabel"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="offsetFromLabelMapUnitScale"/>
<Option type="QString" value="MM" name="offsetFromLabelUnit"/>
</Option>
</callout>
</settings>
</style>
</styles>
</labeling>
<blendMode>0</blendMode>
<layerOpacity>1</layerOpacity>
</qgis>
QGIS上で設定したスタイル情報をMapbox形式で書き出すプラグインが幾つかあるようだが、QGISのプラグインリポジトリ上では見つからなかった."MBStyleGenerator" というプラグインがGitHub上で公開されているが、まだ実験レベルの段階で、機能的にもかなり制限があるようなので今回の目的には使えないだろう.
QGIS上のデータをWEBマップシステムで利用可能な形式で書き出しを行うプラグインとして "qgis2web" というプラグインがあり、こちらの方はQGISのプラグインリポジトリから簡単にインストールできるようだが、ベクタータイルは対象外の様で、ラスターイメージ形式のデータしか取り扱えないようだ.
スタイルデータの変換ツールとして、 "GeoStyler CLI" (https://geostyler.org/) というツールがオープンソースベースで提供されているようなので、今度このツールを使って上手くMapbox形式のスタイルファイルの変換できるかどうか試してみる予定だ.
QGIS上でスタイルの編集を行ってみる
先の記事『MapboxでカスタムWebmap作りに挑戦 #3(地理院のベクタータイルを表示する)』で行ったスタイル変更と同じことをQGIS上で行ってみることにする.
QGISでスタイルを直接変更するには、メインメニューの "Layer" > "Layer Properties..." または画面左下の"Layers"ペーンの該当項目をダブルクリックすれば、"Layer Properties"ダイアログが現れる.ダイアログの左側のペーンでの"Symbology" という項目が表示されているだろう.
スタイルの編集はこの”Symbology" でラインやポリゴンなどの形態や色などの編集を行い、文字(ラベル)のスタイル変更は、"Labels" で行う.
”Symbology"では、スタイルファイルで定義されている一連のレイヤーの項目がリスティングされており、Labelにレイヤの"id"項目、Layerには"source-layer"項目が表示されており、Min ZoomとMax Zoomの値およびFileter項目が表示されている.
QGIS V3.44の "Layer Properties"ダイアログの画面
こちらは QGIS V3.40のドキュメントに記載されている "Layer Properties"ダイアログの画面
https://docs.qgis.org/3.40/ja/docs/user_manual/working_with_vector/vector_properties.html#source-properties より
スタイル変更を行う目的のレイヤーを探す
今回用いたスタイルファイル "pale.json" には、759個ものレイヤーが含まれているので、この中から目的のレイヤーを探すのは一苦労だ."Layer Properties"ダイアログの上部には虫眼鏡のアイコンの検索フィールドが用意されており、ここに目的のレイヤーに関する検索キーワードをしていして、目的のレイヤーを探し出すことができるようになっている.
この検索フィールドに指定できるのは単純な文字列による検索だけで、ANDやORなどの論理演算式は記述できないようなので、検索機能としてはあまり約に立たない.QGISV3.40のドキュメントでは、この"Layer Properties"ダイアログの項目には、"Masks", "3D View", ... とV3.44には存在しない機能があり、クエリビルダ機能を使って高度な検索ができると記されているが、そんな便利な機能はV3.44の"Layer Properties"ダイアログには見当たらない.どういうことだろう???
実は、この一見不可解な現象はV3.40とV3.44の違いではなく、"Vector Tile" と "XYZ Tiles" で設定可能な内容が異なっているため、"Vector Tiles" の "Layer Properties"ダイアログでは、設定可能な機能が大幅に少なくなっていることが原因のようだ.
マニュアルは "XYZ Tiles" を利用することを前提に作られているので、"Vector Tile"の場合はマニュアルは殆ど参考にならないようだ.QGISでは"Vector Tile"のハンドリング機能の実装はまだこれからのようだ.
QGIS V3.44で "XYZ Tiles"の場合の"Layer Properties"ダイアログの画面
とりあえず"Vector Tiles" の "Layer Properties"ダイアログでの検索機能では単純な文字列比較(部分一致)検索しかできないようなので、複雑な条件による絞り込みは諦めることにする.
検索可能な項目は "Label", "Layer", "Min. Zoom", "Max. Zoom", "Filter" の5項目だけで、これらの項目に含まれている文字列データで検索することになる.例えば検索フィールドに "rail" と入力すると"Layer"項目が"railway"となっているレイヤーが全て表示される.
5項目のフィールドの内のどこか一箇所でも検索する文字が含まれていればそのレイヤーが抽出されてしまうので、検索として使い物にならない.『鉄道で単線かつJR』の様な検索を掛けることはできないので、予め抽出したいレイヤーのデータの中身の情報を的確に知っていないとピンポイントで探し出すことは難しいだろう.
Mapbox形式のスタイルファイル "pale.json" の中には "鉄道-JR-通常部-単線" のレイヤーが3つあり、"id" : "gsibv-vectortile-layer-1777" のレイヤーが実際に破線を描いている部分だ."id" の文字列は一意なので、QGISの検索フィールドにそのものずばり "gsibv-vectortile-layer-1777" を指定すれば簡単に該当するレイヤー項目を探し出すことができる.
{
"id" : "gsibv-vectortile-layer-1777",
"type": "line", "source": "gsibv-vectortile-source-1-4-16",
"source-layer": "railway",
"metadata": {
"layer-id": "layer-1313",
"title": "単線",
"path": "鉄道-JR-通常部-単線",
"added": 1
},
"minzoom": 14,
"maxzoom": 17,
"filter": [ "all", [ "in", "ftCode", 8201 ],
[ "==", "snglDbl", 1 ],
[ "any", [ "==", "staCode", "0" ],
[ "!has", "staCode" ]
],
[ "==", "railState", 0 ],
[ "any", [ "all", [ ">=", "rtCode", "40201000000" ],
[ "<", "rtCode", "40202000000" ]
],
[ "all", [ ">=", "rtCode", "40216000000" ],
[ "<", "rtCode", "40217000000" ]
]
]
],
"layout": { "line-cap": "square", "visibility": "visible" },
"paint": { "line-color": "rgba( 100, 100, 100, 1 )",
"line-width": 3.2,"line-dasharray": [ 2, 2 ] }
},
"gsibv-vectortile-layer-1777"で検索すれば簡単に目的のレイヤーを探し出すことができる
今回のように最初から探し出すレイヤーid名が分かっていれば、そのid名で検索すれば一発で探し出せるが、事前の情報が何もない場合は、地理院のベクタータイル提供実験で用いられているデータ仕様を調べて、目的の地物を探し出さなければならない.
鉄道関連の地物を探し出す場合には "source-layer" が "railway" となっているレイヤーを探し出せば良いのだが、"railway"で検索を掛けると駅舎や鉄道のトンネルなど鉄道関連の地物が全て該当してしまうので検索結果が膨大なものとなってしまう.
"railway"で検索すると鉄道関係の地物だけに限定することができるが、数が多すぎて探し出すことができない
"railway"という"source-layer"のキーワードではなく、地物の属性コードである"ftCode" を使って検索してみることにする."ftCode"の値は"Filter"部分の式中に含まれているので、"ftCode"の値を用いても検索を行うことが可能だ.
鉄道関連の "ftCode" は Zoom Level 4〜7 の場合は、"58201", "58203", "58204" の3種類、Zoom Level 8〜16の場合は、全て "8201" となっている.最大ズームレベルの Zoom Level 17の場合は、"8201" 以外に、"2801", "2803", ..., "2843" と細かく別れている.
"8201" で検索を掛けると、"railway"の場合よりは検索結果が少なくなるが、それでも何十行も表示されてしまうので、中々目的のレイヤーを探し出すことができない.文字列の部分一致検索しかできないので、Zoom Level 4〜7 の場合の"58201" も該当してしまう.
今回のように、"鉄道-JR-通常部-単線" に該当するレイヤーを探し出そうとすると、該当する地物の個別属性項目を細かく調べて、
鉄道 : "ftCode" == "8201"
単線 : 個別属性値 "snglDbl" == "1"
JR : 個別属性値 "rtCode1" == 上位5桁の値が "40201" または "40216" (Zoom Level 8〜13)
"rtCode" == 上位5桁の値が "40201" または "40216" (Zoom Level 14〜16)
のように検索するキーワードを探し出さなくてはならない.
QGISの検索フィールドで、"ftCode" == "8201" AND "snglDbl" == "1" AND ... のような論理演算式を用いて検索できれば良いのだが、QGISのベクタータイルレイヤーではこの方法は使えない.
上記のMapbox形式のスタイルファイルのfiler式が複雑なのは国土地理院のベクタータイルの仕様に合わせるとこのような複雑な論理式を組まざる負えないのだろう.ベクタータイルの仕様を見直して、もっとスッキリしたものに作り替えないとこの先普及しないのではないかと思う.
"gsibv-vectortile-layer-1777"のレイヤースタイルはQGISの内部では、次のようなレイヤープロパティとして扱われている.(Filter式は1行の単純な文字列で分かり難いので、改行とインデントを施した物も併記している)
Label : "gsibv-vectortile-layer-1777"
Layer : "railway"
Min. Zoom : "14"
Max. Zoom : "16"
Filter : "("ftCode" IS 8201) AND ("snglDbl" IS 1) AND (("staCode" IS '0') OR ("staCode" IS NULL)) AND ("railState" IS 0) AND ((("rtCode" >= '40201000000') AND ("rtCode" < '40202000000')) OR (("rtCode" >= '40216000000') AND ("rtCode" < '40217000000')))"
-----------------------------------------------------------------------------
( "ftCode" IS 8201 ) AND
( "snglDbl" IS 1 ) AND
( ( "staCode" IS '0' ) OR ( "staCode" IS NULL ) ) AND
( "railState" IS 0 ) AND
( ( ( "rtCode" >= '40201000000' ) AND ( "rtCode" < '40202000000' ) ) OR
( ( "rtCode" >= '40216000000' ) AND ( "rtCode" < '40217000000' ) ) )
-----------------------------------------------------------------------------
QGISのFilter式の文字列を一字一句間違わずに検索フィールドに入力すれば目的のレイヤーだけを探し出すことができるが、こんな複雑な論理式を頭の中で考えて、しかもQGISの内部の表現式通りに入力することなど不可能だ.
Filter式 " ("ftCode" IS 8201) ... AND ("rtCode" < '40217000000'))) " を入力すれば所望の検索結果が得られるが...
QGISの"Layer Properties"ダイアログで "鉄道-JR-通常部-単線" に該当するレイヤーを検索で探し出すことが難しい作業であることがお分かりいただけたであろうか.
該当するレイヤーのスタイルをGUI画面で編集してみる
編集のターゲットとなるレイヤーを見つけたら、"layer Properties"ダイアログ上でそのレイヤをダブルクリックする."Symbol Selector"ダイアログが現れ、ラインの色やラインの種類などをダイアログ上で編集することができる.今回の対象となるレイヤーは地物のタイプが "line" なので、ラインの編集ダイアログが現れたが、水域など地物のタイプが "fill" のレイヤーでは塗りつぶし用のダイアログが現れる.
地物のタイプに応じた編集ダイアログが現れる("line"の場合)
塗りつぶし("fill")の場合の編集ダイアログ
今回は、線路部分の見てくれをラスタータイプの地理院地図のデザインに近付けるので、破線の白と黒部分の間隔を広げてみる.破線の間隔を広げるには "use custom dash pattern" の破線部分をダブルクリックすると、"dash" と"space" の数値を変更して、"Layers Properties"ダイアログ下部の "Apply" ボタンを押下すればQGISの画面に反映される.
破線の間隔の数値を大きくして破線のパターンを変更してみる
変更前の線路のパターン
変更後
QGIS上で国土地理院のベクタータイル地図のスタイルを変更する方法について簡単に説明してきたが、何となくイメージがつかめただろうか.QGISであればWEB系のエンジニアではなくても、国土地理院のベクタータイル地図を使って自分好みのカスタマイズ地図を作成可能であることがお分かりいただけたことと思う.
QGISのベクタータイルのハンドリング機能についてはまだ発展途上で未完成ではあるが、ベクタータイル方式の地図が今後の主流になると思われるので、QGISがバージョンアップされるに従ってベクタータイルの取り扱いが改善されて行くだろう.
現時点では、国土地理院のベクタータイル地図をQGISに取り込んで有効活用しようとしても、掛けた労力に見合った成果が得られない.WEBシステム開発のスキルを有しているのであれば、Mapbox GLなどを利用してWEBマップシステムを作成するほうが自由度が大きく、掛ける手間も少なくて済むのではないかと思う.