Rotation3D.cxx

Go to the documentation of this file.
00001 // @(#)root/mathcore:$Id: Rotation3D.cxx 22516 2008-03-07 15:14:26Z moneta $
00002 // Authors: W. Brown, M. Fischler, L. Moneta    2005  
00003 
00004  /**********************************************************************
00005   *                                                                    *
00006   * Copyright (c) 2005 , LCG ROOT FNAL MathLib Team                    *
00007   *                                                                    *
00008   *                                                                    *
00009   **********************************************************************/
00010 
00011 // Header file for class Rotation in 3 dimensions, represented by 3x3 matrix
00012 //
00013 // Created by: Mark Fischler Tues July 5 2005
00014 //
00015 #include "Math/GenVector/Rotation3D.h"
00016 
00017 #include <cmath>
00018 #include <algorithm>
00019 
00020 #include "Math/GenVector/Cartesian3D.h"
00021 #include "Math/GenVector/DisplacementVector3D.h"
00022 
00023 namespace ROOT {
00024 
00025 namespace Math {
00026 
00027 // ========== Constructors and Assignment =====================
00028 
00029 Rotation3D::Rotation3D() 
00030 {
00031    // constructor of a identity rotation
00032    fM[kXX] = 1.0;  fM[kXY] = 0.0; fM[kXZ] = 0.0;
00033    fM[kYX] = 0.0;  fM[kYY] = 1.0; fM[kYZ] = 0.0;
00034    fM[kZX] = 0.0;  fM[kZY] = 0.0; fM[kZZ] = 1.0;
00035 }
00036 
00037 
00038 void Rotation3D::Rectify()
00039 {
00040    // rectify rotation matrix (make orthogonal) 
00041    // The "nearest" orthogonal matrix X to a nearly-orthogonal matrix A
00042    // (in the sense that X is exaclty orthogonal and the sum of the squares
00043    // of the element differences X-A is as small as possible) is given by
00044    // X = A * inverse(sqrt(A.transpose()*A.inverse())).
00045    
00046    // Step 1 -- form symmetric M = A.transpose * A
00047    
00048    double m11 = fM[kXX]*fM[kXX] + fM[kYX]*fM[kYX] + fM[kZX]*fM[kZX];
00049    double m12 = fM[kXX]*fM[kXY] + fM[kYX]*fM[kYY] + fM[kZX]*fM[kZY];
00050    double m13 = fM[kXX]*fM[kXZ] + fM[kYX]*fM[kYZ] + fM[kZX]*fM[kZZ];
00051    double m22 = fM[kXY]*fM[kXY] + fM[kYY]*fM[kYY] + fM[kZY]*fM[kZY];
00052    double m23 = fM[kXY]*fM[kXZ] + fM[kYY]*fM[kYZ] + fM[kZY]*fM[kZZ];
00053    double m33 = fM[kXZ]*fM[kXZ] + fM[kYZ]*fM[kYZ] + fM[kZZ]*fM[kZZ];
00054    
00055    // Step 2 -- find lower-triangular U such that U * U.transpose = M
00056    
00057    double u11 = std::sqrt(m11);
00058    double u21 = m12/u11;
00059    double u31 = m13/u11;
00060    double u22 = std::sqrt(m22-u21*u21);
00061    double u32 = (m23-m12*m13/m11)/u22;
00062    double u33 = std::sqrt(m33 - u31*u31 - u32*u32);
00063    
00064    
00065    // Step 3 -- find V such that V*V = U.  U is also lower-triangular
00066    
00067    double v33 = 1/u33;
00068    double v32 = -v33*u32/u22;
00069    double v31 = -(v32*u21+v33*u31)/u11;
00070    double v22 = 1/u22;
00071    double v21 = -v22*u21/u11;
00072    double v11 = 1/u11;
00073    
00074    
00075    // Step 4 -- N = V.transpose * V is inverse(sqrt(A.transpose()*A.inverse()))
00076    
00077    double n11 = v11*v11 + v21*v21 + v31*v31;
00078    double n12 = v11*v21 + v21*v22 + v31*v32;
00079    double n13 = v11*v31 + v21*v32 + v31*v33;
00080    double n22 = v21*v21 + v22*v22 + v32*v32;
00081    double n23 = v21*v31 + v22*v32 + v32*v33;
00082    double n33 = v31*v31 + v32*v32 + v33*v33;
00083    
00084    
00085    // Step 5 -- The new matrix is A * N
00086    
00087    double mA[9];
00088    std::copy(fM, &fM[9], mA);
00089    
00090    fM[kXX] = mA[kXX]*n11 + mA[kXY]*n12 + mA[kXZ]*n13;
00091    fM[kXY] = mA[kXX]*n12 + mA[kXY]*n22 + mA[kXZ]*n23;
00092    fM[kXZ] = mA[kXX]*n13 + mA[kXY]*n23 + mA[kXZ]*n33;
00093    fM[kYX] = mA[kYX]*n11 + mA[kYY]*n12 + mA[kYZ]*n13;
00094    fM[kYY] = mA[kYX]*n12 + mA[kYY]*n22 + mA[kYZ]*n23;
00095    fM[kYZ] = mA[kYX]*n13 + mA[kYY]*n23 + mA[kYZ]*n33;
00096    fM[kZX] = mA[kZX]*n11 + mA[kZY]*n12 + mA[kZZ]*n13;
00097    fM[kZY] = mA[kZX]*n12 + mA[kZY]*n22 + mA[kZZ]*n23;
00098    fM[kZZ] = mA[kZX]*n13 + mA[kZY]*n23 + mA[kZZ]*n33;
00099    
00100    
00101 } // Rectify()
00102 
00103 
00104 static inline void swap(double & a, double & b) { 
00105    // swap two values
00106    double t=b; b=a; a=t; 
00107 }
00108 
00109 void Rotation3D::Invert() {
00110    // invert a rotation
00111    swap (fM[kXY], fM[kYX]);
00112    swap (fM[kXZ], fM[kZX]);
00113    swap (fM[kYZ], fM[kZY]);
00114 }
00115 
00116 
00117 Rotation3D Rotation3D::operator * (const AxisAngle   & a) const {
00118    // combine with an AxisAngle rotation
00119    return operator* ( Rotation3D(a) );
00120 }
00121 
00122 Rotation3D Rotation3D::operator * (const EulerAngles & e) const {
00123    // combine with an EulerAngles rotation
00124    return operator* ( Rotation3D(e) );
00125 }
00126 
00127 Rotation3D Rotation3D::operator * (const Quaternion  & q) const {
00128    // combine with a Quaternion rotation
00129    return operator* ( Rotation3D(q) );
00130 }
00131 
00132 Rotation3D Rotation3D::operator * (const RotationZYX  & r) const {
00133    // combine with a RotastionZYX rotation
00134    return operator* ( Rotation3D(r) );
00135 }
00136 
00137 std::ostream & operator<< (std::ostream & os, const Rotation3D & r) {
00138    // TODO - this will need changing for machine-readable issues
00139    //        and even the human readable form needs formatting improvements
00140    double m[9];
00141    r.GetComponents(m, m+9);
00142    os << "\n" << m[0] << "  " << m[1] << "  " << m[2]; 
00143    os << "\n" << m[3] << "  " << m[4] << "  " << m[5]; 
00144    os << "\n" << m[6] << "  " << m[7] << "  " << m[8] << "\n";
00145    return os;
00146 }
00147 
00148 } //namespace Math
00149 } //namespace ROOT

Generated on Tue Jul 5 14:33:07 2011 for ROOT_528-00b_version by  doxygen 1.5.1