グリッドPNGタイル


 グリッドPNGタイルとは,データを表現するための地図タイルで,インターネットを通じて地図上の面的なデータを提供するベースとなるフォーマットです.ユーザーの要望に応じて柔軟かつ高速に利用できることを目的としています.通常のウェブ地図で利用されている地図画像のタイルマップを数値データに応用したもので,インターラクティブなウェブ地図サービスの構築が可能になります.
 グリッドPNGタイルの仕様は以下のサブページにまとめています.

グリッドPNGタイル 仕様
 PNGを使ってデータを表現したものをデータPNGと総称しています.グリッドPNGタイルは,データPNGで格子データを表現するグリッドPNGを地図タイルとして利用したものです.グリッドPNGタイルはデータPNGが最も活用されている分野です.

配信サービス例


 2020年12月15日現在,グリッドPNGタイル仕様準拠を明示してしているサービスはありませんが,以下のような既存のサービスはグリッドPNGタイル仕様に適合しています.
 また,Mapbox GL JSで使用されているMapbox Terrain-RGBという標高タイルフォーマットも数値PNGタイルに適合しています(係数0.1,オフセット-10000になります).

国土地理院 標高タイルPNG形式

 国土地理院は「テキスト形式」及び「PNG形式」の標高タイルを公開しており,これらのうち「PNG形式」はグリッドPNGタイルの数値PNGタイルに適合しています.タイルセットには以下の2種類があります.

標高タイル(基盤地図情報数値標高モデル)
標高タイル(地球地図全球版標高第2版)
上記のタイルはcm単位の標高値を整数値として保持しています.また無効値を示す色としてRGB=(128,0,0)を使用しています.

産総研 シームレス標高タイル

 産総研のシームレス標高タイルで公開されているタイルは,すべてグリッドPNGタイルの数値PNGタイルに適合しています.cm単位の標高値を整数値として保持しています.

シームレス標高タイル

国土交通省 「重ねるハザードマップ」データ配信

 国土交通省ハザードマップポータルサイトでは,「重ねるハザードマップ」で使用している洪水や土砂災害に関するタイルデータを公開しており,これらはグリッドPNGタイルのパレットPNGタイルに適合しています.

国土交通省ハザードマップポータルサイト-「重ねるハザードマップ」のデータ配信について

産総研 20万分の1日本シームレス地質図

 産総研の20万の分の1日本シームレス地質図V2 Web APIのタイルサービスで提供されているレイヤーg(地質レイヤー)のみのタイルはグリッドPNGタイルのパレットPNGタイルに適合しています.

20万の分の1日本シームレス地質図V2 Web API - タイルサービス

利用方法


 グリッドPNGタイルを利用するには,通常はJavaScriptを使ってプログラムを書き,ウェブブラウザで表示させます.

1. 地図として表示

 一般的な地図タイルと同じタイル分割方法ですので,地理院地図などのいくつかのウェブページでは外部タイルを読み込んで表示する機能を使い,表示させるだけでしたらJavaScriptを使わずに行うことができます.通常は, Leaflet,OpenLayers, Google Maps API等の地図表示JavaScriptライブラリを使って,Webブラウザ上に地図として表示させます.
 ただし,20万分の1日本シームレス地質図などではもともと表示用のタイルですので意味がありますが,通常はそのまま表示してもあまり価値がありません.有効活用するためには次項以降のようにプログラムで処理する必要があります.

2. 位置を指定して値を取得

 緯度経度などで位置を指定して,その位置に対応する値を取得することができます.
 この場合,地図タイルにはズームレベルの概念があることに注意してください.指定できるのはあくまでもセル(矩形範囲)であり,その大きさはズームレベルにより異なります.そして,得られる値がその範囲のどの部分に関連付けられるか(中央なのか,北西なのか,ピクセル全体なのかなど)は,タイルを提供するサービスによって異なります.例えば,シームレス標高タイルでは,ピクセルの北西端の標高値を表しています.
 位置を指定して値を取得するステップは以下の通りです.

     
  1. 緯度経度等からタイル座標及びピクセルのタイル内座標を求める
    • 通常は地図ライブラリ内の関数を使用します.
    • 独自に計算してもさほど複雑な式ではありません
  2. タイル画像から該当するピクセルの色を取り出し,値に変換する
    • Imageオブジェクトを作成してタイル画像をロードし,Canvasオブジェクトを使って色を取り出します
    • グリッドPNGタイルの配信仕様に従って,R,G,B値から値を求めす
 Canvasオブジェクトを使って色を取り出しますので,ローカルで直接扱おうとするとクロスオリジンエラーが出て扱えません.この場合は,別途Apache等のHTTPサーバ環境を作ってそこで動作させます.

