ROOT logo
// @(#)root/mathcore:$Id: AxisAngle.h 22516 2008-03-07 15:14:26Z moneta $
// Authors: W. Brown, M. Fischler, L. Moneta    2005  

/**********************************************************************
  *                                                                    *
  * Copyright (c) 2005 , LCG ROOT MathLib Team                         *
  *                                                                    *
  *                                                                    *
  **********************************************************************/

// Header file for class AxisAngle
//
// Created by: Lorenzo Moneta  at Wed May 11 10:37:10 2005
//
// Last update: Wed May 11 10:37:10 2005
//
#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 {


//__________________________________________________________________________________________
   /**
      AxisAngle class describing rotation represented with direction axis (3D Vector) and an
      angle of rotation around that axis.
      
      @ingroup GenVector
      
   */
class AxisAngle {

public:

   typedef double Scalar;

   /**
      definition of vector axis
   */
   typedef DisplacementVector3D<Cartesian3D<Scalar> > AxisVector;


   /**
      Default constructor (axis is z and angle is zero)
   */
   AxisAngle() : fAxis(0,0,1), fAngle(0) { }

   /**
      Construct from a non-zero vector (x,y,z) and an angle.
      Precondition:  the Vector needs to implement x(), y(), z(), and unit()
   */
   template<class AnyVector>
   AxisAngle(const AnyVector & v, Scalar angle) :
      fAxis(v.unit()), fAngle(angle) { }

   /**
      Construct given a pair of pointers or iterators defining the
      beginning and end of an array of four Scalars, to be treated as
      the x, y, and z components of a unit axis vector, and the angle
      of rotation.
      Precondition:  The first three components are assumed to represent
      the rotation axis vector and the 4-th the rotation angle.  
      The angle is assumed to be in the range (-pi,pi].
      The axis vector is automatically normalized to be a unit vector  
   */
   template<class IT>
   AxisAngle(IT begin, IT end) { SetComponents(begin,end); }

   // The compiler-generated copy ctor, copy assignment, and dtor are OK.

   /**
      Re-adjust components to eliminate small deviations from the axis
      being a unit vector and angles out of the canonical range (-pi,pi]
   */
   void Rectify();

   // ======== Construction From other Rotation Forms ==================

   /**
      Construct from another supported rotation type (see gv_detail::convert )
   */
   template <class OtherRotation> 
   explicit AxisAngle(const OtherRotation & r) {gv_detail::convert(r,*this);}


   /**
      Assign from another supported rotation type (see gv_detail::convert )
   */
   template <class OtherRotation> 
   AxisAngle & operator=( OtherRotation const  & r ) { 
      gv_detail::convert(r,*this);
      return *this;
   }

   // ======== Components ==============

