190 #define TOLERANCE (1.0E-6) 
  195 TRotation::TRotation()
 
  196 : fxx(1.0), fxy(0.0), fxz(0.0), fyx(0.0), fyy(1.0), fyz(0.0),
 
  197   fzx(0.0), fzy(0.0), fzz(1.0) {}
 
  202 TRotation::TRotation(
const TRotation & m) : TObject(m),
 
  203   fxx(m.fxx), fxy(m.fxy), fxz(m.fxz), fyx(m.fyx), fyy(m.fyy), fyz(m.fyz),
 
  204   fzx(m.fzx), fzy(m.fzy), fzz(m.fzz) {}
 
  209 TRotation::TRotation(Double_t mxx, Double_t mxy, Double_t mxz,
 
  210                          Double_t myx, Double_t myy, Double_t myz,
 
  211                          Double_t mzx, Double_t mzy, Double_t mzz)
 
  212 : fxx(mxx), fxy(mxy), fxz(mxz), fyx(myx), fyy(myy), fyz(myz),
 
  213   fzx(mzx), fzy(mzy), fzz(mzz) {}
 
  218 Double_t TRotation::operator() (
int i, 
int j)
 const {
 
  220       if (j == 0) { 
return fxx; }
 
  221       if (j == 1) { 
return fxy; }
 
  222       if (j == 2) { 
return fxz; }
 
  224       if (j == 0) { 
return fyx; }
 
  225       if (j == 1) { 
return fyy; }
 
  226       if (j == 2) { 
return fyz; }
 
  228       if (j == 0) { 
return fzx; }
 
  229       if (j == 1) { 
return fzy; }
 
  230       if (j == 2) { 
return fzz; }
 
  233    Warning(
"operator()(i,j)", 
"bad indices (%d , %d)",i,j);
 
  241 TRotation TRotation::operator* (
const TRotation & b)
 const {
 
  242    return TRotation(fxx*b.fxx + fxy*b.fyx + fxz*b.fzx,
 
  243                     fxx*b.fxy + fxy*b.fyy + fxz*b.fzy,
 
  244                     fxx*b.fxz + fxy*b.fyz + fxz*b.fzz,
 
  245                     fyx*b.fxx + fyy*b.fyx + fyz*b.fzx,
 
  246                     fyx*b.fxy + fyy*b.fyy + fyz*b.fzy,
 
  247                     fyx*b.fxz + fyy*b.fyz + fyz*b.fzz,
 
  248                     fzx*b.fxx + fzy*b.fyx + fzz*b.fzx,
 
  249                     fzx*b.fxy + fzy*b.fyy + fzz*b.fzy,
 
  250                     fzx*b.fxz + fzy*b.fyz + fzz*b.fzz);
 
  258 TRotation::TRotation(
const TQuaternion & Q) {
 
  260    double two_r2 = 2 * Q.fRealPart * Q.fRealPart;
 
  261    double two_x2 = 2 * Q.fVectorPart.X() * Q.fVectorPart.X();
 
  262    double two_y2 = 2 * Q.fVectorPart.Y() * Q.fVectorPart.Y();
 
  263    double two_z2 = 2 * Q.fVectorPart.Z() * Q.fVectorPart.Z();
 
  264    double two_xy = 2 * Q.fVectorPart.X() * Q.fVectorPart.Y();
 
  265    double two_xz = 2 * Q.fVectorPart.X() * Q.fVectorPart.Z();
 
  266    double two_xr = 2 * Q.fVectorPart.X() * Q.fRealPart;
 
  267    double two_yz = 2 * Q.fVectorPart.Y() * Q.fVectorPart.Z();
 
  268    double two_yr = 2 * Q.fVectorPart.Y() * Q.fRealPart;
 
  269    double two_zr = 2 * Q.fVectorPart.Z() * Q.fRealPart;
 
  272    double mag2 = Q.QMag2();
 
  276       fxx = two_r2 + two_x2;
 
  277       fyy = two_r2 + two_y2;
 
  278       fzz = two_r2 + two_z2;
 
  281       fxy = two_xy - two_zr;
 
  282       fyx = two_xy + two_zr;
 
  285       fxz = two_xz + two_yr;
 
  286       fzx = two_xz - two_yr;
 
  289       fyz = two_yz - two_xr;
 
  290       fzy = two_yz + two_xr;
 
  293       if (TMath::Abs(mag2-1) > 1e-10) {
 
  315       fxy = fyx = fxz = fzx = fyz = fzy = 0;
 
  324 TRotation & TRotation::Rotate(Double_t a, 
const TVector3& axis) {
 
  326       Double_t ll = axis.Mag();
 
  328          Warning(
"Rotate(angle,axis)",
" zero axis");
 
  330          Double_t sa = TMath::Sin(a), ca = TMath::Cos(a);
 
  331          Double_t dx = axis.X()/ll, dy = axis.Y()/ll, dz = axis.Z()/ll;
 
  333              ca+(1-ca)*dx*dx,          (1-ca)*dx*dy-sa*dz,    (1-ca)*dx*dz+sa*dy,
 
  334              (1-ca)*dy*dx+sa*dz, ca+(1-ca)*dy*dy,          (1-ca)*dy*dz-sa*dx,
 
  335              (1-ca)*dz*dx-sa*dy,    (1-ca)*dz*dy+sa*dx, ca+(1-ca)*dz*dz );
 
  345 TRotation & TRotation::RotateX(Double_t a) {
 
  346    Double_t c = TMath::Cos(a);
 
  347    Double_t s = TMath::Sin(a);
 
  348    Double_t x = fyx, y = fyy, z = fyz;
 
  361 TRotation & TRotation::RotateY(Double_t a){
 
  362    Double_t c = TMath::Cos(a);
 
  363    Double_t s = TMath::Sin(a);
 
  364    Double_t x = fzx, y = fzy, z = fzz;
 
  377 TRotation & TRotation::RotateZ(Double_t a) {
 
  378    Double_t c = TMath::Cos(a);
 
  379    Double_t s = TMath::Sin(a);
 
  380    Double_t x = fxx, y = fxy, z = fxz;
 
  393 TRotation & TRotation::RotateAxes(
const TVector3 &newX,
 
  394                                   const TVector3 &newY,
 
  395                                   const TVector3 &newZ) {
 
  396    Double_t del = 0.001;
 
  397    TVector3 w = newX.Cross(newY);
 
  399    if (TMath::Abs(newZ.X()-w.X()) > del ||
 
  400        TMath::Abs(newZ.Y()-w.Y()) > del ||
 
  401        TMath::Abs(newZ.Z()-w.Z()) > del ||
 
  402        TMath::Abs(newX.Mag2()-1.) > del ||
 
  403        TMath::Abs(newY.Mag2()-1.) > del ||
 
  404        TMath::Abs(newZ.Mag2()-1.) > del ||
 
  405        TMath::Abs(newX.Dot(newY)) > del ||
 
  406        TMath::Abs(newY.Dot(newZ)) > del ||
 
  407        TMath::Abs(newZ.Dot(newX)) > del) {
 
  408       Warning(
"RotateAxes",
"bad axis vectors");
 
  411       return Transform(TRotation(newX.X(), newY.X(), newZ.X(),
 
  412                                  newX.Y(), newY.Y(), newZ.Y(),
 
  413                                  newX.Z(), newY.Z(), newZ.Z()));
 
  420 Double_t TRotation::PhiX()
 const {
 
  421    return (fyx == 0.0 && fxx == 0.0) ? 0.0 : TMath::ATan2(fyx,fxx);
 
  427 Double_t TRotation::PhiY()
 const {
 
  428    return (fyy == 0.0 && fxy == 0.0) ? 0.0 : TMath::ATan2(fyy,fxy);
 
  434 Double_t TRotation::PhiZ()
 const {
 
  435    return (fyz == 0.0 && fxz == 0.0) ? 0.0 : TMath::ATan2(fyz,fxz);
 
  441 Double_t TRotation::ThetaX()
 const {
 
  442    return TMath::ACos(fzx);
 
  448 Double_t TRotation::ThetaY()
 const {
 
  449    return TMath::ACos(fzy);
 
  455 Double_t TRotation::ThetaZ()
 const {
 
  456    return TMath::ACos(fzz);
 
  462 void TRotation::AngleAxis(Double_t &angle, TVector3 &axis)
 const {
 
  463    Double_t cosa  = 0.5*(fxx+fyy+fzz-1);
 
  464    Double_t cosa1 = 1-cosa;
 
  467       axis  = TVector3(0,0,1);
 
  469       Double_t x=0, y=0, z=0;
 
  470       if (fxx > cosa) x = TMath::Sqrt((fxx-cosa)/cosa1);
 
  471       if (fyy > cosa) y = TMath::Sqrt((fyy-cosa)/cosa1);
 
  472       if (fzz > cosa) z = TMath::Sqrt((fzz-cosa)/cosa1);
 
  473       if (fzy < fyz)  x = -x;
 
  474       if (fxz < fzx)  y = -y;
 
  475       if (fyx < fxy)  z = -z;
 
  476       angle = TMath::ACos(cosa);
 
  477       axis  = TVector3(x,y,z);
 
  487 TRotation & TRotation::SetXEulerAngles(Double_t phi,
 
  501 TRotation & TRotation::SetYEulerAngles(Double_t phi,
 
  514 TRotation & TRotation::RotateXEulerAngles(Double_t phi,
 
  518    euler.SetXEulerAngles(phi,theta,psi);
 
  519    return Transform(euler);
 
  525 TRotation & TRotation::RotateYEulerAngles(Double_t phi,
 
  529    euler.SetYEulerAngles(phi,theta,psi);
 
  530    return Transform(euler);
 
  536 void TRotation::SetXPhi(Double_t phi) {
 
  537    SetXEulerAngles(phi,GetXTheta(),GetXPsi());
 
  543 void TRotation::SetXTheta(Double_t theta) {
 
  544    SetXEulerAngles(GetXPhi(),theta,GetXPsi());
 
  550 void TRotation::SetXPsi(Double_t psi) {
 
  551    SetXEulerAngles(GetXPhi(),GetXTheta(),psi);
 
  557 void TRotation::SetYPhi(Double_t phi) {
 
  558    SetYEulerAngles(phi,GetYTheta(),GetYPsi());
 
  564 void TRotation::SetYTheta(Double_t theta) {
 
  565    SetYEulerAngles(GetYPhi(),theta,GetYPsi());
 
  571 void TRotation::SetYPsi(Double_t psi) {
 
  572    SetYEulerAngles(GetYPhi(),GetYTheta(),psi);
 
  578 Double_t TRotation::GetXPhi(
void)
 const {
 
  581    Double_t s2 =  1.0 - fzz*fzz;
 
  583       Warning(
"GetPhi()",
" |fzz| > 1 ");
 
  586    const Double_t sinTheta = TMath::Sqrt(s2);
 
  589       const Double_t cscTheta = 1/sinTheta;
 
  590       Double_t cosAbsPhi =  fzy * cscTheta;
 
  591       if ( TMath::Abs(cosAbsPhi) > 1 ) {        
 
  592          Warning(
"GetPhi()",
"finds | cos phi | > 1");
 
  595       const Double_t absPhi = TMath::ACos(cosAbsPhi);
 
  598       } 
else if (fzx < 0) {
 
  600       } 
else if (fzy > 0) {
 
  603          finalPhi = TMath::Pi();
 
  606       const Double_t absPhi = .5 * TMath::ACos (fxx);
 
  609       } 
else if (fxy < 0) {
 
  614          finalPhi = fzz * TMath::PiOver2();
 
  623 Double_t TRotation::GetYPhi(
void)
 const {
 
  624    return GetXPhi() + TMath::Pi()/2.0;
 
  630 Double_t TRotation::GetXTheta(
void)
 const {
 
  637 Double_t TRotation::GetYTheta(
void)
 const {
 
  644 Double_t TRotation::GetXPsi(
void)
 const {
 
  645    double finalPsi = 0.0;
 
  647    Double_t s2 =  1.0 - fzz*fzz;
 
  649       Warning(
"GetPsi()",
" |fzz| > 1 ");
 
  652    const Double_t sinTheta = TMath::Sqrt(s2);
 
  655       const Double_t cscTheta = 1/sinTheta;
 
  656       Double_t cosAbsPsi =  - fyz * cscTheta;
 
  657       if ( TMath::Abs(cosAbsPsi) > 1 ) {        
 
  658          Warning(
"GetPsi()",
"| cos psi | > 1 ");
 
  661       const Double_t absPsi = TMath::ACos(cosAbsPsi);
 
  664       } 
else if (fxz < 0) {
 
  667          finalPsi = (fyz < 0) ? 0 : TMath::Pi();
 
  670       Double_t absPsi = fxx;
 
  671       if ( TMath::Abs(fxx) > 1 ) {        
 
  672          Warning(
"GetPsi()",
"| fxx | > 1 ");
 
  675       absPsi = .5 * TMath::ACos (absPsi);
 
  678       } 
else if (fyx < 0) {
 
  681          finalPsi = (fxx > 0) ? 0 : TMath::PiOver2();
 
  690 Double_t TRotation::GetYPsi(
void)
 const {
 
  691    return GetXPsi() - TMath::Pi()/2;
 
  697 TRotation & TRotation::SetXAxis(
const TVector3& axis,
 
  698                                 const TVector3& xyPlane) {
 
  699    TVector3 xAxis(xyPlane);
 
  701    TVector3 zAxis(axis);
 
  702    MakeBasis(xAxis,yAxis,zAxis);
 
  703    fxx = zAxis.X();  fyx = zAxis.Y();  fzx = zAxis.Z();
 
  704    fxy = xAxis.X();  fyy = xAxis.Y();  fzy = xAxis.Z();
 
  705    fxz = yAxis.X();  fyz = yAxis.Y();  fzz = yAxis.Z();
 
  712 TRotation & TRotation::SetXAxis(
const TVector3& axis) {
 
  713    TVector3 xyPlane(0.0,1.0,0.0);
 
  714    return SetXAxis(axis,xyPlane);
 
  720 TRotation & TRotation::SetYAxis(
const TVector3& axis,
 
  721                                 const TVector3& yzPlane) {
 
  722    TVector3 xAxis(yzPlane);
 
  724    TVector3 zAxis(axis);
 
  725    MakeBasis(xAxis,yAxis,zAxis);
 
  726    fxx = yAxis.X();  fyx = yAxis.Y();  fzx = yAxis.Z();
 
  727    fxy = zAxis.X();  fyy = zAxis.Y();  fzy = zAxis.Z();
 
  728    fxz = xAxis.X();  fyz = xAxis.Y();  fzz = xAxis.Z();
 
  735 TRotation & TRotation::SetYAxis(
const TVector3& axis) {
 
  736    TVector3 yzPlane(0.0,0.0,1.0);
 
  737    return SetYAxis(axis,yzPlane);
 
  743 TRotation & TRotation::SetZAxis(
const TVector3& axis,
 
  744                                 const TVector3& zxPlane) {
 
  745    TVector3 xAxis(zxPlane);
 
  747    TVector3 zAxis(axis);
 
  748    MakeBasis(xAxis,yAxis,zAxis);
 
  749    fxx = xAxis.X();  fyx = xAxis.Y();  fzx = xAxis.Z();
 
  750    fxy = yAxis.X();  fyy = yAxis.Y();  fzy = yAxis.Z();
 
  751    fxz = zAxis.X();  fyz = zAxis.Y();  fzz = zAxis.Z();
 
  758 TRotation & TRotation::SetZAxis(
const TVector3& axis) {
 
  759    TVector3 zxPlane(1.0,0.0,0.0);
 
  760    return SetZAxis(axis,zxPlane);
 
  766 void TRotation::MakeBasis(TVector3& xAxis,
 
  768                           TVector3& zAxis)
 const {
 
  769    Double_t zmag = zAxis.Mag();
 
  770    if (zmag<TOLERANCE) {
 
  771       Warning(
"MakeBasis(X,Y,Z)",
"non-zero Z Axis is required");
 
  775    Double_t xmag = xAxis.Mag();
 
  776    if (xmag<TOLERANCE*zmag) {
 
  777       xAxis = zAxis.Orthogonal();
 
  782    yAxis = zAxis.Cross(xAxis)*(1.0/xmag);
 
  783    Double_t ymag = yAxis.Mag();
 
  784    if (ymag<TOLERANCE*zmag) {
 
  785       yAxis = zAxis.Orthogonal();
 
  790    xAxis = yAxis.Cross(zAxis);