« 選手のマークの番号を変更可能にした | トップページ | インターネットで見つけたプレイ図ソフト »

2016年11月21日 (月)

SVG の変換行列(CTM)

LongDriver の動作確認をしていて、選手マークをドラッグする時、マークの移動量とマウスの移動量が異なることに気付きました。試しに下に表示している LongDriver でマークをドラッグして下さい。マウスに比べてマークの移動量の小さいことが分かります。

LongDriver では、マークの移動量 deltX, deltY は、次の式で決定しています。


    deltX = (evt.clientX - pad.prevX);	// 右辺はマウスの移動量
    deltY = (evt.clientY - pad.prevY);
    ・・・
    var x = Number(target.getAttribute("x")) + deltX;
    var y = Number(target.getAttribute("y")) + deltY;
    target.setAttribute("x", x);	// target は選手マークを指す
    target.setAttribute("y", y);

このように、マウスの移動量をそのままマークの移動量としているのに、何故両者は一致しないのでしょうか?この原因は LongDriver が縮小表示され、その座標系とブラウザの座標系のスケールが異なることにあります。マウスの位置を表す evt.clientX や、それから得られる deltX 等はブラウザの座標系での値です。しかし target.setAttribute("x", x) を実行する時は LongDriver の座標系に基づいた点が選ばれるのです。そして LongDriver の座標系は縮小されているためマウスの移動量とマークの移動量が異なるのです。

SVG では、表示の大きさが変更された場合、その情報が変換行列 CTM に保存されます。 CTM は3×3行列で、新・旧座標を次の関係で繋ぎます。 \[ \begin{pmatrix} x_{prev} \\ y_{prev} \\ 1 \end{pmatrix} = \begin{pmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} x_{curr} \\ y_{curr} \\ 1 \end{pmatrix} \]

この式で左辺は旧座標系での値、右辺が新座標系での値だということに気を付けて下さい。今の場合、旧座標系とは LongDriver の初期座標系(すなわち、縮小前の座標系)のことです。この初期座標系はブラウザの座標系に一致しています。画面に表示されるのは初期座標系に換算されたものです。

上に表示している LongDriver を例に取ると CTM は \[ \rm{CTM} = \begin{pmatrix} 0.602 & 0 & 0 \\ 0 & 0.602 & 7.229 \\ 0 & 0 & 1 \end{pmatrix} \] になっています。ここで、マウスの移動量を新座標系の LongDriver に代入すると約 0.602 倍され初期座標系での移動量に換算して表示されます。逆の言い方をすると、マウスとマークの移動を一致させるには、マウスの移動量を 0.602 で割った値を選手マークの移動量とすると良いことになります。

さて、ここからは余談ですが、 CTM の成分の名前が \[ \begin{pmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{pmatrix} \] の並びになっているのは、なんとも気持ち悪いものです。何故、 \[ \begin{pmatrix} a & b & c \\ d & e & f \\ 0 & 0 & 1 \end{pmatrix} \] にしなかったのでしょうかね。

« 選手のマークの番号を変更可能にした | トップページ | インターネットで見つけたプレイ図ソフト »

フットボールのプレイ図ソフト」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/584699/64521384

この記事へのトラックバック一覧です: SVG の変換行列(CTM):

« 選手のマークの番号を変更可能にした | トップページ | インターネットで見つけたプレイ図ソフト »