   /**
      Set the axis and then the angle given a pair of pointers or iterators
      defining the beginning and end of an array of four Scalars.
      Precondition:  The first three components are assumed to represent
      the rotation axis vector and the 4-th the rotation angle. 
      The angle is assumed to be in the range (-pi,pi].
      The axis vector is automatically normalized to be a unit vector  
   */
   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);
      // re-normalize the vector
      double tot = fAxis.R();
      if (tot >  0) fAxis /= tot;
   }

   /**
      Get the axis and then the angle into data specified by an iterator begin
      and another to the end of the desired data (4 past start).
   */
   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);
   }

   /**
      Get the axis and then the angle into data specified by an iterator begin
   */
   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;
   }

   /**
      Set components from a non-zero vector (x,y,z) and an angle.
      Precondition:  the Vector needs to implement x(), y(), z(), and unit()
   */
   template<class AnyVector>
   void SetComponents(const AnyVector & v, Scalar angle) {
      fAxis=v.unit();
      fAngle=angle;
   }

   /**
      Set components into a non-zero vector (x,y,z) and an angle.
      The vector is intended to be a cartesian dispalcement vector
      but any vector class assignable from one will work.
   */
   template<class AnyVector>
   void GetComponents(AnyVector & axis, Scalar & angle) const {
      axis  = fAxis;
      angle = fAngle;
   }

   /**
      accesss to rotation axis
   */
   AxisVector Axis() const { return fAxis; }

   /**
      access to rotation angle
   */
   Scalar Angle() const { return fAngle; }

   // =========== operations ==============

   /**
      Rotation operation on a cartesian vector
   */
   typedef  DisplacementVector3D<Cartesian3D<double>, DefaultCoordinateSystemTag > XYZVector; 
   XYZVector operator() (const XYZVector & v) const;

   /**
      Rotation operation on a displacement vector in any coordinate system
   */
   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; 
   }

   /**
      Rotation operation on a position vector in any coordinate system
   */
   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 );
   }

   /**
      Rotation operation on a Lorentz vector in any 4D coordinate system
   */
   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 );
   }


   /**
      Rotation operation on an arbitrary vector v.
      Preconditions:  v must implement methods x(), y(), and z()
      and the arbitrary vector type must have a constructor taking (x,y,z)
   */
   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() );
   }

   /**
      Overload operator * for rotation on a vector
   */
   template <class AVector>
   inline
   AVector operator* (const AVector & v) const
   {
      return operator()(v);
   }

   /**
      Invert an AxisAngle rotation in place
   */
   void Invert() { fAngle = -fAngle; }

   /**
      Return inverse of an AxisAngle rotation
   */
   AxisAngle Inverse() const { AxisAngle result(*this); result.Invert(); return result; }

   // ========= Multi-Rotation Operations ===============

   /**
      Multiply (combine) two rotations
   */
   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;

   /**
      Post-Multiply (on right) by another rotation :  T = T*R
   */
   template <class R>
   AxisAngle & operator *= (const R & r) { return *this = (*this)*r; }


   /**
      Distance between two rotations
   */
   template <class R>
   Scalar Distance ( const R & r ) const {return gv_detail::dist(*this,r);}

   /**
      Equality/inequality operators
   */
   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;      // rotation axis (3D vector)
   Scalar      fAngle;     // rotation angle

   void RectifyAngle();

   static double Pi() { return 3.14159265358979323; }

};  // AxisAngle

// ============ Class AxisAngle ends here ============

/**
   Distance between two rotations
 */
template <class R>
inline
typename AxisAngle::Scalar
Distance ( const AxisAngle& r1, const R & r2) {return gv_detail::dist(r1,r2);}

/**
   Multiplication of an axial rotation by an AxisAngle
 */
AxisAngle operator* (RotationX const & r1, AxisAngle const & r2);
AxisAngle operator* (RotationY const & r1, AxisAngle const & r2);
AxisAngle operator* (RotationZ const & r1, AxisAngle const & r2);

/**
   Stream Output and Input
 */
  // TODO - I/O should be put in the manipulator form 

std::ostream & operator<< (std::ostream & os, const AxisAngle & a);

} // namespace Math
} // namespace ROOT


