機械学習基礎理論独習

誤りがあればご指摘いただけると幸いです。数式が整うまで少し時間かかります。リンクフリーです。

勉強ログです。リンクフリーです
目次へ戻る

canvas座標系からデバイス座標系への変換

canvas座標系とは

htmlにおけるcanvasの左上隅が原点で右側がx+、下側がy+の座標系のことをcanvas座標系と呼ぶことにします。
このcanvas座標系は、縮尺がデバイス座標系と同じでy+の向きが異なるだけですが、あえて取り上げてみることにしました。

canvas座標系のカーソルの座標の取得

アプリケーションで気になるのは、click/mousedown/mousemoveイベントが発生したときのカーソルのcanvas座標系における座標だと思います。
カーソルのcanvas座標系における座標を取得するには、2通りの方法があると思います。(パッと思いついたのが)
そんなに重要でないので、さらっと説明します。

その1: e.offsetX/Yを使う方法
イベントの発生元がcanvasならこれが使えます。

function getPositionInCanvasCoords(e) {
    return { x: e.offsetX, y: e.offsetY, };
}

その2: e.clientX/Yを使う方法
イベントの発生元がcanvasでなくともこれが使えます。
ポイントはブラウザのクライアント原点からcanvasの矩形の左上隅の座標を引いていることです。

function getPositionInCanvasCoords(e) {
    const canvas = document.querySelector('#canvas');
    const rect = canvas.getBoundingClientRect();
    return { x: e.clientX - rect.left, y: e.clientY - rect.top, };
}

canvas座標系からデバイス座標系へ変換


バイス座標系のZ成分は無視して考えます。
(というかcanvas上のカーソル位置から出発しているのでZ座標は定まっていません。)
ビューポートの原点を (left,bottom)、幅と高さを width,height とします。
canvas座標系の原点をビューポートの原点と一致させた後、yを反転すればよいので、求める変換行列 {\bf M}_{{\rm CC}\rightarrow{\rm DC}} は以下のようになります。
ちなみに {\rm CC} canvas coords の略で、{\rm DC} は device coords の略です。

\begin{eqnarray}
{\bf M}_{{\rm CC}\rightarrow{\rm DC}}&=&
\begin{pmatrix}
1 & 0 & 0\\
0 & -1 & 0\\
0 & 0 & 1
\end{pmatrix}
\begin{pmatrix}
1 & 0 & -left\\
0 & 1 & bottom-height\\
0 & 0 & 1
\end{pmatrix}\\
&=&
\begin{pmatrix}
1 & 0 & -left\\
0 & -1 & -bottom+height\\
0 & 0 & 1
\end{pmatrix}
\end{eqnarray}
※ビューポートの原点 (left,bottom) は正規化デバイス座標系における座標です。
ちなみにビューポートは canvasに一致させることが非常に多く、通常は left=0,bottom=0,width=canvasの幅,height=canvasの高さ です。

バイス座標系のZ座標はどうするのよ

例えば、OpenGLWebGLで三角形群を表示していて、クリックした座標における三角形のモデル座標系の座標が取得したいとします。
クリックしたカーソルの座標をデバイス座標まで変換はしたがいいがZ座標はどうしたらよいのでしょう?
一旦、デバイス座標系におけるZ座標は適当な値0などにして、デバイス座標系から正規化デバイス座標系へ変換しましょう。
正規化デバイス座標系はZが-1~1以外の範囲は、クリップされているのでZ座標を-1,1の2点を作成してその2点からなる線分と三角形の交点を求めて、
最も視点に近い座標を採用すればよいと思います。
これについてはWebGLにおけるピックに記載しております。
といった感じで、正規化デバイス座標系のZの値は-1または1を使えばよいのではないでしょうか?
そして、デバイス座標におけるZの値って適当でよいと思っています。(そんなに困ることは無いはず)

最後に

バイス座標系の座標にまで変換出来たら、あとは通常の変換行列(モデル変換、ビュー変換、射影変換、ビューポート変換)を用いれば、どんな座標系にも変換することが可能です。

参考文献

なし

目次へ戻る