TQuaternion.cxx

Go to the documentation of this file.
00001 // @(#)root/physics:$Id: TQuaternion.cxx 20882 2007-11-19 11:31:26Z rdm $
00002 // Author: Eric Anciant 28/06/2005
00003 
00004 
00005 //////////////////////////////////////////////////////////////////////////
00006 //____________________
00007 //                                                                      
00008 //  A Quaternion Class 
00009 // Begin_html
00010 // <p> Quaternion is a 4-component mathematic object quite convenient when dealing with 
00011 // space rotation (or reference frame transformation). </p> 
00012 // </p> 
00013 // <p> In short, think of quaternion Q as a 3-vector augmented by a real number. Q = Q|<sub>r</sub> + Q|<sub>V</sub>
00014 //
00015 // <p> <u> Quaternion multiplication :</u>
00016 // </p>
00017 // <p> Quaternion multiplication is given by :
00018 // <br> Q.Q'        = (Q|<sub>r</sub> + Q|<sub>V</sub> )*( Q'|<sub>r</sub> + Q'|<sub>V</sub>)
00019 // <br>         = [ Q|<sub>r</sub>*Q'|<sub>r</sub> - Q|<sub>V</sub>*Q'|<sub>V</sub> ] + [ Q|<sub>r</sub>*Q'|<sub>V</sub> + Q'|<sub>r</sub>*Q|<sub>V</sub> + Q|<sub>V</sub> X Q'|<sub>V</sub> ]
00020 // <br>
00021 // <br> where : 
00022 // <br> Q|<sub>r</sub>*Q'|<sub>r</sub>  is a real number product of real numbers
00023 // <br> Q|<sub>V</sub>*Q'|<sub>V</sub> is a real number, scalar product of two 3-vectors
00024 // <br> Q|<sub>r</sub>*Q'|<sub>V</sub> is a 3-vector, scaling of a 3-vector by a real number
00025 // <br> Q|<sub>V</sub>XQ'|<sub>V</sub> is a 3-vector, cross product of two 3-vectors
00026 // <br>
00027 // <br> Thus, quaternion product is a generalization of real number product and product of a vector by a real number. Product of two pure vectors gives a quaternion whose real part is the opposite of scalar product and the vector part the cross product…
00028 // </p>
00029 //
00030 // <p> The conjugate of a quaternion Q = Q|<sub>r</sub> + Q|<sub>V</sub> is Q_bar = Q|<sub>r</sub> - Q|<sub>V</sub>
00031 // </p>
00032 // <p> The magnitude of a quaternion Q is given by |Q|² = Q.Q_bar = Q_bar.Q = Q²|<sub>r</sub> + |Q|<sub>V</sub>|²
00033 // </p>
00034 // <p> Therefore, the inverse of a quaternion is Q<sup>-1</sup> = Q_bar /|Q|² 
00035 // </p>
00036 // <p> "unit" quaternion is a quaternion of magnitude 1 : |Q|² = 1.
00037 // <br> Unit quaternions are a subset of the quaternions set.
00038 // </p>
00039 //
00040 // <p> <u>Quaternion and rotations :</u>
00041 // </p> 
00042 //
00043 // <p> A rotation of angle <font face="Symbol">f</font> around a given axis, is represented by a unit quaternion Q :
00044 // <br> -        The axis of the rotation is given by the vector part of Q.
00045 // <br> -        The ratio between the magnitude of the vector part and the real part of Q equals tan(<font face="Symbol">f</font>/2).
00046 // </p> 
00047 // <p> In other words : Q = Q|<sub>r</sub> + Q|<sub>V</sub> = cos(<font face="Symbol">f</font>/2) + sin(<font face="Symbol">f</font>/2).u 
00048 // <br> (where u is a unit vector // to the rotation axis, 
00049 //                        cos(<font face="Symbol">f</font>/2) is the real part, sin(<font face="Symbol">f</font>/2).u is the vector part)
00050 // <br> Note : The quaternion of identity is Q<sub>I</sub> = cos(0) + sin(0)*(any vector) = 1.
00051 // </p>
00052 // <p> The composition of two rotations is described by the product of the two corresponding quaternions.
00053 // <br> As for 3-space rotations, quaternion multiplication is not commutative !
00054 // <br>
00055 // <br> Q = Q<sub>1</sub>.Q<sub>2</sub> represents the composition of the successive rotation R1 and R2 expressed in the <b>current</b> frame (the axis of rotation hold by Q<sub>2</sub> is expressed in the frame as it is after R1 rotation). 
00056 // <br> Q = Q<sub>2</sub>.Q<sub>1</sub> represents the composition of the successive rotation R1 and R2 expressed in the <b>initial</b> reference frame.
00057 // </p>
00058 // <p> The inverse of a rotation is a rotation about the same axis but of opposite angle, thus if Q is a unit quaternion,
00059 // <br> Q = cos(<font face="Symbol">f</font>/2) + sin(<font face="Symbol">f</font>/2).u = Q|<sub>r</sub> + Q|<sub>V</sub>, then :
00060 // <br> Q<sup>-1</sup> =cos(-<font face="Symbol">f</font>/2) + sin(-<font face="Symbol">f</font>/2).u = cos(<font face="Symbol">f</font>/2) - sin(<font face="Symbol">f</font>/2).u = Q|<sub>r</sub> -Q|<sub>V</sub> is its inverse quaternion.
00061 // </p>
00062 // <p> One verifies that :
00063 // <br> Q.Q<sup>-1</sup> = Q<sup>-1</sup>.Q = Q|<sub>r</sub>*Q|<sub>r</sub> + Q|<sub>V</sub>*Q|<sub>V</sub> + Q|<sub>r</sub>*Q|<sub>V</sub> -Q|<sub>r</sub>*Q|<sub>V</sub> + Q|<sub>V</sub>XQ|<sub>V</sub> 
00064 // <br>                 = Q²|<sub>r</sub> + Q²|<sub>V</sub> = 1
00065 // </p>
00066 // <br>
00067 // <p> The rotation of a vector V by the rotation described by a unit quaternion Q is obtained by the following operation : V' = Q*V*Q<sup>-1</sup>, considering V as a quaternion whose real part is null.
00068 // </p>
00069 // <p> <u>Numeric computation considerations :</u>
00070 // </p>
00071 // <p> Numerically, the quaternion multiplication involves 12 additions and 16 multiplications.
00072 // <br> It is therefore faster than 3x3 matrixes multiplication involving 18 additions and 27 multiplications.
00073 // <br>
00074 // <br> On the contrary, rotation of a vector by the above formula ( Q*V*Q<sup>-1</sup> ) involves 18 additions and 24 multiplications, whereas multiplication of a 3-vector by a 3x3 matrix involves only 6 additions and 9 multiplications.
00075 // <br> 
00076 // <br> When dealing with numerous composition of space rotation, it is therefore faster to use quaternion product. On the other hand if a huge set of vectors must be rotated by a given quaternion, it is more optimized to convert the quaternion into a rotation matrix once, and then use that later to rotate the set of vectors.
00077 // </p>
00078 // <p> <u>More information :</u>
00079 // </p>
00080 // <p>
00081 // <A HREF="http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation">
00082 //  en.wikipedia.org/wiki/Quaternions_and_spatial_rotation </A>.
00083 // <br> <br>
00084 // <A HREF="http://en.wikipedia.org/wiki/Quaternion">
00085 //  en.wikipedia.org/wiki/Quaternion </A>.
00086 // </p>
00087 // <p> _______________________________________________
00088 // <br>
00089 // <p> This Class represents all quaternions (unit or non-unit)
00090 // <br> It possesses a Normalize() method to make a given quaternion unit
00091 // <br> The Rotate(TVector3&) and Rotation(TVector3&) methods can be used even for a non-unit quaternion, in that case, the proper normalization is applied to perform the rotation.
00092 // <br>
00093 // <br> A TRotation constructor exists than takes a quaternion for parameter (even non-unit), in that cas the proper normalisation is applied.
00094 // </p>
00095 // End_html
00096 
00097 #include "TMath.h"
00098 #include "TQuaternion.h"
00099 
00100 ClassImp(TQuaternion)
00101 
00102 /****************** CONSTRUCTORS ****************************************************/
00103 //______________________________________________________________________________
00104 TQuaternion::TQuaternion(const TQuaternion & q) : TObject(q),
00105   fRealPart(q.fRealPart), fVectorPart(q.fVectorPart) {}
00106 
00107 TQuaternion::TQuaternion(const TVector3 & vect, Double_t real)
00108         : fRealPart(real), fVectorPart(vect)  {}
00109 
00110 TQuaternion::TQuaternion(const Double_t * x0)
00111         : fRealPart(x0[3]), fVectorPart(x0) {}
00112 
00113 TQuaternion::TQuaternion(const Float_t * x0)
00114         : fRealPart(x0[3]), fVectorPart(x0) {}
00115 
00116 TQuaternion::TQuaternion(Double_t real, Double_t X, Double_t Y, Double_t Z)
00117         : fRealPart(real), fVectorPart(X,Y,Z) {}
00118 
00119 TQuaternion::~TQuaternion() {}
00120 
00121 //______________________________________________________________________________
00122 Double_t TQuaternion::operator () (int i) const {
00123    //dereferencing operator const
00124    switch(i) {
00125       case 0:
00126       case 1:
00127       case 2:
00128          return fVectorPart(i);
00129       case 3:
00130          return fRealPart;
00131       default:
00132          Error("operator()(i)", "bad index (%d) returning 0",i);
00133    }
00134    return 0.;
00135 }
00136 
00137 //______________________________________________________________________________
00138 Double_t & TQuaternion::operator () (int i) {
00139    //dereferencing operator
00140    switch(i) {
00141       case 0:
00142       case 1:
00143       case 2:
00144          return fVectorPart(i);
00145       case 3:
00146          return fRealPart;
00147       default:
00148          Error("operator()(i)", "bad index (%d) returning &fRealPart",i);
00149    }
00150    return fRealPart;
00151 }
00152 //_____________________________________
00153 Double_t TQuaternion::GetQAngle() const {
00154    // Get angle of quaternion (rad)
00155    // N.B : this angle is half of the corresponding rotation angle
00156 
00157    if (fRealPart == 0) return 0;
00158    Double_t denominator = fVectorPart.Mag();
00159    return atan(denominator/fRealPart);
00160 }
00161 
00162 //_____________________________________
00163 TQuaternion& TQuaternion::SetQAngle(Double_t angle) {
00164    // Set angle of quaternion (rad) - keep quaternion norm
00165    // N.B : this angle is half of the corresponding rotation angle
00166  
00167    Double_t norm = Norm();
00168    Double_t normSinV = fVectorPart.Mag();
00169    if (normSinV != 0) fVectorPart *= (sin(angle)*norm/normSinV);
00170    fRealPart = cos(angle)*norm;
00171 
00172    return (*this);
00173 }
00174 
00175 //_____________________________________
00176 TQuaternion& TQuaternion::SetAxisQAngle(TVector3& v,Double_t QAngle) {
00177    // set quaternion from vector and angle (rad)
00178    // quaternion is set as unitary 
00179    // N.B : this angle is half of the corresponding rotation angle
00180         
00181    fVectorPart = v;
00182    double norm = v.Mag();
00183    if (norm>0) fVectorPart*=(1./norm);
00184    fVectorPart*=sin(QAngle);
00185    fRealPart = cos(QAngle);
00186 
00187    return (*this);
00188 }
00189 
00190 /**************** REAL TO QUATERNION ALGEBRA ****************************************/ 
00191 
00192 //_____________________________________
00193 TQuaternion TQuaternion::operator+(Double_t real) const {
00194    // sum of quaternion with a real
00195 
00196    return TQuaternion(fVectorPart, fRealPart + real);
00197 }
00198 
00199 //_____________________________________
00200 TQuaternion TQuaternion::operator-(Double_t real) const {
00201    // substraction of real to quaternion
00202 
00203    return TQuaternion(fVectorPart, fRealPart - real);
00204 }
00205 
00206 //_____________________________________
00207 TQuaternion TQuaternion::operator*(Double_t real) const {
00208    // product of quaternion with a real 
00209 
00210    return TQuaternion(fRealPart*real,fVectorPart.x()*real,fVectorPart.y()*real,fVectorPart.z()*real);
00211 }
00212 
00213 
00214 //_____________________________________
00215 TQuaternion TQuaternion::operator/(Double_t real) const {
00216    // division by a real
00217 
00218    if (real !=0 ) {
00219       return TQuaternion(fRealPart/real,fVectorPart.x()/real,fVectorPart.y()/real,fVectorPart.z()/real);
00220    } else {
00221       Error("operator/(Double_t)", "bad value (%f) ignored",real);
00222    }
00223 
00224    return (*this);
00225 }
00226 
00227 TQuaternion operator + (Double_t r, const TQuaternion & q) { return (q+r); }
00228 TQuaternion operator - (Double_t r, const TQuaternion & q) { return (-q+r); }
00229 TQuaternion operator * (Double_t r, const TQuaternion & q) { return (q*r); }
00230 TQuaternion operator / (Double_t r, const TQuaternion & q) { return (q.Invert()*r); }
00231 
00232 /**************** VECTOR TO QUATERNION ALGEBRA ****************************************/ 
00233 
00234 //_____________________________________
00235 TQuaternion TQuaternion::operator+(const TVector3 &vect) const {
00236    // sum of quaternion with a real
00237 
00238    return TQuaternion(fVectorPart + vect, fRealPart);
00239 }
00240 
00241 //_____________________________________
00242 TQuaternion TQuaternion::operator-(const TVector3 &vect) const {
00243    // substraction of real to quaternion
00244 
00245    return TQuaternion(fVectorPart - vect, fRealPart);
00246 }
00247 
00248 //_____________________________________
00249 TQuaternion& TQuaternion::MultiplyLeft(const TVector3 &vect) {
00250    // left multitplication
00251 
00252    Double_t savedRealPart = fRealPart;
00253    fRealPart = - (fVectorPart * vect);
00254    fVectorPart = vect.Cross(fVectorPart);
00255    fVectorPart += (vect * savedRealPart);
00256 
00257    return (*this);
00258 }
00259 
00260 //_____________________________________
00261 TQuaternion& TQuaternion::operator*=(const TVector3 &vect) {
00262    // right multiplication
00263 
00264    Double_t savedRealPart = fRealPart;
00265    fRealPart = -(fVectorPart * vect);
00266    fVectorPart = fVectorPart.Cross(vect);
00267    fVectorPart += (vect * savedRealPart );
00268 
00269    return (*this);
00270 }
00271 
00272 //_____________________________________
00273 TQuaternion TQuaternion::LeftProduct(const TVector3 &vect) const {
00274    // left product
00275 
00276    return TQuaternion(vect * fRealPart + vect.Cross(fVectorPart), -(fVectorPart * vect));
00277 }
00278 
00279 //_____________________________________
00280 TQuaternion TQuaternion::operator*(const TVector3 &vect) const {
00281    // right product
00282 
00283    return TQuaternion(vect * fRealPart + fVectorPart.Cross(vect), -(fVectorPart * vect));
00284 }
00285 
00286 //_____________________________________
00287 TQuaternion& TQuaternion::DivideLeft(const TVector3 &vect) {
00288    // left division
00289 
00290    Double_t norm2 = vect.Mag2();
00291    MultiplyLeft(vect);
00292    if (norm2 > 0 ) {
00293       // use (1./nom2) to be numericaly compliant with LeftQuotient(const TVector3 &)
00294       (*this) *= -(1./norm2); // minus <- using conjugate of vect
00295    } else {
00296       Error("DivideLeft(const TVector3)", "bad norm2 (%f) ignored",norm2);
00297    }
00298    return (*this);
00299 }
00300 
00301 //_____________________________________
00302 TQuaternion& TQuaternion::operator/=(const TVector3 &vect) {
00303    // right division
00304 
00305    Double_t norm2 = vect.Mag2();
00306    (*this) *= vect;
00307    if (norm2 > 0 ) {
00308       // use (1./real) to be numericaly compliant with operator/(const TVector3 &)
00309       (*this) *= - (1./norm2); // minus <- using conjugate of vect
00310    } else {
00311       Error("operator/=(const TVector3 &)", "bad norm2 (%f) ignored",norm2);
00312    }
00313    return (*this);
00314 }
00315 
00316 //_____________________________________
00317 TQuaternion TQuaternion::LeftQuotient(const TVector3 &vect) const {
00318    // left quotient
00319 
00320    Double_t norm2 = vect.Mag2();
00321 
00322    if (norm2>0) {
00323       double invNorm2 = 1./norm2;
00324       return TQuaternion((vect * -fRealPart - vect.Cross(fVectorPart))*invNorm2,
00325                                                                                                         (fVectorPart * vect ) * invNorm2 );
00326    } else {
00327       Error("LeftQuotient(const TVector3 &)", "bad norm2 (%f) ignored",norm2);
00328    }
00329    return (*this);
00330 }
00331 
00332 //_____________________________________
00333 TQuaternion TQuaternion::operator/(const TVector3 &vect) const {
00334    //  right quotient
00335 
00336    Double_t norm2 = vect.Mag2();
00337 
00338    if (norm2>0) {
00339       double invNorm2 = 1./norm2;
00340       return TQuaternion((vect * -fRealPart - fVectorPart.Cross(vect)) * invNorm2,
00341                                                                                                                 (fVectorPart * vect) * invNorm2 );
00342    } else {
00343       Error("operator/(const TVector3 &)", "bad norm2 (%f) ignored",norm2);
00344    }
00345    return (*this);
00346 }
00347 
00348 TQuaternion operator + (const TVector3 &V, const TQuaternion &Q) { return (Q+V); }
00349 TQuaternion operator - (const TVector3 &V, const TQuaternion &Q) { return (-Q+V); }
00350 TQuaternion operator * (const TVector3 &V, const TQuaternion &Q) { return Q.LeftProduct(V); }
00351 
00352 TQuaternion operator / (const TVector3 &vect, const TQuaternion &quat) {
00353    //divide operator
00354    TQuaternion res(vect);
00355    res /= quat;
00356    return res;
00357 }
00358 
00359 /**************** QUATERNION ALGEBRA ****************************************/ 
00360 
00361 //_____________________________________
00362 TQuaternion& TQuaternion::operator*=(const TQuaternion &quaternion) {
00363    // right multiplication
00364 
00365    Double_t saveRP = fRealPart;
00366    TVector3 cross(fVectorPart.Cross(quaternion.fVectorPart));
00367 
00368    fRealPart = fRealPart * quaternion.fRealPart - fVectorPart * quaternion.fVectorPart;
00369 
00370    fVectorPart *= quaternion.fRealPart;
00371    fVectorPart += quaternion.fVectorPart * saveRP;
00372    fVectorPart += cross;
00373    return (*this);
00374 }
00375 
00376 //_____________________________________
00377 TQuaternion& TQuaternion::MultiplyLeft(const TQuaternion &quaternion) {
00378    // left multiplication
00379 
00380    Double_t saveRP = fRealPart;
00381    TVector3 cross(quaternion.fVectorPart.Cross(fVectorPart));
00382 
00383    fRealPart = fRealPart * quaternion.fRealPart - fVectorPart * quaternion.fVectorPart;
00384 
00385    fVectorPart *= quaternion.fRealPart;
00386    fVectorPart += quaternion.fVectorPart * saveRP;
00387    fVectorPart += cross;
00388 
00389    return (*this);
00390 }
00391 
00392 //_____________________________________
00393 TQuaternion TQuaternion::LeftProduct(const TQuaternion &quaternion) const {
00394    // left product
00395 
00396    return TQuaternion( fVectorPart*quaternion.fRealPart + quaternion.fVectorPart*fRealPart
00397                                  + quaternion.fVectorPart.Cross(fVectorPart),
00398                                    fRealPart*quaternion.fRealPart - fVectorPart*quaternion.fVectorPart );
00399 }
00400 
00401 //_____________________________________
00402 TQuaternion TQuaternion::operator*(const TQuaternion &quaternion) const {
00403    // right product
00404 
00405    return TQuaternion(fVectorPart*quaternion.fRealPart + quaternion.fVectorPart*fRealPart
00406                     + fVectorPart.Cross(quaternion.fVectorPart),
00407                       fRealPart*quaternion.fRealPart - fVectorPart*quaternion.fVectorPart );
00408 }
00409 
00410 //_____________________________________
00411 TQuaternion& TQuaternion::DivideLeft(const TQuaternion &quaternion) {
00412    // left division
00413 
00414    Double_t norm2 = quaternion.Norm2();
00415 
00416    if (norm2 > 0 ) {
00417       MultiplyLeft(quaternion.Conjugate());
00418       (*this) *= (1./norm2);
00419    } else {
00420       Error("DivideLeft(const TQuaternion &)", "bad norm2 (%f) ignored",norm2);
00421    }
00422    return (*this);
00423 }
00424 
00425 //_____________________________________
00426 TQuaternion& TQuaternion::operator/=(const TQuaternion& quaternion) {
00427    // right division
00428 
00429    Double_t norm2 = quaternion.Norm2();
00430 
00431    if (norm2 > 0 ) {
00432       (*this) *= quaternion.Conjugate();
00433       // use (1./norm2) top be numericaly compliant with operator/(const TQuaternion&)
00434       (*this) *= (1./norm2);
00435    } else {
00436       Error("operator/=(const TQuaternion&)", "bad norm2 (%f) ignored",norm2);
00437    }
00438    return (*this);
00439 }
00440 
00441 //_____________________________________
00442 TQuaternion TQuaternion::LeftQuotient(const TQuaternion& quaternion) const {
00443    // left quotient
00444 
00445    Double_t norm2 = quaternion.Norm2();
00446 
00447    if (norm2 > 0 ) {
00448       double invNorm2 = 1./norm2;
00449       return TQuaternion(
00450              (fVectorPart*quaternion.fRealPart - quaternion.fVectorPart*fRealPart
00451                         - quaternion.fVectorPart.Cross(fVectorPart)) * invNorm2,
00452                         (fRealPart*quaternion.fRealPart + fVectorPart*quaternion.fVectorPart)*invNorm2 );
00453    } else {
00454       Error("LeftQuotient(const TQuaternion&)", "bad norm2 (%f) ignored",norm2);
00455    }
00456    return (*this);
00457 }
00458 
00459 //_____________________________________
00460 TQuaternion TQuaternion::operator/(const TQuaternion &quaternion) const {
00461    // right quotient
00462 
00463    Double_t norm2 = quaternion.Norm2();
00464 
00465    if (norm2 > 0 ) {
00466       double invNorm2 = 1./norm2;
00467       return TQuaternion(
00468              (fVectorPart*quaternion.fRealPart - quaternion.fVectorPart*fRealPart
00469                         - fVectorPart.Cross(quaternion.fVectorPart)) * invNorm2,
00470                          (fRealPart*quaternion.fRealPart + fVectorPart*quaternion.fVectorPart) * invNorm2 );
00471    } else {
00472       Error("operator/(const TQuaternion &)", "bad norm2 (%f) ignored",norm2);
00473    }
00474    return (*this);
00475 }
00476 
00477 //_____________________________________
00478 TQuaternion TQuaternion::Invert() const {
00479    // invert
00480 
00481    double norm2 = Norm2();
00482    if (norm2 > 0 ) {
00483       double invNorm2 = 1./norm2;
00484       return TQuaternion(fVectorPart*(-invNorm2), fRealPart*invNorm2 );
00485    } else {
00486       Error("Invert()", "bad norm2 (%f) ignored",norm2);
00487    }
00488    return (*this);
00489 }
00490 
00491 //_____________________________________
00492 void TQuaternion::Rotate(TVector3 & vect) const {
00493    // rotate vect by current quaternion
00494 
00495    vect = Rotation(vect);
00496 }
00497 
00498 //_____________________________________
00499 TVector3 TQuaternion::Rotation(const TVector3 & vect) const {
00500    // rotation of vect by current quaternion
00501 
00502    // Vres = (*this) * vect * (this->Invert());
00503    double norm2 = Norm2();
00504 
00505    if (norm2>0) {
00506       TQuaternion quat(*this);
00507       quat *= vect;
00508 
00509       // only compute vect part : (real part has to be 0 ) : 
00510       // VECT [ quat * ( this->Conjugate() ) ] = quat.fRealPart * -this->fVectorPart
00511       //                                                                                        + this->fRealPart * quat.fVectorPart
00512       //                                                                                        + quat.fVectorPart X (-this->fVectorPart)
00513       TVector3 cross(fVectorPart.Cross(quat.fVectorPart));
00514       quat.fVectorPart *=  fRealPart;
00515       quat.fVectorPart -= fVectorPart * quat.fRealPart;
00516       quat.fVectorPart += cross;
00517 
00518       return quat.fVectorPart*(1./norm2);
00519    } else {
00520       Error("Rotation()", "bad norm2 (%f) ignored",norm2);
00521    }
00522    return vect;
00523 }
00524 
00525 //_____________________________________
00526 void TQuaternion::Print(Option_t*) const
00527 {
00528    //Print Quaternion parameters
00529    Printf("%s %s (r,x,y,z)=(%f,%f,%f,%f) \n (alpha,rho,theta,phi)=(%f,%f,%f,%f)",GetName(),GetTitle(),
00530             fRealPart,fVectorPart.X(),fVectorPart.Y(),fVectorPart.Z(),
00531             GetQAngle()*TMath::RadToDeg(),fVectorPart.Mag(),fVectorPart.Theta()*TMath::RadToDeg(),fVectorPart.Phi()*TMath::RadToDeg());
00532 }

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