点群描画手順

Leaflet上でWebGLを用いて点群を描画する手順について記述(点群PNG0.6を考慮)。

描画先

識別子取得で使用する場合はフレームバッファに描画する(アンチエイリアス無効で色取得可能なため)。

JavaScriptの記述

計算が必要な部分のみ抜粋。uSubtractionOffsetは係数常用対数処理して減算。

const pcpngOffset = [ 0, 0 ];  //点群PNGのオフセット値
const canvasOrigin = [ 0, 0 ]; //Canvas左上座標(Canvasオフセット値)
//uLogarithmとして送る
const logarithm = [ 0, 0 ];    //点群PNGの係数常用対数
//uSubtractionOffsetとして送る
const subtractionOffset = [
  pcpngOffset[0] / Math.pow( 10, logarithm[0] ) - canvasOrigin[0], //係数常用対数処理後に減算
  pcpngOffset[1] / Math.pow( 10, logarithm[1] ) - canvasOrigin[1], //係数常用対数処理後に減算
];

頂点シェーダの記述

点群座標がxyそれぞれ1ピクセルで表現されていると仮定。

//**************************************
//変数
attribute vec4 aPositionX;       //点群x座標のrgba(0 - 255)
attribute vec4 aPositionY;       //点群y座標のrgba(0 - 255)
uniform vec2 uLogarithm;         //点群座標(xとy)の係数常用対数(-128 - 127)
uniform float uSubtractionWmd;   //表示中地図に対する点群のウェブメルカトル次数の差(*1)
uniform vec2 uSubtractionOffset; //点群オフセットに対するCanvas原点の差(*2)
uniform vec2 uInvViewDimension;  //Canvasの幅と高さの逆数
//*1:出力ウェブメルカトル次数 - 点群メルカトル次数
//*2:点群オフセット - Canvas原点(出力するウェブメルカトル次数における)
//**************************************
//ピクセル値(符号付き)計算関数
float rgbaToNumberSigned ( rgba_ ) {
  float r = rgba_.r < 128.0 ? rgba_.r : rgba.r - 255.0;
  float g = rgba_.r < 128.0 ? rgba_.g : rgba.g - 255.0;
  float b = rgba_.r < 128.0 ? rgba_.b : rgba.b - 256.0;
  return r * 256.0 * 256.0 + g * 256.0 + b;
}
//**************************************
//メイン関数
void main ( void ) {
  //点群のウェブメルカトル次数での座標(ここではオフセット値含めず)
  float x = rgbaToNumberSigned( aPositionX )  //ピクセル値を計算
          * pow( 10.0, uLogarithm.x * -1.0 ); //係数常用対数の処理
  float y = rgbaToNumberSigned( aPositionY )  //ピクセル値を計算
          * pow( 10.0, uLogarithm.y * -1.0 ); //係数常用対数の処理
  //出力用ウェブメルカトル次数に変換
  vec2 xy = vec2( x, y ) //vec2にする
          * pow( 2.0, uSubtractionWmd )       //地図のウェブメルカトル次数に変換
          + uSubtractionOffset;               //オフセット差分を加算
  //左上原点0to1座標系に変換
  xy *= uInvViewDimension;
  //中心原点-1to1座標系に変換
  xy = xy * vec2( 1.0, -1.0 ) * 2.0
     + vec2( -1.0, 1.0 );
  //頂点座標決定
  gl_Position = vec4( xy, 0.0, 1.0 );
}

注意事項

highp指定での精度保証(絶対ではない)はWebGLで16ビット(最近の環境では23ビット程度は大丈夫な様子)、WebGL2.0で24ビットとのことなので、WebGL2.0対応で記述するべき(WebGL2.0では24ビット保証)。

rgbaToNumberSigned関数を工夫すれば23ビットの範囲で収まるので、モバイル環境を除けば基本的にWebGLでも対応可能。

rgbaToNumberSigned関数を書き換えて、これで23ビットの範囲に収まるか。「点群オフセットに対するCanvas原点の差」が収まらないか(よく調べる)。

描画条件

  • 画面は4K(3,840×2,160)を最大とする
    23ビットの範囲内
  • 点群座標(xy)は23ビット符号付き
    23ビットの範囲内(多分)
  • 点群オフセットとCanvas原点との差
    23ビットの範囲内に収まるとは限らない

画面の範囲内に収まらない位置にある点の座標値は23ビットの範囲内に収まらない可能性があるが、そのような点は画面に表示されないので23ビットを超えていても問題にならない。

点群座標のウェブメルカトル次数より高いウェブメルカトル次数で表示する際は点の座標値が23ビットの範囲に収まらない可能性がある。