Un Exemple d’Implémentation des Angles d’Euler en C++

Tips and Tricks!

J’adore le langage C++ et comme programmeur scientifique il y a certaines choses que j’aime plus que d’autres. Dans le domaine de la programmation scientifique la surcharge des opérateurs ou plus communément appelé “overload” est définitivement une caractéristique que je trouve pratique.  

Permet de réimplémenter les opérateurs +,-,+= etc qui sont des opérations que la majeure partie des types mathématique supporte.  Au niveau de la programmation, on veut être en mesure d’avoir un équivalent (par exemple je veux multiplier 2 matrices A=B*C. Ainsi un utilisateur de notre librairie mathématique 3D pourrait écrire dans son programme  

Matrice A,B,C et effectuer la multiplication B*C de la même manière qu’il le ferait analytiquement. 

 Prenons le cas des rotations, une rotation est définie par une matrice et que l’on applique sur un objet pour le faire tourner. Un exemple sont les angles d’Euler largement utilises dans les moteurs de jeux vidéo pour leur efficacité. Dans une simulation 3D de corps rigides, on applique constamment des rotations sur les objets physiques pour les animer, notre class de rotation doit supporter plusieurs opérations « *,*= ». Grace à la surcharge des opérateurs en C++, il est facile de reproduire cette opération mathématique.

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