00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ARCHON_MATH_QUATERNION_H
00021 #define ARCHON_MATH_QUATERNION_H
00022
00023 #include <cmath>
00024 #include <algorithm>
00025 #include <iostream>
00026
00027 #include <archon/math/rotation.H>
00028
00029 namespace Archon
00030 {
00031 namespace Math
00032 {
00033 struct Quaternion
00034 {
00035 double w;
00036 Vector3 v;
00037
00038 static const Quaternion zero()
00039 {
00040 static Quaternion q = makeZero();
00041 return q;
00042 }
00043
00044 static const Quaternion one()
00045 {
00046 static Quaternion q = makeOne();
00047 return q;
00048 }
00049
00050 Quaternion() {}
00051 Quaternion(double w, const Vector3 &v): w(w), v(v) {}
00052
00053 double squareSum() const { return w*w + v.squareSum(); }
00054 double length() const { return sqrt(squareSum()); }
00055
00056 Quaternion operator+(const Quaternion &q) const { Quaternion r(*this); return r += q; }
00057 Quaternion operator-(const Quaternion &q) const { Quaternion r(*this); return r -= q; }
00058 Quaternion operator*(const Quaternion &q) const { Quaternion r(*this); return r *= q; }
00059 Quaternion operator*(double f) const { Quaternion q(*this); return q *= f; }
00060 Quaternion operator/(double f) const { Quaternion q(*this); return q /= f; }
00061 Quaternion operator-() const { Quaternion q(*this); q.negate(); return q; }
00062
00063 Quaternion &operator+=(const Quaternion &q) { w += q.w; v += q.v; return *this; }
00064 Quaternion &operator-=(const Quaternion &q) { w -= q.w; v -= q.v; return *this; }
00065
00081 Quaternion &operator*=(const Quaternion &q)
00082 {
00083 Vector3 w1 = v;
00084 w1 *= q.v;
00085 Vector3 w2 = v;
00086 w2 *= q.w;
00087 w1 += w2;
00088 w2 = q.v;
00089 w2 *= w;
00090 w1 += w2;
00091 w = w*q.w - dot(v,q.v);
00092 v = w1;
00093 return *this;
00094 }
00095
00096 Quaternion &operator/=(const Quaternion &q) { Quaternion r(q); r.inverse(); *this *= r; return *this; }
00097
00098 Quaternion &operator*=(double f) { w *= f; v *= f; return *this; }
00099 Quaternion &operator/=(double f) { w /= f; v /= f; return *this; }
00100
00101 bool operator==(const Quaternion &q) const { return w == q.w && v == q.v; }
00102 bool operator!=(const Quaternion &q) const { return w != q.w || v != q.v; }
00103
00104 void set(const Vector3 &v, double w) { this->w = w; this->v = v; }
00105 void negate() { w = -w; v.negate(); }
00106 void normalize() { *this /= length(); }
00107 void conjugate() { v.negate(); }
00108 void inverse() { *this /= squareSum(); v.negate(); }
00109
00116 void setRotation(const Rotation3 &r)
00117 {
00118 v = r.axis;
00119 double a = r.angle / 2;
00120 v *= sin(a);
00121 w = cos(a);
00122 }
00123
00130 void setRotation(const Vector3 &axis, double cosineOfAngle)
00131 {
00132 v = axis;
00133 double k = (cosineOfAngle + 1)/2;
00134 v *= sqrt(k-cosineOfAngle);
00135 w = sqrt(k);
00136 }
00137
00143 void getRotation(Rotation3 &r) const
00144 {
00145 double l = v.squareSum();
00146 if(l==0)
00147 {
00148 r.axis = Vector3(0, 1 ,0);
00149 r.angle = 0;
00150 return;
00151 }
00152 l = sqrt(l + sq(w));
00153 double a = acos(w/l);
00154 l *= sin(a);
00155 if(l==0)
00156 {
00157 r.axis = Vector3(0, 1 ,0);
00158 r.angle = 0;
00159 return;
00160 }
00161 r.angle = 2*a;
00162 r.axis = v;
00163 r.axis /= l;
00164 }
00165
00166 private:
00167 static Quaternion makeZero()
00168 {
00169 return Quaternion(0, Vector3::zero());
00170 }
00171
00172 static Quaternion makeOne()
00173 {
00174 return Quaternion(1, Vector3::zero());
00175 }
00176 };
00177
00178 inline Quaternion operator*(double f, const Quaternion &q)
00179 {
00180 Quaternion r = q; return r *= f;
00181 }
00182
00183 inline Quaternion operator/(double f, const Quaternion &q)
00184 {
00185 Quaternion r = q; r.inverse(); return r *= f;
00186 }
00187
00188 inline Quaternion normalize(const Quaternion &q)
00189 {
00190 Quaternion r = q; r.normalize(); return r;
00191 }
00192
00193 inline Quaternion conjugate(const Quaternion &q)
00194 {
00195 Quaternion r = q; r.conjugate(); return r;
00196 }
00197
00198 inline Quaternion inverse(const Quaternion &q)
00199 {
00200 Quaternion r = q; r.inverse(); return r;
00201 }
00202
00203 std::ostream &operator<<(std::ostream &, const Quaternion &);
00204 }
00205 }
00206
00207 #endif // ARCHON_MATH_QUATERNION_H