An Example of a C++ class Implementation Of Euler Angles

Tips and Tricks

As a scientific programmer one of the thing that I like with C++ is the overload operator.  

When programming such math stuff you want to be able to support that kind of operations at the programming level.  I just want to write code like this  

Matrix A,B,C and then do the math operation A=B*C. With overload you can do that. This way you can model mathematical operation naturally. As a user what you with such rotation matrice is the support of the multiply operation.  

Object oriented is about modeling type that match real world entity. In scientific programming math entity are matrices, scalar field and … With operator overloading you can represent those type naturally and write code that is close as you were writing it manually. That’s a rally nice feature!!  

I present a case of the Euler angles (rotation matrices that are used in physics 3D or math 3d to animate rigid body for example). In the example with the Euler angles, there is a set of operations defined in class for multiplying rotation matrices. They are represented by operator* which allowed user or programmer to write code as the one above.


namespace Sfx {
 namespace Mth {

// _________________________________________________________
//
class EulerAngles 
{
   public:
     typedef double Scalar;

     //
     // Ctor summary
     //

     // default ctor
     EulerAngles() 
     : fPhi  ( 0.0), 
       fTheta( 0.0), 
       fPsi  ( 0.0) 
     {}

     // ...
     EulerAngles( Scalar phi, Scalar theta, Scalar psi ) 
     : fPhi(phi), 
       fTheta(theta), 
       fPsi(psi)
     { Rectify();}            

     // ...
     template
     EulerAngles( IT begin, IT end) { SetComponents( begin, end); }

     // NOTE:
     // The compiler-generated copy ctor, copy assignment, and dtor are OK.

     void Rectify();
     
     //
     // ======== Construction From other Rotation Forms ==================
     //

     explicit EulerAngles( const Rotation3D & r)  { Mth::convert( r, *this);}
     explicit EulerAngles( const Quaternion & q)  { Mth::convert( q, *this);}
     explicit EulerAngles( const AxisAngle  & a ) { Mth::convert( a, *this);}
     explicit EulerAngles( RotationZ const  & r ) { Mth::convert( r, *this);}
     explicit EulerAngles( RotationY const  & r ) { Mth::convert( r, *this);}
     explicit EulerAngles( RotationX const  & r ) { Mth::convert( r, *this);}

     EulerAngles &
       operator = ( Rotation3D const  & r ) { return operator= ( EulerAngles(r)); }

     EulerAngles &
       operator = ( AxisAngle const & a ) { return operator= ( EulerAngles(a)); }

     EulerAngles &
       operator = ( Quaternion const  & q ) {return operator= ( EulerAngles(q)); }

     EulerAngles &
       operator = ( RotationZ const & r ) { return operator= ( EulerAngles(r)); }

     EulerAngles &
       operator = ( RotationY const & r ) { return operator= ( EulerAngles(r)); }

     EulerAngles &
       operator = ( RotationX const & r ) { return operator= ( EulerAngles(r)); }
  
.....
    //
    // ========= Multi-Rotation Operations ===============
    //

     EulerAngles operator * ( const Rotation3D  & r) const;
     EulerAngles operator * ( const AxisAngle   & a) const;
     EulerAngles operator * ( const EulerAngles & e) const;
     EulerAngles operator * ( const Quaternion  & q) const;
     EulerAngles operator * ( const RotationX  & rx) const;
     EulerAngles operator * ( const RotationY  & ry) const;
     EulerAngles operator * ( const RotationZ  & rz) const;

     // _____________________________________________
     //
     template 
     EulerAngles & operator *= ( const R & r) { return *this = (*this)*r;}

...
};
}}

 

clients and partners

Autolog