本文轉自http://blog.sina.com.cn/s/blog_557d254601018dfv.html
一、四元數概念及運算
將實數域擴充到複數域,並用複數來表示平面向量,用複數的加、乘運算表示平面向量的合成、伸縮和旋轉變換,這些觀念已經在中學課程中學過了。那麼,很自然的問題就是,在三維,或更高維空間中是否也有複數的類似物?也就是說,像擴充實數那樣,在複數域的基礎上添加一個或幾個新的元素,並且讓它們跟原來的複數做加減乘除,是否就可以得到一個新的數集,並且其中的元素還可以像複數域那樣做加、減、乘、除運算,並滿足通常複數的那些運算律,包括加法和乘法的交換律與結合律、乘法對加法的分配律等待?更進一步,我們是否可以期望用這樣的數來表示三維或更高維空間中的伸縮和旋轉,就像用複數表示平面向量的伸縮旋轉那樣方便?
歷史上有很多數學家試圖尋找過三維的複數,但後來證明這樣的三維複數是不存在的
,即使不考慮空間旋轉,只從代數角度來說,三維的複數域作爲普通複數域的擴張域也是不存在的。
知道了複數不能推廣到三維,我們把目光移向四維複數,即四元數。四元數是由愛爾蘭數學家威廉·盧雲·哈密頓在1843年發現的。複數推廣到四元數,必須犧牲掉數域的某一條或幾條性質,哈密爾頓拋棄了乘法交換律。
四元數都是 1、i、j 和 k 的線性組合,一般可表示爲 d + ai + bj + ck, a、b、c、d是實數。 如把四元數的集合考慮成多維實數空間的話,四元數就代表着一個四維空間,相對於複數爲二維空間。
3.加乘運算
要把兩個四元數相加只需將相類的係數加起來就可以,就像複數一樣。至於乘法則可跟隨以下的乘數表:
以上表格中,最左邊的列表示被乘數,最上面行表示乘數。
即 i^2=j^2=k^2=-1,ij=k,
ji=-k, jk=i, kj=-i, ki=j, ik=-j
可以立即驗證加法交換律、結合律,以及等式 p+0=0+p=p,方程 p+x=0 恆有解,乘法結合律,還有乘法對加法的分配律都是成立的,只不過沒有乘法交換律。
例如:
假設:x = 3 + i, y
= 5i + j - 2k
那麼:
x + y = 3 + 6i + j - 2k
xy =( {3 + i} )( {5i + j - 2k} ) = 15i + 3j - 6k + 5i^2 + ij - 2ik
= 15i + 3j - 6k - 5 + k + 2j = - 5 + 15i + 5j - 5k
四元數也可以表示爲: q=[w,v], 其中v=(x,y,z)是矢量,w是標量。
如果向量部分外積爲零,兩個四元數的乘積就可交換了。
4.模的定義
四元數也是可以歸一化的,四元數的單位化與Vector類似,首先(a^2+b^2+c^2+d^2)的平方根 稱爲四元數的模,即||q|| = Norm(q)=sqrt(w2 + x2 + y2 + z2),這裏2指平方, 如w2指w的平方。
因爲w2 + x2 + y2 + z2=1 所以Normlize(q)=q/Norm(q)=q / sqrt(w2 + x2 + y2 + z2)
5.共軛定義
若p=w+xi+yj+zk=w+v,則p*=w-xi-yj-zk=w-v 表示與p實部相等,向量部分相反的四元數,稱爲p的共軛。
6.逆的定義
如果 ,
二、四元數與三維空間的旋轉
我們要關心的是三維空間上任意的伸縮旋轉變換是否可用四元數的乘積來表示,而這一點對四元數來說是完全能夠勝任的。
如果已知一個三維空間的伸縮旋轉的轉軸方向、旋轉角度和伸縮比例,來求相應的四元數,是比較容易的。
特別地,單位化的四元數用來描述旋轉:
以原點爲旋轉中心,旋轉的軸是(α, β, γ)( α^2 + β^2 + γ^2 = 1),
(右手系的座標定義的話,望向向量(α, β, γ)的前進方向反時針) 轉θ角的旋轉,用四元數表示就是,Q = (cos(θ/2); α sin(θ/2), β sin(θ/2), γ sin(θ/2))
四元數的乘法的意義類似於Matrix的乘法-可以將兩個旋轉合併,例如:
Q=Q1*Q2 表示Q的是先做Q2的旋轉,再做Q1的旋轉的結果,而多個四元數的旋轉也是可以合併的,當有多次旋轉操作時,使用四元數可以獲得更高的計算效率。
例子代碼
/// Quaternion.cpp
#include <math.h>
#include <iostream.h>
/// Define Data type
typedef struct
{
double t; // real-component
double x; // x-component
double y; // y-component
double z; // z-component
} quaternion;
////
Bill 注:Kakezan 在日語裏是 “乘法”的意思
quaternion Kakezan(quaternion left, quaternion right)
{
quaternion ans;
double d1, d2, d3, d4;
d1 = left.t * right.t;
d2 = -left.x * right.x;
d3 = -left.y * right.y;
d4 = -left.z * right.z;
ans.t = d1+ d2+ d3+ d4;
d1 = left.t * right.x;
d2 = right.t * left.x;
d3 = left.y * right.z;
d4 = -left.z * right.y;
ans.x = d1+ d2+ d3+ d4;
d1 = left.t * right.y;
d2 =