1. 無職の学び舎
  2. >
  3. 無職はゲーム数学の勉強をする
  4. >
  5. ベクトルの回転

ベクトルの回転

ベクトルを回転させる方法について記載していきます。

方法

$ \vec{a} = (a_{x}, a_{y}) $:回転前のベクトル
$ \vec{b} = (b_{x}, b_{y}) $:$\vec{a}$ を $\theta$ 回転させたベクトル

とすると

$ b_{x} = a_{x} cos(\theta) - a_{y} sin(\theta) $
$ b_{y} = a_{x} sin(\theta) + a_{y} cos(\theta) $

という計算で、$\vec{a}$ を $\theta$ 回転させた結果が得られます。

この魔法の計算をするとベクトルが回転するにはするんですが、なぜこの計算でベクトルを回転する事ができるのかがモヤっとします。

というわけで、もう少し掘り下げていきたいと思います。

なぜ、上記の計算でベクトルが回転するのか

$\alpha$ 回転した $\vec{a} = (a_{x}, a_{y})$ の $x$座標 と $y$座標 は以下のようにあらわす事ができます。

$ (a_{x}, a_{y}) = (|\vec{a}| cos(\alpha), |\vec{a}|sin(\alpha)) $

ちなみに数式を書いておきながらなんですが、無職は数式アレルギーというか数式が見えた瞬間に記事を読む気力が奪われがちです。

上の式もどういうこっちゃとなってしまうので、泥臭く計算してみることにしました。

$a_{x} = |\vec{a}|cos(\alpha)$
$ \ \ \ \ = |\vec{a}| \frac{a_{x}}{|\vec{a}|} $
$ \ \ \ \ = a_{x} $

$a_{y} = |\vec{a}|sin(\alpha)$
$ \ \ \ \ = |\vec{a}| \frac{a_{y}}{|\vec{a}|} $
$ \ \ \ \ = a_{y} $

$cos = \frac{底辺}{斜辺}$、$cos = \frac{高さ}{斜辺}$ なので、その通りに計算してみると確かに合っています。

次に、$\vec{a}$ から $\theta$ 回転させた $\vec{b} = (b_{x}, b_{y})$ について見ていきます。

$\vec{b}$ と $x軸$ の間の角度は $\alpha + \theta$ なので
$\vec{b} = (b_{x}, b_{y})$ の $x座標$ と $y座標$ は以下のようにあらわす事ができます。

$ (b_{x}, b_{y}) = (|\vec{b}|cos(\alpha + \theta), |\vec{b}|sin(\alpha + \theta))$

$\vec{b}$ は $\vec{a}$ は回転しただけなので長さは同じです。

$|\vec{b}|$ = |$\vec{a}|$ なので
$ (b_{x}, b_{y}) = (|\vec{a}|cos(\alpha + \theta), |\vec{a}|sin(\alpha + \theta))$

そして、このサイトでも何度か登場している、三角関数の加法定理というものがあります。

$ sin(\alpha + \theta) = sin(\alpha)cos(\theta) + cos(\alpha)sin(\theta) $ $ cos(\alpha + \theta) = cos(\alpha)cos(\theta) - sin(\alpha)sin(\theta) $

この式を当てはめていきます。

$ b_{x} = |\vec{a}|(cos(\alpha)cos(\theta) - sin(\alpha)sin(\theta)) $
$ b_{y} = |\vec{a}|(sin(\alpha)cos(\theta) + cos(\alpha)sin(\theta)) $

長かったので$b_{x} b_{y}$を分けて記載しました。

この式をまた泥臭く計算してみます。

$ b_{x} = |\vec{a}|(cos(\alpha)cos(\theta) - sin(\alpha)sin(\theta)) $
$cos(\alpha) = \frac{a_{x}}{|\vec{a}|}, sin(\alpha) = \frac{a_{y}}{|\vec{a}|} $ なので
$ = |\vec{a}|(\frac{a_{x}}{|\vec{a}|} cos(\theta) - \frac{a_{y}}{|\vec{a}|}sin(\theta)) $
$ = |\vec{a}|\frac{a_{x}}{|\vec{a}|} cos(\theta) - |\vec{a}|\frac{a_{y}}{|\vec{a}|}sin(\theta) $
$ = a_{x} cos(\theta) - a_{y}sin(\theta) $

$ b_{y} = |\vec{a}|(sin(\alpha)cos(\theta) + cos(\alpha)sin(\theta)) $
$ sin(\alpha) = \frac{a_{y}}{|\vec{a}|}, cos(\alpha) = \frac{a_{x}}{|\vec{a}|} $ なので
$ b_{y} = |\vec{a}|( \frac{a_{y}}{|\vec{a}|} cos(\theta) + \frac{a_{x}}{|\vec{a}|}sin(\theta)) $
$ b_{y} = |\vec{a}| \frac{a_{y}}{|\vec{a}|} cos(\theta) + |\vec{a}| \frac{a_{x}}{|\vec{a}|}sin(\theta) $
$ b_{y} = a_{y} cos(\theta) + a_{x} sin(\theta) $
$ b_{y} = a_{x} sin(\theta) + a_{y} cos(\theta)$

整理すると

$ b_{x} = a_{x} cos(\theta) - a_{y} sin(\theta) $
$ b_{y} = a_{x} sin(\theta) + a_{y} cos(\theta) $

記事の冒頭で紹介した計算式と同じになりました!

行列で書くと

泥臭く計算していたためとても長々しくなりましたが、行列を使って書くともう少しスッキリするようです。

$ \vec{b} = |\vec{a}| \begin{pmatrix} cos(\alpha)cos(\theta) - sin(\alpha)sin(\theta) \\ sin(\alpha)cos(\theta) + cos(\alpha)sin(\theta) \end{pmatrix} $

$ \ \ = |\vec{a}| \begin{pmatrix} cos(\theta) - sin(\theta) \\ sin(\theta) + cos(\theta) \end{pmatrix} \begin{pmatrix} cos(\alpha) \\ sin(\alpha) \end{pmatrix} $

$ \ \ = \begin{pmatrix} cos(\theta) - sin(\theta) \\ sin(\theta) + cos(\theta) \end{pmatrix} \begin{pmatrix} |\vec{a}| cos(\alpha) \\ |\vec{a}| sin(\alpha) \end{pmatrix} $

$ \ \ = \begin{pmatrix} cos(\theta) - sin(\theta) \\ sin(\theta) + cos(\theta) \end{pmatrix} \begin{pmatrix} a_{x} \\ a_{y} \end{pmatrix} $

なんだか頭の良さそうな式ですが、無職は行列は計算の順序などになれていないため、泥臭く計算しないとなかなか理解できないのでした。

サンプルコード

/**
 * ベクトルの回転
 * @param v 回転させたいベクトル
 * @param rad 回転させる角度(ラジアン)
*/
function rotate(v:Vector2, rad:number) {
  const { x, y } = v;

  v.x = x * Math.cos(rad) - y * Math.sin(rad);
  v.y = x * Math.sin(rad) + y * Math.cos(rad);
}