正距方位図法で描画した地図に対する経緯線の描画をWebGLで実装する方法。
経線・緯線に沿った点列を生成しそれを正方向の投影変換を掛けた上でラインとして結合して描画する方法ではなく、逆方向の投影変換を用いてほとんどの演算をWebGL側で実施し描画する方法について。
目的
- 画像を正距方位図法で投影して描画した地図上に経緯線を重ねたい。
- 参考: WebGLによる画像の正距方位図法への投影変換
- JavaScriptで点列を生成して曲線を描画する方法ではいくつか難点があり、それを改善したい。
- 特にパフォーマンス面を改善したい。
以前の方法
当初は経緯線の描画として以下のような方法を使用していた。考え方としてはごく普通の方法。
- 緯度経度座標系上で、緯度あるいは経度が固定の値をとる点列を生成。
- 生成した点列に対して正方向の投影変換で座標変換を実施。
- 変換した点列を元にラインとして結合して描画。
この方法は考え方はシンプルだが、以下のようなデメリットがある。
- 滑らかな曲線を描画しようとすると、密な点列を生成する必要がある。
- 外周部(対蹠点)付近では、いくら点列を密に生成したところで大きな飛びが発生してしまう。
- 上記の結果、滑らかな緯線・経線を描画しようとすると、処理が結構重くなる。
- 外周部(対蹠点)付近での飛びの対策や、曲率の変化に応じた点列の密度の調整などを考慮すると、点列の生成処理が簡単ではなくなる。
特にスマホなどの端末ではパフォーマンス上の問題が大きく、これを改善するために次のような抜本的な変更を行った。
改善した方法
概要
改善した方法では、正方向ではなく逆方向の投影変換を使用する。予め点列を生成することも行わない。基本的にほとんどの演算と描画がWebGLだけで完結する。
考え方のイメージは以下の通り。
- 経緯線の間隔ごと(例えば10度ごと)に色を塗り分けた緯度経度座標系上の画像を生成する。
- 生成した画像に正距方位図法の投影変換を適用する。
- 投影変換された画像に対し、LaplacianフィルタやSobelフィルタなどを用いてエッジを検出し、それを元に経緯線として描画する。
但し実際には内部では画像は生成しておらず、色を塗り分けるための関数と投影変換の処理を直接使用して線を求めている。画像の投影変換と同じような処理となるため、逆方向の投影変換を使用することとなる。
実際には、経度±180度付近での不連続性などへの対応などの細かい調整も必要となる。
実装例
正距方位図法の場合の実装例は以下の通り。
- ソースコード
- https://github.com/tomosn/simple-raster-projection/blob/master/graticule-aeqd.html
- 表示例
- 経緯線のみの場合
- 画像付きの場合
※ 画像付きの場合については20度間隔に設定。
評価
以前の方法と比較し、以下のような利点あり。
- パフォーマンスの改善。特にスマホからの表示時のパフォーマンスが大幅に改善。
- 外周部(対蹠点)付近でも特別な処理なしに描画可能。
- 外周部(対蹠点)付近に特化した処理(線の反対側への飛びなどへの対応)も不要となった。
- 外周部付近では経緯線の描画自体を抑制する、というような対応も不要。
- 他の投影図法でも逆方向の変換さえあれば大きな変更なしで対応できる可能性が高い。
- 点列を生成して描画する方法の場合、対蹠点の扱いや周期性の扱いなどで図法ごとの調整が必要な場合があった。
- JavaScript側の処理の大幅な削減。
一方で以下のような課題あり。
- 線の滑らかさの問題。
- 投影変換に基づく大きな変化に対しては今回の方法に利点あり。
- 但し、エッジ検出の方法に基づくピクセル単位での粗さへの対応が課題。
- 線の濃淡の調整方法の問題。
他の投影図法
他の投影図法でもこの方法は適用可能と思われる。
少なくとも、以下の投影図法でも同じ方法で描画可能。
ランベルト正積方位図法
- ソースコード
- https://github.com/tomosn/simple-raster-projection/blob/master/graticule-laea.html
- 表示例
- 経緯線のみの場合
- 画像付きの場合
横メルカトル図法
- ソースコード
- https://github.com/tomosn/simple-raster-projection/blob/master/graticule-tmerc.html
- 表示例
- 経緯線のみの場合
- 画像付きの場合