/* dtkQuaternion.tpp --- * * Author: Thibaud Kloczko * Copyright (C) 2008 - Thibaud Kloczko, Inria. * Created: Mon Jul 12 16:18:19 2010 (+0200) * Version: $Id: 7787d17a64131dea86035c5f1195c74ef74792f8 $ * Last-Updated: jeu. mars 26 11:16:30 2015 (+0100) * By: Thibaud Kloczko * Update #: 6 */ /* Commentary: * */ /* Change log: * */ #ifndef DTKQUATERNION_TPP #define DTKQUATERNION_TPP #include "dtkVector.h" #include "dtkVector3D.h" using std::exp; using std::log; // ///////////////////////////////////////////////////////////////// // dtkQuaternion implementation // ///////////////////////////////////////////////////////////////// namespace dtkDeprecated { template inline dtkQuaternion::dtkQuaternion(const T& elemIm0, const T& elemIm1, const T& elemIm2, const T& elemReal) : dtkVector(4U) { (*this)[0] = elemIm0; (*this)[1] = elemIm1; (*this)[2] = elemIm2; (*this)[3] = elemReal; } template inline dtkQuaternion::dtkQuaternion(const T& elemReal) : dtkVector(4U) { (*this)[0] = dtkZero(); (*this)[1] = dtkZero(); (*this)[2] = dtkZero(); (*this)[3] = elemReal; } template inline dtkQuaternion::dtkQuaternion(const dtkVector3D& vecIm, const T& elemReal) : dtkVector(4U) { (*this)[0] = vecIm[0]; (*this)[1] = vecIm[1]; (*this)[2] = vecIm[2]; (*this)[3] = elemReal; } template inline dtkQuaternion::dtkQuaternion(const dtkMatrix& mat, unsigned irowStart, unsigned icolStart) : dtkVector(mat, irowStart, icolStart, irowStart + 3) { } template inline dtkQuaternion::dtkQuaternion(const dtkVector& vec, unsigned irowStart) : dtkVector(vec, irowStart, irowStart + 3) { } template dtkQuaternion::dtkQuaternion(const T& r, const dtkVector3D& vec, const T& angle) : dtkVector(4U) { T rsina = r * sin(angle); (*this)[0] = vec[0] * rsina; (*this)[1] = vec[1] * rsina; (*this)[2] = vec[2] * rsina; (*this)[3] = r * cos(angle); } template QString dtkQuaternion::identifier(void) const { return QString("dtkQuaternion<%1>").arg(typeid(T).name()); } template inline void dtkQuaternion::mapInto(const dtkMatrix& mat, unsigned irowStart, unsigned icolStart) { dtkVector::mapInto(mat, irowStart, icolStart, irowStart + 3); } template inline void dtkQuaternion::mapInto(const dtkVector& vec, unsigned irowStart) { dtkVector::mapInto(vec, irowStart, irowStart + 3); } template inline dtkQuaternion& dtkQuaternion::operator =(const dtkQuaternion& qtn) { return static_cast(dtkMatrix::operator=(qtn)); } template inline dtkQuaternion& dtkQuaternion::operator =(const dtkVector3D& vec) { (*this)[0] = vec[0]; (*this)[1] = vec[1]; (*this)[2] = vec[2]; (*this)[3] = dtkZero(); return *this; } template inline dtkQuaternion& dtkQuaternion::operator +=(const dtkQuaternion& qtn) { return static_cast(dtkMatrix::operator+=(qtn)); } template inline dtkQuaternion& dtkQuaternion::operator -=(const dtkQuaternion& qtn) { return static_cast(dtkMatrix::operator-=(qtn)); } template inline dtkQuaternion& dtkQuaternion::operator *=(const T& value) { return static_cast(dtkMatrix::operator*=(value)); } template inline dtkQuaternion& dtkQuaternion::operator *=(const dtkQuaternion& qtn) { return (*this) = (*this) * qtn; } template inline dtkQuaternion& dtkQuaternion::operator /=(const T& value) { T tTmp = dtkUnity(); tTmp /= value; return (*this) *= tTmp; } template inline dtkQuaternion& dtkQuaternion::operator /=(const dtkQuaternion& qtn) { return (*this) = (*this) / qtn; } template dtkQuaternion dtkQuaternion::operator +(const dtkQuaternion& qtn) const { return dtkQuaternion(*this) += qtn; } template dtkQuaternion dtkQuaternion::operator -(const dtkQuaternion& qtn) const { return dtkQuaternion(*this) -= qtn; } template dtkQuaternion dtkQuaternion::operator -(void) const { T tTmp = dtkZero(); tTmp -= dtkUnity(); return (*this) * tTmp; } template dtkQuaternion dtkQuaternion::operator *(const T& value) const { return dtkQuaternion(*this) *= value; } template void dtkQuaternion::storeProduct(const dtkQuaternion& qtnLeft, const dtkQuaternion& qtnRight) { T qtnLeft0 = qtnLeft[0]; T qtnLeft1 = qtnLeft[1]; T qtnLeft2 = qtnLeft[2]; T qtnLeft3 = qtnLeft[3]; T qtnRight0 = qtnRight[0]; T qtnRight1 = qtnRight[1]; T qtnRight2 = qtnRight[2]; T qtnRight3 = qtnRight[3]; (*this)[0] = qtnLeft0 * qtnRight3 + qtnLeft1 * qtnRight2 - qtnLeft2 * qtnRight1 + qtnLeft3 * qtnRight0; (*this)[1] = -qtnLeft0 * qtnRight2 + qtnLeft1 * qtnRight3 + qtnLeft2 * qtnRight0 + qtnLeft3 * qtnRight1; (*this)[2] = qtnLeft0 * qtnRight1 - qtnLeft1 * qtnRight0 + qtnLeft2 * qtnRight3 + qtnLeft3 * qtnRight2; (*this)[3] = -qtnLeft0 * qtnRight0 - qtnLeft1 * qtnRight1 - qtnLeft2 * qtnRight2 + qtnLeft3 * qtnRight3; } template dtkQuaternion dtkQuaternion::operator *(const dtkQuaternion& qtn) const { dtkQuaternion qtnResult; qtnResult.storeProduct(*this, qtn); return qtnResult; } template dtkQuaternion dtkQuaternion::operator /(const dtkQuaternion& qtn) const { return (*this) * dtkInverse(qtn); } template void dtkQuaternion::storeConjugate(const dtkQuaternion& qtn) { (*this) = qtn; makeConjugate(); } template void dtkQuaternion::makeConjugate(void) { T tTmp = dtkZero(); tTmp -= dtkUnity(); (*this)[0] *= tTmp; (*this)[1] *= tTmp; (*this)[2] *= tTmp; } template inline dtkQuaternion operator *(const T& value, const dtkQuaternion& qtn) { return qtn * value; } template inline T dtkRe(const dtkQuaternion& qtn) { return qtn[3]; } template dtkVector3D dtkIm(const dtkQuaternion& qtn) { return dtkVector3D(qtn[0], qtn[1], qtn[2]); } template dtkQuaternion dtkConjugate(const dtkQuaternion& qtn) { dtkQuaternion qtnResult(qtn); qtnResult.makeConjugate(); return qtnResult; } template dtkQuaternion dtkInverse(const dtkQuaternion& qtn) { T qtn0 = qtn[0]; T qtn1 = qtn[1]; T qtn2 = qtn[2]; T qtn3 = qtn[3]; T tTmp = qtn0; tTmp *= qtn0; tTmp += qtn1 * qtn1 + qtn2 * qtn2 + qtn3 * qtn3; return dtkConjugate(qtn) / tTmp; } template inline dtkQuaternion dtkDirection(const dtkQuaternion& qtn) { return qtn.unit(); } template inline T dtkArgument(const dtkQuaternion& qtn) { return atan2(dtkNorm(dtkIm(qtn)), dtkRe(qtn)); } template dtkQuaternion dtkExp(const dtkQuaternion& qtn) { dtkVector3D vec = dtkIm(qtn); T len = dtkNorm(vec); if (len == dtkZero()) return dtkExp(dtkRe(qtn)) * dtkQuaternion(dtkZero(), dtkZero(), dtkZero(), cos(len)); else return dtkExp(dtkRe(qtn)) * dtkQuaternion(dtkDirection(vec) * sin(len), cos(len)); } template dtkQuaternion dtkLogQ(const dtkQuaternion& qtn) { dtkVector3D vec = dtkIm(qtn); T len = dtkNorm(vec); if (len == dtkZero()) return dtkQuaternion(dtkZero(), dtkZero(), dtkZero(), dtkLogQ(dtkNorm(qtn))); else return dtkQuaternion(dtkDirection(vec) * dtkArgument(qtn), dtkLogQ(dtkNorm(qtn))); } template inline dtkQuaternion dtkPowQ(const dtkQuaternion& qtn1, const dtkQuaternion& qtn2) { return dtkExp(qtn2 * dtkLogQ(qtn1)); } } // end of namespace #endif