#ifndef ROOT_Math_GenVector_EulerAngles
#define ROOT_Math_GenVector_EulerAngles 1
#include "Math/GenVector/Rotation3D.h"
#include "Math/GenVector/DisplacementVector3D.h"
#include "Math/GenVector/PositionVector3D.h"
#include "Math/GenVector/LorentzVector.h"
#include "Math/GenVector/3DConversions.h"
#include <algorithm>
#include <cassert>
namespace ROOT {
namespace Math {
class EulerAngles {
public:
typedef double Scalar;
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<class IT>
EulerAngles(IT begin, IT end) { SetComponents(begin,end); }
void Rectify();
template <class OtherRotation>
explicit EulerAngles(const OtherRotation & r) {gv_detail::convert(r,*this);}
template <class OtherRotation>
EulerAngles & operator=( OtherRotation const & r ) {
gv_detail::convert(r,*this);
return *this;
}
#ifdef OLD
explicit EulerAngles(const Rotation3D & r) {gv_detail::convert(r,*this);}
explicit EulerAngles(const Rotation3D & r) {gv_detail::convert(r,*this);}
explicit EulerAngles(const Quaternion & q) {gv_detail::convert(q,*this);}
explicit EulerAngles(const AxisAngle & a ) { gv_detail::convert(a, *this); }
explicit EulerAngles( RotationZ const & r ) { gv_detail::convert(r, *this); }
explicit EulerAngles( RotationY const & r ) { gv_detail::convert(r, *this); }
explicit EulerAngles( RotationX const & r ) { gv_detail::convert(r, *this); }
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)); }
#endif
template<class IT>
void SetComponents(IT begin, IT end) {
(void)end;
fPhi = *begin++;
fTheta = *begin++;
fPsi = *begin++;
assert(begin == end);
Rectify();
}
template<class IT>
void GetComponents(IT begin, IT end) const {
(void)end;
*begin++ = fPhi;
*begin++ = fTheta;
*begin++ = fPsi;
assert(begin == end);
}
template<class IT>
void GetComponents(IT begin) const {
*begin++ = fPhi;
*begin++ = fTheta;
*begin = fPsi;
}
void SetComponents(Scalar phi, Scalar theta, Scalar psi) {
fPhi=phi; fTheta=theta; fPsi=psi;
Rectify();
}
void GetComponents(Scalar & phi, Scalar & theta, Scalar & psi) const {
phi=fPhi; theta=fTheta; psi=fPsi;
}
void SetPhi(Scalar phi) { fPhi=phi; Rectify(); }
Scalar Phi() const { return fPhi; }
void SetTheta(Scalar theta) { fTheta=theta; Rectify(); }
Scalar Theta() const { return fTheta; }
void SetPsi(Scalar psi) { fPsi=psi; Rectify(); }
Scalar Psi() const { return fPsi; }
template <class CoordSystem, class U>
DisplacementVector3D<CoordSystem,U>
operator() (const DisplacementVector3D<CoordSystem,U> & v) const {
return Rotation3D(*this) ( v );
}
template <class CoordSystem, class U>
PositionVector3D<CoordSystem, U>
operator() (const PositionVector3D<CoordSystem,U> & v) const {
DisplacementVector3D< Cartesian3D<double>,U > xyz(v);
DisplacementVector3D< Cartesian3D<double>,U > rxyz = operator()(xyz);
return PositionVector3D<CoordSystem,U> ( rxyz );
}
template <class CoordSystem>
LorentzVector<CoordSystem>
operator() (const LorentzVector<CoordSystem> & v) const {
DisplacementVector3D< Cartesian3D<double> > xyz(v.Vect());
xyz = operator()(xyz);
LorentzVector< PxPyPzE4D<double> > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E());
return LorentzVector<CoordSystem> ( xyzt );
}
template <class ForeignVector>
ForeignVector
operator() (const ForeignVector & v) const {
DisplacementVector3D< Cartesian3D<double> > xyz(v);
DisplacementVector3D< Cartesian3D<double> > rxyz = operator()(xyz);
return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() );
}
template <class AVector>
inline
AVector operator* (const AVector & v) const
{
return operator()(v);
}
void Invert() {
Scalar tmp = -fPhi;
fPhi = -fPsi + Pi();
fPsi=tmp + Pi();
}
EulerAngles Inverse() const { return EulerAngles(-fPsi + Pi(), fTheta, -fPhi + Pi()); }
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 <class R>
EulerAngles & operator *= (const R & r) { return *this = (*this)*r; }
template <class R>
Scalar Distance ( const R & r ) const {return gv_detail::dist(*this,r);}
bool operator == (const EulerAngles & rhs) const {
if( fPhi != rhs.fPhi ) return false;
if( fTheta != rhs.fTheta ) return false;
if( fPsi != rhs.fPsi ) return false;
return true;
}
bool operator != (const EulerAngles & rhs) const {
return ! operator==(rhs);
}
private:
double fPhi;
double fTheta;
double fPsi;
static double Pi() { return M_PI; }
};
template <class R>
inline
typename EulerAngles::Scalar
Distance ( const EulerAngles& r1, const R & r2) {return gv_detail::dist(r1,r2);}
EulerAngles operator* (RotationX const & r1, EulerAngles const & r2);
EulerAngles operator* (RotationY const & r1, EulerAngles const & r2);
EulerAngles operator* (RotationZ const & r1, EulerAngles const & r2);
std::ostream & operator<< (std::ostream & os, const EulerAngles & e);
}
}
#endif /* ROOT_Math_GenVector_EulerAngles */