00001 // @(#)root/mathcore:$Id: EulerAngles.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 EulerAngles 00012 // 00013 // Created by: Mark Fischler Thurs June 9 2005 00014 // 00015 // Last update: $Id: EulerAngles.cxx 22516 2008-03-07 15:14:26Z moneta $ 00016 // 00017 #include "Math/GenVector/EulerAngles.h" 00018 00019 #include <cmath> 00020 00021 #include "Math/GenVector/Cartesian3D.h" 00022 #include "Math/GenVector/DisplacementVector3D.h" 00023 #include "Math/GenVector/EulerAngles.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 void EulerAngles::Rectify() 00039 { 00040 // rectify 00041 if ( fTheta < 0 || fTheta > Pi() ) { 00042 Scalar t = fTheta - std::floor( fTheta/(2*Pi()) ) * 2*Pi(); 00043 if ( t <= Pi() ) { 00044 fTheta = t; 00045 } else { 00046 fTheta = 2*Pi() - t; 00047 fPhi = fPhi + Pi(); 00048 fPsi = fPsi + Pi(); 00049 } 00050 } 00051 00052 if ( fPhi <= -Pi()|| fPhi > Pi() ) { 00053 fPhi = fPhi - std::floor( fPhi/(2*Pi()) +.5 ) * 2*Pi(); 00054 } 00055 00056 if ( fPsi <= -Pi()|| fPsi > Pi() ) { 00057 fPsi = fPsi - std::floor( fPsi/(2*Pi()) +.5 ) * 2*Pi(); 00058 } 00059 00060 } // Rectify() 00061 00062 00063 // ========== Operations ===================== 00064 00065 // DisplacementVector3D< Cartesian3D<double> > 00066 // EulerAngles:: 00067 // operator() (const DisplacementVector3D< Cartesian3D<double> > & v) const 00068 // { 00069 // return Rotation3D(*this)(v); 00070 // } 00071 00072 00073 EulerAngles EulerAngles::operator * (const Rotation3D & r) const { 00074 // combine with a Rotation3D 00075 return EulerAngles ( Rotation3D(*this) * r ); 00076 } 00077 00078 EulerAngles EulerAngles::operator * (const AxisAngle & a) const { 00079 // combine with a AxisAngle 00080 return EulerAngles ( Quaternion(*this) * Quaternion(a) ); 00081 } 00082 00083 EulerAngles EulerAngles::operator * (const EulerAngles & e) const { 00084 // combine with a EulerAngles 00085 return EulerAngles ( Quaternion(*this) * Quaternion(e) ); 00086 } 00087 EulerAngles EulerAngles::operator * (const Quaternion & q) const { 00088 // combination with a Quaternion 00089 return EulerAngles ( Quaternion(*this) * q ); 00090 } 00091 00092 EulerAngles EulerAngles::operator * (const RotationX & r) const { 00093 // combine with a RotationX 00094 return EulerAngles ( Quaternion(*this) * r ); 00095 } 00096 00097 EulerAngles EulerAngles::operator * (const RotationY & r) const { 00098 // combine with a RotationY 00099 return EulerAngles ( Quaternion(*this) * r ); 00100 } 00101 00102 EulerAngles EulerAngles::operator * (const RotationZ & r) const { 00103 // combine with a RotationZ 00104 // TODO -- this can be made much faster because it merely adds 00105 // the r.Angle() to phi. 00106 Scalar newPhi = fPhi + r.Angle(); 00107 if ( newPhi <= -Pi()|| newPhi > Pi() ) { 00108 newPhi = newPhi - std::floor( newPhi/(2*Pi()) +.5 ) * 2*Pi(); 00109 } 00110 return EulerAngles ( newPhi, fTheta, fPsi ); 00111 } 00112 00113 EulerAngles operator * ( RotationX const & r, EulerAngles const & e ) { 00114 return EulerAngles(r) * e; // TODO: improve performance 00115 } 00116 00117 EulerAngles operator * ( RotationY const & r, EulerAngles const & e ) { 00118 return EulerAngles(r) * e; // TODO: improve performance 00119 } 00120 00121 EulerAngles 00122 operator * ( RotationZ const & r, EulerAngles const & e ) { 00123 return EulerAngles(r) * e; // TODO: improve performance 00124 } 00125 00126 // ========== I/O ===================== 00127 00128 std::ostream & operator<< (std::ostream & os, const EulerAngles & e) { 00129 // TODO - this will need changing for machine-readable issues 00130 // and even the human readable form may need formatiing improvements 00131 os << "\n{phi: " << e.Phi() << " theta: " << e.Theta() 00132 << " psi: " << e.Psi() << "}\n"; 00133 return os; 00134 } 00135 00136 00137 } //namespace Math 00138 } //namespace ROOT