数値PNGタイル

 数値PNGタイルの場合は,係数,オフセットの値を使って,R,G,B値から数値を求めます.
 以下にJavaScriptによるサンプル関数を示します.
/// ****************
// latLngToTile 緯度経度をタイル座標に変換する関数
//  latLng: 緯度経度オブジェクト(lat,lngフィールドを持ちます)
//  z: ズームレベル
//  戻り値: タイル座標オブジェクト(x, yフィールドを持ちます)
//    ※通常,地図ライブラリ内に同様の関数が用意されています.
/// ****************
function latLngToTile( latLng, z ) {
	const
		w = Math.pow( 2, ( z === undefined ) ? 0 : z ) / 2,		// 世界全体のピクセル幅
		yrad = Math.log( Math.tan( Math.PI * ( 90 + latLng.lat ) / 360) );

	return { x: ( latLng.lng / 180 + 1 ) * w, y: ( 1 - yrad / Math.PI) * w };
};

/// ****************
// getNumericalValue タイルURL,座標,ズームレベルを指定して数値を取得する関数
//	url: タイル画像のURLテンプレート.
//		ズームレベル,X, Y座標をそれぞれ{z},{x},{y}として埋め込む
//	ll: 緯度経度オブジェクト(lat,lngフィールドを持ちます)
//  z: ズームレベル
//  factor: 数値を求めるときに使用する係数,デフォルト1
//  offset: 数値を求めるときに使用するオフセット,デフォルト0
//  invalid: 追加無効値を相当する数値で指定.デフォルトは指定なし
//  戻り値: 成功時に数値を受け取るプロミス.無効値の場合はNaNを受け取ります
/// ****************
function getNumericalValue( url, ll, z, factor = 1 , offset = 0, invalid = undefined ) {
	return new Promise( function( resolve, reject ) {
		const
			p = latLngToTile( ll, z ),
			x = Math.floor( p.x ),			// タイルX座標
			y = Math.floor( p.y ),			// タイルY座標
			i = ( p.x - x ) * 256,			// タイル内i座標
			j = ( p.y - y ) * 256,			// タイル内j座標
			img = new Image();

		img.crossOrigin = 'anonymous';	// 画像ファイルからデータを取り出すために必要です
		img.onload = function(){
			const
				canvas = document.createElement( 'canvas' ),
				context = canvas.getContext( '2d' );
			let
				r2,
				v,
				data;

			canvas.width = 1;
			canvas.height = 1;
			context.drawImage( img, i, j, 1, 1, 0, 0, 1, 1 );
			data = context.getImageData( 0, 0, 1, 1 ).data;
			r2 = ( data[ 0 ] < 2**7 ) ? data[ 0 ] : data[ 0 ] - 2**8;
			v = r2 * 2**16 + data[ 1 ] * 2**8 + data[ 2 ];
			if ( data[ 3 ] !== 255 || ( invalid != undefined && v == invalid ) ) {
				v = NaN;
			}
			resolve( v * factor+ offset );
		}
		img.onerror = function(){
			reject( null );
		}
		img.src = url.replace( '{z}', z ).replace( '{y}', y ).replace( '{x}', x );
	} );
};
 上記の関数とLeafletを使ったサンプルプログラムを以下に示します.  

パレットPNGタイル

 パレットPNGタイルの場合は,凡例情報内を検索して,R,G,B値がい一致する凡例項目を求めます.
 以下にJavaScriptによるサンプル関数を示します.
