ROOT logo
// @(#)root/mathcore:$Id$
// Authors: J. Palacios, L. Moneta    2007  

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

// Header file for class Rotation in 3 dimensions, described by 3 Z-Y-X  Euler angles 
// representing a rotation along Z, Y and X
//
// Created by: Lorenzo Moneta, Wed. May 22, 2007
//
// Last update: $Id$
//
#ifndef ROOT_Math_GenVector_RotationZYX 
#define ROOT_Math_GenVector_RotationZYX  1

#ifndef ROOT_Math_Math
#include "Math/Math.h"
#endif

#ifndef ROOT_Math_GenVector_Rotation3D 
#include "Math/GenVector/Rotation3D.h"
#endif


#ifndef ROOT_Math_GenVector_DisplacementVector3D
#include "Math/GenVector/DisplacementVector3D.h"
#endif

#ifndef ROOT_Math_GenVector_PositionVector3D
#include "Math/GenVector/PositionVector3D.h"
#endif

#ifndef ROOT_Math_GenVector_LorentzVector
#include "Math/GenVector/LorentzVector.h"
#endif

#ifndef ROOT_Math_GenVector_3DConversions
#include "Math/GenVector/3DConversions.h"
#endif


#include <algorithm>
#include <cassert>
#include <iostream>


namespace ROOT {
namespace Math {


//__________________________________________________________________________________________
  /**
     Rotation class with the (3D) rotation represented by
     angles describing first a rotation of 
     an angle phi (yaw) about the  Z axis, 
     followed by a rotation of an angle theta (pitch) about the new Y' axis, 
     followed by a third rotation of an angle psi (roll) about the final X'' axis. 
     This is  sometimes referred to as the Euler 321 sequence.
     It has not to be confused with the typical Goldstein definition of the Euler Angles 
     (Z-X-Z or 313 sequence) which is used by the ROOT::Math::EulerAngles class.  


     @ingroup GenVector
  */

class RotationZYX {

public:

   typedef double Scalar;


   // ========== Constructors and Assignment =====================

   /**
      Default constructor
   */
   RotationZYX() : fPhi(0.0), fTheta(0.0), fPsi(0.0) { }

   /**
      Constructor from phi, theta and psi
   */
   RotationZYX( Scalar phi, Scalar theta, Scalar psi ) :
      fPhi(phi), fTheta(theta), fPsi(psi)
   {Rectify();}  // Added 27 Jan. 06   JMM

   /**
      Construct given a pair of pointers or iterators defining the
      beginning and end of an array of three Scalars, to be treated as
      the angles phi, theta and psi.
   */
   template<class IT>
   RotationZYX(IT begin, IT end) { SetComponents(begin,end); }

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

   /**
      Re-adjust components place angles in canonical ranges
   */
   void Rectify();


   // ======== Construction and Assignment From other Rotation Forms ==================

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


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


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

   /**
      Set the three Euler angles given a pair of pointers or iterators
      defining the beginning and end of an array of three Scalars.
   */
   template<class IT>
   void SetComponents(IT begin, IT end) {
      (void)end;
      fPhi   = *begin++;
      fTheta = *begin++;
      fPsi   = *begin++;
      assert(begin == end); 
      Rectify();
   }

   /**
      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 {
      (void)end; 
      *begin++ = fPhi;
      *begin++ = fTheta;
      *begin++ = fPsi;
      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 {
      *begin++ = fPhi;
      *begin++ = fTheta;
      *begin   = fPsi;
   }

   /**
      Set the components phi, theta, psi based on three Scalars.
   */
   void SetComponents(Scalar phi, Scalar theta, Scalar psi) {
      fPhi=phi; fTheta=theta; fPsi=psi; 
      Rectify();
   }

   /**
      Get the components phi, theta, psi into three Scalars.
   */
   void GetComponents(Scalar & phi, Scalar & theta, Scalar & psi) const {
      phi=fPhi; theta=fTheta; psi=fPsi;
   }

   /**
      Set Phi angle (Z rotation angle)
   */
   void SetPhi(Scalar phi) { fPhi=phi; Rectify(); }

   /**
      Return Phi angle (Z rotation angle)
   */
   Scalar Phi() const { return fPhi; }

   /**
      Set Theta angle (Y' rotation angle)
   */
   void SetTheta(Scalar theta) { fTheta=theta; Rectify(); }

   /**
      Return Theta angle (Y' rotation angle)
   */
   Scalar Theta() const { return fTheta; }

   /**
      Set Psi angle (X'' rotation angle)
   */
   void SetPsi(Scalar psi) { fPsi=psi; Rectify(); }

   /**
      Return Psi angle (X'' rotation angle)
   */
   Scalar Psi() const { return fPsi; }

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


   /**
      Rotation operation on a displacement vector in any coordinate system and tag
   */
   template <class CoordSystem, class U>
   DisplacementVector3D<CoordSystem,U>
   operator() (const DisplacementVector3D<CoordSystem,U> & v) const {
      return Rotation3D(*this) ( v );
   }

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

   /**
      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 a rotation in place
   */
   void Invert(); 

   /**
      Return inverse of a rotation
   */
   RotationZYX Inverse() const { 
      RotationZYX r(*this); 
      r.Invert(); 
      return r;
   }


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

   /**
      Multiply (combine) two rotations
   */
   RotationZYX operator * (const RotationZYX & e) const;
   RotationZYX operator * (const Rotation3D  & r) const;
   RotationZYX operator * (const AxisAngle   & a) const;
   RotationZYX operator * (const Quaternion  & q) const;
   RotationZYX operator * (const EulerAngles & q) const;
   RotationZYX operator * (const RotationX  & rx) const;
   RotationZYX operator * (const RotationY  & ry) const;
   RotationZYX operator * (const RotationZ  & rz) const;

   /**
      Post-Multiply (on right) by another rotation :  T = T*R
   */
   template <class R>
   RotationZYX & 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 RotationZYX & 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 RotationZYX & rhs) const {
      return ! operator==(rhs);
   }

private:

   double fPhi;      // Z rotation angle (yaw)    defined in (-PI,PI]
   double fTheta;    // Y' rotation angle (pitch) defined in [-PI/2,PI/2]
   double fPsi;      // X'' rotation angle (roll) defined in (-PI,PI]

   static double Pi() { return M_PI; }

};  // RotationZYX

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

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

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

std::ostream & operator<< (std::ostream & os, const RotationZYX & e);
 
  
} // namespace Math
} // namespace ROOT

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