TEveTrans.cxx

Go to the documentation of this file.
00001 // @(#)root/eve:$Id: TEveTrans.cxx 32931 2010-04-09 16:29:40Z matevz $
00002 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TEveTrans.h"
00013 #include "TEveUtil.h"
00014 
00015 #include "TMath.h"
00016 #include "TClass.h"
00017 
00018 #include "Riostream.h"
00019 
00020 #include <cctype>
00021 
00022 #define F00  0
00023 #define F01  4
00024 #define F02  8
00025 #define F03 12
00026 
00027 #define F10  1
00028 #define F11  5
00029 #define F12  9
00030 #define F13 13
00031 
00032 #define F20  2
00033 #define F21  6
00034 #define F22 10
00035 #define F23 14
00036 
00037 #define F30  3
00038 #define F31  7
00039 #define F32 11
00040 #define F33 15
00041 
00042 //______________________________________________________________________________
00043 //
00044 // TEveTrans is a 4x4 transformation matrix for homogeneous coordinates
00045 // stored internaly in a column-major order to allow direct usage by
00046 // GL. The element type is Double32_t as statically the floats would
00047 // be precise enough but continuous operations on the matrix must
00048 // retain precision of column vectors.
00049 //
00050 // Cartan angles are stored in fA[1-3] (+z, -y, +x). They are
00051 // recalculated on demand.
00052 //
00053 // Direct  element access (first two should be used with care):
00054 // operator[i]    direct access to elements,   i:0->15
00055 // CM(i,j)        element 4*j + i;           i,j:0->3    { CM ~ c-matrix }
00056 // operator(i,j)  element 4*(j-1) + i - 1    i,j:1->4
00057 //
00058 // Column-vector access:
00059 // USet Get/SetBaseVec(), Get/SetPos() and Arr[XYZT]() methods.
00060 //
00061 // For all methods taking the matrix indices:
00062 // 1->X, 2->Y, 3->Z; 4->Position (if applicable). 0 reserved for time.
00063 //
00064 // Shorthands in method-names:
00065 // LF ~ LocalFrame; PF ~ ParentFrame; IP ~ InPlace
00066 
00067 ClassImp(TEveTrans);
00068 
00069 //______________________________________________________________________________
00070 TEveTrans::TEveTrans() :
00071    TObject(),
00072    fA1(0), fA2(0), fA3(0), fAsOK(kFALSE),
00073    fUseTrans (kTRUE),
00074    fEditTrans(kFALSE),
00075    fEditRotation(kTRUE),
00076    fEditScale(kTRUE)
00077 {
00078    // Default constructor.
00079 
00080    UnitTrans();
00081 }
00082 
00083 //______________________________________________________________________________
00084 TEveTrans::TEveTrans(const TEveTrans& t) :
00085    TObject(),
00086    fA1(t.fA1), fA2(t.fA2), fA3(t.fA3), fAsOK(t.fAsOK),
00087    fUseTrans (t.fUseTrans),
00088    fEditTrans(t.fEditTrans),
00089    fEditRotation(kTRUE),
00090    fEditScale(kTRUE)
00091 {
00092    // Constructor.
00093 
00094    SetTrans(t, kFALSE);
00095 }
00096 
00097 //______________________________________________________________________________
00098 TEveTrans::TEveTrans(const Double_t arr[16]) :
00099    TObject(),
00100    fA1(0), fA2(0), fA3(0), fAsOK(kFALSE),
00101    fUseTrans (kTRUE),
00102    fEditTrans(kFALSE),
00103    fEditRotation(kTRUE),
00104    fEditScale(kTRUE)
00105 {
00106    // Constructor.
00107 
00108    SetFromArray(arr);
00109 }
00110 
00111 //______________________________________________________________________________
00112 TEveTrans::TEveTrans(const Float_t arr[16]) :
00113    TObject(),
00114    fA1(0), fA2(0), fA3(0), fAsOK(kFALSE),
00115    fUseTrans (kTRUE),
00116    fEditTrans(kFALSE),
00117    fEditRotation(kTRUE),
00118    fEditScale(kTRUE)
00119 {
00120    // Constructor.
00121 
00122    SetFromArray(arr);
00123 }
00124 
00125 /******************************************************************************/
00126 
00127 //______________________________________________________________________________
00128 void TEveTrans::UnitTrans()
00129 {
00130    // Reset matrix to unity.
00131 
00132    memset(fM, 0, 16*sizeof(Double_t));
00133    fM[F00] = fM[F11] = fM[F22] = fM[F33] = 1;
00134    fA1 = fA2 = fA3 = 0;
00135    fAsOK = kTRUE;
00136 }
00137 
00138 //______________________________________________________________________________
00139 void TEveTrans::ZeroTrans(Double_t w)
00140 {
00141    // Reset matrix to zero, only the perspective scaling is set to w
00142    // (1 by default).
00143 
00144    memset(fM, 0, 16*sizeof(Double_t));
00145    fM[F33] = w;
00146    fA1 = fA2 = fA3 = 0;
00147    fAsOK = kFALSE;
00148 }
00149 
00150 //______________________________________________________________________________
00151 void TEveTrans::UnitRot()
00152 {
00153    // Reset rotation part of the matrix to unity.
00154 
00155    memset(fM, 0, 12*sizeof(Double_t));
00156    fM[F00] = fM[F11] = fM[F22] = 1;
00157    fA1 = fA2 = fA3 = 0;
00158    fAsOK = kTRUE;
00159 }
00160 
00161 //______________________________________________________________________________
00162 void TEveTrans::SetTrans(const TEveTrans& t, Bool_t copyAngles)
00163 {
00164    // Set matrix from another,
00165 
00166    memcpy(fM, t.fM, sizeof(fM));
00167    if (copyAngles && t.fAsOK) {
00168       fAsOK = kTRUE;
00169       fA1 = t.fA1; fA2 = t.fA2; fA3 = t.fA3;
00170    } else {
00171       fAsOK = kFALSE;
00172    }
00173 }
00174 
00175 //______________________________________________________________________________
00176 void TEveTrans::SetFromArray(const Double_t arr[16])
00177 {
00178    // Set matrix from Double_t array.
00179 
00180    for(Int_t i=0; i<16; ++i) fM[i] = arr[i];
00181    fAsOK = kFALSE;
00182 }
00183 
00184 //______________________________________________________________________________
00185 void TEveTrans::SetFromArray(const Float_t arr[16])
00186 {
00187    // Set matrix from Float_t array.
00188 
00189    for(Int_t i=0; i<16; ++i) fM[i] = arr[i];
00190    fAsOK = kFALSE;
00191 }
00192 
00193 //______________________________________________________________________________
00194 void TEveTrans::SetupRotation(Int_t i, Int_t j, Double_t f)
00195 {
00196    // Setup the matrix as an elementary rotation.
00197    // Optimized versions of left/right multiplication with an elementary
00198    // rotation matrix are implemented in RotatePF/RotateLF.
00199    // Expects identity matrix.
00200 
00201    if(i == j) return;
00202    TEveTrans& t = *this;
00203    t(i,i) = t(j,j) = TMath::Cos(f);
00204    Double_t s = TMath::Sin(f);
00205    t(i,j) = -s; t(j,i) = s;
00206    fAsOK = kFALSE;
00207 }
00208 
00209 //______________________________________________________________________________
00210 void TEveTrans::SetupFromToVec(const TEveVector& from, const TEveVector& to)
00211 {
00212    // A function for creating a rotation matrix that rotates a vector called
00213    // "from" into another vector called "to".
00214    // Input : from[3], to[3] which both must be *normalized* non-zero vectors
00215    // Output: mtx[3][3] -- a 3x3 matrix in colum-major form
00216    // Authors: Tomas Möller, John Hughes
00217    //          "Efficiently Building a Matrix to Rotate One Vector to Another"
00218    //          Journal of Graphics Tools, 4(4):1-4, 1999
00219 
00220    static const float kFromToEpsilon = 0.000001f;
00221 
00222    ZeroTrans();
00223 
00224    Float_t e, f;
00225    e = from.Dot(to);
00226    f = (e < 0.0f) ? -e : e;
00227 
00228    if (f > 1.0f - kFromToEpsilon) /* "from" and "to"-vector almost parallel */
00229    {
00230       TEveVector u, v;       /* temporary storage vectors */
00231       TEveVector x;          /* vector most nearly orthogonal to "from" */
00232       Float_t    c1, c2, c3; /* coefficients for later use */
00233 
00234       x.fX = (from.fX > 0.0f) ? from.fX : -from.fX;
00235       x.fY = (from.fY > 0.0f) ? from.fY : -from.fY;
00236       x.fZ = (from.fZ > 0.0f) ? from.fZ : -from.fZ;
00237 
00238       if (x.fX < x.fY)
00239       {
00240          if (x.fX < x.fZ) {
00241             x.fX = 1.0f; x.fY = x.fZ = 0.0f;
00242          } else {
00243             x.fZ = 1.0f; x.fX = x.fY = 0.0f;
00244          }
00245       }
00246       else
00247       {
00248          if (x.fY < x.fZ) {
00249             x.fY = 1.0f; x.fX = x.fZ = 0.0f;
00250          } else {
00251             x.fZ = 1.0f; x.fX = x.fY = 0.0f;
00252          }
00253       }
00254 
00255       u.Sub(x, from);
00256       v.Sub(x, to);
00257 
00258       c1 = 2.0f / u.Mag2();
00259       c2 = 2.0f / v.Mag2();
00260       c3 = c1 * c2  * u.Dot(v);
00261 
00262       for (int i = 0; i < 3; i++) {
00263          for (int j = 0; j < 3; j++) {
00264             CM(i, j) =  - c1 * u[i] * u[j]
00265                - c2 * v[i] * v[j]
00266                + c3 * v[i] * u[j];
00267          }
00268          CM(i, i) += 1.0;
00269       }
00270    }
00271    else  /* the most common case, unless "from"="to", or "from"=-"to" */
00272    {
00273       TEveVector v = from.Cross(to);
00274 
00275       Float_t h, hvx, hvz, hvxy, hvxz, hvyz;
00276       h   = 1.0f/(1.0f + e);
00277       hvx = h * v.fX;
00278       hvz = h * v.fZ;
00279       hvxy = hvx * v.fY;
00280       hvxz = hvx * v.fZ;
00281       hvyz = hvz * v.fY;
00282 
00283       CM(0, 0) = e + hvx * v.fX;
00284       CM(0, 1) = hvxy - v.fZ;
00285       CM(0, 2) = hvxz + v.fY;
00286 
00287       CM(1, 0) = hvxy + v.fZ;
00288       CM(1, 1) = e + h * v.fY * v.fY;
00289       CM(1, 2) = hvyz - v.fX;
00290 
00291       CM(2, 0) = hvxz - v.fY;
00292       CM(2, 1) = hvyz + v.fX;
00293       CM(2, 2) = e + hvz * v.fZ;
00294    }
00295 }
00296 
00297 /******************************************************************************/
00298 
00299 // OrtoNorm3 and Invert are near the bottom.
00300 
00301 /******************************************************************************/
00302 
00303 //______________________________________________________________________________
00304 void TEveTrans::MultLeft(const TEveTrans& t)
00305 {
00306    // Multiply from left: this = t * this.
00307 
00308    Double_t  buf[4];
00309    Double_t* col = fM;
00310    for(int c=0; c<4; ++c, col+=4) {
00311       const Double_t* row = t.fM;
00312       for(int r=0; r<4; ++r, ++row)
00313          buf[r] = row[0]*col[0] + row[4]*col[1] + row[8]*col[2] + row[12]*col[3];
00314       col[0] = buf[0]; col[1] = buf[1]; col[2] = buf[2]; col[3] = buf[3];
00315    }
00316    fAsOK = kFALSE;
00317 }
00318 
00319 //______________________________________________________________________________
00320 void TEveTrans::MultRight(const TEveTrans& t)
00321 {
00322    // Multiply from right: this = this * t.
00323 
00324    Double_t  buf[4];
00325    Double_t* row = fM;
00326    for(int r=0; r<4; ++r, ++row) {
00327       const Double_t* col = t.fM;
00328       for(int c=0; c<4; ++c, col+=4)
00329          buf[c] = row[0]*col[0] + row[4]*col[1] + row[8]*col[2] + row[12]*col[3];
00330       row[0] = buf[0]; row[4] = buf[1]; row[8] = buf[2]; row[12] = buf[3];
00331    }
00332    fAsOK = kFALSE;
00333 }
00334 
00335 //______________________________________________________________________________
00336 TEveTrans TEveTrans::operator*(const TEveTrans& t)
00337 {
00338    // Copy, multiply from right and return product.
00339    // Avoid unless necessary.
00340 
00341    TEveTrans b(*this);
00342    b.MultRight(t);
00343    return b;
00344 }
00345 
00346 /******************************************************************************/
00347 
00348 //______________________________________________________________________________
00349 void TEveTrans::TransposeRotationPart()
00350 {
00351    // Transpose 3x3 rotation sub-matrix.
00352 
00353    Double_t x;
00354    x = fM[F01]; fM[F01] = fM[F10]; fM[F10] = x;
00355    x = fM[F02]; fM[F02] = fM[F20]; fM[F20] = x;
00356    x = fM[F12]; fM[F12] = fM[F21]; fM[F21] = x;
00357    fAsOK = kFALSE;
00358 }
00359 
00360 /******************************************************************************/
00361 // Move & Rotate
00362 /******************************************************************************/
00363 
00364 //______________________________________________________________________________
00365 void TEveTrans::MoveLF(Int_t ai, Double_t amount)
00366 {
00367    // Move in local-frame along axis with index ai.
00368 
00369    const Double_t *col = fM + 4*--ai;
00370    fM[F03] += amount*col[0]; fM[F13] += amount*col[1]; fM[F23] += amount*col[2];
00371 }
00372 
00373 //______________________________________________________________________________
00374 void TEveTrans::Move3LF(Double_t x, Double_t y, Double_t z)
00375 {
00376    // General move in local-frame.
00377 
00378    fM[F03] += x*fM[0] + y*fM[4] + z*fM[8];
00379    fM[F13] += x*fM[1] + y*fM[5] + z*fM[9];
00380    fM[F23] += x*fM[2] + y*fM[6] + z*fM[10];
00381 }
00382 
00383 //______________________________________________________________________________
00384 void TEveTrans::RotateLF(Int_t i1, Int_t i2, Double_t amount)
00385 {
00386    // Rotate in local frame. Does optimised version of MultRight.
00387 
00388    if(i1 == i2) return;
00389    // Algorithm: TEveTrans a; a.SetupRotation(i1, i2, amount); MultRight(a);
00390    // Optimized version:
00391    const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
00392    Double_t  b1, b2;
00393    Double_t* row = fM;
00394    --i1 <<= 2; --i2 <<= 2; // column major
00395    for (int r=0; r<4; ++r, ++row) {
00396       b1 = cos*row[i1] + sin*row[i2];
00397       b2 = cos*row[i2] - sin*row[i1];
00398       row[i1] = b1; row[i2] = b2;
00399    }
00400    fAsOK = kFALSE;
00401 }
00402 
00403 /******************************************************************************/
00404 
00405 //______________________________________________________________________________
00406 void TEveTrans::MovePF(Int_t ai, Double_t amount)
00407 {
00408    // Move in parent-frame along axis index ai.
00409 
00410    fM[F03 + --ai] += amount;
00411 }
00412 
00413 //______________________________________________________________________________
00414 void TEveTrans::Move3PF(Double_t x, Double_t y, Double_t z)
00415 {
00416    // General move in parent-frame.
00417 
00418    fM[F03] += x;
00419    fM[F13] += y;
00420    fM[F23] += z;
00421 }
00422 
00423 //______________________________________________________________________________
00424 void TEveTrans::RotatePF(Int_t i1, Int_t i2, Double_t amount)
00425 {
00426    // Rotate in parent frame. Does optimised version of MultLeft.
00427 
00428    if(i1 == i2) return;
00429    // Algorithm: TEveTrans a; a.SetupRotation(i1, i2, amount); MultLeft(a);
00430 
00431    // Optimized version:
00432    const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
00433    Double_t  b1, b2;
00434    Double_t* col = fM;
00435    --i1; --i2;
00436    for(int c=0; c<4; ++c, col+=4) {
00437       b1 = cos*col[i1] - sin*col[i2];
00438       b2 = cos*col[i2] + sin*col[i1];
00439       col[i1] = b1; col[i2] = b2;
00440    }
00441    fAsOK = kFALSE;
00442 }
00443 
00444 /******************************************************************************/
00445 
00446 //______________________________________________________________________________
00447 void TEveTrans::Move(const TEveTrans& a, Int_t ai, Double_t amount)
00448 {
00449    // Move in a's coord-system along axis-index ai.
00450 
00451    const Double_t* vec = a.fM + 4*--ai;
00452    fM[F03] += amount*vec[0];
00453    fM[F13] += amount*vec[1];
00454    fM[F23] += amount*vec[2];
00455 }
00456 
00457 //______________________________________________________________________________
00458 void TEveTrans::Move3(const TEveTrans& a, Double_t x, Double_t y, Double_t z)
00459 {
00460    // General move in a's coord-system.
00461 
00462    const Double_t* m = a.fM;
00463    fM[F03] += x*m[F00] + y*m[F01] + z*m[F02];
00464    fM[F13] += x*m[F10] + y*m[F11] + z*m[F12];
00465    fM[F23] += x*m[F20] + y*m[F21] + z*m[F22];
00466 }
00467 
00468 //______________________________________________________________________________
00469 void TEveTrans::Rotate(const TEveTrans& a, Int_t i1, Int_t i2, Double_t amount)
00470 {
00471    // Rotate in a's coord-system, rotating base vector with index i1
00472    // into i2.
00473 
00474    if(i1 == i2) return;
00475    TEveTrans x(a);
00476    x.Invert();
00477    MultLeft(x);
00478    RotatePF(i1, i2, amount);
00479    MultLeft(a);
00480    fAsOK = kFALSE;
00481 }
00482 
00483 /******************************************************************************/
00484 // Base-vector interface
00485 /******************************************************************************/
00486 
00487 //______________________________________________________________________________
00488 void TEveTrans::SetBaseVec(Int_t b, Double_t x, Double_t y, Double_t z)
00489 {
00490    // Set base-vector with index b.
00491 
00492    Double_t* col = fM + 4*--b;
00493    col[0] = x; col[1] = y; col[2] = z;
00494    fAsOK = kFALSE;
00495 }
00496 
00497 //______________________________________________________________________________
00498 void TEveTrans::SetBaseVec(Int_t b, const TVector3& v)
00499 {
00500    // Set base-vector with index b.
00501 
00502    Double_t* col = fM + 4*--b;
00503    v.GetXYZ(col);
00504    fAsOK = kFALSE;
00505 }
00506 
00507 //______________________________________________________________________________
00508 TVector3 TEveTrans::GetBaseVec(Int_t b) const
00509 {
00510    // Get base-vector with index b.
00511 
00512    return TVector3(&fM[4*--b]);
00513 }
00514 
00515 void TEveTrans::GetBaseVec(Int_t b, TVector3& v) const
00516 {
00517    // Get base-vector with index b.
00518 
00519    const Double_t* col = fM + 4*--b;
00520    v.SetXYZ(col[0], col[1], col[2]);
00521 }
00522 
00523 /******************************************************************************/
00524 // Position interface
00525 /******************************************************************************/
00526 
00527 //______________________________________________________________________________
00528 void TEveTrans::SetPos(Double_t x, Double_t y, Double_t z)
00529 {
00530    // Set position (base-vec 4).
00531    fM[F03] = x; fM[F13] = y; fM[F23] = z;
00532 }
00533 
00534 void TEveTrans::SetPos(Double_t* x)
00535 {
00536    // Set position (base-vec 4).
00537    fM[F03] = x[0]; fM[F13] = x[1]; fM[F23] = x[2];
00538 }
00539 
00540 void TEveTrans::SetPos(Float_t* x)
00541 {
00542    // Set position (base-vec 4).
00543    fM[F03] = x[0]; fM[F13] = x[1]; fM[F23] = x[2];
00544 }
00545 
00546 void TEveTrans::SetPos(const TEveTrans& t)
00547 {
00548    // Set position (base-vec 4).
00549    const Double_t* m = t.fM;
00550    fM[F03] = m[F03]; fM[F13] = m[F13]; fM[F23] = m[F23];
00551 }
00552 
00553 //______________________________________________________________________________
00554 void TEveTrans::GetPos(Double_t& x, Double_t& y, Double_t& z) const
00555 {
00556    // Get position (base-vec 4).
00557    x = fM[F03]; y = fM[F13]; z = fM[F23];
00558 }
00559 
00560 void TEveTrans::GetPos(Double_t* x) const
00561 {
00562    // Get position (base-vec 4).
00563    x[0] = fM[F03]; x[1] = fM[F13]; x[2] = fM[F23];
00564 }
00565 
00566 void TEveTrans::GetPos(Float_t* x) const
00567 {
00568    // Get position (base-vec 4).
00569    x[0] = fM[F03]; x[1] = fM[F13]; x[2] = fM[F23];
00570 }
00571 
00572 void TEveTrans::GetPos(TVector3& v) const
00573 {
00574    // Get position (base-vec 4).
00575    v.SetXYZ(fM[F03], fM[F13], fM[F23]);
00576 }
00577 
00578 TVector3 TEveTrans::GetPos() const
00579 {
00580    // Get position (base-vec 4).
00581    return TVector3(fM[F03], fM[F13], fM[F23]);
00582 }
00583 
00584 /******************************************************************************/
00585 // Cardan angle interface
00586 /******************************************************************************/
00587 
00588 namespace
00589 {
00590 inline void clamp_angle(Float_t& a)
00591 {
00592    while(a < -TMath::TwoPi()) a += TMath::TwoPi();
00593    while(a >  TMath::TwoPi()) a -= TMath::TwoPi();
00594 }
00595 }
00596 
00597 void TEveTrans::SetRotByAngles(Float_t a1, Float_t a2, Float_t a3)
00598 {
00599    // Sets Rotation part as given by angles:
00600    // a1 around z, -a2 around y, a3 around x.
00601 
00602    clamp_angle(a1); clamp_angle(a2); clamp_angle(a3);
00603 
00604    Double_t a, b, c, d, e, f;
00605    a = TMath::Cos(a3); b = TMath::Sin(a3);
00606    c = TMath::Cos(a2); d = TMath::Sin(a2); // should be -sin(a2) for positive direction
00607    e = TMath::Cos(a1); f = TMath::Sin(a1);
00608    Double_t ad = a*d, bd = b*d;
00609 
00610    fM[F00] = c*e; fM[F01] = -bd*e - a*f; fM[F02] = -ad*e + b*f;
00611    fM[F10] = c*f; fM[F11] = -bd*f + a*e; fM[F12] = -ad*f - b*e;
00612    fM[F20] = d;   fM[F21] =  b*c;        fM[F22] =  a*c;
00613 
00614    fA1 = a1; fA2 = a2; fA3 = a3;
00615    fAsOK = kTRUE;
00616 }
00617 
00618 //______________________________________________________________________________
00619 void TEveTrans::SetRotByAnyAngles(Float_t a1, Float_t a2, Float_t a3,
00620                                   const char* pat)
00621 {
00622    // Sets Rotation part as given by angles a1, a1, a3 and pattern pat.
00623    // Pattern consists of "XxYyZz" characters.
00624    // eg: x means rotate about x axis, X means rotate in negative direction
00625    // xYz -> R_x(a3) * R_y(-a2) * R_z(a1); (standard Gled representation)
00626    // Note that angles and pattern elements have inversed order!
00627    //
00628    // Implements Eulerian/Cardanian angles in a uniform way.
00629 
00630    int n = strspn(pat, "XxYyZz"); if(n > 3) n = 3;
00631    // Build Trans ... assign ...
00632    Float_t a[] = { a3, a2, a1 };
00633    UnitRot();
00634    for(int i=0; i<n; i++) {
00635       if(isupper(pat[i])) a[i] = -a[i];
00636       switch(pat[i]) {
00637          case 'x': case 'X': RotateLF(2, 3, a[i]); break;
00638          case 'y': case 'Y': RotateLF(3, 1, a[i]); break;
00639          case 'z': case 'Z': RotateLF(1, 2, a[i]); break;
00640       }
00641    }
00642    fAsOK = kFALSE;
00643 }
00644 
00645 //______________________________________________________________________________
00646 void TEveTrans::GetRotAngles(Float_t* x) const
00647 {
00648    // Get Cardan rotation angles (pattern xYz above).
00649 
00650    if(!fAsOK) {
00651       Double_t sx, sy, sz;
00652       GetScale(sx, sy, sz);
00653       Double_t d = fM[F20]/sx;
00654       if(d>1) d=1; else if(d<-1) d=-1; // Fix numerical errors
00655       fA2 = TMath::ASin(d);
00656       Double_t cos = TMath::Cos(fA2);
00657       if(TMath::Abs(cos) > 8.7e-6) {
00658          fA1 = TMath::ATan2(fM[F10], fM[F00]);
00659          fA3 = TMath::ATan2(fM[F21]/sy, fM[F22]/sz);
00660       } else {
00661          fA1 = TMath::ATan2(fM[F10]/sx, fM[F11]/sy);
00662          fA3 = 0;
00663       }
00664       fAsOK = kTRUE;
00665    }
00666    x[0] = fA1; x[1] = fA2; x[2] = fA3;
00667 }
00668 
00669 /******************************************************************************/
00670 // Scaling
00671 /******************************************************************************/
00672 
00673 //______________________________________________________________________________
00674 void TEveTrans::Scale(Double_t sx, Double_t sy, Double_t sz)
00675 {
00676    // Scale matrix. Translation part untouched.
00677 
00678    fM[F00] *= sx; fM[F10] *= sx; fM[F20] *= sx;
00679    fM[F01] *= sy; fM[F11] *= sy; fM[F21] *= sy;
00680    fM[F02] *= sz; fM[F12] *= sz; fM[F22] *= sz;
00681 }
00682 
00683 //______________________________________________________________________________
00684 Double_t TEveTrans::Unscale()
00685 {
00686    // Remove scaling, make all base vectors of unit length.
00687 
00688    Double_t sx, sy, sz;
00689    Unscale(sx, sy, sz);
00690    return (sx + sy + sz)/3;
00691 }
00692 
00693 //______________________________________________________________________________
00694 void TEveTrans::Unscale(Double_t& sx, Double_t& sy, Double_t& sz)
00695 {
00696    // Remove scaling, make all base vectors of unit length.
00697 
00698    GetScale(sx, sy, sz);
00699    fM[F00] /= sx; fM[F10] /= sx; fM[F20] /= sx;
00700    fM[F01] /= sy; fM[F11] /= sy; fM[F21] /= sy;
00701    fM[F02] /= sz; fM[F12] /= sz; fM[F22] /= sz;
00702 }
00703 
00704 //______________________________________________________________________________
00705 void TEveTrans::GetScale(Double_t& sx, Double_t& sy, Double_t& sz) const
00706 {
00707    // Deduce scales from sizes of base vectors.
00708 
00709    sx = TMath::Sqrt( fM[F00]*fM[F00] + fM[F10]*fM[F10] + fM[F20]*fM[F20] );
00710    sy = TMath::Sqrt( fM[F01]*fM[F01] + fM[F11]*fM[F11] + fM[F21]*fM[F21] );
00711    sz = TMath::Sqrt( fM[F02]*fM[F02] + fM[F12]*fM[F12] + fM[F22]*fM[F22] );
00712 }
00713 
00714 //______________________________________________________________________________
00715 void TEveTrans::SetScale(Double_t sx, Double_t sy, Double_t sz)
00716 {
00717    // Set scaling.
00718 
00719    sx /= TMath::Sqrt( fM[F00]*fM[F00] + fM[F10]*fM[F10] + fM[F20]*fM[F20] );
00720    sy /= TMath::Sqrt( fM[F01]*fM[F01] + fM[F11]*fM[F11] + fM[F21]*fM[F21] );
00721    sz /= TMath::Sqrt( fM[F02]*fM[F02] + fM[F12]*fM[F12] + fM[F22]*fM[F22] );
00722 
00723    fM[F00] *= sx; fM[F10] *= sx; fM[F20] *= sx;
00724    fM[F01] *= sy; fM[F11] *= sy; fM[F21] *= sy;
00725    fM[F02] *= sz; fM[F12] *= sz; fM[F22] *= sz;
00726 }
00727 
00728 //______________________________________________________________________________
00729 void TEveTrans::SetScaleX(Double_t sx)
00730 {
00731    // Change x scaling.
00732 
00733    sx /= TMath::Sqrt( fM[F00]*fM[F00] + fM[F10]*fM[F10] + fM[F20]*fM[F20] );
00734    fM[F00] *= sx; fM[F10] *= sx; fM[F20] *= sx;
00735 }
00736 
00737 //______________________________________________________________________________
00738 void TEveTrans::SetScaleY(Double_t sy)
00739 {
00740    // Change y scaling.
00741 
00742    sy /= TMath::Sqrt( fM[F01]*fM[F01] + fM[F11]*fM[F11] + fM[F21]*fM[F21] );
00743    fM[F01] *= sy; fM[F11] *= sy; fM[F21] *= sy;
00744 }
00745 
00746 //______________________________________________________________________________
00747 void TEveTrans::SetScaleZ(Double_t sz)
00748 {
00749    // Change z scaling.
00750 
00751    sz /= TMath::Sqrt( fM[F02]*fM[F02] + fM[F12]*fM[F12] + fM[F22]*fM[F22] );
00752    fM[F02] *= sz; fM[F12] *= sz; fM[F22] *= sz;
00753 }
00754 
00755 
00756 /******************************************************************************/
00757 // Operations on vectors
00758 /******************************************************************************/
00759 
00760 //______________________________________________________________________________
00761 void TEveTrans::MultiplyIP(TVector3& v, Double_t w) const
00762 {
00763    // Multiply vector in-place.
00764 
00765    v.SetXYZ(fM[F00]*v.x() + fM[F01]*v.y() + fM[F02]*v.z() + fM[F03]*w,
00766             fM[F10]*v.x() + fM[F11]*v.y() + fM[F12]*v.z() + fM[F13]*w,
00767             fM[F20]*v.x() + fM[F21]*v.y() + fM[F22]*v.z() + fM[F23]*w);
00768 }
00769 
00770 //______________________________________________________________________________
00771 void TEveTrans::MultiplyIP(Double_t* v, Double_t w) const
00772 {
00773    // Multiply vector in-place.
00774 
00775    Double_t r[3] = { v[0], v[1], v[2] };
00776    v[0] = fM[F00]*r[0] + fM[F01]*r[1] + fM[F02]*r[2] + fM[F03]*w;
00777    v[1] = fM[F10]*r[0] + fM[F11]*r[1] + fM[F12]*r[2] + fM[F13]*w;
00778    v[2] = fM[F20]*r[0] + fM[F21]*r[1] + fM[F22]*r[2] + fM[F23]*w;
00779 }
00780 
00781 //______________________________________________________________________________
00782 void TEveTrans::MultiplyIP(Float_t* v, Double_t w) const
00783 {
00784    // Multiply vector in-place.
00785 
00786    Double_t r[3] = { v[0], v[1], v[2] };
00787    v[0] = fM[F00]*r[0] + fM[F01]*r[1] + fM[F02]*r[2] + fM[F03]*w;
00788    v[1] = fM[F10]*r[0] + fM[F11]*r[1] + fM[F12]*r[2] + fM[F13]*w;
00789    v[2] = fM[F20]*r[0] + fM[F21]*r[1] + fM[F22]*r[2] + fM[F23]*w;
00790 }
00791 
00792 //______________________________________________________________________________
00793 TVector3 TEveTrans::Multiply(const TVector3& v, Double_t w) const
00794 {
00795    // Multiply vector and return it.
00796 
00797    return TVector3(fM[F00]*v.x() + fM[F01]*v.y() + fM[F02]*v.z() + fM[F03]*w,
00798                    fM[F10]*v.x() + fM[F11]*v.y() + fM[F12]*v.z() + fM[F13]*w,
00799                    fM[F20]*v.x() + fM[F21]*v.y() + fM[F22]*v.z() + fM[F23]*w);
00800 }
00801 
00802 //______________________________________________________________________________
00803 void TEveTrans::Multiply(const Double_t *vin, Double_t* vout, Double_t w) const
00804 {
00805    // Multiply vector and fill output array vout.
00806 
00807    vout[0] = fM[F00]*vin[0] + fM[F01]*vin[1] + fM[F02]*vin[2] + fM[F03]*w;
00808    vout[1] = fM[F10]*vin[0] + fM[F11]*vin[1] + fM[F12]*vin[1] + fM[F13]*w;
00809    vout[2] = fM[F20]*vin[0] + fM[F21]*vin[1] + fM[F22]*vin[1] + fM[F23]*w;
00810 }
00811 
00812 //______________________________________________________________________________
00813 void TEveTrans::RotateIP(TVector3& v) const
00814 {
00815    // Rotate vector in-place. Translation is NOT applied.
00816 
00817    v.SetXYZ(fM[F00]*v.x() + fM[F01]*v.y() + fM[F02]*v.z(),
00818             fM[F10]*v.x() + fM[F11]*v.y() + fM[F12]*v.z(),
00819             fM[F20]*v.x() + fM[F21]*v.y() + fM[F22]*v.z());
00820 }
00821 
00822 //______________________________________________________________________________
00823 void TEveTrans::RotateIP(Double_t* v) const
00824 {
00825    // Rotate vector in-place. Translation is NOT applied.
00826 
00827    Double_t t[3] = { v[0], v[1], v[2] };
00828 
00829    v[0] = fM[F00]*t[0] + fM[F01]*t[1] + fM[F02]*t[2];
00830    v[1] = fM[F10]*t[0] + fM[F11]*t[1] + fM[F12]*t[2];
00831    v[2] = fM[F20]*t[0] + fM[F21]*t[1] + fM[F22]*t[2];
00832 }
00833 
00834 //______________________________________________________________________________
00835 void TEveTrans::RotateIP(Float_t* v) const
00836 {
00837    // Rotate vector in-place. Translation is NOT applied.
00838 
00839    Double_t t[3] = { v[0], v[1], v[2] };
00840 
00841    v[0] = fM[F00]*t[0] + fM[F01]*t[1] + fM[F02]*t[2];
00842    v[1] = fM[F10]*t[0] + fM[F11]*t[1] + fM[F12]*t[2];
00843    v[2] = fM[F20]*t[0] + fM[F21]*t[1] + fM[F22]*t[2];
00844 }
00845 
00846 //______________________________________________________________________________
00847 TVector3 TEveTrans::Rotate(const TVector3& v) const
00848 {
00849    // Rotate vector and return the rotated vector. Translation is NOT applied.
00850 
00851    return TVector3(fM[F00]*v.x() + fM[F01]*v.y() + fM[F02]*v.z(),
00852                    fM[F10]*v.x() + fM[F11]*v.y() + fM[F12]*v.z(),
00853                    fM[F20]*v.x() + fM[F21]*v.y() + fM[F22]*v.z());
00854 }
00855 
00856 /******************************************************************************/
00857 // Normalization, ortogonalization
00858 /******************************************************************************/
00859 
00860 //______________________________________________________________________________
00861 Double_t TEveTrans::Norm3Column(Int_t col)
00862 {
00863    // Norm 3-vector in column col.
00864 
00865    Double_t* c = fM + 4*--col;
00866    const Double_t  l = TMath::Sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
00867    c[0] /= l; c[1] /= l; c[2] /= l;
00868    return l;
00869 }
00870 
00871 //______________________________________________________________________________
00872 Double_t TEveTrans::Orto3Column(Int_t col, Int_t ref)
00873 {
00874    // Orto-norm 3-vector in column col with respect to column ref.
00875 
00876    Double_t* c =  fM + 4*--col;
00877    Double_t* rc = fM + 4*--ref;
00878    const Double_t dp = c[0]*rc[0] + c[1]*rc[1] + c[2]*rc[2];
00879    c[0] -= rc[0]*dp; c[1] -= rc[1]*dp; c[2] -= rc[2]*dp;
00880    return dp;
00881 }
00882 
00883 //______________________________________________________________________________
00884 void TEveTrans::OrtoNorm3()
00885 {
00886    // Orto-norm columns 1 to 3.
00887 
00888    Norm3Column(1);
00889    Orto3Column(2,1); Norm3Column(2);
00890    fM[F02] = fM[F10]*fM[F21] - fM[F11]*fM[F20];
00891    fM[F12] = fM[F20]*fM[F01] - fM[F21]*fM[F00];
00892    fM[F22] = fM[F00]*fM[F11] - fM[F01]*fM[F10];
00893    // Cross-product faster than the following.
00894    // Orto3Column(3,1); Orto3Column(3,2); Norm3Column(3);
00895 }
00896 
00897 /******************************************************************************/
00898 // Inversion
00899 /******************************************************************************/
00900 
00901 //______________________________________________________________________________
00902 Double_t TEveTrans::Invert()
00903 {
00904    // Invert matrix.
00905    // Copied from ROOT's TMatrixFCramerInv.
00906 
00907    static const TEveException eh("TEveTrans::Invert ");
00908 
00909    // Find all NECESSARY 2x2 dets:  (18 of them)
00910    const Double_t det2_12_01 = fM[F10]*fM[F21] - fM[F11]*fM[F20];
00911    const Double_t det2_12_02 = fM[F10]*fM[F22] - fM[F12]*fM[F20];
00912    const Double_t det2_12_03 = fM[F10]*fM[F23] - fM[F13]*fM[F20];
00913    const Double_t det2_12_13 = fM[F11]*fM[F23] - fM[F13]*fM[F21];
00914    const Double_t det2_12_23 = fM[F12]*fM[F23] - fM[F13]*fM[F22];
00915    const Double_t det2_12_12 = fM[F11]*fM[F22] - fM[F12]*fM[F21];
00916    const Double_t det2_13_01 = fM[F10]*fM[F31] - fM[F11]*fM[F30];
00917    const Double_t det2_13_02 = fM[F10]*fM[F32] - fM[F12]*fM[F30];
00918    const Double_t det2_13_03 = fM[F10]*fM[F33] - fM[F13]*fM[F30];
00919    const Double_t det2_13_12 = fM[F11]*fM[F32] - fM[F12]*fM[F31];
00920    const Double_t det2_13_13 = fM[F11]*fM[F33] - fM[F13]*fM[F31];
00921    const Double_t det2_13_23 = fM[F12]*fM[F33] - fM[F13]*fM[F32];
00922    const Double_t det2_23_01 = fM[F20]*fM[F31] - fM[F21]*fM[F30];
00923    const Double_t det2_23_02 = fM[F20]*fM[F32] - fM[F22]*fM[F30];
00924    const Double_t det2_23_03 = fM[F20]*fM[F33] - fM[F23]*fM[F30];
00925    const Double_t det2_23_12 = fM[F21]*fM[F32] - fM[F22]*fM[F31];
00926    const Double_t det2_23_13 = fM[F21]*fM[F33] - fM[F23]*fM[F31];
00927    const Double_t det2_23_23 = fM[F22]*fM[F33] - fM[F23]*fM[F32];
00928 
00929    // Find all NECESSARY 3x3 dets:   (16 of them)
00930    const Double_t det3_012_012 = fM[F00]*det2_12_12 - fM[F01]*det2_12_02 + fM[F02]*det2_12_01;
00931    const Double_t det3_012_013 = fM[F00]*det2_12_13 - fM[F01]*det2_12_03 + fM[F03]*det2_12_01;
00932    const Double_t det3_012_023 = fM[F00]*det2_12_23 - fM[F02]*det2_12_03 + fM[F03]*det2_12_02;
00933    const Double_t det3_012_123 = fM[F01]*det2_12_23 - fM[F02]*det2_12_13 + fM[F03]*det2_12_12;
00934    const Double_t det3_013_012 = fM[F00]*det2_13_12 - fM[F01]*det2_13_02 + fM[F02]*det2_13_01;
00935    const Double_t det3_013_013 = fM[F00]*det2_13_13 - fM[F01]*det2_13_03 + fM[F03]*det2_13_01;
00936    const Double_t det3_013_023 = fM[F00]*det2_13_23 - fM[F02]*det2_13_03 + fM[F03]*det2_13_02;
00937    const Double_t det3_013_123 = fM[F01]*det2_13_23 - fM[F02]*det2_13_13 + fM[F03]*det2_13_12;
00938    const Double_t det3_023_012 = fM[F00]*det2_23_12 - fM[F01]*det2_23_02 + fM[F02]*det2_23_01;
00939    const Double_t det3_023_013 = fM[F00]*det2_23_13 - fM[F01]*det2_23_03 + fM[F03]*det2_23_01;
00940    const Double_t det3_023_023 = fM[F00]*det2_23_23 - fM[F02]*det2_23_03 + fM[F03]*det2_23_02;
00941    const Double_t det3_023_123 = fM[F01]*det2_23_23 - fM[F02]*det2_23_13 + fM[F03]*det2_23_12;
00942    const Double_t det3_123_012 = fM[F10]*det2_23_12 - fM[F11]*det2_23_02 + fM[F12]*det2_23_01;
00943    const Double_t det3_123_013 = fM[F10]*det2_23_13 - fM[F11]*det2_23_03 + fM[F13]*det2_23_01;
00944    const Double_t det3_123_023 = fM[F10]*det2_23_23 - fM[F12]*det2_23_03 + fM[F13]*det2_23_02;
00945    const Double_t det3_123_123 = fM[F11]*det2_23_23 - fM[F12]*det2_23_13 + fM[F13]*det2_23_12;
00946 
00947    // Find the 4x4 det:
00948    const Double_t det = fM[F00]*det3_123_123 - fM[F01]*det3_123_023 +
00949       fM[F02]*det3_123_013 - fM[F03]*det3_123_012;
00950 
00951    if(det == 0) {
00952       throw(eh + "matrix is singular.");
00953    }
00954 
00955    const Double_t oneOverDet = 1.0/det;
00956    const Double_t mn1OverDet = - oneOverDet;
00957 
00958    fM[F00] = det3_123_123 * oneOverDet;
00959    fM[F01] = det3_023_123 * mn1OverDet;
00960    fM[F02] = det3_013_123 * oneOverDet;
00961    fM[F03] = det3_012_123 * mn1OverDet;
00962 
00963    fM[F10] = det3_123_023 * mn1OverDet;
00964    fM[F11] = det3_023_023 * oneOverDet;
00965    fM[F12] = det3_013_023 * mn1OverDet;
00966    fM[F13] = det3_012_023 * oneOverDet;
00967 
00968    fM[F20] = det3_123_013 * oneOverDet;
00969    fM[F21] = det3_023_013 * mn1OverDet;
00970    fM[F22] = det3_013_013 * oneOverDet;
00971    fM[F23] = det3_012_013 * mn1OverDet;
00972 
00973    fM[F30] = det3_123_012 * mn1OverDet;
00974    fM[F31] = det3_023_012 * oneOverDet;
00975    fM[F32] = det3_013_012 * mn1OverDet;
00976    fM[F33] = det3_012_012 * oneOverDet;
00977 
00978    fAsOK = kFALSE;
00979    return det;
00980 }
00981 
00982 /******************************************************************************/
00983 
00984 //______________________________________________________________________________
00985 void TEveTrans::Streamer(TBuffer &R__b)
00986 {
00987    // Stream an object of class TEveTrans.
00988 
00989    if (R__b.IsReading()) {
00990       TEveTrans::Class()->ReadBuffer(R__b, this);
00991       fAsOK = kFALSE;
00992    } else {
00993       TEveTrans::Class()->WriteBuffer(R__b, this);
00994    }
00995 }
00996 
00997 /******************************************************************************/
00998 /******************************************************************************/
00999 
01000 //______________________________________________________________________________
01001 void TEveTrans::Print(Option_t* /*option*/) const
01002 {
01003    // Print in reasonable format.
01004 
01005    const Double_t* row = fM;
01006    for(Int_t i=0; i<4; ++i, ++row)
01007       printf("%8.3f %8.3f %8.3f | %8.3f\n", row[0], row[4], row[8], row[12]);
01008 }
01009 
01010 #include <iomanip>
01011 
01012 //______________________________________________________________________________
01013 ostream& operator<<(ostream& s, const TEveTrans& t)
01014 {
01015    // Print to ostream.
01016 
01017    s.setf(std::ios::fixed, std::ios::floatfield);
01018    s.precision(3);
01019    for(Int_t i=1; i<=4; i++)
01020       for(Int_t j=1; j<=4; j++)
01021          s << t(i,j) << ((j==4) ? "\n" : "\t");
01022    return s;
01023 }
01024 
01025 /******************************************************************************/
01026 // TEveUtil stuff
01027 /******************************************************************************/
01028 
01029 #include "TGeoMatrix.h"
01030 #include "TBuffer3D.h"
01031 
01032 void TEveTrans::SetFrom(Double_t* carr)
01033 {
01034    // Initialize from array.
01035 
01036    fUseTrans = kTRUE;
01037    memcpy(fM, carr, 16*sizeof(Double_t));
01038    fAsOK = kFALSE;
01039 }
01040 
01041 //______________________________________________________________________________
01042 void TEveTrans::SetFrom(const TGeoMatrix& mat)
01043 {
01044    // Initialize from TGeoMatrix.
01045 
01046    fUseTrans = kTRUE;
01047    const Double_t *r = mat.GetRotationMatrix();
01048    const Double_t *t = mat.GetTranslation();
01049    const Double_t *s = mat.GetScale();
01050    Double_t       *m = fM;
01051    m[0] = r[0]*s[0]; m[1] = r[3]*s[0]; m[2] = r[6]*s[0]; m[3] = 0; m += 4;
01052    m[0] = r[1]*s[1]; m[1] = r[4]*s[1]; m[2] = r[7]*s[1]; m[3] = 0; m += 4;
01053    m[0] = r[2]*s[2]; m[1] = r[5]*s[2]; m[2] = r[8]*s[2]; m[3] = 0; m += 4;
01054    m[0] = t[0];      m[1] = t[1];      m[2] = t[2];      m[3] = 1;
01055    fAsOK = kFALSE;
01056 }
01057 
01058 //______________________________________________________________________________
01059 void TEveTrans::SetGeoHMatrix(TGeoHMatrix& mat)
01060 {
01061    // Set TGeoHMatrix mat.
01062 
01063    Double_t *r = mat.GetRotationMatrix();
01064    Double_t *t = mat.GetTranslation();
01065    Double_t *s = mat.GetScale();
01066    if (fUseTrans)
01067    {
01068       mat.SetBit(TGeoMatrix::kGeoGenTrans);
01069       Double_t *m = fM;
01070       GetScale(s[0], s[1], s[2]);
01071       r[0] = m[0]/s[0]; r[3] = m[1]/s[0]; r[6] = m[2]/s[0]; m += 4;
01072       r[1] = m[0]/s[1]; r[4] = m[1]/s[1]; r[7] = m[2]/s[1]; m += 4;
01073       r[2] = m[0]/s[2]; r[5] = m[1]/s[2]; r[8] = m[2]/s[2]; m += 4;
01074       t[0] = m[0];      t[1] = m[1];      t[2] = m[2];
01075    } else {
01076       mat.ResetBit(TGeoMatrix::kGeoGenTrans);
01077       r[0] = 1; r[3] = 0; r[6] = 0;
01078       r[1] = 0; r[4] = 1; r[7] = 0;
01079       r[2] = 0; r[5] = 0; r[8] = 1;
01080       s[0] = s[1] = s[2] = 1;
01081       t[0] = t[1] = t[2] = 0;
01082    }
01083 }
01084 
01085 //______________________________________________________________________________
01086 void TEveTrans::SetBuffer3D(TBuffer3D& buff)
01087 {
01088    // Fill transformation part TBuffer3D core section.
01089 
01090    buff.fLocalFrame = fUseTrans;
01091    if (fUseTrans) {
01092       // In phys-shape ctor the rotation part is transposed, due to
01093       // TGeo's convention for rotation matrix. So we have to transpose
01094       // it here, also.
01095       Double_t *m = buff.fLocalMaster;
01096       m[0]  = fM[0];  m[1]  = fM[4];  m[2]  = fM[8];  m[3]  = fM[3];
01097       m[4]  = fM[1];  m[5]  = fM[5];  m[6]  = fM[9];  m[7]  = fM[7];
01098       m[8]  = fM[2];  m[9]  = fM[6];  m[10] = fM[10]; m[11] = fM[11];
01099       m[12] = fM[12]; m[13] = fM[13]; m[14] = fM[14]; m[15] = fM[15];
01100       // Otherwise this would do:
01101       // memcpy(buff.fLocalMaster, fM, 16*sizeof(Double_t));
01102    }
01103 }
01104 
01105 //______________________________________________________________________________
01106 Bool_t TEveTrans::IsScale(Double_t low, Double_t high) const
01107 {
01108    // Test if the transformation is a scale.
01109    // To be used by ROOT TGLObject descendants that potentially need to
01110    // use GL_NORMALIZE.
01111    // The low/high limits are expected to be squares of acutal limits.
01112    //
01113    // Ideally this should be done by the TGLViewer [but is not].
01114 
01115    if (!fUseTrans) return kFALSE;
01116    Double_t s;
01117    s = fM[F00]*fM[F00] + fM[F10]*fM[F10] + fM[F20]*fM[F20];
01118    if (s < low || s > high) return kTRUE;
01119    s = fM[F01]*fM[F01] + fM[F11]*fM[F11] + fM[F21]*fM[F21];
01120    if (s < low || s > high) return kTRUE;
01121    s = fM[F02]*fM[F02] + fM[F12]*fM[F12] + fM[F22]*fM[F22];
01122    if (s < low || s > high) return kTRUE;
01123    return kFALSE;
01124 }

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