euler.h

Go to the documentation of this file.
00001 /*******************************************************************
00002  *
00003  *    DESCRIPTION: euler.h
00004  *
00005  *    AUTHOR: Converted from Ken Shoemake's Graphics Gems IV code by Dan Silva
00006  *
00007  *    HISTORY:  converted 11/21/96
00008  *
00009  *              RB: This file provides only a subset of those
00010  *                  found in the original Graphics Gems paper.
00011  *                  All orderings are 'static axis'.
00012  *
00013  *******************************************************************/
00014 
00015 #pragma once
00016 
00017 #include "GeomExport.h"
00018 #include "maxheap.h"
00019 #include "matrix3.h"
00020 #include "quat.h"
00021 
00022 #define EULERTYPE_XYZ   0
00023 #define EULERTYPE_XZY   1
00024 #define EULERTYPE_YZX   2
00025 #define EULERTYPE_YXZ   3
00026 #define EULERTYPE_ZXY   4
00027 #define EULERTYPE_ZYX   5
00028 #define EULERTYPE_XYX   6
00029 #define EULERTYPE_YZY   7
00030 #define EULERTYPE_ZXZ   8
00031 
00032 #define EULERTYPE_RF    16  // rotating frame (axes)  --prs.
00033 
00034 GEOMEXPORT void QuatToEuler(const Quat &q, float *ang, int type, bool flag = false);    // flag added 001101  --prs.
00035 GEOMEXPORT void EulerToQuat(float *ang, Quat &q,int type);
00036 GEOMEXPORT void MatrixToEuler(const Matrix3 &mat, float *ang, int type, bool flag = FALSE);
00037 GEOMEXPORT void EulerToMatrix(float *ang, Matrix3 &mat, int type);
00038 GEOMEXPORT float GetEulerQuatAngleRatio(Quat &quat1,Quat &quat2, float *euler1, float *euler2, int type = EULERTYPE_XYZ);
00039 GEOMEXPORT float GetEulerMatAngleRatio(Matrix3 &mat1,Matrix3 &mat2, float *euler1, float *euler2, int type = EULERTYPE_XYZ);
00040 GEOMEXPORT void ContinuousQuatToEuler(const Quat& quat, float ang[3], int order);
00041 
00091 class RotationValue: public MaxHeapOperators {
00092 //
00093 // There are two classes of Euler angle types, that of which rotation
00094 // axes are not repeated, from kXYZ to kZYX, and one of which an axis is
00095 // repeated, from kXYX to kZXZ. Repeated types starts from kReptd.
00096 // For non-repetitive Euler angles, there are two well-defined methods
00097 // to associate three ordered angles, to axes. First, we can associate
00098 // them with x-, y-, and z-, axes in order. The first angle, for example,
00099 // is always associated with the x-axis, no matter where it appears
00100 // in the Euler type (x-axis appears at second place in kZXY, for example).
00101 // Second, we can associate them by position: the first angle is always
00102 // associated with the first axis in the Euler type. For examples,
00103 // the first angle is applied to the x-axis for kXYZ and kXZY, to the
00104 // y-axis for kYXZ and kYZX, etc.
00105 // Let's call the first method by (axis) name, and the second method
00106 // by order. We associate angles by name for non-repetitive Euler types.
00107 // For repetitive types, by-name is not well-defined, because there is
00108 // a missing axis. For repetitive types, we associate angles by-order.
00109 // Example:
00110 //   Point3 a = Euler(RotationValue::kZYX);
00111 // then, a.x, a.y, a.z, are the Euler angles for the x-axis, y-axis,
00112 // and z-axis.
00113 //   Point3 a = Euler(RotationValue::kZXZ);
00114 // then, a.x is angle applied to the first z-axis (from left), a.y is
00115 // applied to the x-axis, and a.z is applied to the second z-axis.
00116 //
00117 public:
00118     enum EulerType {
00119         kXYZ = EULERTYPE_XYZ,
00120         kXZY,
00121         kYZX,
00122         kYXZ,
00123         kZXY,
00124         kZYX,
00125         kXYX,
00126         kYZY,
00127         kZXZ
00128     };
00129     enum {
00130         kReptd = kXYX,
00131         kQuat = 100
00132     };
00137     static bool IsEuler(int rep) { return (kXYZ <= rep && rep <= kZXZ); }
00143     static bool IsRepetitive(int rep) {
00144         // Pre-cond: IsEuler(rep)
00145         return rep >= kReptd; }
00150     static bool IsQuat(int rep) { return rep == kQuat; }
00151 
00158     void Set(const Point3& a, EulerType et) {
00159         mQ.x = a.x;
00160         mQ.y = a.y;
00161         mQ.z = a.z;
00162         mRep = (short)et; }
00166     void Set(const Quat& q) {
00167         mQ = q;
00168         mRep = kQuat; }
00170     RotationValue() : mQ(), mRep(kXYZ) {}
00172     RotationValue(const Point3& a, EulerType et) { Set(a, et); }
00175     RotationValue(const Quat& q) { Set(q); }
00177     RotationValue(const RotationValue& src) : mQ(src.mQ), mRep(src.mRep) {}
00178 
00188     Point3 Euler(EulerType et =kXYZ) const {
00189         if (et == mRep) return Point3(mQ.x, mQ.y, mQ.z);
00190         else return ToEulerAngles(et); }
00192     operator Quat() const {
00193         if (mRep == kQuat) return mQ;
00194         else return ToQuat(); }
00196     GEOMEXPORT operator Matrix3() const;
00200     GEOMEXPORT void PreApplyTo(Matrix3& m) const; // m = *this * m
00204     GEOMEXPORT void PostApplyTo(Matrix3& m) const; // m = m * *this
00205     // *this = *this * aa
00206     // Post-condition: NativeRep() will be changed after RotateBy()
00215     GEOMEXPORT void PostRotate(const AngAxis& aa);
00216 
00221     int     NativeRep() const { return mRep; }
00224     Quat    GetNative() const { return mQ; }
00225 
00226     // Suppose a and o are Point3's, which holds Euler angles by axis name
00227     // and by order, respectively. That is, a[0] is applied to the x-axis and
00228     // o[0] is applied to the first axis (from left in the Euler type).
00229     // Let et be non-repetitive Euler type. Then,
00230     //      o[kAxisToOrdinal[et][i]] = a[i]
00231     // and  a[kOrdinalToAxis[et][i]] = o[i]
00232     //
00233     static const int kAxisToOrdinal[kReptd][3];
00234     static const int kOrdinalToAxis[kZXZ+1][3];
00235 
00236 protected:
00237     GEOMEXPORT Point3   ToEulerAngles(EulerType et) const;
00238     GEOMEXPORT Quat ToQuat() const;
00239 
00240 private:
00241     Quat    mQ;
00242     short   mRep;
00243 };
00244