MapLibre – GeoJSONのソースを描画する

基本形

  • Mapオブジェクトのonメソッドで、マップのロード後処理として記述する
  • MapオブジェクトのaddSourceメソッドで図形を定義し、addLayerメソッドでレンダリング方法などを記述する
  • addLayerでソースIDを指定する

addSource

  • 第1引数でソースIDを設定し、第2引数に図形のGeoJSONを記述する

addLayer

詳細はMapLibreのLayerのドキュメントを参照。

  • id:一意なレイヤーID
  • type:形状タイプ
    • 'fill', 'line', 'symbol', 'circle', 'heatmap', 'fill-extrusion', 'raster', 'hillshade', 'background'
    • 形状タイプごとの描画仕様は、その内容によってlayoutpaintで指定する
  • source:このレイヤーに描かれるソースのIDを指定
  • layout:形状タイプごとの描画スタイルを設定
    • たとえば'line'の場合、'line-width', 'line-cap', 'line-join'など
  • paint:図形を描く色などを指定
    • たとえば'circle'の場合、'circle-color', 'circle-radius'など

図形の描画例

 

MapLibre – 多角形を描く

1つの多角形を描く

多角形(’Polygon')は'coordinates'を多角形の頂点の3次元配列で与え、始点と終点で同じ座標とする。レイアウトの'type''fill'

以下の例では、ベクトルタイルの地理院地図上に3つの頂点を持つ三角形を描いている。'paint'で外枠の線を青、塗りつぶしの色を緑、塗りつぶしの不透明度を0.4としている。

dataで直接Polygonを指定できる。

複数の多角形を描く

以下の例ではaddSourceで2つのPolygonを描いている。addLayoutは上と同じものを使っており、addSourceaddLayermap.onメソッド内で実行させる。

'FeatureCollection'の代わりに直接'MultiPolygon'で書くと以下の通り。Polygonの場合は頂点の経緯度配列の3次元配列だったが、MultiPolygonの場合はさらにそれらの配列、4次元配列になる

これは折れ線の時と比べるとおかしく思えるが、後述のように1つの図形で複数の閉曲線を持つ場合があるためと考えられる。

捩じれたポリゴンは描けない

以下のように捩じれたポリゴンは描かれない。

ドーナッツは描ける

1つのフィーチャーで外側のポリゴンに内側のポリゴンが収まっていれば、描画方向に関わらずドーナッツのようなポリゴンになる。ただしドーナッツの穴の中にポリゴンを置くとうまく描かれない。

 

MapLibre – 折れ線を描く

1つの折れ線を描く

折れ線(LineString)は'coordinates'を折れ線の各点の2次元配列として与える。以下の例では、ベクトルタイルの地理院地図上に3つの点を結ぶ折れ線を描いている。レイアウトの'type''line'。線の色と太さは'paint'で設定し、'layout'では線の端部を丸く、折れ線の角を尖らせている。

dataで直接'LineString'を指定できる。

複数の折れ線を描く

以下の例ではaddSourceで2つのLineStringを描いている。addLayoutは上と同じものを使っており、addSourceaddLayermap.onメソッド内で実行させる。

'FeatureCollection'の代わりに直接'MultiLineString'で書くと以下の通り。LineStringの場合は通過点の経緯度の配列の2次元配列だったが、MultiLineStringの場合はさらにそれらの配列、3次元配列になっている。

 

MapLibre – 点を描く

1つの点を描く

以下の例では、ベクトルタイルの地理院地図の中央に1つの点を描き、そのスタイルを半径20の青い丸と設定している。

dataで直接'Point'を指定できる。

複数の点を描く

以下の例ではdata'type''FeatureCollection'として2つの点を描いている。点を青い丸で描くレイアウトは上と同じ。

'FeatureCollection'の代わりに直接'MultiPoint'で描くと以下の通り。Pointのときは経度・緯度を要素とする配列だったが、MultiPointの場合はそれらの2次元配列になっている。

 

MapLibre – MapBoxDrawによる描画機能

実装例

手順

  1. head要素内で以下を読み込む
    • turf.js:空間演算用のライブラリー(Turf.js)
    • mapbox-gl-draw.js
    • mapbox-gl-draw.css
  2. Mapオブジェクトを生成する
  3. MapboxDrawオブジェクトを生成する
  4. 生成したMapboxDrawオブジェクトをMapオブジェクトのコントロールとして追加する

MapBoxDrawコンストラクターのパラメーター

パラメーターなしの場合

パラメーターなしの場合、Line、Polygon、Point、trashとCombine、Uncombineのボタンが準備される。

パラメーターありの場合

表示されるボタンを選ぶことができる。

  1. displayControlsDefaultfalseにセット
  2. controlsの連想配列で必要なボタンをtrueにセット
    • line_string, polygon, point, trash, combine_features, uncombine_features

 

Linux – 削除できません: 許可されていない操作です

Vagrantの共有ディレクトリーにホスト側のWindowsからディレクトリーをコピーしてmvやrmdirを実行しようとしたとき、以下のようなエラーになった。

rm: `...'を削除できません: 許可されていない操作です
rm: cannot remove `...': Operation not permitted

この場合、ディレクトリーのスティッキービットを外すことで通常通り削除が可能になる。

単一のディレクトリーのスティッキービットを外すには以下の通り入力。

ディレクトリー下に再帰的に行うには以下の通り入力。

 

MapLibre – 表示の基本 – 地理院地図の例

基本形

有償となったMapBoxの代わりにオープンソースのMapLibreで地理院地図ベクトルタイルを表示する例。

要点は以下の通り。

  • 冒頭でサイトからライブラリーとスタイルを読み込むか、あらかじめダウンロードしておいたライブラリーを指定する
  • マップを表示するコンテナー要素を準備する
  • スクリプトでmaplibregl.Mapクラスのインスタンスを生成する
    • コンテナーに準備した要素のidを指定
    • 地理院地図のスタイルを指定
    • 地図表示の中心経緯度を指定~経度・緯度の順番なので注意
    • ズーム関係のパラメーターを指定

デフォルトでのマウス/キー操作

デフォルト設定では、以下のマウス操作が可能になっている。

  • ドラッグによる地図の移動
  • SHIFT+ドラッグによるボックスズームイン
  • CTRL+ドラッグによる回転と傾斜
  • ダブルクリックによるズームイン
  • SHIFT+ダブルクリックによるズームアウト

また、地図コンテナーにフォーカスがある状態で以下のキー操作が可能

  • カーソルキーによる地図の移動
  • SHIFT+←/→キーによる地図の回転
  • SHIFT+↑/↓キーによる傾斜

スタイルでソースを指定している

上記コードでは、表示させるターゲットの地理院地図ベクトルタイルが明示されていないが、実はターゲットとなるデータはstyleで示されるJSON中で指定されている。

  • sourceのIDは"gsibv-vectortile-source-1-4-16"
  • layerのIDは"gsibv-vectortile-layer-761"
  • sourceで指定するtilesは、地理院サイトで示されているURL

タイル画像のズームについて

概要

地理院タイルの画像を並べて表示し、ズームイン/ズームアウトの機能を実装したときの整理。マウスカーソルを置いた位置を固定して、そこを中心にズームイン/ズームアウトをするのにちょっと手間取った。

基本の考え方

共通する考え方は以下の通り。

  1. マウスクリック位置を記録する
  2. 拡大/縮小対象のタイルを拡大/縮小し、マウス位置もそれに合わせて変換
  3. 変換後の位置がマウス位置に重なるよう、タイルを平行移動

なお地理院タイルではタイルそのものを表す「タイル座標」を定義しているが、ピクセルの座標との区別を明確にするため、ここでは「タイルアドレス」と表現し、ピクセル単位の座標を「ピクセル座標」と表現する。

ズームインの場合

ズームインの場合、マウス位置がタイルの左側か右側か、上側か下側かによって拡大するタイルやスライドの方向・量が異なる。以下ではxとyがともに左・上、右・下のケースで整理しているが、xとyは独立に判定してよい。

マウス位置がタイルの幅/高さの半分未満の時

下図の緑色のタイルが現在表示されているタイルでタイルの幅をw、高さをhとする。また黒い点(x, y)をマウス位置とする。位置(x, y)はタイル左上の点からのオフセットで表しているが、タイルを表示するcanvasなどの座標に相当する。

タイルアドレスをr/cとして、マウス位置がタイルの幅/高さの半分より左/上の場合を考える。拡大するタイルはr/cに対して青いタイル2r/2cで、拡大前の幅w/2、高さh/2が2倍になり、元のタイルと同じサイズになる。

拡大後のタイルでは、マウス位置(x, y)にあった地上の位置はタイルの拡大につれて(2x, 2y)となる。マウス位置(x, y)は拡大後のタイル上でも同じ。

拡大後の地上の位置を元の位置に合わせるためタイルをスライドさせる。スライド量は(2x, 2y)と(x, y)の差(x, y)で、スライド方向は左上の方向。

マウス位置がタイルの幅/高さの半分以上の時

元のタイルr/cに対して拡大するタイルは2r+1/2c+1となる。また、拡大するタイル内での地上位置のオフセットは(x – w/2, y – h/2)となる。

タイルを拡大すると、地上の位置のオフセットは(2x – w, 2y – h)となる。マウス位置は(x, y)のまま。

地上の位置をマウス位置に合わせるためタイルをスライドさせる。スライド量は(x, y)と(2x – w, 2y – h)の差で(w – x, h – y)。スライド方向は右下の方向。

ズームアウトの場合

ズームインの場合、タイルアドレスが偶数か奇数かによって縮小するタイルやスライドの方向・量が異なる。以下ではxとyがともに偶数/基数のケースで整理しているが、xとyは独立に判定してよい。

タイルアドレスが偶数の場合

緑色のタイルが現在表示されているタイルで、アドレスが偶数の場合、縮小するタイルは右/下方向に広がった青いタイルr/c。その幅・高さは2w、2cから半分のw、cとなる。サイズが半分になる前の地上位置のオフセットは、(x, y)。

ここではタイルのサイズを上の図の2倍のサイズで描いている。タイル縮小後の元の位置は、タイル幅/高さが1/2になるのに伴って(x/2, y/2)となる。マウス位置(x, y)は元のまま。

地上の位置をマウス位置に合わせるためタイルをスライドさせる。スライド量は(x, y)と(x/2, y/2)の差で(x/2, y/2)。スライド方向は右下の方向。

タイルアドレスが奇数の場合

緑色のタイルが現在表示されているタイルで、アドレスが奇数の場合縮小するタイルは左/上方向に広がった青いタイルr/c。縮小するタイル上での縮小前の地上位置のオフセットは(x + w, y +h)

ここではタイルのサイズを上の図の2倍のサイズで描いている。タイル縮小後の元の位置は、タイル幅/高さが1/2になるのに伴って((x + w)/2, (y + h)/2)となる。マウス位置(x, y)は元のまま。

地上の位置をマウス位置に合わせるためタイルをスライドさせる。スライド量は((x + w)/2, (y + h)/2と(x/2, y/2)の差で((w – x)/2, (h – y)/2)。スライド方向は左上の方向。

 

地理院タイル

概要

国土地理院により、ラスタータイプのタイル地図が「地理院タイル」として提供されている。その仕様についてまとめてみた。

地理院タイルの考え方

地理院タイルは、地球全体をメルカトル投影により正方形化し、それがズームレベルに従って辺長1/2のエリアに分割されていく。

  1. 経緯度表現の全球をメルカトル投影により変換
  2. 投影後の形が正方形になるよう南北を制限
  3. 投影後正方形の地球全図をズームレベル0とする
  4. その後順次、同じ範囲に辺長を1/2の正方形が収まるよう分割

具体のタイル

具体の地理院タイルとタイル座標はタイル座標確認ページで確認できる。最小ズームレベル2で表示すると以下のように横長く表示されるが、正方形の世界全図が経度方向に繰り返されているのがわかる。

たとえば2/1/3のタイルの場合、ズームレベルが2、タイルのx座標、y座標がそれぞれ1、3ということになる。

ズームイン

ズームレベルを日本付近で上げていくと詳細な地図に変化していく。以下は首都圏付近のズームレベル9のタイル。首都圏中心部のタイルは454/201となっている。

最大ズームレベル18のタイルまで準備されている。以下は日本水準原点付近のタイルの例。

日本付近ではズームレベル18まで準備されているが、それ以外の地域で準備されているタイルはズームレベル8まで。以下は与那国島~台湾付近を順次拡大していった様子。

タイル座標

たとえばズームレベル2の場合、タイル座標は0/0~3/3、縦4×横4の16タイルで構成されている。ズームレベルが3になると、タイル座標は0/0~7/7、縦8×横8の64タイルで構成されている。

つまり、ズームレベルがzのとき、タイル座標は0~2z、タイルの枚数は2z×2z=22z枚ということになる。

タイルの取得

以下のURLを指定して、地理院サイトからタイル画像を取得することができる。

{t}は「データID」で、標準地図ならstd、単色地図ならpaleなどのコードが与えられている。{z}はズームレベル、{x}{y}はタイル座標値、{ext}は拡張子で、たとえば標準地図や単色地図ならpng

タイルピクセル

タイルサイズは、ズームレベルに関わらず256ピクセル×256ピクセルとなっている。

たとえばズームレベル2の場合は縦横256×4=1024ピクセルで構成され、ズームレベルが3になると縦横256×8=2048ピクセルでズームレベル2の時の倍のピクセル数となる。

一般にズームレベルzのとき、全球地図の縦・横のタイルピクセル数は256×2zとなり、ズームレベルが1つ上がるごとに倍になっていく。

タイル座標とタイルピクセル位置の関係

タイル座標とタイルピクセル位置の関係は、int(タイルピクセル位置/256)となる。そしてタイルピクセル位置からタイル座標値の256倍を引いた値(タイルピクセル位置を256で割った剰余)は、そのタイルピクセルを含むタイル内でのピクセルのオフセット位置になる。

たとえばズームレベル2の場合、(896, 448)のピクセルが属するタイルは3/1となり、このタイル内でのピクセルのオフセットは(128, 192)となる。

 

QGIS3 – 都道府県区域への融合

概要

国土数値情報で読み込み市区町村単位でマルチパート化したポリゴンを、都道府県単位にまとめる。

複数のポリゴンの接する境界をなくしてひとつながりのポリゴンとするため、Dissolveという処理を行う。

令和4年度の行政区域データでは「無効なジオメトリ」のために処理ができなかったため、これを無視する手順も記録した。

Dissolve処理~無効なGeometryで停止

Dissolve(融合)はメニューの「ベクタ」→「融合(dissolve)」を選択する。

すると以下のようなダイアログが表示される。

ここでポリゴンを融合するキーを選択するため、「基準となる属性」を選んでいく。右にある”…”をクリックするとパラメーター選択の表示になるので、都道府県の属性N03_001にチェックを入れてOKをクリック。

もとのダイアログに戻るので「実行」ボタンをクリック。ところが、この時点で以下のようなエラーが出て処理が停止した。

無効なジオメトリがあるので処理が停止したとのこと。これを確認してみたが、無効な部分を最大に拡大しても特に交差しているなどの形は見られなかった。

無効なジオメトリーの無視設定

ここではプロセッシングツールで無効なジオメトリーを無視するよう設定した。この設定では無効なジオメトリーを修正はせず、無視して実行が続けられる。

都道府県単位の融合結果

上記の設定後にDissolve処理を実行すると、警告は表示されるものの処理は続行されて完了。以下のように都道府県単位にポリゴンがまとめられた。

なお、新たにまとめられた都道府県のポリゴンが入っているレイヤーが作成されるが、一時レイヤーの場合はこれを保存しておく。

属性テーブルを確認すると、以下のように都道府県に対応する47個のオブジェクトにまとめられている。

ただしまとめられたオブジェクトの属性は、たまたま先頭にあったレコードのものが用いられる。このため自治体コードは市区町村のものだったり、NULLであったりする。