00001 // @(#)root/mathcore:$Id: RotationZYX.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 // Implementation file for rotation in 3 dimensions, represented by RotationZYX 00012 // 00013 // Created by: Lorenzo Moneta, May 23 2007 00014 // 00015 // Last update: $Id: RotationZYX.cxx 22516 2008-03-07 15:14:26Z moneta $ 00016 // 00017 #include "Math/GenVector/RotationZYX.h" 00018 00019 #include <cmath> 00020 00021 #include "Math/GenVector/Cartesian3D.h" 00022 #include "Math/GenVector/DisplacementVector3D.h" 00023 #include "Math/GenVector/RotationZYX.h" 00024 #include "Math/GenVector/Rotation3D.h" 00025 #include "Math/GenVector/Quaternion.h" 00026 #include "Math/GenVector/RotationX.h" 00027 #include "Math/GenVector/RotationY.h" 00028 #include "Math/GenVector/RotationZ.h" 00029 00030 #include "Math/GenVector/AxisAnglefwd.h" 00031 00032 namespace ROOT { 00033 00034 namespace Math { 00035 00036 // ========== Constructors and Assignment ===================== 00037 00038 00039 00040 // ========== Operations ===================== 00041 00042 // DisplacementVector3D< Cartesian3D<double> > 00043 // RotationZYX:: 00044 // operator() (const DisplacementVector3D< Cartesian3D<double> > & v) const 00045 // { 00046 // return Rotation3D(*this)(v); 00047 // } 00048 00049 00050 RotationZYX RotationZYX::operator * (const Rotation3D & r) const { 00051 // combine with a Rotation3D 00052 return RotationZYX ( Rotation3D(*this) * r ); 00053 } 00054 00055 RotationZYX RotationZYX::operator * (const AxisAngle & a) const { 00056 // combine with a AxisAngle 00057 return RotationZYX ( Quaternion(*this) * Quaternion(a) ); 00058 } 00059 00060 RotationZYX RotationZYX::operator * (const EulerAngles & e) const { 00061 // combine with EulerAngles 00062 return RotationZYX ( Quaternion(*this) * Quaternion(e) ); 00063 } 00064 00065 RotationZYX RotationZYX::operator * (const RotationZYX & e) const { 00066 // combine with a RotationZYX 00067 //return RotationZYX ( Quaternion(*this) * Quaternion(e) ); 00068 return RotationZYX ( Rotation3D(*this) * Rotation3D(e) ); 00069 } 00070 RotationZYX RotationZYX::operator * (const Quaternion & q) const { 00071 // combination with a Quaternion 00072 return RotationZYX ( Quaternion(*this) * q ); 00073 } 00074 00075 RotationZYX RotationZYX::operator * (const RotationX & r) const { 00076 // combine with a RotationX 00077 return RotationZYX ( Quaternion(*this) * r ); 00078 } 00079 00080 RotationZYX RotationZYX::operator * (const RotationY & r) const { 00081 // combine with a RotationY 00082 return RotationZYX ( Quaternion(*this) * r ); 00083 } 00084 00085 RotationZYX RotationZYX::operator * (const RotationZ & r) const { 00086 // combine with a RotationZ 00087 // TODO -- this can be made much faster because it merely adds 00088 // the r.Angle() to phi. 00089 Scalar newPhi = fPhi + r.Angle(); 00090 if ( newPhi <= -Pi()|| newPhi > Pi() ) { 00091 newPhi = newPhi - std::floor( newPhi/(2*Pi()) +.5 ) * 2*Pi(); 00092 } 00093 return RotationZYX ( newPhi, fTheta, fPsi ); 00094 } 00095 00096 RotationZYX operator * ( RotationX const & r, RotationZYX const & e ) { 00097 return RotationZYX(r) * e; // TODO: improve performance 00098 } 00099 00100 RotationZYX operator * ( RotationY const & r, RotationZYX const & e ) { 00101 return RotationZYX(r) * e; // TODO: improve performance 00102 } 00103 00104 RotationZYX 00105 operator * ( RotationZ const & r, RotationZYX const & e ) { 00106 return RotationZYX(r) * e; // TODO: improve performance 00107 } 00108 00109 void RotationZYX::Rectify() 00110 { 00111 // rectify . The angle theta must be defined between [-PI/2,PI.2] 00112 // same as Euler- Angles, just here Theta is shifted by PI/2 with respect to 00113 // the theta of the EulerAngles class 00114 00115 Scalar theta2 = fTheta + M_PI_2; 00116 if ( theta2 < 0 || theta2 > Pi() ) { 00117 Scalar t = theta2 - std::floor( theta2/(2*Pi() ) ) * 2*Pi(); 00118 if ( t <= Pi() ) { 00119 theta2 = t; 00120 } else { 00121 theta2 = 2*Pi() - t; 00122 fPhi = fPhi + Pi(); 00123 fPsi = fPsi + Pi(); 00124 } 00125 // ftheta is shifted of PI/2 w.r.t theta2 00126 fTheta = theta2 - M_PI_2; 00127 } 00128 00129 if ( fPhi <= -Pi()|| fPhi > Pi() ) { 00130 fPhi = fPhi - std::floor( fPhi/(2*Pi()) +.5 ) * 2*Pi(); 00131 } 00132 00133 if ( fPsi <= -Pi()|| fPsi > Pi() ) { 00134 fPsi = fPsi - std::floor( fPsi/(2*Pi()) +.5 ) * 2*Pi(); 00135 } 00136 00137 } // Rectify() 00138 00139 void RotationZYX::Invert() 00140 { 00141 // invert this rotation. 00142 // use Rotation3D. TO Do :have algorithm to invert it directly 00143 Rotation3D r(*this); 00144 //Quaternion r(*this); 00145 r.Invert(); 00146 *this = r; 00147 } 00148 00149 // ========== I/O ===================== 00150 00151 std::ostream & operator<< (std::ostream & os, const RotationZYX & e) { 00152 // TODO - this will need changing for machine-readable issues 00153 // and even the human readable form may need formatiing improvements 00154 os << "\n{phi(Z angle): " << e.Phi() << " theta(Y angle): " << e.Theta() 00155 << " psi(X angle): " << e.Psi() << "}\n"; 00156 return os; 00157 } 00158 00159 00160 } //namespace Math 00161 } //namespace ROOT