/// ****************
// getLegendItem 凡例情報,タイルURL,座標,ズームレベルを指定して凡例項目を取得する関数
//  legend: 凡例情報オブジェクト.r,g,b,titleを持つ凡例項目オブジェクトの配列
//	url: タイル画像のURLテンプレート.
//		ズームレベル,X, Y座標をそれぞれ{z},{x},{y}として埋め込む
//	ll: 緯度経度オブジェクト(lat,lngフィールドを持ちます)
//  z: ズームレベル
//  invalid: 追加無効値を相当する数値で指定.デフォルトは指定なし
//  戻り値: 成功時に凡例項目オブジェクトを受け取るプロミス.該当するものがない場合はnullを受け取ります
/// ****************
function getLegendItem( legend, url, ll, z, invalid = undefined ) {
	return new Promise( function( resolve, reject ) {
		const
			p = latLngToTile( ll, z ),
			x = Math.floor( p.x ),			// タイルX座標
			y = Math.floor( p.y ),			// タイルY座標
			i = ( p.x - x ) * 256,			// タイル内i座標
			j = ( p.y - y ) * 256,			// タイル内j座標
			img = new Image();

		img.crossOrigin = 'anonymous';	// 画像ファイルからデータを取り出すために必要です
		img.onload = function(){
			const
				canvas = document.createElement( 'canvas' ),
				context = canvas.getContext( '2d' );
			let
				v,
				d;

			canvas.width = 1;
			canvas.height = 1;
			context.drawImage( img, i, j, 1, 1, 0, 0, 1, 1 );
			d = context.getImageData( 0, 0, 1, 1 ).data;
			if ( d[ 3 ] !== 255 ) {
				v = null;
			} else {
				v = legend.find( o => o.r == d[ 0 ] && o.g == d[ 1 ] && o.b == d[ 2 ] )
			}
			resolve( v );
		}
		img.onerror = function(){
			resolve( null );
		}
		img.src = url.replace( '{z}', z ).replace( '{y}', y ).replace( '{x}', x );
	} );
};
 上記の関数とLeafletを使ったサンプルプログラムを以下に示します.  

3. 3Dで表示

 標高データの場合はCesium等の3D描画ライブラリで地形データとして利用できます.Cesiumの場合は利用するための追加プログラムが必要です(本サイトでPNG標高タイルTerrainProviderを公開しています).
 なお,標高データ以外のデータPNGタイルでも,PNG標高タイルTerrainProviderを使って,標高データの代りに地形に反映させることができます.

※PNG標高タイルTerrainProviderは値をメートル単位として扱います.起伏が激しすぎる(または緩すぎる)場合は,オプションのheightScaleを指定して調整してください.

4. タイル画像を処理して地図表示

 通常の地図描画ライブラリには,何らかの方法で元タイルを処理してから地図に表示する方法があります.これを利用して,グリッドPNGタイルに何らかの処理を加えて,用途に応じた変換を行ってから表示することができます.例えば,標高タイルを処理して標高ごとに色分けした段彩図を描くことができます.また,隣のピクセルの値との差分を取って傾斜量図を描くことも可能です.
 Leafletを使って,ユーザーが指定した凡例だけを標示するサンプルプログラムを以下に示します.  

5. 複数のグリッドPNGタイルを使って演算

 より高度な使い方として,複数のグリッドPNGタイルの間で演算を行い,その結果を地図表示させることができます.例えば傾斜量と降水量のタイルから地滑り危険地を抽出して表示するといったことが可能になります.

作成方法


 グリッドPNGタイルの作成方法はおおむね以下のような工程にわけられます.

  1. グリッドデータをPNG化(データPNGと呼んでいます)
  2. データPNGの投影法,範囲などを指定してタイルを生成

1. グリッドデータをPNG化

 グリッドデータは,CSV,GeoTiff,NetCDFなどで提供されます.これらをPNGに変換します.PNGへの変換では,値のR,G,B分解が必要ですが,既存のGISアプリケーションやツールには対応しているものがほとんどないので,独自にプログラムを作成する必要があるかと思われます.ただし,仕様はシンプルですので変換プログラムの作成は比較的簡単です.