#endif /* ROOT_Math_GenVector_AxisAngle  */
 AxisAngle.h:1
 AxisAngle.h:2
 AxisAngle.h:3
 AxisAngle.h:4
 AxisAngle.h:5
 AxisAngle.h:6
 AxisAngle.h:7
 AxisAngle.h:8
 AxisAngle.h:9
 AxisAngle.h:10
 AxisAngle.h:11
 AxisAngle.h:12
 AxisAngle.h:13
 AxisAngle.h:14
 AxisAngle.h:15
 AxisAngle.h:16
 AxisAngle.h:17
 AxisAngle.h:18
 AxisAngle.h:19
 AxisAngle.h:20
 AxisAngle.h:21
 AxisAngle.h:22
 AxisAngle.h:23
 AxisAngle.h:24
 AxisAngle.h:25
 AxisAngle.h:26
 AxisAngle.h:27
 AxisAngle.h:28
 AxisAngle.h:29
 AxisAngle.h:30
 AxisAngle.h:31
 AxisAngle.h:32
 AxisAngle.h:33
 AxisAngle.h:34
 AxisAngle.h:35
 AxisAngle.h:36
 AxisAngle.h:37
 AxisAngle.h:38
 AxisAngle.h:39
 AxisAngle.h:40
 AxisAngle.h:41
 AxisAngle.h:42
 AxisAngle.h:43
 AxisAngle.h:44
 AxisAngle.h:45
 AxisAngle.h:46
 AxisAngle.h:47
 AxisAngle.h:48
 AxisAngle.h:49
 AxisAngle.h:50
 AxisAngle.h:51
 AxisAngle.h:52
 AxisAngle.h:53
 AxisAngle.h:54
 AxisAngle.h:55
 AxisAngle.h:56
 AxisAngle.h:57
 AxisAngle.h:58
 AxisAngle.h:59
 AxisAngle.h:60
 AxisAngle.h:61
 AxisAngle.h:62
 AxisAngle.h:63
 AxisAngle.h:64
 AxisAngle.h:65
 AxisAngle.h:66
 AxisAngle.h:67
 AxisAngle.h:68
 AxisAngle.h:69
 AxisAngle.h:70
 AxisAngle.h:71
 AxisAngle.h:72
 AxisAngle.h:73
 AxisAngle.h:74
 AxisAngle.h:75
 AxisAngle.h:76
 AxisAngle.h:77
 AxisAngle.h:78
 AxisAngle.h:79
 AxisAngle.h:80
 AxisAngle.h:81
 AxisAngle.h:82
 AxisAngle.h:83
 AxisAngle.h:84
 AxisAngle.h:85
 AxisAngle.h:86
 AxisAngle.h:87
 AxisAngle.h:88
 AxisAngle.h:89
 AxisAngle.h:90
 AxisAngle.h:91
 AxisAngle.h:92
 AxisAngle.h:93
 AxisAngle.h:94
 AxisAngle.h:95
 AxisAngle.h:96
 AxisAngle.h:97
 AxisAngle.h:98
 AxisAngle.h:99
 AxisAngle.h:100
 AxisAngle.h:101
 AxisAngle.h:102
 AxisAngle.h:103
 AxisAngle.h:104
 AxisAngle.h:105
 AxisAngle.h:106
 AxisAngle.h:107
 AxisAngle.h:108
 AxisAngle.h:109
 AxisAngle.h:110
 AxisAngle.h:111
 AxisAngle.h:112
 AxisAngle.h:113
 AxisAngle.h:114
 AxisAngle.h:115
 AxisAngle.h:116
 AxisAngle.h:117
 AxisAngle.h:118
 AxisAngle.h:119
 AxisAngle.h:120
 AxisAngle.h:121
 AxisAngle.h:122
 AxisAngle.h:123
 AxisAngle.h:124
 AxisAngle.h:125
 AxisAngle.h:126
 AxisAngle.h:127
 AxisAngle.h:128
 AxisAngle.h:129
 AxisAngle.h:130
 AxisAngle.h:131
 AxisAngle.h:132
 AxisAngle.h:133
 AxisAngle.h:134
 AxisAngle.h:135
 AxisAngle.h:136
 AxisAngle.h:137
 AxisAngle.h:138
 AxisAngle.h:139
 AxisAngle.h:140
 AxisAngle.h:141
 AxisAngle.h:142
 AxisAngle.h:143
 AxisAngle.h:144
 AxisAngle.h:145
 AxisAngle.h:146
 AxisAngle.h:147
 AxisAngle.h:148
 AxisAngle.h:149
 AxisAngle.h:150
 AxisAngle.h:151
 AxisAngle.h:152
 AxisAngle.h:153
 AxisAngle.h:154
 AxisAngle.h:155
 AxisAngle.h:156
 AxisAngle.h:157
 AxisAngle.h:158
 AxisAngle.h:159
 AxisAngle.h:160
 AxisAngle.h:161
 AxisAngle.h:162
 AxisAngle.h:163
 AxisAngle.h:164
 AxisAngle.h:165
 AxisAngle.h:166
 AxisAngle.h:167
 AxisAngle.h:168
 AxisAngle.h:169
 AxisAngle.h:170
 AxisAngle.h:171
 AxisAngle.h:172
 AxisAngle.h:173
 AxisAngle.h:174
 AxisAngle.h:175
 AxisAngle.h:176
 AxisAngle.h:177
 AxisAngle.h:178
 AxisAngle.h:179
 AxisAngle.h:180
 AxisAngle.h:181
 AxisAngle.h:182
 AxisAngle.h:183
 AxisAngle.h:184
 AxisAngle.h:185
 AxisAngle.h:186
 AxisAngle.h:187
 AxisAngle.h:188
 AxisAngle.h:189
 AxisAngle.h:190
 AxisAngle.h:191
 AxisAngle.h:192
 AxisAngle.h:193
 AxisAngle.h:194
 AxisAngle.h:195
 AxisAngle.h:196
 AxisAngle.h:197
 AxisAngle.h:198
 AxisAngle.h:199
 AxisAngle.h:200
 AxisAngle.h:201
 AxisAngle.h:202
 AxisAngle.h:203
 AxisAngle.h:204
 AxisAngle.h:205
 AxisAngle.h:206
 AxisAngle.h:207
 AxisAngle.h:208
 AxisAngle.h:209
 AxisAngle.h:210
 AxisAngle.h:211
 AxisAngle.h:212
 AxisAngle.h:213
 AxisAngle.h:214
 AxisAngle.h:215
 AxisAngle.h:216
 AxisAngle.h:217
 AxisAngle.h:218
 AxisAngle.h:219
 AxisAngle.h:220
 AxisAngle.h:221
 AxisAngle.h:222
 AxisAngle.h:223
 AxisAngle.h:224
 AxisAngle.h:225
 AxisAngle.h:226
 AxisAngle.h:227
 AxisAngle.h:228
 AxisAngle.h:229
 AxisAngle.h:230
 AxisAngle.h:231
 AxisAngle.h:232
 AxisAngle.h:233
 AxisAngle.h:234
 AxisAngle.h:235
 AxisAngle.h:236
 AxisAngle.h:237
 AxisAngle.h:238
 AxisAngle.h:239
 AxisAngle.h:240
 AxisAngle.h:241
 AxisAngle.h:242
 AxisAngle.h:243
 AxisAngle.h:244
 AxisAngle.h:245
 AxisAngle.h:246
 AxisAngle.h:247
 AxisAngle.h:248
 AxisAngle.h:249
 AxisAngle.h:250
 AxisAngle.h:251
 AxisAngle.h:252
 AxisAngle.h:253
 AxisAngle.h:254
 AxisAngle.h:255
 AxisAngle.h:256
 AxisAngle.h:257
 AxisAngle.h:258
 AxisAngle.h:259
 AxisAngle.h:260
 AxisAngle.h:261
 AxisAngle.h:262
 AxisAngle.h:263
 AxisAngle.h:264
 AxisAngle.h:265
 AxisAngle.h:266
 AxisAngle.h:267
 AxisAngle.h:268
 AxisAngle.h:269
 AxisAngle.h:270
 AxisAngle.h:271
 AxisAngle.h:272
 AxisAngle.h:273
 AxisAngle.h:274
 AxisAngle.h:275
 AxisAngle.h:276
 AxisAngle.h:277
 AxisAngle.h:278
 AxisAngle.h:279
 AxisAngle.h:280
 AxisAngle.h:281
 AxisAngle.h:282
 AxisAngle.h:283
 AxisAngle.h:284
 AxisAngle.h:285
 AxisAngle.h:286
 AxisAngle.h:287
 AxisAngle.h:288
 AxisAngle.h:289
 AxisAngle.h:290
 AxisAngle.h:291
 AxisAngle.h:292
 AxisAngle.h:293
 AxisAngle.h:294
 AxisAngle.h:295
 AxisAngle.h:296
 AxisAngle.h:297
 AxisAngle.h:298
 AxisAngle.h:299
 AxisAngle.h:300
 AxisAngle.h:301
 AxisAngle.h:302
 AxisAngle.h:303
 AxisAngle.h:304
 AxisAngle.h:305
 AxisAngle.h:306
 AxisAngle.h:307
 AxisAngle.h:308
 AxisAngle.h:309
 AxisAngle.h:310
 AxisAngle.h:311
 AxisAngle.h:312
 AxisAngle.h:313
 AxisAngle.h:314
 AxisAngle.h:315
 AxisAngle.h:316
 AxisAngle.h:317
 AxisAngle.h:318
 AxisAngle.h:319
 AxisAngle.h:320
 AxisAngle.h:321
 AxisAngle.h:322
 AxisAngle.h:323
 AxisAngle.h:324
 AxisAngle.h:325
 AxisAngle.h:326
 AxisAngle.h:327
 AxisAngle.h:328
 AxisAngle.h:329
 AxisAngle.h:330
 AxisAngle.h:331
 AxisAngle.h:332
 AxisAngle.h:333
 AxisAngle.h:334
 AxisAngle.h:335
 AxisAngle.h:336
 AxisAngle.h:337
 AxisAngle.h:338