00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 #include "TMath.h"
00098 #include "TQuaternion.h"
00099
00100 ClassImp(TQuaternion)
00101
00102
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
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
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
00155
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
00165
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
00178
00179
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
00191
00192
00193 TQuaternion TQuaternion::operator+(Double_t real) const {
00194
00195
00196 return TQuaternion(fVectorPart, fRealPart + real);
00197 }
00198
00199
00200 TQuaternion TQuaternion::operator-(Double_t real) const {
00201
00202
00203 return TQuaternion(fVectorPart, fRealPart - real);
00204 }
00205
00206
00207 TQuaternion TQuaternion::operator*(Double_t real) const {
00208
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
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
00233
00234
00235 TQuaternion TQuaternion::operator+(const TVector3 &vect) const {
00236
00237
00238 return TQuaternion(fVectorPart + vect, fRealPart);
00239 }
00240
00241
00242 TQuaternion TQuaternion::operator-(const TVector3 &vect) const {
00243
00244
00245 return TQuaternion(fVectorPart - vect, fRealPart);
00246 }
00247
00248
00249 TQuaternion& TQuaternion::MultiplyLeft(const TVector3 &vect) {
00250
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
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
00275
00276 return TQuaternion(vect * fRealPart + vect.Cross(fVectorPart), -(fVectorPart * vect));
00277 }
00278
00279
00280 TQuaternion TQuaternion::operator*(const TVector3 &vect) const {
00281
00282
00283 return TQuaternion(vect * fRealPart + fVectorPart.Cross(vect), -(fVectorPart * vect));
00284 }
00285
00286
00287 TQuaternion& TQuaternion::DivideLeft(const TVector3 &vect) {
00288
00289
00290 Double_t norm2 = vect.Mag2();
00291 MultiplyLeft(vect);
00292 if (norm2 > 0 ) {
00293
00294 (*this) *= -(1./norm2);
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
00304
00305 Double_t norm2 = vect.Mag2();
00306 (*this) *= vect;
00307 if (norm2 > 0 ) {
00308
00309 (*this) *= - (1./norm2);
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
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
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
00354 TQuaternion res(vect);
00355 res /= quat;
00356 return res;
00357 }
00358
00359
00360
00361
00362 TQuaternion& TQuaternion::operator*=(const TQuaternion &quaternion) {
00363
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
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
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
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
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
00428
00429 Double_t norm2 = quaternion.Norm2();
00430
00431 if (norm2 > 0 ) {
00432 (*this) *= quaternion.Conjugate();
00433
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
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
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
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
00494
00495 vect = Rotation(vect);
00496 }
00497
00498
00499 TVector3 TQuaternion::Rotation(const TVector3 & vect) const {
00500
00501
00502
00503 double norm2 = Norm2();
00504
00505 if (norm2>0) {
00506 TQuaternion quat(*this);
00507 quat *= vect;
00508
00509
00510
00511
00512
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
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 }