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);