3DConversions.cxx

Go to the documentation of this file.
00001 // @(#)root/mathcore:$Id: 3DConversions.cxx 22516 2008-03-07 15:14:26Z moneta $
00002 // Authors: W. Brown, M. Fischler, L. Moneta    2005  
00003 
00004  /**********************************************************************
00005   *                                                                    *
00006   * Copyright (c) 2005, LCG ROOT FNAL MathLib Team                    *
00007   *                                                                    *
00008   *                                                                    *
00009   **********************************************************************/
00010 
00011 // Source file for something else
00012 //
00013 // Created by: Mark Fischler and Walter Brown Thurs July 7, 2005
00014 //
00015 // Last update: $Id: 3DConversions.cxx 22516 2008-03-07 15:14:26Z moneta $
00016 //
00017 
00018 // TODO - For now, all conversions are grouped in this one compilation unit.
00019 //        The intention is to seraparte them into a few .cpp files instead,
00020 //        so that users needing one form need not incorporate code for them all.
00021 
00022 #include <cmath>
00023 #include <limits>
00024 
00025 
00026 #include "Math/Math.h"
00027 
00028 #include "Math/GenVector/3DConversions.h"
00029 
00030 #include "Math/GenVector/Rotation3D.h"
00031 #include "Math/GenVector/AxisAngle.h"
00032 #include "Math/GenVector/EulerAngles.h"
00033 #include "Math/GenVector/Quaternion.h"
00034 #include "Math/GenVector/RotationZYX.h"
00035 #include "Math/GenVector/RotationX.h"
00036 #include "Math/GenVector/RotationY.h"
00037 #include "Math/GenVector/RotationZ.h"
00038 
00039 
00040 namespace ROOT {
00041 namespace Math {
00042 namespace gv_detail {
00043 
00044 enum ERotation3DMatrixIndex
00045 { kXX = Rotation3D::kXX, kXY = Rotation3D::kXY, kXZ = Rotation3D::kXZ
00046 , kYX = Rotation3D::kYX, kYY = Rotation3D::kYY, kYZ = Rotation3D::kYZ
00047 , kZX = Rotation3D::kZX, kZY = Rotation3D::kZY, kZZ = Rotation3D::kZZ
00048 };
00049 
00050 
00051 // ----------------------------------------------------------------------
00052 void convert( Rotation3D const & from, AxisAngle   & to)
00053 {
00054    // conversions from Rotation3D
00055    double m[9];
00056    from.GetComponents(m, m+9);
00057    
00058    const double  uZ = m[kYX] - m[kXY];
00059    const double  uY = m[kXZ] - m[kZX];
00060    const double  uX = m[kZY] - m[kYZ];
00061 
00062 
00063    // in case of rotaiton of an angle PI, the rotation matrix is symmetric and 
00064    // uX = uY = uZ  = 0. Use then conversion through the quaternion
00065    if ( std::fabs( uX ) < 8.*std::numeric_limits<double>::epsilon() &&
00066         std::fabs( uY ) < 8.*std::numeric_limits<double>::epsilon() && 
00067         std::fabs( uZ ) < 8.*std::numeric_limits<double>::epsilon() ) { 
00068       Quaternion tmp;
00069       convert (from,tmp); 
00070       convert (tmp,to); 
00071       return; 
00072    }
00073 
00074    AxisAngle::AxisVector u;
00075 
00076    u.SetCoordinates( uX, uY, uZ );
00077    
00078    static const double pi = M_PI;
00079    
00080    double angle;
00081    const double cosdelta = (m[kXX] + m[kYY] + m[kZZ] - 1.0) / 2.0;
00082    if (cosdelta > 1.0) {
00083       angle = 0;
00084    } else if (cosdelta < -1.0) {
00085       angle = pi;
00086    } else {
00087       angle = std::acos( cosdelta );
00088    }
00089 
00090 
00091    //to.SetAngle(angle);
00092    to.SetComponents(u, angle);
00093    to.Rectify();
00094    
00095 } // convert to AxisAngle
00096 
00097 static void correctByPi ( double& psi, double& phi ) {
00098    static const double pi = M_PI;
00099    if (psi > 0) {
00100       psi -= pi;
00101    } else {
00102       psi += pi;
00103    }
00104    if (phi > 0) {
00105       phi -= pi;
00106    } else {
00107       phi += pi;
00108    }  
00109 }
00110 
00111 void convert( Rotation3D const & from, EulerAngles & to)
00112 {
00113    // conversion from Rotation3D to Euler Angles
00114    // Mathematical justification appears in 
00115    // http://www.cern.ch/mathlibs/documents/eulerAngleComputation.pdf
00116    
00117    double r[9];
00118    from.GetComponents(r,r+9);
00119    
00120    double phi, theta, psi;
00121    double psiPlusPhi, psiMinusPhi;
00122    static const double pi = M_PI;
00123    static const double pi_2 = M_PI_2;
00124    
00125    theta = (std::fabs(r[kZZ]) <= 1.0) ? std::acos(r[kZZ]) :
00126       (r[kZZ]  >  0.0) ?     0            : pi;
00127    
00128    double cosTheta = r[kZZ];
00129    if (cosTheta > 1)  cosTheta = 1;
00130    if (cosTheta < -1) cosTheta = -1;
00131    
00132    // Compute psi +/- phi:  
00133    // Depending on whether cosTheta is positive or negative and whether it
00134    // is less than 1 in absolute value, different mathematically equivalent
00135    // expressions are numerically stable.
00136    if (cosTheta == 1) {
00137       psiPlusPhi = atan2 ( r[kXY] - r[kYX], r[kXX] + r[kYY] );
00138       psiMinusPhi = 0;     
00139    } else if (cosTheta >= 0) {
00140       psiPlusPhi = atan2 ( r[kXY] - r[kYX], r[kXX] + r[kYY] );
00141       double s = -r[kXY] - r[kYX]; // sin (psi-phi) * (1 - cos theta)
00142       double c =  r[kXX] - r[kYY]; // cos (psi-phi) * (1 - cos theta)
00143       psiMinusPhi = atan2 ( s, c );
00144    } else if (cosTheta > -1) {
00145       psiMinusPhi = atan2 ( -r[kXY] - r[kYX], r[kXX] - r[kYY] );
00146       double s = r[kXY] - r[kYX]; // sin (psi+phi) * (1 + cos theta)
00147       double c = r[kXX] + r[kYY]; // cos (psi+phi) * (1 + cos theta)
00148       psiPlusPhi = atan2 ( s, c );
00149    } else { // cosTheta == -1
00150       psiMinusPhi = atan2 ( -r[kXY] - r[kYX], r[kXX] - r[kYY] );
00151       psiPlusPhi = 0;
00152    }
00153    
00154    psi = .5 * (psiPlusPhi + psiMinusPhi); 
00155    phi = .5 * (psiPlusPhi - psiMinusPhi); 
00156    
00157    // Now correct by pi if we have managed to get a value of psiPlusPhi
00158    // or psiMinusPhi that was off by 2 pi:
00159    
00160    // set up w[i], all of which would be positive if sin and cosine of
00161    // psi and phi were positive:
00162    double w[4];
00163    w[0] = r[kXZ]; w[1] = r[kZX]; w[2] = r[kYZ]; w[3] = -r[kZY];
00164    
00165    // find biggest relevant term, which is the best one to use in correcting.
00166    double maxw = std::fabs(w[0]); 
00167    int imax = 0;
00168    for (int i = 1; i < 4; ++i) {
00169       if (std::fabs(w[i]) > maxw) {
00170          maxw = std::fabs(w[i]);
00171          imax = i;
00172       }
00173    }
00174    // Determine if the correction needs to be applied:  The criteria are 
00175    // different depending on whether a sine or cosine was the determinor: 
00176    switch (imax) {
00177       case 0:
00178          if (w[0] > 0 && psi < 0)               correctByPi ( psi, phi );
00179          if (w[0] < 0 && psi > 0)               correctByPi ( psi, phi );
00180             break;
00181       case 1:
00182          if (w[1] > 0 && phi < 0)               correctByPi ( psi, phi );
00183          if (w[1] < 0 && phi > 0)               correctByPi ( psi, phi );
00184             break;
00185       case 2:
00186          if (w[2] > 0 && std::fabs(psi) > pi_2) correctByPi ( psi, phi );    
00187          if (w[2] < 0 && std::fabs(psi) < pi_2) correctByPi ( psi, phi );    
00188             break;
00189       case 3:
00190          if (w[3] > 0 && std::fabs(phi) > pi_2) correctByPi ( psi, phi );    
00191          if (w[3] < 0 && std::fabs(phi) < pi_2) correctByPi ( psi, phi );    
00192             break;
00193    }          
00194    
00195    to.SetComponents( phi, theta, psi );
00196    
00197 } // convert to EulerAngles
00198 
00199 //------------------------------------------------------------------------
00200 void convert( Rotation3D const & from, Quaternion  & to)
00201 {
00202    // conversion from Rotation3D to Quaternion
00203    
00204    double m[9];
00205    from.GetComponents(m, m+9);
00206    
00207    const double d0 =   m[kXX] + m[kYY] + m[kZZ];
00208    const double d1 = + m[kXX] - m[kYY] - m[kZZ];
00209    const double d2 = - m[kXX] + m[kYY] - m[kZZ];
00210    const double d3 = - m[kXX] - m[kYY] + m[kZZ];
00211    
00212    // these are related to the various q^2 values;
00213    // choose the largest to avoid dividing two small numbers and losing accuracy.
00214    
00215    if ( d0 >= d1 && d0 >= d2 && d0 >= d3 ) {
00216       const double q0 = .5*std::sqrt(1+d0);
00217       const double f  = .25/q0;
00218       const double q1 = f*(m[kZY]-m[kYZ]);
00219       const double q2 = f*(m[kXZ]-m[kZX]);
00220       const double q3 = f*(m[kYX]-m[kXY]);
00221       to.SetComponents(q0,q1,q2,q3);
00222       to.Rectify();
00223       return;
00224    } else if ( d1 >= d2 && d1 >= d3 ) {
00225       const double q1 = .5*std::sqrt(1+d1);
00226       const double f  = .25/q1;
00227       const double q0 = f*(m[kZY]-m[kYZ]);
00228       const double q2 = f*(m[kXY]+m[kYX]); 
00229       const double q3 = f*(m[kXZ]+m[kZX]);
00230       to.SetComponents(q0,q1,q2,q3);
00231       to.Rectify();
00232       return;
00233    } else if ( d2 >= d3 ) {
00234       const double q2 = .5*std::sqrt(1+d2);
00235       const double f  = .25/q2;
00236       const double q0 = f*(m[kXZ]-m[kZX]);
00237       const double q1 = f*(m[kXY]+m[kYX]);
00238       const double q3 = f*(m[kYZ]+m[kZY]);
00239       to.SetComponents(q0,q1,q2,q3);
00240       to.Rectify();
00241       return;
00242    } else {
00243       const double q3 = .5*std::sqrt(1+d3);
00244       const double f  = .25/q3;
00245       const double q0 = f*(m[kYX]-m[kXY]);
00246       const double q1 = f*(m[kXZ]+m[kZX]);
00247       const double q2 = f*(m[kYZ]+m[kZY]);
00248       to.SetComponents(q0,q1,q2,q3);
00249       to.Rectify();
00250       return;
00251    }
00252 }  // convert to Quaternion
00253 
00254 //------------------------------------------------------------------------
00255 void convert( Rotation3D const & from, RotationZYX  & to)
00256 {
00257    // conversion from Rotation3D to RotationZYX
00258    // same Math used as for EulerAngles apart from some different meaning of angles and 
00259    // matrix elements. But the basic algoprithms principles are the same described in 
00260    // http://www.cern.ch/mathlibs/documents/eulerAngleComputation.pdf
00261 
00262    // theta is assumed to be in range [-PI/2,PI/2]. 
00263    // this is guranteed by the Rectify function
00264 
00265    static const double pi_2 = M_PI_2;
00266 
00267    double r[9]; 
00268    from.GetComponents(r,r+9);
00269 
00270    double phi,theta,psi = 0;
00271 
00272    // careful for numeical error make sin(theta) ourtside [-1,1]
00273    double sinTheta =  r[kXZ]; 
00274    if ( sinTheta < -1.0) sinTheta = -1.0;
00275    if ( sinTheta >  1.0) sinTheta =  1.0;
00276    theta = std::asin( sinTheta );
00277 
00278    // compute psi +/- phi
00279    // Depending on whether cosTheta is positive or negative and whether it
00280    // is less than 1 in absolute value, different mathematically equivalent
00281    // expressions are numerically stable.
00282    // algorithm from 
00283    // adapted for the case 3-2-1
00284    
00285    double psiPlusPhi = 0; 
00286    double psiMinusPhi = 0; 
00287 
00288    // valid if sinTheta not eq to -1 otherwise is zero
00289    if (sinTheta > - 1.0) 
00290       psiPlusPhi = atan2 ( r[kYX] + r[kZY], r[kYY] - r[kZX] );
00291 
00292    // valid if sinTheta not eq. to 1
00293    if (sinTheta < 1.0) 
00294       psiMinusPhi = atan2 ( r[kZY] - r[kYX] , r[kYY] + r[kZX] );
00295 
00296    psi = .5 * (psiPlusPhi + psiMinusPhi); 
00297    phi = .5 * (psiPlusPhi - psiMinusPhi); 
00298 
00299    // correction is not necessary if sinTheta = +/- 1
00300    //if (sinTheta == 1.0 || sinTheta == -1.0) return;
00301 
00302    // apply the corrections according to max of the other terms
00303    // I think is assumed convention that theta is between -PI/2,PI/2. 
00304    // OTHERWISE RESULT MIGHT BE DIFFERENT ???
00305 
00306    //since we determine phi+psi or phi-psi phi and psi can be both have a shift of +/- PI.
00307    // The shift must be applied on both (the sum (or difference) is knows to +/- 2PI ) 
00308    //This can be fixed looking at the other 4 matrix terms, which have terms in sin and cos of psi 
00309    // and phi. sin(psi+/-PI) = -sin(psi) and cos(psi+/-PI) = -cos(psi). 
00310    //Use then the biggest term for making the correction to minimize possible numerical errors   
00311 
00312    // set up w[i], all of which would be positive if sin and cosine of
00313    // psi and phi were positive:
00314    double w[4];
00315    w[0] = -r[kYZ]; w[1] = -r[kXY]; w[2] = r[kZZ]; w[3] = r[kXX];
00316    
00317    // find biggest relevant term, which is the best one to use in correcting.
00318    double maxw = std::fabs(w[0]); 
00319    int imax = 0;
00320    for (int i = 1; i < 4; ++i) {
00321       if (std::fabs(w[i]) > maxw) {
00322          maxw = std::fabs(w[i]);
00323          imax = i;
00324       }
00325    }
00326 
00327    // Determine if the correction needs to be applied:  The criteria are 
00328    // different depending on whether a sine or cosine was the determinor: 
00329    switch (imax) {
00330       case 0:
00331          if (w[0] > 0 && psi < 0)               correctByPi ( psi, phi );
00332          if (w[0] < 0 && psi > 0)               correctByPi ( psi, phi );
00333             break;
00334       case 1:
00335          if (w[1] > 0 && phi < 0)               correctByPi ( psi, phi );
00336          if (w[1] < 0 && phi > 0)               correctByPi ( psi, phi );
00337             break;
00338       case 2:
00339          if (w[2] > 0 && std::fabs(psi) > pi_2) correctByPi ( psi, phi );    
00340          if (w[2] < 0 && std::fabs(psi) < pi_2) correctByPi ( psi, phi );    
00341             break;
00342       case 3:
00343          if (w[3] > 0 && std::fabs(phi) > pi_2) correctByPi ( psi, phi );    
00344          if (w[3] < 0 && std::fabs(phi) < pi_2) correctByPi ( psi, phi );    
00345             break;
00346    }          
00347 
00348    to.SetComponents(phi, theta, psi);
00349       
00350 } // convert to RotationZYX
00351 
00352 // ----------------------------------------------------------------------
00353 // conversions from AxisAngle
00354 
00355 void convert( AxisAngle const & from, Rotation3D  & to)
00356 {
00357    // conversion from AxixAngle to Rotation3D 
00358    
00359    const double sinDelta = std::sin( from.Angle() );
00360    const double cosDelta = std::cos( from.Angle() );
00361    const double oneMinusCosDelta = 1.0 - cosDelta;
00362    
00363    const AxisAngle::AxisVector & u = from.Axis();
00364    const double uX = u.X();
00365    const double uY = u.Y();
00366    const double uZ = u.Z();
00367    
00368    double m[9];
00369    
00370    m[kXX] = oneMinusCosDelta * uX * uX  +  cosDelta;
00371    m[kXY] = oneMinusCosDelta * uX * uY  -  sinDelta * uZ;
00372    m[kXZ] = oneMinusCosDelta * uX * uZ  +  sinDelta * uY;
00373    
00374    m[kYX] = oneMinusCosDelta * uY * uX  +  sinDelta * uZ;
00375    m[kYY] = oneMinusCosDelta * uY * uY  +  cosDelta;
00376    m[kYZ] = oneMinusCosDelta * uY * uZ  -  sinDelta * uX;
00377    
00378    m[kZX] = oneMinusCosDelta * uZ * uX  -  sinDelta * uY;
00379    m[kZY] = oneMinusCosDelta * uZ * uY  +  sinDelta * uX;
00380    m[kZZ] = oneMinusCosDelta * uZ * uZ  +  cosDelta;
00381    
00382    to.SetComponents(m,m+9);
00383 } // convert to Rotation3D
00384 
00385 void convert( AxisAngle const & from , EulerAngles & to  )
00386 {
00387    // conversion from AxixAngle to EulerAngles 
00388    // TODO better : temporary make conversion using  Rotation3D
00389    
00390    Rotation3D tmp; 
00391    convert(from,tmp); 
00392    convert(tmp,to);
00393 }
00394 
00395 void convert( AxisAngle const & from, Quaternion  & to)
00396 {
00397    // conversion from AxixAngle to Quaternion  
00398    
00399    double s = std::sin (from.Angle()/2);
00400    DisplacementVector3D< Cartesian3D<double> > axis = from.Axis();
00401    
00402    to.SetComponents( std::cos(from.Angle()/2),
00403                      s*axis.X(),
00404                      s*axis.Y(),
00405                      s*axis.Z()
00406                      );
00407 } // convert to Quaternion
00408 
00409 void convert( AxisAngle const & from , RotationZYX & to  )
00410 {
00411    // conversion from AxisAngle to RotationZYX
00412    // TODO better : temporary make conversion using  Rotation3D   
00413    Rotation3D tmp; 
00414    convert(from,tmp); 
00415    convert(tmp,to);
00416 }
00417 
00418 
00419 // ----------------------------------------------------------------------
00420 // conversions from EulerAngles
00421 
00422 void convert( EulerAngles const & from, Rotation3D  & to)
00423 {
00424    // conversion from EulerAngles to Rotation3D 
00425    
00426    typedef double Scalar; 
00427    const Scalar sPhi   = std::sin( from.Phi()   );
00428    const Scalar cPhi   = std::cos( from.Phi()   );
00429    const Scalar sTheta = std::sin( from.Theta() );
00430    const Scalar cTheta = std::cos( from.Theta() );
00431    const Scalar sPsi   = std::sin( from.Psi()   );
00432    const Scalar cPsi   = std::cos( from.Psi()   );
00433    to.SetComponents  
00434       (  cPsi*cPhi-sPsi*cTheta*sPhi,  cPsi*sPhi+sPsi*cTheta*cPhi, sPsi*sTheta
00435          , -sPsi*cPhi-cPsi*cTheta*sPhi, -sPsi*sPhi+cPsi*cTheta*cPhi, cPsi*sTheta
00436          ,        sTheta*sPhi,              -sTheta*cPhi,            cTheta
00437          );
00438 }
00439 
00440 void convert( EulerAngles const & from, AxisAngle   & to)
00441 {
00442    // conversion from EulerAngles to AxisAngle
00443    // make converting first to quaternion
00444    Quaternion q;
00445    convert (from, q);
00446    convert (q, to);
00447 }
00448 
00449 void convert( EulerAngles const & from, Quaternion  & to)
00450 {
00451    // conversion from EulerAngles to Quaternion 
00452    
00453    typedef double Scalar; 
00454    const Scalar plus   = (from.Phi()+from.Psi())/2;
00455    const Scalar minus  = (from.Phi()-from.Psi())/2;
00456    const Scalar sPlus  = std::sin( plus  );
00457    const Scalar cPlus  = std::cos( plus  );  
00458    const Scalar sMinus = std::sin( minus );
00459    const Scalar cMinus = std::cos( minus );  
00460    const Scalar sTheta = std::sin( from.Theta()/2 );
00461    const Scalar cTheta = std::cos( from.Theta()/2 );
00462    
00463    to.SetComponents ( cTheta*cPlus, -sTheta*cMinus, -sTheta*sMinus, -cTheta*sPlus );
00464    // TODO -- carefully check that this is correct
00465 }
00466 
00467 void convert( EulerAngles const & from , RotationZYX & to  )
00468 {
00469    // conversion from EulerAngles to RotationZYX
00470    // TODO better : temporary make conversion using  Rotation3D   
00471    Rotation3D tmp; 
00472    convert(from,tmp); 
00473    convert(tmp,to);
00474 }
00475 
00476 
00477 // ----------------------------------------------------------------------
00478 // conversions from Quaternion
00479 
00480 void convert( Quaternion const & from, Rotation3D  & to)
00481 {
00482    // conversion from Quaternion to Rotation3D 
00483    
00484    const double q0 = from.U();
00485    const double q1 = from.I();
00486    const double q2 = from.J();
00487    const double q3 = from.K();
00488    const double q00 = q0*q0;
00489    const double q01 = q0*q1;
00490    const double q02 = q0*q2;
00491    const double q03 = q0*q3;
00492    const double q11 = q1*q1;
00493    const double q12 = q1*q2;
00494    const double q13 = q1*q3;
00495    const double q22 = q2*q2;
00496    const double q23 = q2*q3;
00497    const double q33 = q3*q3;
00498    
00499    to.SetComponents (
00500                      q00+q11-q22-q33 , 2*(q12-q03)     , 2*(q02+q13),
00501                      2*(q12+q03)     , q00-q11+q22-q33 , 2*(q23-q01),
00502                      2*(q13-q02)     , 2*(q23+q01)     , q00-q11-q22+q33 );
00503    
00504 } // conversion to Rotation3D
00505 
00506 void convert( Quaternion const & from, AxisAngle   & to)
00507 {
00508    // conversion from Quaternion to AxisAngle 
00509    
00510    double u = from.U();
00511    if ( u >= 0 ) {
00512       if ( u > 1 ) u = 1;
00513       const double angle = 2.0 * std::acos ( from.U() );
00514       DisplacementVector3D< Cartesian3D<double> >
00515          axis (from.I(), from.J(), from.K());
00516       to.SetComponents ( axis, angle );
00517    } else {
00518       if ( u < -1 ) u = -1;
00519       const double angle = 2.0 * std::acos ( -from.U() );
00520       DisplacementVector3D< Cartesian3D<double> >
00521          axis (-from.I(), -from.J(), -from.K());
00522       to.SetComponents ( axis, angle );
00523    }
00524 } // conversion to AxisAngle
00525 
00526 void convert( Quaternion const &  from, EulerAngles & to  )
00527 {
00528    // conversion from Quaternion to EulerAngles 
00529    // TODO better 
00530    // temporary make conversion using  Rotation3D
00531    
00532    Rotation3D tmp; 
00533    convert(from,tmp); 
00534    convert(tmp,to);
00535 }
00536 
00537 void convert( Quaternion const & from , RotationZYX & to  )
00538 {
00539    // conversion from Quaternion to RotationZYX
00540    // TODO better : temporary make conversion using  Rotation3D   
00541    Rotation3D tmp; 
00542    convert(from,tmp); 
00543    convert(tmp,to);
00544 }
00545 
00546 // ----------------------------------------------------------------------
00547 // conversions from RotationZYX
00548 void convert( RotationZYX const & from, Rotation3D  & to) { 
00549    // conversion to Rotation3D (matrix)
00550 
00551    double phi,theta,psi = 0;
00552    from.GetComponents(phi,theta,psi);
00553    to.SetComponents( std::cos(theta)*std::cos(phi), 
00554                       - std::cos(theta)*std::sin(phi), 
00555                       std::sin(theta), 
00556                       
00557                       std::cos(psi)*std::sin(phi) + std::sin(psi)*std::sin(theta)*std::cos(phi), 
00558                       std::cos(psi)*std::cos(phi) - std::sin(psi)*std::sin(theta)*std::sin(phi), 
00559                       -std::sin(psi)*std::cos(theta), 
00560                       
00561                       std::sin(psi)*std::sin(phi) - std::cos(psi)*std::sin(theta)*std::cos(phi), 
00562                       std::sin(psi)*std::cos(phi) + std::cos(psi)*std::sin(theta)*std::sin(phi), 
00563                       std::cos(psi)*std::cos(theta)
00564       );
00565 
00566 }
00567 void convert( RotationZYX const & from, AxisAngle   & to) { 
00568    // conversion to axis angle
00569    // TODO better : temporary make conversion using  Rotation3D   
00570    Rotation3D tmp; 
00571    convert(from,tmp); 
00572    convert(tmp,to);
00573 }
00574 void convert( RotationZYX const & from, EulerAngles & to) {
00575    // conversion to Euler angle
00576    // TODO better : temporary make conversion using  Rotation3D   
00577    Rotation3D tmp; 
00578    convert(from,tmp); 
00579    convert(tmp,to);
00580 }
00581 void convert( RotationZYX const & from, Quaternion  & to) { 
00582    double phi,theta,psi = 0;
00583    from.GetComponents(phi,theta,psi);
00584 
00585    double sphi2   = std::sin(phi/2); 
00586    double cphi2   = std::cos(phi/2); 
00587    double stheta2 = std::sin(theta/2); 
00588    double ctheta2 = std::cos(theta/2); 
00589    double spsi2   = std::sin(psi/2); 
00590    double cpsi2   = std::cos(psi/2); 
00591    to.SetComponents(  cphi2 * cpsi2 * ctheta2 - sphi2 * spsi2 * stheta2, 
00592                       sphi2 * cpsi2 * stheta2 + cphi2 * spsi2 * ctheta2, 
00593                       cphi2 * cpsi2 * stheta2 - sphi2 * spsi2 * ctheta2, 
00594                       sphi2 * cpsi2 * ctheta2 + cphi2 * spsi2 * stheta2 
00595       );
00596 }
00597 
00598 
00599 // ----------------------------------------------------------------------
00600 // conversions from RotationX
00601 
00602 void convert( RotationX const & from, Rotation3D  & to)
00603 {
00604    // conversion from RotationX to Rotation3D 
00605    
00606    const double c = from.CosAngle();
00607    const double s = from.SinAngle();
00608    to.SetComponents ( 1,  0,  0,
00609                       0,  c, -s,
00610                       0,  s,  c );
00611 }
00612 
00613 void convert( RotationX const & from, AxisAngle   & to)
00614 {
00615    // conversion from RotationX to AxisAngle 
00616    
00617    DisplacementVector3D< Cartesian3D<double> > axis (1, 0, 0);
00618    to.SetComponents ( axis, from.Angle() );
00619 }
00620 
00621 void convert( RotationX const & from , EulerAngles &  to  )
00622 {
00623    // conversion from RotationX to EulerAngles 
00624    //TODO better: temporary make conversion using  Rotation3D
00625    
00626    Rotation3D tmp; 
00627    convert(from,tmp); 
00628    convert(tmp,to);
00629 }
00630 
00631 void convert( RotationX const & from, Quaternion  & to)
00632 {
00633    // conversion from RotationX to Quaternion 
00634    
00635    to.SetComponents (std::cos(from.Angle()/2), std::sin(from.Angle()/2), 0, 0);
00636 }
00637 
00638 void convert( RotationX const & from , RotationZYX & to  )
00639 {
00640    // conversion from RotationX to RotationZYX 
00641    to.SetComponents(0,0,from.Angle());
00642 }
00643 
00644 
00645 // ----------------------------------------------------------------------
00646 // conversions from RotationY
00647 
00648 void convert( RotationY const & from, Rotation3D  & to)
00649 {
00650    // conversion from RotationY to Rotation3D
00651    
00652    const double c = from.CosAngle();
00653    const double s = from.SinAngle();
00654    to.SetComponents (  c, 0, s,
00655                        0, 1, 0,
00656                       -s, 0, c );
00657 }
00658 
00659 void convert( RotationY const & from, AxisAngle   & to)
00660 {
00661    // conversion from RotationY to AxisAngle
00662    
00663    DisplacementVector3D< Cartesian3D<double> > axis (0, 1, 0);
00664    to.SetComponents ( axis, from.Angle() );
00665 }
00666 
00667 void convert( RotationY const & from, EulerAngles & to  )
00668 {
00669    // conversion from RotationY to EulerAngles
00670    // TODO better: temporary make conversion using  Rotation3D
00671    
00672    Rotation3D tmp; 
00673    convert(from,tmp); 
00674    convert(tmp,to);
00675 }
00676 
00677 void convert( RotationY const & from , RotationZYX & to  )
00678 {
00679    // conversion from RotationY to RotationZYX 
00680    to.SetComponents(0,from.Angle(),0);
00681 }
00682 
00683 
00684 void convert( RotationY const & from, Quaternion  & to)
00685 {
00686    // conversion from RotationY to Quaternion
00687    
00688    to.SetComponents (std::cos(from.Angle()/2), 0, std::sin(from.Angle()/2), 0);
00689 }
00690 
00691 
00692 
00693 // ----------------------------------------------------------------------
00694 // conversions from RotationZ
00695 
00696 void convert( RotationZ const & from, Rotation3D  & to)
00697 {
00698    // conversion from RotationZ to Rotation3D
00699    
00700    const double c = from.CosAngle();
00701    const double s = from.SinAngle();
00702    to.SetComponents ( c, -s, 0,
00703                       s,  c, 0,
00704                       0,  0, 1 );
00705 }
00706 
00707 void convert( RotationZ const & from, AxisAngle   & to)
00708 {
00709    // conversion from RotationZ to AxisAngle
00710    
00711    DisplacementVector3D< Cartesian3D<double> > axis (0, 0, 1);
00712    to.SetComponents ( axis, from.Angle() );
00713 }
00714 
00715 void convert( RotationZ const & from  , EulerAngles & to  )
00716 {
00717    // conversion from RotationZ to EulerAngles
00718    // TODO better: temporary make conversion using  Rotation3D
00719    
00720    Rotation3D tmp; 
00721    convert(from,tmp); 
00722    convert(tmp,to);
00723 }
00724 
00725 void convert( RotationZ const & from , RotationZYX & to  )
00726 {
00727    // conversion from RotationY to RotationZYX 
00728    to.SetComponents(from.Angle(),0,0);
00729 }
00730 
00731 void convert( RotationZ const & from, Quaternion  & to)
00732 {
00733    // conversion from RotationZ to Quaternion
00734    
00735    to.SetComponents (std::cos(from.Angle()/2), 0, 0, std::sin(from.Angle()/2));
00736 }
00737 
00738 } //namespace gv_detail
00739 } //namespace Math
00740 } //namespace ROOT

Generated on Tue Jul 5 14:30:52 2011 for ROOT_528-00b_version by  doxygen 1.5.1