Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
AxisAngle.h
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Authors: W. Brown, M. Fischler, L. Moneta 2005
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2005 , LCG ROOT MathLib Team *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Header file for class AxisAngle
12 //
13 // Created by: Lorenzo Moneta at Wed May 11 10:37:10 2005
14 //
15 // Last update: Wed May 11 10:37:10 2005
16 //
17 #ifndef ROOT_Math_GenVector_AxisAngle
18 #define ROOT_Math_GenVector_AxisAngle 1
19 
25 #include <algorithm>
26 #include <cassert>
27 
28 
29 namespace ROOT {
30 namespace Math {
31 
32 
33 //__________________________________________________________________________________________
34  /**
35  AxisAngle class describing rotation represented with direction axis (3D Vector) and an
36  angle of rotation around that axis.
37 
38  @ingroup GenVector
39 
40  */
41 class AxisAngle {
42 
43 public:
44 
45  typedef double Scalar;
46 
47  /**
48  definition of vector axis
49  */
50  typedef DisplacementVector3D<Cartesian3D<Scalar> > AxisVector;
51 
52 
53  /**
54  Default constructor (axis is z and angle is zero)
55  */
56  AxisAngle() : fAxis(0,0,1), fAngle(0) { }
57 
58  /**
59  Construct from a non-zero vector (x,y,z) and an angle.
60  Precondition: the Vector needs to implement x(), y(), z(), and unit()
61  */
62  template<class AnyVector>
63  AxisAngle(const AnyVector & v, Scalar angle) :
64  fAxis(v.unit()), fAngle(angle) { }
65 
66  /**
67  Construct given a pair of pointers or iterators defining the
68  beginning and end of an array of four Scalars, to be treated as
69  the x, y, and z components of a unit axis vector, and the angle
70  of rotation.
71  Precondition: The first three components are assumed to represent
72  the rotation axis vector and the 4-th the rotation angle.
73  The angle is assumed to be in the range (-pi,pi].
74  The axis vector is automatically normalized to be a unit vector
75  */
76  template<class IT>
77  AxisAngle(IT begin, IT end) { SetComponents(begin,end); }
78 
79  // The compiler-generated copy ctor, copy assignment, and dtor are OK.
80 
81  /**
82  Re-adjust components to eliminate small deviations from the axis
83  being a unit vector and angles out of the canonical range (-pi,pi]
84  */
85  void Rectify();
86 
87  // ======== Construction From other Rotation Forms ==================
88 
89  /**
90  Construct from another supported rotation type (see gv_detail::convert )
91  */
92  template <class OtherRotation>
93  explicit AxisAngle(const OtherRotation & r) {gv_detail::convert(r,*this);}
94 
95 
96  /**
97  Assign from another supported rotation type (see gv_detail::convert )
98  */
99  template <class OtherRotation>
100  AxisAngle & operator=( OtherRotation const & r ) {
101  gv_detail::convert(r,*this);
102  return *this;
103  }
104 
105  // ======== Components ==============
106 
107  /**
108  Set the axis and then the angle given a pair of pointers or iterators
109  defining the beginning and end of an array of four Scalars.
110  Precondition: The first three components are assumed to represent
111  the rotation axis vector and the 4-th the rotation angle.
112  The angle is assumed to be in the range (-pi,pi].
113  The axis vector is automatically normalized to be a unit vector
114  */
115  template<class IT>
116 #ifndef NDEBUG
117  void SetComponents(IT begin, IT end) {
118 #else
119  void SetComponents(IT begin, IT ) {
120 #endif
121  IT a = begin; IT b = ++begin; IT c = ++begin;
122  fAxis.SetCoordinates(*a,*b,*c);
123  fAngle = *(++begin);
124  assert (++begin==end);
125  // re-normalize the vector
126  double tot = fAxis.R();
127  if (tot > 0) fAxis /= tot;
128  }
129 
130  /**
131  Get the axis and then the angle into data specified by an iterator begin
132  and another to the end of the desired data (4 past start).
133  */
134  template<class IT>
135 #ifndef NDEBUG
136  void GetComponents(IT begin, IT end) const {
137 #else
138  void GetComponents(IT begin, IT ) const {
139 #endif
140  IT a = begin; IT b = ++begin; IT c = ++begin;
141  fAxis.GetCoordinates(*a,*b,*c);
142  *(++begin) = fAngle;
143  assert (++begin==end);
144  }
145 
146  /**
147  Get the axis and then the angle into data specified by an iterator begin
148  */
149  template<class IT>
150  void GetComponents(IT begin) const {
151  double ax,ay,az = 0;
152  fAxis.GetCoordinates(ax,ay,az);
153  *begin++ = ax;
154  *begin++ = ay;
155  *begin++ = az;
156  *begin = fAngle;
157  }
158 
159  /**
160  Set components from a non-zero vector (x,y,z) and an angle.
161  Precondition: the Vector needs to implement x(), y(), z(), and unit()
162  */
163  template<class AnyVector>
164  void SetComponents(const AnyVector & v, Scalar angle) {
165  fAxis=v.unit();
166  fAngle=angle;
167  }
168 
169  /**
170  Set components into a non-zero vector (x,y,z) and an angle.
171  The vector is intended to be a cartesian dispalcement vector
172  but any vector class assignable from one will work.
173  */
174  template<class AnyVector>
175  void GetComponents(AnyVector & axis, Scalar & angle) const {
176  axis = fAxis;
177  angle = fAngle;
178  }
179 
180  /**
181  accesss to rotation axis
182  */
183  AxisVector Axis() const { return fAxis; }
184 
185  /**
186  access to rotation angle
187  */
188  Scalar Angle() const { return fAngle; }
189 
190  // =========== operations ==============
191 
192  /**
193  Rotation operation on a cartesian vector
194  */
195  typedef DisplacementVector3D<Cartesian3D<double>, DefaultCoordinateSystemTag > XYZVector;
196  XYZVector operator() (const XYZVector & v) const;
197 
198  /**
199  Rotation operation on a displacement vector in any coordinate system
200  */
201  template <class CoordSystem, class Tag>
202  DisplacementVector3D<CoordSystem, Tag>
203  operator() (const DisplacementVector3D<CoordSystem, Tag> & v) const {
204  DisplacementVector3D< Cartesian3D<double> > xyz(v.X(), v.Y(), v.Z());
205  DisplacementVector3D< Cartesian3D<double> > rxyz = operator()(xyz);
206  DisplacementVector3D< CoordSystem, Tag > vNew;
207  vNew.SetXYZ( rxyz.X(), rxyz.Y(), rxyz.Z() );
208  return vNew;
209  }
210 
211  /**
212  Rotation operation on a position vector in any coordinate system
213  */
214  template <class CoordSystem, class Tag>
215  PositionVector3D<CoordSystem, Tag>
216  operator() (const PositionVector3D<CoordSystem,Tag> & p) const {
217  DisplacementVector3D< Cartesian3D<double>,Tag > xyz(p);
218  DisplacementVector3D< Cartesian3D<double>,Tag > rxyz = operator()(xyz);
219  return PositionVector3D<CoordSystem,Tag> ( rxyz );
220  }
221 
222  /**
223  Rotation operation on a Lorentz vector in any 4D coordinate system
224  */
225  template <class CoordSystem>
226  LorentzVector<CoordSystem>
227  operator() (const LorentzVector<CoordSystem> & v) const {
228  DisplacementVector3D< Cartesian3D<double> > xyz(v.Vect());
229  xyz = operator()(xyz);
230  LorentzVector< PxPyPzE4D<double> > xyzt (xyz.X(), xyz.Y(), xyz.Z(), v.E());
231  return LorentzVector<CoordSystem> ( xyzt );
232  }
233 
234 
235  /**
236  Rotation operation on an arbitrary vector v.
237  Preconditions: v must implement methods x(), y(), and z()
238  and the arbitrary vector type must have a constructor taking (x,y,z)
239  */
240  template <class ForeignVector>
241  ForeignVector
242  operator() (const ForeignVector & v) const {
243  DisplacementVector3D< Cartesian3D<double> > xyz(v);
244  DisplacementVector3D< Cartesian3D<double> > rxyz = operator()(xyz);
245  return ForeignVector ( rxyz.X(), rxyz.Y(), rxyz.Z() );
246  }
247 
248  /**
249  Overload operator * for rotation on a vector
250  */
251  template <class AVector>
252  inline
253  AVector operator* (const AVector & v) const
254  {
255  return operator()(v);
256  }
257 
258  /**
259  Invert an AxisAngle rotation in place
260  */
261  void Invert() { fAngle = -fAngle; }
262 
263  /**
264  Return inverse of an AxisAngle rotation
265  */
266  AxisAngle Inverse() const { AxisAngle result(*this); result.Invert(); return result; }
267 
268  // ========= Multi-Rotation Operations ===============
269 
270  /**
271  Multiply (combine) two rotations
272  */
273  AxisAngle operator * (const Rotation3D & r) const;
274  AxisAngle operator * (const AxisAngle & a) const;
275  AxisAngle operator * (const EulerAngles & e) const;
276  AxisAngle operator * (const Quaternion & q) const;
277  AxisAngle operator * (const RotationZYX & r) const;
278  AxisAngle operator * (const RotationX & rx) const;
279  AxisAngle operator * (const RotationY & ry) const;
280  AxisAngle operator * (const RotationZ & rz) const;
281 
282  /**
283  Post-Multiply (on right) by another rotation : T = T*R
284  */
285  template <class R>
286  AxisAngle & operator *= (const R & r) { return *this = (*this)*r; }
287 
288 
289  /**
290  Distance between two rotations
291  */
292  template <class R>
293  Scalar Distance ( const R & r ) const {return gv_detail::dist(*this,r);}
294 
295  /**
296  Equality/inequality operators
297  */
298  bool operator == (const AxisAngle & rhs) const {
299  if( fAxis != rhs.fAxis ) return false;
300  if( fAngle != rhs.fAngle ) return false;
301  return true;
302  }
303  bool operator != (const AxisAngle & rhs) const {
304  return ! operator==(rhs);
305  }
306 
307 private:
308 
309  AxisVector fAxis; // rotation axis (3D vector)
310  Scalar fAngle; // rotation angle
311 
312  void RectifyAngle();
313 
314  static double Pi() { return 3.14159265358979323; }
315 
316 }; // AxisAngle
317 
318 // ============ Class AxisAngle ends here ============
319 
320 /**
321  Distance between two rotations
322  */
323 template <class R>
324 inline
325 typename AxisAngle::Scalar
326 Distance ( const AxisAngle& r1, const R & r2) {return gv_detail::dist(r1,r2);}
327 
328 /**
329  Multiplication of an axial rotation by an AxisAngle
330  */
331 AxisAngle operator* (RotationX const & r1, AxisAngle const & r2);
332 AxisAngle operator* (RotationY const & r1, AxisAngle const & r2);
333 AxisAngle operator* (RotationZ const & r1, AxisAngle const & r2);
334 
335 /**
336  Stream Output and Input
337  */
338  // TODO - I/O should be put in the manipulator form
339 
340 std::ostream & operator<< (std::ostream & os, const AxisAngle & a);
341 
342 } // namespace Math
343 } // namespace ROOT
344 
345 
346 #endif /* ROOT_Math_GenVector_AxisAngle */