Quaternionによる3次元の回転変換

コンピュータグラフィックスにおいて、図形を変換するには、ベクトルやマトリックス（行列）の演算が多用されます。その中でも、Quaternion(= 4元数 = 虚数単位が3つある複素数)を用いて回転変換を表現する手法の数学的な解説をしたいと思います。通常の複素数の掛け算が、2次元複素平面での回転変換を表現できることの3次元への応用ともなっています。

補記：この記事は、Qiita でLaTeXを利用してみたい(参照：『[Qiita 上で数式を美しく書けるようになっていた件 (MathJax)](http://qiita.com/iizukak/items/04d6e226982bc108bc16)』）、というモチベーションで書いています。この記事『[Java3Dの数学](http://objectclub.jp/download/files/vecmath/vecmath.pdf)』の一部抜粋を読みやすくしたものです。また、コンピュータグラフィックスに慣れた読者には、最初の準備は長いと思いますので、後半のみ読んでください。

# (準備1) 点とベクトル、それらの座標系を用いた表現

数学的な準備からはじめましょう。点もベクトル（有向線分）ももともとは図形、すなわち幾何的な実在であり、数とは直接関係していません。図形を数と関係付けるためには座標系を導入する必要があります。座標系を導入することで幾何を代数の言葉で表現できるようになります。すなわち、数式を使って図形を扱うことができるのです！これは数学者デカルトの功績であり、直交座標系はデカルト座標系とも呼ばれます。

![image](https://qiita-image-store.s3.amazonaws.com/0/51055/7a32ce29-6929-2ea7-12b8-5fc65c40691c.png)

$O$が座標系の原点です。ここでは座標系として右手系を使います。すなわち$O$を中心に$x$座標の+方向から$y$座標の+方向へと右ねじを回したときにねじの進む方向が$z$座標の+方向となるように規定します。あるいは，右手の親指と人差し指と中指を互いに直交するように伸ばしたとき，$x, y, z$ 軸がそれぞれ親指，人差し指，中指になるような配置とも言えます。図で$v$はベクトル、$P$は点を示しています。座標系を導入することで、点もベクトルも３つの実数の組で表現されます。ここではそれらの数学的記述として列ベクトルを用います。点$P$およびベクトル$v$は以下のように表されます．

```math
P = \left(
\begin{array}{cc}
p_x \\
p_y \\
p_z \\
\end{array}
\right),  
v = \left(
\begin{array}{cc}
v_x \\
v_y \\
v_z \\
\end{array}
\right)
```

----
メモ：点もベクトルも同じような表現になりますが、両者は区別して扱う必要があります。ベクトルは向きと大きさを持つ量であり、平行移動しても同じとみなされます（実際は「有向線分」を並行移動で"割った"ものです）。図で$v$と記された２つのベクトルは同一視され、同じ値で表現されます。これに対して、点は平行移動すると別の点になり、別の値で表現されます。他にも違いがあります。２つの点の間には距離が定義できますが、２つのベクトルの間には距離が定義されません。その代わりベクトルには長さが定義されますが、点には長さが定義されません。さらに、ベクトル同士には足し算、引き算、およびスカラー(実数)倍の演算が規定されていますが、点同士は足し算ができませんし、スカラー倍も定義できません(これらの演算は座標系の取り方によって結果が変わってしまいます)。だだし，点同士の引き算はベクトルを生じ，点にベクトルを加えると新たな点が生成されます。

通常の教科書では、点は原点とその点を結ぶベクトル（位置ベクトル）として考えます。しかし、座標系を換えてしまうとその位置ベクトルは変化してしまうため、点の位置ベクトルは束縛ベクトルとも呼ばれます。（座標系に依らない、点とベクトルの代数系をご存知の方は教えてください。点ー点＝ベクトル、点＋ベクトル＝点、のようなデカルト座標を持ち込まない系の代数です。。。）

（2020/10/11修正 まさに、 **Weylの公理系** というのがそれに相当するようです。参考『線型代数学』佐武一郎）

----

# (準備2) マトリクスと変換

コンピュータグラフィックスでは、点およびベクトルの「変換」(他の点やベクトルに移動すること)は最も基本的な操作です。ここでは、変換とそれを表現するマトリクスについて説明します。

## ベクトルと変換

まず、ベクトルの変換から考えてみます。前述のように座標家を考えると3次元空間のベクトルは３つの実数の組で表されます。ある変換$T$を考え、ベクトル$v$が変換$T$によって$v’$に変換されたとします．これを，

```math
v = \left(
\begin{array}{cc}
v_x \\
v_y \\
v_z \\
\end{array}
\right)

\space \space \space \space \underrightarrow{T} \space \space \space \space 

v' = \left(
\begin{array}{cc}
v'_x \\
v'_y \\
v'_z \\
\end{array}
\right)

```

と書き、簡単に、

```math
v
\space \space \space \space \underrightarrow{T} \space \space \space \space 
v'
```

とか、逆向きに、

```math
v' = T(v)
```

と書きます。この変換$T$が、仮に９つのパラメータ $m_{00} \sim m_{22}$ を使って，

```math
\begin{array}{c}
v_x' = m_{00} v_x + m_{01} v_y + m_{02} v_z \\
v_y' = m_{10} v_x + m_{11} v_y + m_{12} v_z \\
v_z' = m_{20} v_x + m_{21} v_y + m_{22} v_z
\end{array}
```

と記述できるとき、この変換を「線形変換」といいます。ここで $3 \times 3$ マトリクス $M$ を，

```math
M = \left(
\begin{array}{cc}
m_{00} & m_{01} & m_{02} \\
m_{10} & m_{11} & m_{12} \\
m_{20} & m_{21} & m_{22} \\
\end{array}
\right)
```

と定義すると、変換 $T$ は、

```math
\left(
\begin{array}{cc}
v'_x \\
v'_y \\
v'_z \\
\end{array}
\right) = 
\left(
\begin{array}{cc}
m_{00} & m_{01} & m_{02} \\
m_{10} & m_{11} & m_{12} \\
m_{20} & m_{21} & m_{22} \\
\end{array}
\right)
\left(
\begin{array}{cc}
v_x \\
v_y \\
v_z \\
\end{array}
\right)
```

すなわち、

```math
v' = M v
```

と書けます。$M$ を $T$ を表現する変換マトリクスと呼びます。すべての変換が線形変換ではありません。すなわち、すべての変換がマトリクス $M$ で表現できるわけではありません。さまざまな変換の中でも、マトリクスの掛け算で表現できる変換を線形変換と呼ぶのです。（線形変換の性質、別の定義法については後述します。）

また、点の変換については点を位置ベクトルとして表現したものを変換すると考えると同じ結果になります。

## 回転変換

線形変換の例として、$z$ 軸回りの $\theta$ ラジアン回転変換は、

```math
\left(
\begin{array}{cc}
v'_x \\
v'_y \\
v'_z \\
\end{array}
\right) = 
\left(
\begin{array}{cc}
\cos\theta  & -\sin\theta & 0 \\
\sin\theta & \cos\theta & 0 \\
0 & 0 & 1
\end{array}
\right)
\left(
\begin{array}{cc}
v_x \\
v_y \\
v_z \\
\end{array}
\right)

```

この場合の変換マトリックス$T$は、 $R(\theta)$ で表現され、

```math
R(\theta) =
\left(
\begin{array}{cc}
\cos\theta  & -\sin\theta & 0 \\
\sin\theta & \cos\theta & 0 \\
0 & 0 & 1
\end{array}
\right)
```

です。3次元空間上の任意の軸に関する回転はやや複雑なのでQuaternionとともに後述します．

## スケール変換

回転と同様に、原点を中心としたスケール変換（$s$ 倍）に関する変換行列は、

```math
S(s) =
\left(
\begin{array}{cc}
s  & 0 & 0 \\
0 & s & 0 \\
0 & 0 & s
\end{array}
\right) = s I \space  (Iは単位行列)
```

となります。

## 線形変換の性質

これまで回転変換とスケール変換を例にして、線形変換を説明しました。ここでベクトルの線形変換の性質を改めて見てみましょう。ベクトルの線形変換には、名前からも明らかなように「線形性」があります。「線形性」とは，２つのベクトルの和を変換すると、個々のベクトルを変換した後に和をとったものと等しくなること、および、スカラー倍したベクトルを変換すると、もとのベクトルを変換した後にスカラー倍したものと等しくなることです。式で表すと，次のようになります。

```math
\begin{array}{c}
T(\mathbf{v_1} + \mathbf{v_2}) = T(\mathbf{v_1}) + T(\mathbf{v_2}) \\
T(s \mathbf{v}) = s T(\mathbf{v})
\end{array}
```

最初の式が和に対する線形性、次の式がスカラー倍に対する線形成を表しています。$T$ が線形変換の場合、$T(v) = M v$ と書けることから上記の性質は自然に成り立つことがわかります。

最初、線形変換を「マトリクスで表現できること」と定義し、その性質として「線形性」を導きましたが、実は「線形性」そのものを線形変換の定義とし、そこから「マトリクスで表現できる」という性質を導くこともできます。

線形性に関する性質の中でも特にスカラー倍に関する性質から、「0ベクトルは0ベクトルに変換される」という大切な性質が導かれます。

```math
T(\mathbf{0}) = \mathbf{0}
```

## 点の平行移動と同次ベクトル

これまで回転変換とスケール変換を見てきました。これらはマトリクスで表現される線形変換です。次に、平行移動について考えてみます。べクトルに関しては平行移動は意味をなしません。平行移動してもベクトルの値は変化しないのですから。

点の平行移動は、点にベクトルを足すことで得られますが、これを変換マトリクスで表現することはできません。なぜでしょう？線形変換は0ベクトルを0ベクトルに変換するという性質がありますが，点を位置ベクトルとして捉えた場合，この性質は「原点は動かない」と読み替えることができます。平行移動は明らかにこの性質を満たしません。すなわち、点の並行移動は線形変換ではなく、そのままマトリクスの掛け算として扱うことはできないのです。

最初に述べたように、そもそも点という概念に対しては加算やスカラー倍が定義できないため、点の集合が代数でいう「線形空間」を形成してないことに問題があります。そこで、「３次元の点」を「４次元ベクトル」で表現するという工夫をします。これはコンピュータグラフィックスの数学で古くから行われている技法です。この４次元ベクトルを同次ベクトル（斉次ベクトル）と呼びます。４次元ベクトルを考え、4つ目の要素で残りの３つの要素を割り算したものを、３次元の点と同一視します。(※この図形的イメージについてどこかに書く)

```math
\mathbf{p} =
\left(
\begin{array}{cc}
x \\
y \\
z \\
w
\end{array}
\right) 

\iff 

\mathbf{p} =
\left(
\begin{array}{cc}
x/w \\
y/w \\
z/w
\end{array}
\right) 
```

通常は、$w$ は常に 1 と考えておけば，4次元ベクトルの$x, y, z$ 座標がそのまま３次元の点の$x, y, z$ 座標と一致します．同次座標を導入することで，点の平行移動もマトリクスと列ベクトルとの積で表現できるようになります．すなわち，点$P$を，ベクトル $\mathbf{t} = (t_x, t_y, t_z)$ だけ平行移動した点を $P'$とすると

```math
\begin{array}{c}
p_x' = p_x + t_x \\
p_y' = p_y + t_y \\
p_z' = p_z + t_z
\end{array}
```

となるので、同次ベクトルを用いると、

```math
\left(
\begin{array}{cc}
p'_x \\
p'_y \\
p'_z \\
1
\end{array}
\right) = 
\left(
\begin{array}{cc}
1 & 0 & 0 & t_x \\
0 & 1 & 0 & t_y \\
0 & 0 & 1 & t_z \\
0 & 0 & 0 & 1
\end{array}
\right)
\left(
\begin{array}{cc}
p_x \\
p_y \\
p_z \\
1
\end{array}
\right)
```

あるいは、

```math
\mathbf{p'} = T( \mathbf{t}) \mathbf{p}
```

ここで、

```math
T( \mathbf{t} )= \left(
\begin{array}{cc}
1 & 0 & 0 \\
0 & 1 & 0 & \mathbf{t} \\
0 & 0 & 1  \\
0 & 0 & 0 & 1
\end{array}
\right),
\mathbf{t} = 
\left(
\begin{array}{cc}
t_x \\
t_y \\
t_z
\end{array}
\right)
```


と書くことができます。

## 各変換まとめ

このように，４次元同次ベクトルと４次元マトリクスを用いることで，平行移動も、線形変換と同様にマトリクスの掛け算で扱うことができるようになります。これまで見た平行移動以外の回転、スケールの変換マトリクスはそのまま４次元に拡張できるので、回転、スケール、平行移動の３種類の変換はすべて 4x4 のマトリクスで表現できたことになります。

各変換は連続して行うことができます。たとえば、$z$軸回りに回転した後、スケールして平行移動する変換マトリクス $M$ は、

```math
M = T( \mathbf{t})  S(s)  R( \theta)
```

という具合です．この場合，順に変換マトリクスを左から積算した結果できるマトリクスが合成変換のマトリクスとなります。

ちなみに 3 次元の点の４次元ベクトルへの拡張は，平行移動をも含めて点の変換をマトリクスの掛け算で扱おうという目的が主ですが、他にも $w = 0$ とすることである方向の無限遠点を表現できたり、特定の場面で数値計算による誤差を押さえたり、さらに後述するように回転変換を表すQuaternionとの自然な演算が定義できるという数学的な利点もあります。

また、ここでは述べませんでしたが、他に、鏡像、せん断、と呼ばれる変換があります。鏡像は鏡に写した像を得る変換であり、せん断は斜めにつぶす変換です。せん断は、正方形を平行四辺形に変換します。回転、スケール、平行移動、鏡像、せん断から合成される変換をアフィン変換といいます。アフィン変換は，幾何的には「平行線を平行線に写す」という特徴で定義されます。

![image](https://qiita-image-store.s3.amazonaws.com/0/51055/cbcb1d41-88c7-d1e9-8621-338096b3cb15.png)


図中，射影変換はアフィン変換ではありませんが後述するので並べて掲載しています。中でも回転、スケール、平行移動の３つのアフィン変換は，図形の形を変えないためコンピュータグラフィックスで頻繁に用いられます。

アフィン変換を表現するの 4x4 のマトリクスは，

1. 左上の 3x3 成分で，回転とスケールを表現
1. 第４列（最も右の列）で平行移動を表現
1. 第４行（最も下の行）はいつでも (0 0 0 1)

という特徴があります。次に、ようやく、先の回転変換と密接な関係をもつ Quaternion について説します。（ここまでが長い前置きです）

# Quaternion

前節では、マトリクスによる回転の表現を見てきました。$z$軸回りの回転のみを扱ったのは、任意の軸回りの回転はマトリクス表現では非常に複雑になってしまうからです。また、マトリクスによる表現はすべてのアフィン変換を扱うことができるため、変数の数が 4x4 = 16 (うち使うのは13)と多くなってしまいます．回転変換のみに焦点をあてたコンパクトな表現は他にないでしょうか?

回転の中心を原点と仮定すると、２次元ならば，回転角度だけで十分なのですが，３次元では任意の軸に関しての回転を表現する必要があるため、２次元ほど簡単ではないようです。

![image](https://qiita-image-store.s3.amazonaws.com/0/51055/8aadab5a-9b24-c271-9384-9087c6fab19a.png)


Quaternion は数学者ハミルトンによって導入された数です。クオータニオンと読み、日本語では４元数と訳されます(Quarter は4の意)。文字通り４つの要素を持つ数です。複素数の自然拡張になっており、３次元での回転変換を表現するのに便利であるため特にコンピュータグラフィックスで最近よく利用されます。

Quaternion は代数的に非常に美しい回転変換の表現です。美しいというのは，例えば Quaternion 同士の足し算や掛け算をも、意味をもって定義できるのです。また，マトリクスのようにアフィン変換すべてを表現しているわけではありません。３次元の回転変換の表現によくマッチした数であり，「スピナー(Spinner)」という回転を意味する別名を持っています。

結論だけ先に簡潔に述べると、単位ベクトル $v =(v_x, v_y, v_z)$ 回りの $\theta$ラジアン回転を表す Quaternion $q$ は，

```math
\mathbf{q} = 
\left(
\begin{array}{cc}
v_x \sin \theta/2 \\
v_y \sin \theta/2 \\
v_z \sin \theta/2 \\
\cos \theta/2
\end{array}
\right)
```

と表現されます。以下では、簡単に Quaternion を導入し回転変換との関係を解説しましょう。

## 定義

２つの実数の組で複素数を表現した時と同様に、4つの実数の組で Quaternion を表現します．まず，３つの単位虚数$i , j , k$を導入することからはじめましょう。$i , j , k$ は次の演算規則に従うものとします。

```math
\begin{array}{c}
\mathbf{ i }^2 = \mathbf{ j }^2 = \mathbf{ k }^2 = -1 \\
\mathbf{ i } \mathbf{ j } = \mathbf{ k },  \mathbf{ j }  \mathbf{ k } = \mathbf{ i }, \mathbf{ k }  \mathbf{ i } = \mathbf{ j } \\
\mathbf{ i } \mathbf{ j } \mathbf{ k } = -1
\end{array}
```

ここで、$i, j, k$ の掛け算は非可換(交代)であることに注意してください。例えば、$ji$ = $-k$ となります。

そして，４つの実数要素$x, y, z, w$ を持つ Quaternion $q$ を以下のように定義します。

```math
\begin{array}{c}
\mathbf {q} = (x, y, z, w) = x \mathbf i + y \mathbf j + z \mathbf k + w = ((x, y, z), w) = (\mathbf v, w) \\
x, y, z \in \mathbf R,  \mathbf v \in \mathbf R^3
\end{array}
```

$w$ を実部、といい、$(x, y, z)$を虚部といいます。

## Quaternion の性質

Quaternion はベクトルと考えることで、和、スカラー倍が定義できますし、

```math
\begin{array}{c}
\mathbf q = (x, y, z, w) = x \mathbf i + y \mathbf j + z \mathbf k + w = ((x, y, z), w) = (\mathbf v, w) \\

和: \mathbf q_1 + \mathbf q_2 = (\mathbf v_1 + \mathbf v_2, w_1+w_2) \\
スカラー倍: k \mathbf q = (k \mathbf v, k w)
\end{array}
```

虚数単位の演算規則を適用することでQuaternion同士の積も計算できます（計算は各自やってみてください）。

```math
積: \mathbf{q_1} \mathbf{q_2} =  (\mathbf{v_1} \times \mathbf{v_2} + w_2 \mathbf{v_1} + w_1 \mathbf{v_2}, 
w_1 w_2 - \mathbf{v_1} \cdotp \mathbf{v_2})
```

また、ある Quaternion $q$ に対して共役 Quaternion $q^*$を、「実部のみもとの Quaternion と同じで虚部がもとの値のマイナスのもの」と定義します。

```math
\mathbf q^* = (-x, -y, -z, w) = (- \mathbf v, w) = -x \mathbf i -y \mathbf j -z \mathbf k + w
```

すると、Quaternion とその共役 Quaternion との積はスカラーになり、Quaternion のノルム(長さ)の２乗になります(虚部が0のQuaternionは実数と同一視します)。

```math
\begin{array}{c}
|\mathbf q|^2 = \mathbf{q} \mathbf{q}^* = x^2+y^2+z^2+w^2 \\
|\mathbf q| = \sqrt{x^2+y^2+z^2+w^2}
\end{array}
```

逆 Quaternionを、「元のQuaternionと掛けたら1になるQuaternion」と定義します。

```math
\mathbf q \mathbf q^{-1} = \mathbf q^{-1}  \mathbf q = 1
```

すると、共役Quaternionを使って、次のように求めることができます。

```math
\mathbf q^{-1} = \frac{\mathbf q^*}{|\mathbf q|^2}
```


特に、ノルムが１の Quaternion を単位 Quaternion と呼びます，単位 Quaternion は3次元の回転変換と結びつく興味深い性質があります。

# 単位 Quaternion の性質

単位 Quaternion は次の性質をもつ Quaternion です。

```math
|\mathbf q| = 1
```

通常の Quaternion を「単位化」するには、その長さで割ります。

```math
\frac{\mathbf q}{|\mathbf q|}
```

以降、Quaternionは単位化されているとすると、次のような便利な性質があります。

```math
\mathbf{q^{-1}} = \mathbf{ q^*} (共役が逆元)
```

さらに、長さが1であることから三角関数を使って、このように表現することができます。

```math
\begin{array}{c}
\mathbf{q} = (\mathbf{v} \sin \Theta, \cos \Theta) \\
 \mathbf{v} \in R^3, |\mathbf{v}| = 1
\end{array}
```

これは、絶対値１の複素数の表現と非常によく似ていることがわかります。単位 Quaternion も，$v$ と $\Theta$ を適当に選べば絶対値１の複素数と同じ形式で記述できます。数学に詳しい人なら、複素平面において絶対値１の複素数の掛け算が回転変換を表現することを思い出すでしょう。驚くべきことに、Quaternion においてもこの表記は、3次元空間での$v$を回転軸としたベクトルの回転を表現しているのです！

# Quaternion と回転変換（ようやくハイライト）

では、点の回転を Quaternion で表現することを考えてみましょう。点の回転を Quaternion で回転を表現するためには、3次元の点と Quaternion の演算を定義しなければなりません。3次元の点$P$ を４次元同次ベクトルで表し、それを Quaternion で表現しましょう。

そして先ほど定義した「積」の規則を使って，Quaternion $q$ に対応する $P \rightarrow P'$ の変換$T$ を次のように定義します。

```math
\mathbf{p'} = T( \mathbf p ) = \mathbf{q} \mathbf{p} \mathbf{q^{-1}}
```

これで、点と Quaternion の演算が可能になります。実際に単位 Quaternion $q$ と点$P$ について前の変換を計算してみましょう。

```math
\begin{array}{c}
\mathbf{q} = (\mathbf{v} \sin \Theta, \cos \Theta), \mathbf p = (\mathbf u, w) \\
w \in R, \mathbf{u}, \mathbf{v} \in R^3, |\mathbf{v}| = 1
\end{array}
```

として、$p'=qpq^{-1}$ と積の計算を行うと(ちょっとしんどいですが、机上で地道に計算します。実は「[Java3Dの数学](http://objectclub.jp/download/files/vecmath/vecmath.pdf)」ではこの式が間違っていたことが、今日判明しました。一項目の外積、$u$ と $v$ が逆で、$u \times v \times u$ でなく、$v \times u \times v$ が正解でした。16年たって発見されました!!)、


```math
\mathbf{p'} = \mathbf{q} \mathbf{p} \mathbf{q^{-1}} = (- \sin^2 \Theta \mathbf v \times \mathbf u \times \mathbf v + \cos^2 \Theta \mathbf u - 2 \sin \Theta \cos \Theta \mathbf u \times \mathbf v + \sin^2 \Theta (\mathbf u \cdotp \mathbf v) \mathbf v , w)
```

となります。少し複雑に見えますが、ここから、

>$P'$はベクトル$v$を軸として点$P$を$2 \Theta $ 回転したものになっている

ことを示しましょう。$u$ を $v$ と平行な成分 $\mathbf u_{\parallel}$ と v と直交する成分$\mathbf u_{\perp}$との２つのベクトルの和であると考えます。

```math
\mathbf{p} = (\mathbf u_{\parallel} + \mathbf u_{\perp}, w)
```

ここで、 $\mathbf u_{\parallel}, \mathbf u_{\perp}$は次のように求められます。

```math
\begin{array}{c}
\mathbf u_{\parallel} = (\mathbf u \cdotp \mathbf v) \mathbf v \\
\mathbf u_{\perp} = \mathbf u - \mathbf u_{\parallel}
\end{array}
```

$\mathbf u_{\parallel}, \mathbf u_{\perp}$はその定義から、次のような性質があります。

```math
\begin{array}{c}
\mathbf v \times \mathbf u_{\parallel} = \mathbf u_{\parallel} \times \mathbf v = \mathbf 0 \\
\mathbf v \cdotp \mathbf u_{\perp} = 0 \\
\mathbf v \times \mathbf u_{\perp} \times \mathbf v = \mathbf u_{\perp}
\end{array}
```

最後の式は難しいですが、$u_{\perp}$に直行する単位ベクトル($v$)を2回外積すると元にもどるベクトルの性質です。これらを使って計算を進めると、

```math
\begin{align}
\mathbf{p'} &= \mathbf{q} \mathbf{p} \mathbf{q^{-1}} \\
 &= (- \sin^2 \Theta \mathbf v \times \mathbf u \times \mathbf v 
+ \cos^2 \Theta \mathbf u 
- 2 \sin \Theta \cos \Theta \mathbf u \times \mathbf v 
+ \sin^2 \Theta (\mathbf u \cdotp \mathbf v) \mathbf v 
, w)　\\
&= ( 
-\sin^2 \Theta \mathbf v \times ( \mathbf u_{\parallel} + \mathbf u_{\perp} ) \times \mathbf v 
+ \cos^2 \Theta (\mathbf u_{\parallel} + \mathbf u_{\perp} ) 
- 2 \sin \Theta \cos \Theta (\mathbf u_{\parallel} + \mathbf u_{\perp} ) \times \mathbf v 
+ \sin^2 \Theta ((\mathbf u_{\parallel} + \mathbf u_{\perp}) \cdotp \mathbf v)) \mathbf v 
, w)　\\
&= ( 
-\sin^2 \Theta \mathbf v \times \mathbf u_{\perp} \times \mathbf v 
+ \cos^2 \Theta (\mathbf u_{\parallel} + \mathbf u_{\perp} ) 
- 2 \sin \Theta \cos \Theta \mathbf u_{\perp} \times \mathbf v 
+ \sin^2 \Theta \mathbf u_{\parallel}
, w) \\
&= (
-\sin^2 \Theta \mathbf u_{\perp} 
+ \cos^2 \Theta \mathbf u_{\perp}
- 2 \sin \Theta \cos \Theta \mathbf u_{\perp} \times \mathbf v 
+ ( \cos^2 \Theta + \sin^2 \Theta) \mathbf u_{\parallel}
, w) \\
&= (
 \mathbf u_{\parallel} + \cos 2 \Theta \mathbf u_{\perp}
+ \sin 2 \Theta \mathbf v \times \mathbf u_{\perp} 
, w) 
\end{align}
```
というすっきりした式に置きかえることができます。計算途中で三角関数の２倍角の公式を使っています．$v \times u_{\perp}$ は，$v$ と$u_{\perp}$の両方に直交し、$u_{\perp}$と同じ長さのベクトルになります。この式を見ると、$u$の$v$ 軸に平行成分はそのままにして，垂直成分のみを軸の回りに$２ \Theta$ 回転させていることが分かるでしょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/51055/94c176e8-c163-b4a5-b221-eca70020d100.png)

すなわち，単位ベクトル $\mathbf v =(v_x, v_y, v_z)$回りの$\theta$回転を表す Quaternion $q$ は，$\theta =2 \Theta$ と置けば、

```math
\begin{align}
\mathbf{q} &= (v_x \sin \theta/2, v_y \sin \theta/2, v_z \sin \theta/2, \cos \theta/2) \\
&= (\sin \theta/2 \mathbf v, \cos \theta/2)
\end{align}
```

## 大円補完

Quaternion のもう１つの大きな特長は，２つのQuaternion の補間ができるということです．ある回転と別の回転との中間にあたる回転を求めたり，２つの回転の間を滑らかにつなぐ回転の計算を得意とします．一般の３次元の回転は，回転軸が固定されているならば角度のみの補間でかまいませんが，回転軸が変化する場合はマトリクスではうまい補間法がありません．回転をオイラー角のように x, y, z 軸の回転に分解する方法でも，分解方法が一意でないことから，補間は難しいとされています。ここでも、Quaternion が力を発揮します。

単位 Quaternion は，４次元空間の原点を中心とする半径１の球の表面にマップして考えることができます．すなわち，どんな単位 Quaternion でもその球面上の１点と考えることができるのです．これは，長さ1のQuaternion が $x^2 + y^2 + z^2 + w^2 = 1$ を満たすことから容易に想像できるでしょう．Quaternion の補間では，球面上の２つのQuaternion を結ぶ大円(球面上の半径最大の円)を考え，その大円上で補間を行います．この大円補間は 以下のように定式化されます．

```math
\begin{array}{c}
\mathbf q = \frac{\sin (1-t) \theta}{\sin \theta} \mathbf q_1 + \frac{\sin t \theta}{\sin \theta} \mathbf q_2 \\
\theta = \angle q_1 q_2 = \cos ^{-1} (\mathbf q_1 \cdotp \mathbf q_2 )
\end{array}
```


この式の意味を理解するために，まず簡単な幾何の定理を示します。ここでは，長さ1の3つのベクトル$a, b, c$ が，角度$\alpha, \beta$をなして並んでいます。


![Q.png](https://qiita-image-store.s3.amazonaws.com/0/51055/3ab79a8b-6730-e8e2-68b6-c2e45ac33de6.png)


この３つのベクトルには、

```math
\sin (\alpha + \beta) \mathbf c  =   (\sin \beta) \mathbf a +   (\sin \alpha)  \mathbf b
```

の関係が成り立つことが知られています。この定理をふまえて、大円での断面図上に３つのQuaternion を描いたものを右に示しました．前述の定理から，Quaternion の大円補間の意味が理解できると思います。

（おしまい：最後まで読んで頂ありがとうございました。過去の記事から思考を再度トレースしてみましたが、数式のバグを２つ発見しました。）

# (参考)Java と C++ のライブラリ

この辺りの数学を実装さした vecmath というライブラリをソースコードで公開しています。

* [Unofficial Java3D vecmath package implementation](http://objectclub.jp/download/vecmath1)

![vecmathclasses.png](https://qiita-image-store.s3.amazonaws.com/0/51055/9cdeac33-1748-578c-e7a9-f9e09c4d456e.png)