#ifndef ROOT_Math_GenVector_AxisAngle
#define ROOT_Math_GenVector_AxisAngle 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 AxisAngle {
public:
typedef double Scalar;
typedef DisplacementVector3D<Cartesian3D<Scalar> > AxisVector;
AxisAngle() : fAxis(0,0,1), fAngle(0) { }
template<class AnyVector>
AxisAngle(const AnyVector & v, Scalar angle) :
fAxis(v.unit()), fAngle(angle) { }
template<class IT>
AxisAngle(IT begin, IT end) { SetComponents(begin,end); }
void Rectify();
template <class OtherRotation>
explicit AxisAngle(const OtherRotation & r) {gv_detail::convert(r,*this);}
template <class OtherRotation>
AxisAngle & operator=( OtherRotation const & r ) {
gv_detail::convert(r,*this);
return *this;
}
template<class IT>
void SetComponents(IT begin, IT end) {
IT a = begin; IT b = ++begin; IT c = ++begin;
fAxis.SetCoordinates(*a,*b,*c);
fAngle = *(++begin);
assert (++begin==end);
double tot = fAxis.R();
if (tot > 0) fAxis /= tot;
}
template<class IT>
void GetComponents(IT begin, IT end) const {
IT a = begin; IT b = ++begin; IT c = ++begin;
fAxis.GetCoordinates(*a,*b,*c);
*(++begin) = fAngle;
assert (++begin==end);
}
template<class IT>
void GetComponents(IT begin) const {
double ax,ay,az = 0;
fAxis.GetCoordinates(ax,ay,az);
*begin++ = ax;
*begin++ = ay;
*begin++ = az;
*begin = fAngle;
}
template<class AnyVector>
void SetComponents(const AnyVector & v, Scalar angle) {
fAxis=v.unit();
fAngle=angle;
}
template<class AnyVector>
void GetComponents(AnyVector & axis, Scalar & angle) const {
axis = fAxis;
angle = fAngle;
}
AxisVector Axis() const { return fAxis; }
Scalar Angle() const { return fAngle; }
typedef DisplacementVector3D<Cartesian3D<double>, DefaultCoordinateSystemTag > XYZVector;
XYZVector operator() (const XYZVector & v) const;
template <class CoordSystem, class Tag>
DisplacementVector3D<CoordSystem, Tag>
operator() (const DisplacementVector3D<CoordSystem, Tag> & v) const {
DisplacementVector3D< Cartesian3D<double> > xyz(v.X(), v.Y(), v.Z());
DisplacementVector3D< Cartesian3D<double> > rxyz = operator()(xyz);
DisplacementVector3D< CoordSystem, Tag > vNew;
vNew.SetXYZ( rxyz.X(), rxyz.Y(), rxyz.Z() );
return vNew;
}
template <class CoordSystem, class Tag>
PositionVector3D<CoordSystem, Tag>
operator() (const PositionVector3D<CoordSystem,Tag> & p) const {
DisplacementVector3D< Cartesian3D<double>,Tag > xyz(p);
DisplacementVector3D< Cartesian3D<double>,Tag > rxyz = operator()(xyz);
return PositionVector3D<CoordSystem,Tag> ( 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() { fAngle = -fAngle; }
AxisAngle Inverse() const { AxisAngle result(*this); result.Invert(); return result; }
AxisAngle operator * (const Rotation3D & r) const;
AxisAngle operator * (const AxisAngle & a) const;
AxisAngle operator * (const EulerAngles & e) const;
AxisAngle operator * (const Quaternion & q) const;
AxisAngle operator * (const RotationZYX & r) const;
AxisAngle operator * (const RotationX & rx) const;
AxisAngle operator * (const RotationY & ry) const;
AxisAngle operator * (const RotationZ & rz) const;
template <class R>
AxisAngle & 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 AxisAngle & rhs) const {
if( fAxis != rhs.fAxis ) return false;
if( fAngle != rhs.fAngle ) return false;
return true;
}
bool operator != (const AxisAngle & rhs) const {
return ! operator==(rhs);
}
private:
AxisVector fAxis;
Scalar fAngle;
void RectifyAngle();
static double Pi() { return 3.14159265358979323; }
};
template <class R>
inline
typename AxisAngle::Scalar
Distance ( const AxisAngle& r1, const R & r2) {return gv_detail::dist(r1,r2);}
AxisAngle operator* (RotationX const & r1, AxisAngle const & r2);
AxisAngle operator* (RotationY const & r1, AxisAngle const & r2);
AxisAngle operator* (RotationZ const & r1, AxisAngle const & r2);
std::ostream & operator<< (std::ostream & os, const AxisAngle & a);
}
}
#endif /* ROOT_Math_GenVector_AxisAngle */