```// @(#)root/physics:\$Id\$
// Author: Peter Malzacher   19/06/99

//______________________________________________________________________________
//*-*-*-*-*-*-*-*-*-*-*-*The Physics Vector package *-*-*-*-*-*-*-*-*-*-*-*
//*-*                    ==========================                       *
//*-* The Physics Vector package consists of five classes:                *
//*-*   - TVector2                                                        *
//*-*   - TVector3                                                        *
//*-*   - TRotation                                                       *
//*-*   - TLorentzVector                                                  *
//*-*   - TLorentzRotation                                                *
//*-* It is a combination of CLHEPs Vector package written by             *
//*-* Leif Lonnblad, Andreas Nilsson and Evgueni Tcherniaev               *
//*-* and a ROOT package written by Pasha Murat.                          *
//*-* for CLHEP see:  http://wwwinfo.cern.ch/asd/lhc++/clhep/             *
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//BEGIN_HTML <!--
/* -->
<H2>
TRotation</H2>
The TRotation class describes a rotation of objects of the TVector3 class.
It is a 3*3 matrix of Double_t:

<P><TT>| xx&nbsp; xy&nbsp; xz |</TT>
<BR><TT>| yx&nbsp; yy&nbsp; yz |</TT>
<BR><TT>| zx&nbsp; zy&nbsp; zz |</TT>

<P>It describes a so called active rotation, i.e. rotation of objects inside
a static system of coordinates. In case you want to rotate the frame and
want to know the coordinates of objects in the rotated system, you should
apply the inverse rotation to the objects. If you want to transform coordinates
from the rotated frame to the original frame you have to apply the direct
transformation.

<P>A rotation around a specified axis means counterclockwise rotation around
the positive direction of the axis.
<BR>&nbsp;
<H3>
Declaration, Access, Comparisons</H3>
<TT>&nbsp; TRotation r;&nbsp;&nbsp;&nbsp; // r initialized as identity</TT>
<BR><TT>&nbsp; TRotation m(r); // m = r</TT>

<P>There is no direct way to set the matrix elements - to ensure that
a <TT>TRotation</TT> object always describes a real rotation. But you can get the
values by the member functions <TT>XX()..ZZ()</TT> or the<TT> (,)</TT>
operator:

<P><TT>&nbsp; Double_t xx = r.XX();&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; the
same as xx=r(0,0)</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xx
= r(0,0);</TT>

<P><TT>&nbsp; if (r==m) {...}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// test for equality</TT>
<BR><TT>&nbsp; if (r!=m) {..}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// test for inequality</TT>
<BR><TT>&nbsp; if (r.IsIdentity()) {...} // test for identity</TT>
<BR>&nbsp;
<H3>
Rotation around axes</H3>
The following matrices desrcibe counterclockwise rotations around coordinate
axes

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 1&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp;&nbsp; |</TT>
<BR><TT>Rx(a) = | 0 cos(a) -sin(a) |</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 0 sin(a) cos(a)&nbsp;
|</TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | cos(a)&nbsp; 0 sin(a)
|</TT>
<BR><TT>Ry(a) = |&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp; |</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | -sin(a) 0 cos(a) |</TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | cos(a) -sin(a) 0 |</TT>
<BR><TT>Rz(a) = | sin(a) cos(a) 0 |</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp;&nbsp;&nbsp; 1 |</TT>
<BR>and are implemented as member functions <TT>RotateX()</TT>, <TT>RotateY()</TT>
and <TT>RotateZ()</TT>:

<P><TT>&nbsp; r.RotateX(TMath::Pi()); // rotation around the x-axis</TT>
<H3>
Rotation around arbitary axis</H3>
The member function <TT>Rotate()</TT> allows to rotate around an arbitary vector
(not neccessary a unit one) and returns the result.

<P><TT>&nbsp; r.Rotate(TMath::Pi()/3,TVector3(3,4,5));</TT>

<P>It is possible to find a unit vector and an angle, which describe the
same rotation as the current one:

<P><TT>&nbsp; Double_t angle;</TT>
<BR><TT>&nbsp; TVector3 axis;</TT>
<BR><TT>&nbsp; r.GetAngleAxis(angle,axis);</TT>
<H3>
Rotation of local axes</H3>
Member function <TT>RotateAxes()</TT> adds a rotation of local axes to
the current rotation and returns the result:

<P><TT>&nbsp; TVector3 newX(0,1,0);</TT>
<BR><TT>&nbsp; TVector3 newY(0,0,1);</TT>
<BR><TT>&nbsp; TVector3 newZ(1,0,0);</TT>
<BR><TT>&nbsp; a.RotateAxes(newX,newY,newZ);</TT>

<P>Member functions <TT>ThetaX()</TT>, <TT>ThetaY()</TT>, <TT>ThetaZ()</TT>,
<TT>PhiX()</TT>, <TT>PhiY()</TT>,<TT>PhiZ()</TT> return azimuth and polar
angles of the rotated axes:

<P><TT>&nbsp; Double_t tx,ty,tz,px,py,pz;</TT>
<BR><TT>&nbsp; tx= a.ThetaX();</TT>
<BR><TT>&nbsp; ...</TT>
<BR><TT>&nbsp; pz= a.PhiZ();</TT>

<H3>
Setting The Rotations</H3>
The member function <TT>SetToIdentity()</TT> will set the rotation object
to the identity (no rotation).

With a minor caveat, the Euler angles of the rotation may be set using
<TT>SetXEulerAngles()</TT> or individually set with <TT>SetXPhi()</TT>,
<TT>SetXTheta()</TT>, and <TT>SetXPsi()</TT>.  These routines set the Euler
angles using the X-convention which is defined by a rotation about the Z-axis,
about the new X-axis, and about the new Z-axis.  This is the convention used
in Landau and Lifshitz, Goldstein and other common physics texts.  The
Y-convention euler angles can be set with <TT>SetYEulerAngles()</TT>,
<TT>SetYPhi()</TT>, <TT>SetYTheta()</TT>, and <TT>SetYPsi()</TT>.  The caveat
is that Euler angles usually define the rotation of the new coordinate system
with respect to the original system, however, the TRotation class specifies
the rotation of the object in the original system (an active rotation).  To
recover the usual Euler rotations (ie. rotate the system not the object), you
must take the inverse of the rotation.

The member functions <TT>SetXAxis()</TT>, <TT>SetYAxis()</TT>, and
<TT>SetZAxis()</TT> will create a rotation which rotates the requested axis
of the object to be parallel to a vector.  If used with one argument, the
rotation about that axis is arbitrary.  If used with two arguments, the
second variable defines the <TT>XY</TT>, <TT>YZ</TT>, or <TT>ZX</TT>
respectively.

<H3>
Inverse rotation</H3>
<TT>&nbsp; TRotation a,b;</TT>
<BR><TT>&nbsp; ...</TT>
<BR><TT>&nbsp; b = a.Inverse();&nbsp; // b is inverse of a, a is unchanged</TT>
<BR><TT>&nbsp; b = a.Invert();&nbsp;&nbsp; // invert a and set b = a</TT>
<H3>
Compound Rotations</H3>
The <TT>operator *</TT> has been implemented in a way that follows the
mathematical notation of a product of the two matrices which describe the
two consecutive rotations. Therefore the second rotation should be placed
first:

<P><TT>&nbsp; r = r2 * r1;</TT>
<H3>
Rotation of TVector3</H3>
The TRotation class provides an <TT>operator *</TT> which allows to express
a rotation of a <TT>TVector3</TT> analog to the mathematical notation

<P><TT>&nbsp; | x' |&nbsp;&nbsp; | xx xy xz | | x |</TT>
<BR><TT>&nbsp; | y' | = | yx yy yz | | y |</TT>
<BR><TT>&nbsp; | z' |&nbsp;&nbsp; | zx zy zz | | z |</TT><TT></TT>

<P>e.g.:

<P><TT>&nbsp; TVector3 v(1,1,1);</TT>
<BR><TT>&nbsp; v = r * v;</TT><TT></TT>

<P>You can also use the <TT>Transform()</TT> member function or the o<TT>perator
*=</TT> of the
<BR>TVector3 class:<TT></TT>

<P><TT>&nbsp; TVector3 v;</TT>
<BR><TT>&nbsp; TRotation r;</TT>
<BR><TT>&nbsp; v.Transform(r);</TT>
<BR><TT>&nbsp; v *= r;&nbsp; //Attention v = r * v</TT>
<!--*/
// -->END_HTML
//

#include "TRotation.h"
#include "TMath.h"
#include "TQuaternion.h"
#include "TError.h"

ClassImp(TRotation)

#define TOLERANCE (1.0E-6)

TRotation::TRotation()
: fxx(1.0), fxy(0.0), fxz(0.0), fyx(0.0), fyy(1.0), fyz(0.0),
fzx(0.0), fzy(0.0), fzz(1.0) {}

TRotation::TRotation(const TRotation & m) : TObject(m),
fxx(m.fxx), fxy(m.fxy), fxz(m.fxz), fyx(m.fyx), fyy(m.fyy), fyz(m.fyz),
fzx(m.fzx), fzy(m.fzy), fzz(m.fzz) {}

TRotation::TRotation(Double_t mxx, Double_t mxy, Double_t mxz,
Double_t myx, Double_t myy, Double_t myz,
Double_t mzx, Double_t mzy, Double_t mzz)
: fxx(mxx), fxy(mxy), fxz(mxz), fyx(myx), fyy(myy), fyz(myz),
fzx(mzx), fzy(mzy), fzz(mzz) {}

Double_t TRotation::operator() (int i, int j) const {
//dereferencing operator const
if (i == 0) {
if (j == 0) { return fxx; }
if (j == 1) { return fxy; }
if (j == 2) { return fxz; }
} else if (i == 1) {
if (j == 0) { return fyx; }
if (j == 1) { return fyy; }
if (j == 2) { return fyz; }
} else if (i == 2) {
if (j == 0) { return fzx; }
if (j == 1) { return fzy; }
if (j == 2) { return fzz; }
}

Warning("operator()(i,j)", "bad indices (%d , %d)",i,j);

return 0.0;
}

TRotation TRotation::operator* (const TRotation & b) const {
//multiplication operator
return TRotation(fxx*b.fxx + fxy*b.fyx + fxz*b.fzx,
fxx*b.fxy + fxy*b.fyy + fxz*b.fzy,
fxx*b.fxz + fxy*b.fyz + fxz*b.fzz,
fyx*b.fxx + fyy*b.fyx + fyz*b.fzx,
fyx*b.fxy + fyy*b.fyy + fyz*b.fzy,
fyx*b.fxz + fyy*b.fyz + fyz*b.fzz,
fzx*b.fxx + fzy*b.fyx + fzz*b.fzx,
fzx*b.fxy + fzy*b.fyy + fzz*b.fzy,
fzx*b.fxz + fzy*b.fyz + fzz*b.fzz);
}

//_____________________________________
TRotation::TRotation(const TQuaternion & Q) {
// Constructor for a rotation based on a Quaternion
// if magnitude of quaternion is null, creates identity rotation
// if quaternion is non-unit, creates rotation corresponding to the normalized (unit) quaternion

double two_r2 = 2 * Q.fRealPart * Q.fRealPart;
double two_x2 = 2 * Q.fVectorPart.X() * Q.fVectorPart.X();
double two_y2 = 2 * Q.fVectorPart.Y() * Q.fVectorPart.Y();
double two_z2 = 2 * Q.fVectorPart.Z() * Q.fVectorPart.Z();
double two_xy = 2 * Q.fVectorPart.X() * Q.fVectorPart.Y();
double two_xz = 2 * Q.fVectorPart.X() * Q.fVectorPart.Z();
double two_xr = 2 * Q.fVectorPart.X() * Q.fRealPart;
double two_yz = 2 * Q.fVectorPart.Y() * Q.fVectorPart.Z();
double two_yr = 2 * Q.fVectorPart.Y() * Q.fRealPart;
double two_zr = 2 * Q.fVectorPart.Z() * Q.fRealPart;

// protect agains zero quaternion
double mag2 = Q.QMag2();
if (mag2 > 0) {

// diago + identity
fxx = two_r2 + two_x2;
fyy = two_r2 + two_y2;
fzz = two_r2 + two_z2;

//        line 0 column 1 and conjugate
fxy = two_xy - two_zr;
fyx = two_xy + two_zr;

//        line 0 column 2 and conjugate
fxz = two_xz + two_yr;
fzx = two_xz - two_yr;

//        line 1 column 2 and conjugate
fyz = two_yz - two_xr;
fzy = two_yz + two_xr;

// protect agains non-unit quaternion
if (TMath::Abs(mag2-1) > 1e-10) {
fxx /= mag2;
fyy /= mag2;
fzz /= mag2;
fxy /= mag2;
fyx /= mag2;
fxz /= mag2;
fzx /= mag2;
fyz /= mag2;
fzy /= mag2;
}

// diago : remove identity
fxx -= 1;
fyy -= 1;
fzz -= 1;

} else {
// Identity

fxx = fyy = fzz = 1;
fxy = fyx = fxz = fzx = fyz = fzy = 0;

}

}

TRotation & TRotation::Rotate(Double_t a, const TVector3& axis) {
//rotate along an axis
if (a != 0.0) {
Double_t ll = axis.Mag();
if (ll == 0.0) {
Warning("Rotate(angle,axis)"," zero axis");
} else {
Double_t sa = TMath::Sin(a), ca = TMath::Cos(a);
Double_t dx = axis.X()/ll, dy = axis.Y()/ll, dz = axis.Z()/ll;
TRotation m(
ca+(1-ca)*dx*dx,          (1-ca)*dx*dy-sa*dz,    (1-ca)*dx*dz+sa*dy,
(1-ca)*dy*dx+sa*dz, ca+(1-ca)*dy*dy,          (1-ca)*dy*dz-sa*dx,
(1-ca)*dz*dx-sa*dy,    (1-ca)*dz*dy+sa*dx, ca+(1-ca)*dz*dz );
Transform(m);
}
}
return *this;
}

TRotation & TRotation::RotateX(Double_t a) {
//rotate around x
Double_t c = TMath::Cos(a);
Double_t s = TMath::Sin(a);
Double_t x = fyx, y = fyy, z = fyz;
fyx = c*x - s*fzx;
fyy = c*y - s*fzy;
fyz = c*z - s*fzz;
fzx = s*x + c*fzx;
fzy = s*y + c*fzy;
fzz = s*z + c*fzz;
return *this;
}

TRotation & TRotation::RotateY(Double_t a){
//rotate around y
Double_t c = TMath::Cos(a);
Double_t s = TMath::Sin(a);
Double_t x = fzx, y = fzy, z = fzz;
fzx = c*x - s*fxx;
fzy = c*y - s*fxy;
fzz = c*z - s*fxz;
fxx = s*x + c*fxx;
fxy = s*y + c*fxy;
fxz = s*z + c*fxz;
return *this;
}

TRotation & TRotation::RotateZ(Double_t a) {
//rotate around z
Double_t c = TMath::Cos(a);
Double_t s = TMath::Sin(a);
Double_t x = fxx, y = fxy, z = fxz;
fxx = c*x - s*fyx;
fxy = c*y - s*fyy;
fxz = c*z - s*fyz;
fyx = s*x + c*fyx;
fyy = s*y + c*fyy;
fyz = s*z + c*fyz;
return *this;
}

TRotation & TRotation::RotateAxes(const TVector3 &newX,
const TVector3 &newY,
const TVector3 &newZ) {
//rotate axes
Double_t del = 0.001;
TVector3 w = newX.Cross(newY);

if (TMath::Abs(newZ.X()-w.X()) > del ||
TMath::Abs(newZ.Y()-w.Y()) > del ||
TMath::Abs(newZ.Z()-w.Z()) > del ||
TMath::Abs(newX.Mag2()-1.) > del ||
TMath::Abs(newY.Mag2()-1.) > del ||
TMath::Abs(newZ.Mag2()-1.) > del ||
TMath::Abs(newX.Dot(newY)) > del ||
TMath::Abs(newY.Dot(newZ)) > del ||
TMath::Abs(newZ.Dot(newX)) > del) {
return *this;
} else {
return Transform(TRotation(newX.X(), newY.X(), newZ.X(),
newX.Y(), newY.Y(), newZ.Y(),
newX.Z(), newY.Z(), newZ.Z()));
}
}

Double_t TRotation::PhiX() const {
//return Phi
return (fyx == 0.0 && fxx == 0.0) ? 0.0 : TMath::ATan2(fyx,fxx);
}

Double_t TRotation::PhiY() const {
//return Phi
return (fyy == 0.0 && fxy == 0.0) ? 0.0 : TMath::ATan2(fyy,fxy);
}

Double_t TRotation::PhiZ() const {
//return Phi
return (fyz == 0.0 && fxz == 0.0) ? 0.0 : TMath::ATan2(fyz,fxz);
}

Double_t TRotation::ThetaX() const {
//return Phi
return TMath::ACos(fzx);
}

Double_t TRotation::ThetaY() const {
//return Theta
return TMath::ACos(fzy);
}

Double_t TRotation::ThetaZ() const {
//return Theta
return TMath::ACos(fzz);
}

void TRotation::AngleAxis(Double_t &angle, TVector3 &axis) const {
//rotation defined by an angle and a vector
Double_t cosa  = 0.5*(fxx+fyy+fzz-1);
Double_t cosa1 = 1-cosa;
if (cosa1 <= 0) {
angle = 0;
axis  = TVector3(0,0,1);
} else {
Double_t x=0, y=0, z=0;
if (fxx > cosa) x = TMath::Sqrt((fxx-cosa)/cosa1);
if (fyy > cosa) y = TMath::Sqrt((fyy-cosa)/cosa1);
if (fzz > cosa) z = TMath::Sqrt((fzz-cosa)/cosa1);
if (fzy < fyz)  x = -x;
if (fxz < fzx)  y = -y;
if (fyx < fxy)  z = -z;
angle = TMath::ACos(cosa);
axis  = TVector3(x,y,z);
}
}

TRotation & TRotation::SetXEulerAngles(Double_t phi,
Double_t theta,
Double_t psi) {
// Rotate using the x-convention (Landau and Lifshitz, Goldstein, &c) by
// doing the explicit rotations.  This is slightly less efficient than
// directly applying the rotation, but makes the code much clearer.  My
// presumption is that this code is not going to be a speed bottle neck.

SetToIdentity();
RotateZ(phi);
RotateX(theta);
RotateZ(psi);

return *this;
}

TRotation & TRotation::SetYEulerAngles(Double_t phi,
Double_t theta,
Double_t psi) {
// Rotate using the y-convention.

SetToIdentity();
RotateZ(phi);
RotateY(theta);
RotateZ(psi);
return *this;
}

TRotation & TRotation::RotateXEulerAngles(Double_t phi,
Double_t theta,
Double_t psi) {
// Rotate using the x-convention.
TRotation euler;
euler.SetXEulerAngles(phi,theta,psi);
return Transform(euler);
}

TRotation & TRotation::RotateYEulerAngles(Double_t phi,
Double_t theta,
Double_t psi) {
// Rotate using the y-convention.
TRotation euler;
euler.SetYEulerAngles(phi,theta,psi);
return Transform(euler);
}

void TRotation::SetXPhi(Double_t phi) {
//set XPhi
SetXEulerAngles(phi,GetXTheta(),GetXPsi());
}

void TRotation::SetXTheta(Double_t theta) {
//set XTheta
SetXEulerAngles(GetXPhi(),theta,GetXPsi());
}

void TRotation::SetXPsi(Double_t psi) {
//set XPsi
SetXEulerAngles(GetXPhi(),GetXTheta(),psi);
}

void TRotation::SetYPhi(Double_t phi) {
//set YPhi
SetYEulerAngles(phi,GetYTheta(),GetYPsi());
}

void TRotation::SetYTheta(Double_t theta) {
//set YTheta
SetYEulerAngles(GetYPhi(),theta,GetYPsi());
}

void TRotation::SetYPsi(Double_t psi) {
//set YPsi
SetYEulerAngles(GetYPhi(),GetYTheta(),psi);
}

Double_t TRotation::GetXPhi(void) const {
//return phi angle
Double_t finalPhi;

Double_t s2 =  1.0 - fzz*fzz;
if (s2 < 0) {
Warning("GetPhi()"," |fzz| > 1 ");
s2 = 0;
}
const Double_t sinTheta = TMath::Sqrt(s2);

if (sinTheta != 0) {
const Double_t cscTheta = 1/sinTheta;
Double_t cosAbsPhi =  fzy * cscTheta;
if ( TMath::Abs(cosAbsPhi) > 1 ) {        // NaN-proofing
Warning("GetPhi()","finds | cos phi | > 1");
cosAbsPhi = 1;
}
const Double_t absPhi = TMath::ACos(cosAbsPhi);
if (fzx > 0) {
finalPhi = absPhi;
} else if (fzx < 0) {
finalPhi = -absPhi;
} else if (fzy > 0) {
finalPhi = 0.0;
} else {
finalPhi = TMath::Pi();
}
} else {              // sinTheta == 0 so |Fzz| = 1
const Double_t absPhi = .5 * TMath::ACos (fxx);
if (fxy > 0) {
finalPhi =  -absPhi;
} else if (fxy < 0) {
finalPhi =   absPhi;
} else if (fxx>0) {
finalPhi = 0.0;
} else {
finalPhi = fzz * TMath::PiOver2();
}
}
return finalPhi;
}

Double_t TRotation::GetYPhi(void) const {
//return YPhi
return GetXPhi() + TMath::Pi()/2.0;
}

Double_t TRotation::GetXTheta(void) const {
//return XTheta
return  ThetaZ();
}

Double_t TRotation::GetYTheta(void) const {
//return YTheta
return  ThetaZ();
}

Double_t TRotation::GetXPsi(void) const {
//Get psi angle
double finalPsi = 0.0;

Double_t s2 =  1.0 - fzz*fzz;
if (s2 < 0) {
Warning("GetPsi()"," |fzz| > 1 ");
s2 = 0;
}
const Double_t sinTheta = TMath::Sqrt(s2);

if (sinTheta != 0) {
const Double_t cscTheta = 1/sinTheta;
Double_t cosAbsPsi =  - fyz * cscTheta;
if ( TMath::Abs(cosAbsPsi) > 1 ) {        // NaN-proofing
Warning("GetPsi()","| cos psi | > 1 ");
cosAbsPsi = 1;
}
const Double_t absPsi = TMath::ACos(cosAbsPsi);
if (fxz > 0) {
finalPsi = absPsi;
} else if (fxz < 0) {
finalPsi = -absPsi;
} else {
finalPsi = (fyz < 0) ? 0 : TMath::Pi();
}
} else {              // sinTheta == 0 so |Fzz| = 1
Double_t absPsi = fxx;
if ( TMath::Abs(fxx) > 1 ) {        // NaN-proofing
Warning("GetPsi()","| fxx | > 1 ");
absPsi = 1;
}
absPsi = .5 * TMath::ACos (absPsi);
if (fyx > 0) {
finalPsi = absPsi;
} else if (fyx < 0) {
finalPsi = -absPsi;
} else {
finalPsi = (fxx > 0) ? 0 : TMath::PiOver2();
}
}
return finalPsi;
}

Double_t TRotation::GetYPsi(void) const {
//return YPsi
return GetXPsi() - TMath::Pi()/2;
}

TRotation & TRotation::SetXAxis(const TVector3& axis,
const TVector3& xyPlane) {
//set X axis
TVector3 xAxis(xyPlane);
TVector3 yAxis;
TVector3 zAxis(axis);
MakeBasis(xAxis,yAxis,zAxis);
fxx = zAxis.X();  fyx = zAxis.Y();  fzx = zAxis.Z();
fxy = xAxis.X();  fyy = xAxis.Y();  fzy = xAxis.Z();
fxz = yAxis.X();  fyz = yAxis.Y();  fzz = yAxis.Z();
return *this;
}

TRotation & TRotation::SetXAxis(const TVector3& axis) {
//set X axis
TVector3 xyPlane(0.0,1.0,0.0);
return SetXAxis(axis,xyPlane);
}

TRotation & TRotation::SetYAxis(const TVector3& axis,
const TVector3& yzPlane) {
//set Y axis
TVector3 xAxis(yzPlane);
TVector3 yAxis;
TVector3 zAxis(axis);
MakeBasis(xAxis,yAxis,zAxis);
fxx = yAxis.X();  fyx = yAxis.Y();  fzx = yAxis.Z();
fxy = zAxis.X();  fyy = zAxis.Y();  fzy = zAxis.Z();
fxz = xAxis.X();  fyz = xAxis.Y();  fzz = xAxis.Z();
return *this;
}

TRotation & TRotation::SetYAxis(const TVector3& axis) {
//set Y axis
TVector3 yzPlane(0.0,0.0,1.0);
return SetYAxis(axis,yzPlane);
}

TRotation & TRotation::SetZAxis(const TVector3& axis,
const TVector3& zxPlane) {
//set Z axis
TVector3 xAxis(zxPlane);
TVector3 yAxis;
TVector3 zAxis(axis);
MakeBasis(xAxis,yAxis,zAxis);
fxx = xAxis.X();  fyx = xAxis.Y();  fzx = xAxis.Z();
fxy = yAxis.X();  fyy = yAxis.Y();  fzy = yAxis.Z();
fxz = zAxis.X();  fyz = zAxis.Y();  fzz = zAxis.Z();
return *this;
}

TRotation & TRotation::SetZAxis(const TVector3& axis) {
//set Z axis
TVector3 zxPlane(1.0,0.0,0.0);
return SetZAxis(axis,zxPlane);
}

void TRotation::MakeBasis(TVector3& xAxis,
TVector3& yAxis,
TVector3& zAxis) const {
// Make the Z axis into a unit variable.
Double_t zmag = zAxis.Mag();
if (zmag<TOLERANCE) {
Warning("MakeBasis(X,Y,Z)","non-zero Z Axis is required");
}
zAxis *= (1.0/zmag);

Double_t xmag = xAxis.Mag();
if (xmag<TOLERANCE*zmag) {
xAxis = zAxis.Orthogonal();
xmag = 1.0;
}

// Find the Y axis
yAxis = zAxis.Cross(xAxis)*(1.0/xmag);
Double_t ymag = yAxis.Mag();
if (ymag<TOLERANCE*zmag) {
yAxis = zAxis.Orthogonal();
} else {
yAxis *= (1.0/ymag);
}

xAxis = yAxis.Cross(zAxis);
}
```
TRotation.cxx:1
TRotation.cxx:2
TRotation.cxx:3
TRotation.cxx:4
TRotation.cxx:5
TRotation.cxx:6
TRotation.cxx:7
TRotation.cxx:8
TRotation.cxx:9
TRotation.cxx:10
TRotation.cxx:11
TRotation.cxx:12
TRotation.cxx:13
TRotation.cxx:14
TRotation.cxx:15
TRotation.cxx:16
TRotation.cxx:17
TRotation.cxx:18
TRotation.cxx:19
TRotation.cxx:20
TRotation.cxx:21
TRotation.cxx:22
TRotation.cxx:23
TRotation.cxx:24
TRotation.cxx:25
TRotation.cxx:26
TRotation.cxx:27
TRotation.cxx:28
TRotation.cxx:29
TRotation.cxx:30
TRotation.cxx:31
TRotation.cxx:32
TRotation.cxx:33
TRotation.cxx:34
TRotation.cxx:35
TRotation.cxx:36
TRotation.cxx:37
TRotation.cxx:38
TRotation.cxx:39
TRotation.cxx:40
TRotation.cxx:41
TRotation.cxx:42
TRotation.cxx:43
TRotation.cxx:44
TRotation.cxx:45
TRotation.cxx:46
TRotation.cxx:47
TRotation.cxx:48
TRotation.cxx:49
TRotation.cxx:50
TRotation.cxx:51
TRotation.cxx:52
TRotation.cxx:53
TRotation.cxx:54
TRotation.cxx:55
TRotation.cxx:56
TRotation.cxx:57
TRotation.cxx:58
TRotation.cxx:59
TRotation.cxx:60
TRotation.cxx:61
TRotation.cxx:62
TRotation.cxx:63
TRotation.cxx:64
TRotation.cxx:65
TRotation.cxx:66
TRotation.cxx:67
TRotation.cxx:68
TRotation.cxx:69
TRotation.cxx:70
TRotation.cxx:71
TRotation.cxx:72
TRotation.cxx:73
TRotation.cxx:74
TRotation.cxx:75
TRotation.cxx:76
TRotation.cxx:77
TRotation.cxx:78
TRotation.cxx:79
TRotation.cxx:80
TRotation.cxx:81
TRotation.cxx:82
TRotation.cxx:83
TRotation.cxx:84
TRotation.cxx:85
TRotation.cxx:86
TRotation.cxx:87
TRotation.cxx:88
TRotation.cxx:89
TRotation.cxx:90
TRotation.cxx:91
TRotation.cxx:92
TRotation.cxx:93
TRotation.cxx:94
TRotation.cxx:95
TRotation.cxx:96
TRotation.cxx:97
TRotation.cxx:98
TRotation.cxx:99
TRotation.cxx:100
TRotation.cxx:101
TRotation.cxx:102
TRotation.cxx:103
TRotation.cxx:104
TRotation.cxx:105
TRotation.cxx:106
TRotation.cxx:107
TRotation.cxx:108
TRotation.cxx:109
TRotation.cxx:110
TRotation.cxx:111
TRotation.cxx:112
TRotation.cxx:113
TRotation.cxx:114
TRotation.cxx:115
TRotation.cxx:116
TRotation.cxx:117
TRotation.cxx:118
TRotation.cxx:119
TRotation.cxx:120
TRotation.cxx:121
TRotation.cxx:122
TRotation.cxx:123
TRotation.cxx:124
TRotation.cxx:125
TRotation.cxx:126
TRotation.cxx:127
TRotation.cxx:128
TRotation.cxx:129
TRotation.cxx:130
TRotation.cxx:131
TRotation.cxx:132
TRotation.cxx:133
TRotation.cxx:134
TRotation.cxx:135
TRotation.cxx:136
TRotation.cxx:137
TRotation.cxx:138
TRotation.cxx:139
TRotation.cxx:140
TRotation.cxx:141
TRotation.cxx:142
TRotation.cxx:143
TRotation.cxx:144
TRotation.cxx:145
TRotation.cxx:146
TRotation.cxx:147
TRotation.cxx:148
TRotation.cxx:149
TRotation.cxx:150
TRotation.cxx:151
TRotation.cxx:152
TRotation.cxx:153
TRotation.cxx:154
TRotation.cxx:155
TRotation.cxx:156
TRotation.cxx:157
TRotation.cxx:158
TRotation.cxx:159
TRotation.cxx:160
TRotation.cxx:161
TRotation.cxx:162
TRotation.cxx:163
TRotation.cxx:164
TRotation.cxx:165
TRotation.cxx:166
TRotation.cxx:167
TRotation.cxx:168
TRotation.cxx:169
TRotation.cxx:170
TRotation.cxx:171
TRotation.cxx:172
TRotation.cxx:173
TRotation.cxx:174
TRotation.cxx:175
TRotation.cxx:176
TRotation.cxx:177
TRotation.cxx:178
TRotation.cxx:179
TRotation.cxx:180
TRotation.cxx:181
TRotation.cxx:182
TRotation.cxx:183
TRotation.cxx:184
TRotation.cxx:185
TRotation.cxx:186
TRotation.cxx:187
TRotation.cxx:188
TRotation.cxx:189
TRotation.cxx:190
TRotation.cxx:191
TRotation.cxx:192
TRotation.cxx:193
TRotation.cxx:194
TRotation.cxx:195
TRotation.cxx:196
TRotation.cxx:197
TRotation.cxx:198
TRotation.cxx:199
TRotation.cxx:200
TRotation.cxx:201
TRotation.cxx:202
TRotation.cxx:203
TRotation.cxx:204
TRotation.cxx:205
TRotation.cxx:206
TRotation.cxx:207
TRotation.cxx:208
TRotation.cxx:209
TRotation.cxx:210
TRotation.cxx:211
TRotation.cxx:212
TRotation.cxx:213
TRotation.cxx:214
TRotation.cxx:215
TRotation.cxx:216
TRotation.cxx:217
TRotation.cxx:218
TRotation.cxx:219
TRotation.cxx:220
TRotation.cxx:221
TRotation.cxx:222
TRotation.cxx:223
TRotation.cxx:224
TRotation.cxx:225
TRotation.cxx:226
TRotation.cxx:227
TRotation.cxx:228
TRotation.cxx:229
TRotation.cxx:230
TRotation.cxx:231
TRotation.cxx:232
TRotation.cxx:233
TRotation.cxx:234
TRotation.cxx:235
TRotation.cxx:236
TRotation.cxx:237
TRotation.cxx:238
TRotation.cxx:239
TRotation.cxx:240
TRotation.cxx:241
TRotation.cxx:242
TRotation.cxx:243
TRotation.cxx:244
TRotation.cxx:245
TRotation.cxx:246
TRotation.cxx:247
TRotation.cxx:248
TRotation.cxx:249
TRotation.cxx:250
TRotation.cxx:251
TRotation.cxx:252
TRotation.cxx:253
TRotation.cxx:254
TRotation.cxx:255
TRotation.cxx:256
TRotation.cxx:257
TRotation.cxx:258
TRotation.cxx:259
TRotation.cxx:260
TRotation.cxx:261
TRotation.cxx:262
TRotation.cxx:263
TRotation.cxx:264
TRotation.cxx:265
TRotation.cxx:266
TRotation.cxx:267
TRotation.cxx:268
TRotation.cxx:269
TRotation.cxx:270
TRotation.cxx:271
TRotation.cxx:272
TRotation.cxx:273
TRotation.cxx:274
TRotation.cxx:275
TRotation.cxx:276
TRotation.cxx:277
TRotation.cxx:278
TRotation.cxx:279
TRotation.cxx:280
TRotation.cxx:281
TRotation.cxx:282
TRotation.cxx:283
TRotation.cxx:284
TRotation.cxx:285
TRotation.cxx:286
TRotation.cxx:287
TRotation.cxx:288
TRotation.cxx:289
TRotation.cxx:290
TRotation.cxx:291
TRotation.cxx:292
TRotation.cxx:293
TRotation.cxx:294
TRotation.cxx:295
TRotation.cxx:296
TRotation.cxx:297
TRotation.cxx:298
TRotation.cxx:299
TRotation.cxx:300
TRotation.cxx:301
TRotation.cxx:302
TRotation.cxx:303
TRotation.cxx:304
TRotation.cxx:305
TRotation.cxx:306
TRotation.cxx:307
TRotation.cxx:308
TRotation.cxx:309
TRotation.cxx:310
TRotation.cxx:311
TRotation.cxx:312
TRotation.cxx:313
TRotation.cxx:314
TRotation.cxx:315
TRotation.cxx:316
TRotation.cxx:317
TRotation.cxx:318
TRotation.cxx:319
TRotation.cxx:320
TRotation.cxx:321
TRotation.cxx:322
TRotation.cxx:323
TRotation.cxx:324
TRotation.cxx:325
TRotation.cxx:326
TRotation.cxx:327
TRotation.cxx:328
TRotation.cxx:329
TRotation.cxx:330
TRotation.cxx:331
TRotation.cxx:332
TRotation.cxx:333
TRotation.cxx:334
TRotation.cxx:335
TRotation.cxx:336
TRotation.cxx:337
TRotation.cxx:338
TRotation.cxx:339
TRotation.cxx:340
TRotation.cxx:341
TRotation.cxx:342
TRotation.cxx:343
TRotation.cxx:344
TRotation.cxx:345
TRotation.cxx:346
TRotation.cxx:347
TRotation.cxx:348
TRotation.cxx:349
TRotation.cxx:350
TRotation.cxx:351
TRotation.cxx:352
TRotation.cxx:353
TRotation.cxx:354
TRotation.cxx:355
TRotation.cxx:356
TRotation.cxx:357
TRotation.cxx:358
TRotation.cxx:359
TRotation.cxx:360
TRotation.cxx:361
TRotation.cxx:362
TRotation.cxx:363
TRotation.cxx:364
TRotation.cxx:365
TRotation.cxx:366
TRotation.cxx:367
TRotation.cxx:368
TRotation.cxx:369
TRotation.cxx:370
TRotation.cxx:371
TRotation.cxx:372
TRotation.cxx:373
TRotation.cxx:374
TRotation.cxx:375
TRotation.cxx:376
TRotation.cxx:377
TRotation.cxx:378
TRotation.cxx:379
TRotation.cxx:380
TRotation.cxx:381
TRotation.cxx:382
TRotation.cxx:383
TRotation.cxx:384
TRotation.cxx:385
TRotation.cxx:386
TRotation.cxx:387
TRotation.cxx:388
TRotation.cxx:389
TRotation.cxx:390
TRotation.cxx:391
TRotation.cxx:392
TRotation.cxx:393
TRotation.cxx:394
TRotation.cxx:395
TRotation.cxx:396
TRotation.cxx:397
TRotation.cxx:398
TRotation.cxx:399
TRotation.cxx:400
TRotation.cxx:401
TRotation.cxx:402
TRotation.cxx:403
TRotation.cxx:404
TRotation.cxx:405
TRotation.cxx:406
TRotation.cxx:407
TRotation.cxx:408
TRotation.cxx:409
TRotation.cxx:410
TRotation.cxx:411
TRotation.cxx:412
TRotation.cxx:413
TRotation.cxx:414
TRotation.cxx:415
TRotation.cxx:416
TRotation.cxx:417
TRotation.cxx:418
TRotation.cxx:419
TRotation.cxx:420
TRotation.cxx:421
TRotation.cxx:422
TRotation.cxx:423
TRotation.cxx:424
TRotation.cxx:425
TRotation.cxx:426
TRotation.cxx:427
TRotation.cxx:428
TRotation.cxx:429
TRotation.cxx:430
TRotation.cxx:431
TRotation.cxx:432
TRotation.cxx:433
TRotation.cxx:434
TRotation.cxx:435
TRotation.cxx:436
TRotation.cxx:437
TRotation.cxx:438
TRotation.cxx:439
TRotation.cxx:440
TRotation.cxx:441
TRotation.cxx:442
TRotation.cxx:443
TRotation.cxx:444
TRotation.cxx:445
TRotation.cxx:446
TRotation.cxx:447
TRotation.cxx:448
TRotation.cxx:449
TRotation.cxx:450
TRotation.cxx:451
TRotation.cxx:452
TRotation.cxx:453
TRotation.cxx:454
TRotation.cxx:455
TRotation.cxx:456
TRotation.cxx:457
TRotation.cxx:458
TRotation.cxx:459
TRotation.cxx:460
TRotation.cxx:461
TRotation.cxx:462
TRotation.cxx:463
TRotation.cxx:464
TRotation.cxx:465
TRotation.cxx:466
TRotation.cxx:467
TRotation.cxx:468
TRotation.cxx:469
TRotation.cxx:470
TRotation.cxx:471
TRotation.cxx:472
TRotation.cxx:473
TRotation.cxx:474
TRotation.cxx:475
TRotation.cxx:476
TRotation.cxx:477
TRotation.cxx:478
TRotation.cxx:479
TRotation.cxx:480
TRotation.cxx:481
TRotation.cxx:482
TRotation.cxx:483
TRotation.cxx:484
TRotation.cxx:485
TRotation.cxx:486
TRotation.cxx:487
TRotation.cxx:488
TRotation.cxx:489
TRotation.cxx:490
TRotation.cxx:491
TRotation.cxx:492
TRotation.cxx:493
TRotation.cxx:494
TRotation.cxx:495
TRotation.cxx:496
TRotation.cxx:497
TRotation.cxx:498
TRotation.cxx:499
TRotation.cxx:500
TRotation.cxx:501
TRotation.cxx:502
TRotation.cxx:503
TRotation.cxx:504
TRotation.cxx:505
TRotation.cxx:506
TRotation.cxx:507
TRotation.cxx:508
TRotation.cxx:509
TRotation.cxx:510
TRotation.cxx:511
TRotation.cxx:512
TRotation.cxx:513
TRotation.cxx:514
TRotation.cxx:515
TRotation.cxx:516
TRotation.cxx:517
TRotation.cxx:518
TRotation.cxx:519
TRotation.cxx:520
TRotation.cxx:521
TRotation.cxx:522
TRotation.cxx:523
TRotation.cxx:524
TRotation.cxx:525
TRotation.cxx:526
TRotation.cxx:527
TRotation.cxx:528
TRotation.cxx:529
TRotation.cxx:530
TRotation.cxx:531
TRotation.cxx:532
TRotation.cxx:533
TRotation.cxx:534
TRotation.cxx:535
TRotation.cxx:536
TRotation.cxx:537
TRotation.cxx:538
TRotation.cxx:539
TRotation.cxx:540
TRotation.cxx:541
TRotation.cxx:542
TRotation.cxx:543
TRotation.cxx:544
TRotation.cxx:545
TRotation.cxx:546
TRotation.cxx:547
TRotation.cxx:548
TRotation.cxx:549
TRotation.cxx:550
TRotation.cxx:551
TRotation.cxx:552
TRotation.cxx:553
TRotation.cxx:554
TRotation.cxx:555
TRotation.cxx:556
TRotation.cxx:557
TRotation.cxx:558
TRotation.cxx:559
TRotation.cxx:560
TRotation.cxx:561
TRotation.cxx:562
TRotation.cxx:563
TRotation.cxx:564
TRotation.cxx:565
TRotation.cxx:566
TRotation.cxx:567
TRotation.cxx:568
TRotation.cxx:569
TRotation.cxx:570
TRotation.cxx:571
TRotation.cxx:572
TRotation.cxx:573
TRotation.cxx:574
TRotation.cxx:575
TRotation.cxx:576
TRotation.cxx:577
TRotation.cxx:578
TRotation.cxx:579
TRotation.cxx:580
TRotation.cxx:581
TRotation.cxx:582
TRotation.cxx:583
TRotation.cxx:584
TRotation.cxx:585
TRotation.cxx:586
TRotation.cxx:587
TRotation.cxx:588
TRotation.cxx:589
TRotation.cxx:590
TRotation.cxx:591
TRotation.cxx:592
TRotation.cxx:593
TRotation.cxx:594
TRotation.cxx:595
TRotation.cxx:596
TRotation.cxx:597
TRotation.cxx:598
TRotation.cxx:599
TRotation.cxx:600
TRotation.cxx:601
TRotation.cxx:602
TRotation.cxx:603
TRotation.cxx:604
TRotation.cxx:605
TRotation.cxx:606
TRotation.cxx:607
TRotation.cxx:608
TRotation.cxx:609
TRotation.cxx:610
TRotation.cxx:611
TRotation.cxx:612
TRotation.cxx:613
TRotation.cxx:614
TRotation.cxx:615
TRotation.cxx:616
TRotation.cxx:617
TRotation.cxx:618
TRotation.cxx:619
TRotation.cxx:620
TRotation.cxx:621
TRotation.cxx:622
TRotation.cxx:623
TRotation.cxx:624
TRotation.cxx:625
TRotation.cxx:626
TRotation.cxx:627
TRotation.cxx:628
TRotation.cxx:629
TRotation.cxx:630
TRotation.cxx:631
TRotation.cxx:632
TRotation.cxx:633
TRotation.cxx:634
TRotation.cxx:635
TRotation.cxx:636
TRotation.cxx:637
TRotation.cxx:638
TRotation.cxx:639
TRotation.cxx:640
TRotation.cxx:641
TRotation.cxx:642
TRotation.cxx:643
TRotation.cxx:644
TRotation.cxx:645
TRotation.cxx:646
TRotation.cxx:647
TRotation.cxx:648
TRotation.cxx:649
TRotation.cxx:650
TRotation.cxx:651
TRotation.cxx:652
TRotation.cxx:653
TRotation.cxx:654
TRotation.cxx:655
TRotation.cxx:656
TRotation.cxx:657
TRotation.cxx:658
TRotation.cxx:659
TRotation.cxx:660
TRotation.cxx:661
TRotation.cxx:662
TRotation.cxx:663
TRotation.cxx:664
TRotation.cxx:665
TRotation.cxx:666
TRotation.cxx:667
TRotation.cxx:668
TRotation.cxx:669
TRotation.cxx:670
TRotation.cxx:671
TRotation.cxx:672
TRotation.cxx:673
TRotation.cxx:674
TRotation.cxx:675
TRotation.cxx:676
TRotation.cxx:677
TRotation.cxx:678
TRotation.cxx:679
TRotation.cxx:680
TRotation.cxx:681
TRotation.cxx:682
TRotation.cxx:683
TRotation.cxx:684
TRotation.cxx:685
TRotation.cxx:686
TRotation.cxx:687
TRotation.cxx:688
TRotation.cxx:689
TRotation.cxx:690
TRotation.cxx:691
TRotation.cxx:692
TRotation.cxx:693
TRotation.cxx:694
TRotation.cxx:695
TRotation.cxx:696
TRotation.cxx:697
TRotation.cxx:698
TRotation.cxx:699
TRotation.cxx:700
TRotation.cxx:701
TRotation.cxx:702
TRotation.cxx:703
TRotation.cxx:704
TRotation.cxx:705
TRotation.cxx:706
TRotation.cxx:707
TRotation.cxx:708
TRotation.cxx:709