36 #ifndef FGQUATERNION_H
37 #define FGQUATERNION_H
44 #include "FGJSBBase.h"
45 #include "FGColumnVector3.h"
92 data[1] = data[2] = data[3] = 0.0;
118 : mCacheValid(false) {
120 double angle2 = 0.5*angle;
122 double Sangle2 = sin(angle2);
123 double Cangle2 = cos(angle2);
131 }
else if (idx == eTht) {
153 : mCacheValid(false) {
155 double angle2 = 0.5 * angle;
158 double Sangle2 = sin(angle2) / length;
159 double Cangle2 = cos(angle2);
162 data[1] = Sangle2 * axis(1);
163 data[2] = Sangle2 * axis(2);
164 data[3] = Sangle2 * axis(3);
212 return mEulerAngles(i);
222 return radtodeg*mEulerAngles(i);
231 return radtodeg*mEulerAngles;
239 return mEulerSines(i);
247 return mEulerCosines(i);
259 double operator()(
unsigned int idx)
const {
return data[idx-1]; }
270 double&
operator()(
unsigned int idx) { mCacheValid =
false;
return data[idx-1]; }
285 double Entry(
unsigned int idx)
const {
return data[idx-1]; }
318 mCacheValid = q.mCacheValid;
322 mEulerAngles = q.mEulerAngles;
323 mEulerSines = q.mEulerSines;
324 mEulerCosines = q.mEulerCosines;
336 return data[0] == q.data[0] && data[1] == q.data[1]
337 && data[2] == q.data[2] && data[3] == q.data[3];
346 data[0] += q.data[0];
347 data[1] += q.data[1];
348 data[2] += q.data[2];
349 data[3] += q.data[3];
359 data[0] -= q.data[0];
360 data[1] -= q.data[1];
361 data[2] -= q.data[2];
362 data[3] -= q.data[3];
390 return FGQuaternion(data[0]+q.data[0], data[1]+q.data[1],
391 data[2]+q.data[2], data[3]+q.data[3]);
398 return FGQuaternion(data[0]-q.data[0], data[1]-q.data[1],
399 data[2]-q.data[2], data[3]-q.data[3]);
407 return FGQuaternion(data[0]*q.data[0]-data[1]*q.data[1]-data[2]*q.data[2]-data[3]*q.data[3],
408 data[0]*q.data[1]+data[1]*q.data[0]+data[2]*q.data[3]-data[3]*q.data[2],
409 data[0]*q.data[2]-data[1]*q.data[3]+data[2]*q.data[0]+data[3]*q.data[1],
410 data[0]*q.data[3]+data[1]*q.data[2]-data[2]*q.data[1]+data[3]*q.data[0]);
418 double q0 = data[0]*q.data[0]-data[1]*q.data[1]-data[2]*q.data[2]-data[3]*q.data[3];
419 double q1 = data[0]*q.data[1]+data[1]*q.data[0]+data[2]*q.data[3]-data[3]*q.data[2];
420 double q2 = data[0]*q.data[2]-data[1]*q.data[3]+data[2]*q.data[0]+data[3]*q.data[1];
421 double q3 = data[0]*q.data[3]+data[1]*q.data[2]-data[2]*q.data[1]+data[3]*q.data[0];
440 double rNorm = 1.0/norm;
442 -data[2]*rNorm, -data[3]*rNorm );
451 return FGQuaternion( data[0], -data[1], -data[2], -data[3] );
467 return data[0]*data[0] + data[1]*data[1]
468 + data[2]*data[2] + data[3]*data[3];
482 std::string Dump(
const std::string& delimiter)
const;
488 FGQuaternion(
double q1,
double q2,
double q3,
double q4) : mCacheValid(false)
489 { data[0] = q1; data[1] = q2; data[2] = q3; data[3] = q4; }
494 void ComputeDerivedUnconditional(
void)
const;
502 void ComputeDerived(
void)
const {
504 ComputeDerivedUnconditional();
516 mutable bool mCacheValid;
519 mutable FGMatrix33 mT;
520 mutable FGMatrix33 mTInv;
523 mutable FGColumnVector3 mEulerAngles;
526 mutable FGColumnVector3 mEulerSines;
527 mutable FGColumnVector3 mEulerCosines;
529 void InitializeFromEulerAngles(
double phi,
double tht,
double psi);
540 return FGQuaternion(scalar*q.data[0], scalar*q.data[1], scalar*q.data[2], scalar*q.data[3]);
551 double sina_a = angle > 0.0 ? sin(angle)/angle : 1.0;
553 qexp.data[0] = cos(angle);
554 qexp.data[1] = omega(1) * sina_a;
555 qexp.data[2] = omega(2) * sina_a;
556 qexp.data[3] = omega(3) * sina_a;
565 std::ostream& operator<<(std::ostream& os,
const FGQuaternion& q);