2. データPNGの投影法,範囲などを指定してタイルを生成

 いったんデータPNGにすると,後は様々なGISアプリケーションやツールでタイル化が可能です.この工程は通常の地図タイルと同じなので,一般的なGISアプリですとたいてい対応可能です.
 ただし,データPNGタイルの場合はデータの性質によってリサンプルアルゴリズムを適切に選ぶ必要があります.通常は平滑化や最近隣方が選ばれますが,データによって好ましくない場合もあります.例えば地質図の場合は,低解像度では小さいポリゴンはつぶれてしまうので,多数決解決法(ある範囲内で最も出現度が多い値を採用する)が優れている場合が多いです.
 また,パレットPNGタイルの場合は,ポリゴン境界部でディザがかからないように注意する必要があります.

解説


コンセプト

 グリッドPNGタイルの設計コンセプトは「Web Cookable Data」(Webで調理可能なデータ)です.位置情報を持った面的なデータをウェブを使って提供し,それを様々に加工するサービスの構築を支援するためのフォーマットです.特に大量データの場合に力を発揮します.データ量が少ない場合もタイル分割するメリットが少なくはなりますが,他のタイルデータと組み合わせて利用する場合などはグリッドPNGタイルマップで提供することは有効です.
 グリッドPNGタイルの背景にある考え方は,ユーザに柔軟でテンポの良いアプリケーションを提供するために,データを扱いやすいサイズに分け,汎用的なフォーマットを利用するということです.この手法により,リアルタイムでの高速な変換が可能になります.

地図タイルについて

 グリッドPNGタイルは,現在のほとんどのWeb地図サービスで利用されている地図タイルをデータに応用したものです.地図タイルは,大量の地図データをユーザ環境で高速に扱うために考案されたもので,地図画像を正方形の小さなタイルに分割し,サーバ側に設置して利用する方法です.地図タイルセットには異なる解像度(ズームレベル)のものが含まれており,ユーザ側のパソコンは必要なときに必要な解像度と範囲のタイル画像をサーバに要求することにより,最低限のコストで最高のパフォーマンスが得られるように工夫されています.

投影法

 グリッドPNGタイルは,地図投影法やタイルの分割法については規定しませんが,通常の地図タイルで使われているグーグルマップ互換のWebメルカトル図法を用いるのがもっとも一般的であると思われます.地理院タイルでも同様のものが用いられています.
 一方,Webメルカトル図法では北極や南極付近が表現できません.これらの地域も表現したい場合は,正距円筒図法(緯度と経度をそのまま座標に読み替えるような投影法)によるタイルが最も有効です.
 グリッドPNGタイルは比較的広い範囲のデータを提供する場合に有効な方法なので,上記2種類の投影法以外が用いられることはあまりないと思われますが,解像度が高い情報を,ある程度広範囲で提供したい場合はUTMや平面直角座標系でも有効です.しかし,将来的に他のデータとの連携を考えるとWebメルカトルか正距円筒図法に変換して提供する方が良いでしょう.

ピクセルの色の扱い方

 あるピクセルのR,G,B値の扱い方は提供するサービスの仕様に依存しますが,グリッドPNGタイルの数値PNGタイルでは浮動小数点数として扱う方法,パレットPNGタイルでは24ビット符号無し整数として扱う方法を示しています.
 また,R,G,B値の取り扱い方は,大きく離散型と連続型に分けることができます.

 さらに,24bitのデータ幅を2つに分割して12ビットづつの2つの値でベクトルを表現したり,24bit浮動小数点として精度の大きく異なるデータが混在する場合に対応するなど,様々な応用が考えられます.

ピクセルの値と地図上の範囲との関係

 データタイルマップの画像の1つのピクセルは,地図上のある矩形の範囲に対応します.
 データタイルマップのピクセルが示す値とこの範囲との関係は,提供されるサービスの仕様に依存しますが,大きく2つにわけられます.

 タイル作成という立場から見た場合,上記の例の中では,セルの北西端とした場合がもっとも単純なアルゴリズムとなります.この場合,あるズームレベルから1つ小さいズームレベルのタイル画像を生成するには,単純に4つのうちの左上のピクセルの値をとれば良いことになります.