x軸とy軸からなる直交座標(「デカルト座標系」)における任意の点$(x, y)$を、原点$(0, 0)$から角度$\theta$回した座標$(x', y')$はつぎの式で求められます。
x' = x\cos\theta - y\sin\theta\\
y' = x\sin\theta + y\cos\theta
結論は以上です。本稿はこの式について、数学のいくつかの分野から異なる切り口で考えてみます。
#三角関数のsinとcosの定義
まず、三角関数の$\sin$と$\cos$です。つぎのように定義されます。
半径1の円(「単位円」)の円周上の点$(x, y)$がx軸の正方向と角度$\theta$をなすとき、その座標は$(\cos\theta, \sin\theta)$で表されます。
高校の数学で、三角関数は直角三角形の辺の比(三角比)で習ったという方も多いでしょう。それはもう忘れてください。
平面上の座標は、$(x, y)$のほかにも表し方があります。たとえば、レーダーでは距離と角度で位置を示します(これを「極座標」といいます)。北東$1km$の座標を$(x, y)$で表したらどうなるでしょう。$(\cos45°, \sin45°)$(単位$km$)ですね。
つまり、三角関数の$\sin$と$\cos$は、レーダーの極座標を$(x, y)$座標に換える関数なのです。原点からの距離を$r$、角度が$\theta$とすれば、座標はただちに$(r\cos\theta, r\sin\theta)$で表せます。それが具体的にどういう数値になるかという計算はコンピュータに任せればよいことです。
#座標を原点から指定した角度回す
つぎに、座標$(x, y) = (r\cos\theta, r\sin\theta)$をさらに原点から角度$\omega$(オメガ)回しましょう。原点からの距離は、三平方の定理から$r = \sqrt{x^2 + y^2}$です。この長さは変えません。すると、回転したあとの座標は、$(x', y') = (r\cos(\theta + \omega), r\sin(\theta + \omega))$となります。
もちろん、計算はコンピュータに任せます。とはいえ、平面上のたくさんの点をすべて、原点から同じ角度($\omega$)回す場合、計算の負荷が上がりそうです。原点からの距離($r$)も角度($\theta$)も点ごとに違います。for
ループの中で、距離($r$)を三平方の定理、角度($\theta$)はMath.atan2()
メソッドで調べたうえで、Math.cos()
とMath.sin()
により計算しなければならないのです。
改めて、はじめに示した式をご覧ください。回す角度($\omega$)が一定なら、$cos$と$sin$の値はfor
ループの外で変数に入れてしまえます。そして、それぞれの点の$(x, y)$座標の値にもとづいて計算しますから、原点からの距離も求めずに済むのです。
#ベクトルと行列
平面上の座標は、ベクトルと捉えることもできます。その座標$(x, y)$を原点から角度$\theta$回す場合には、つぎのような回転行列を座標ベクトルに(左から)乗じます。
\begin{pmatrix}
\cos\theta & -\sin\theta\\
\sin\theta & \cos\theta
\end{pmatrix}
\begin{pmatrix}
x\\
y
\end{pmatrix}\\
=
\begin{pmatrix}
x\cos\theta - y\sin\theta\\
x\sin\theta + y\cos\theta
\end{pmatrix}
ここではベクトルや行列、それらの演算について知らなくて構いません。計算結果は、はじめに示した式と同じですから。
#複素数
今度は、複素数です。実数と虚数の和で表されます($a + bi$)。虚数単位$i$は、2乗すると$i^2 = -1$になるという摩訶不思議な性質をもちます。2次方程式の解に表れました。
実数は数直線上の点で表せます。実数の数直線を水平軸(実軸)としたとき、虚数の数直線を原点0で直行する垂直軸(虚軸)とすると、任意の複素数はこの直交座標上の点として示されます。これを「複素平面」と呼びます。
複素平面でも三角関数の$sin$と$cos$は同じように使えます。つまり、単位円上にある複素数は、実軸の正方向となす角度が$\theta$なら$\cos\theta + i\sin\theta$と表せるのです。
ふたつの複素数$\alpha$と$\beta$の乗算を考えましょう。積の複素数$\alpha\beta$は、原点からの距離$|\alpha\beta|$がそれぞれの絶対値を掛け合わせた$|\alpha||\beta|$になります。これは実数と同じです。つぎに実軸となす角度が$\alpha$は$\theta$、$\beta$が$\omega$だったとき、積$\alpha\beta$の角度はふたつの和$\theta + \omega$となることが、複素平面の研究からわかりました。
ここで、任意の複素数$z = x + iy$を原点から角度$\theta$回してみましょう。原点からの距離は変えないのですから、絶対値が1で角度$\theta$の複素数、つまり$\cos\theta + i\sin\theta$を掛け合わせればよいのです。
(x + iy)(\cos\theta + i\sin\theta)\\
= (x\cos\theta - y\sin\theta) + i(x\sin\theta + y\cos\theta)
求められた複素数をxy直交座標で表せば、$(x\cos\theta - y\sin\theta, x\sin\theta + y\cos\theta)$となって、やはりはじめに示した式と同じになります。
#座標回転の式を使った作例
座標回転の式を使った作例もひとつご紹介しておきましょう。JavaScriptライブラリのCreateJSでつくった「EaselJSのMatrix2Dクラスを用いた3次元表現」です。マウスポインタの位置に応じて、3次元空間で立方体が回ります。
####図004▪️3次元で立方体をマウスポインタに合わせて回す
>> jsdo.itへ
つぎのようなJavaScriptの関数で、立方体の頂点を回しています。Point
は、xy座標をプロパティに備えたCreateJSのオブジェクトです。3次元なのにxy座標だけで回せるのかと疑問に思われるかもしれません。3次元の回転は、xy平面、yz平面、zx平面の3つに分けて座標を計算すればよいので、2次元平面における回転の組み合わせになるのです。
function rotatePoint2D(nRadians, nX, nY) {
var nSin = Math.sin(nRadians);
var nCos = Math.cos(nRadians);
var point2D = new createjs.Point();
point2D.x = nCos * nX - nSin * nY;
point2D.y = nSin * nX + nCos * nY;
return point2D;
}