TGeoMatrix.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoMatrix.cxx 36535 2010-11-08 14:41:54Z agheata $
00002 // Author: Andrei Gheata   25/10/01
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 // Author : Andrei Gheata - Wed 24 Oct 2001 09:46:13 AM CEST
00012 
00013 ////////////////////////////////////////////////////////////////////////////////
00014 // Geometrical transformation package.
00015 //
00016 //   All geometrical transformations handled by the modeller are provided as a
00017 // built-in package. This was designed to minimize memory requirements and
00018 // optimize performance of point/vector master-to-local and local-to-master
00019 // computation. We need to have in mind that a transformation in TGeo has 2 
00020 // major use-cases. The first one is for defining the placement of a volume
00021 // with respect to its container reference frame. This frame will be called
00022 // 'master' and the frame of the positioned volume - 'local'. If T is a 
00023 // transformation used for positioning volume daughters, then:
00024 //
00025 //          MASTER = T * LOCAL
00026 //  
00027 //   Therefore a local-to-master conversion will be performed by using T, while
00028 // a master-to-local by using its inverse. The second use case is the computation
00029 // of the global transformation of a given object in the geometry. Since the
00030 // geometry is built as 'volumes-inside-volumes', this global transformation 
00031 // represent the pile-up of all local transformations in the corresponding
00032 // branch. The conversion from the global reference frame and the given object
00033 // is also called master-to-local, but it is handled by the manager class.
00034 //   A general homogenous transformation is defined as a 4x4 matrix embeeding
00035 // a rotation, a translation and a scale. The advantage of this description
00036 // is that each basic transformation can be represented as a homogenous matrix, 
00037 // composition being performed as simple matrix multiplication.
00038 //   Rotation:                      Inverse rotation:
00039 //         r11  r12  r13   0              r11  r21  r31   0
00040 //         r21  r22  r23   0              r12  r22  r32   0
00041 //         r31  r32  r33   0              r13  r23  r33   0
00042 //          0    0    0    1               0    0    0    1
00043 //
00044 //   Translation:                   Inverse translation:
00045 //          1    0    0    tx               1    0    0   -tx
00046 //          0    1    0    ty               0    1    0   -ty
00047 //          0    0    1    tz               0    0    1   -tz
00048 //          0    0    0    1                0    0    0   1
00049 //
00050 //   Scale:                         Inverse scale:
00051 //          sx   0    0    0              1/sx  0    0    0
00052 //          0    sy   0    0               0   1/sy  0    0
00053 //          0    0    sz   0               0    0   1/sz  0
00054 //          0    0    0    1               0    0    0    1
00055 // 
00056 //  where: rij are the 3x3 rotation matrix components, 
00057 //         tx, ty, tz are the translation components
00058 //         sx, sy, sz are arbitrary scale constants on the eacks axis,
00059 //
00060 //   The disadvantage in using this approach is that computation for 4x4 matrices
00061 // is expensive. Even combining two translation would become a multiplication
00062 // of their corresponding matrices, which is quite an undesired effect. On the 
00063 // other hand, it is not a good idea to store a translation as a block of 16
00064 // numbers. We have therefore chosen to implement each basic transformation type 
00065 // as a class deriving from the same basic abstract class and handling its specific
00066 // data and point/vector transformation algorithms.
00067 //
00068 //Begin_Html
00069 /*
00070 <img src="gif/t_transf.jpg">
00071 */
00072 //End_Html
00073 //
00074 // The base class TGeoMatrix defines abstract metods for:
00075 //
00076 // - translation, rotation and scale getters. Every derived class stores only
00077 //   its specific data, e.g. a translation stores an array of 3 doubles and a
00078 //   rotation an array of 9. However, asking which is the rotation array of a
00079 //   TGeoTranslation through the base TGeoMatrix interface is a legal operation.
00080 //   The answer in this case is a pointer to a global constant array representing
00081 //   an identity rotation.
00082 //      Double_t *TGeoMatrix::GetTranslation()
00083 //      Double_t *TGeoMatrix::GetRotation()
00084 //      Double_t *TGeoMatrix::GetScale()
00085 //
00086 // - MasterToLocal() and LocalToMaster() point and vector transformations :
00087 //      void      TGeoMatrix::MasterToLocal(const Double_t *master, Double_t *local)
00088 //      void      TGeoMatrix::LocalToMaster(const Double_t *local, Double_t *master)
00089 //      void      TGeoMatrix::MasterToLocalVect(const Double_t *master, Double_t *local)
00090 //      void      TGeoMatrix::LocalToMasterVect(const Double_t *local, Double_t *master)
00091 //   These allow correct conversion also for reflections.
00092 // - Transformation type getters :
00093 //      Bool_t    TGeoMatrix::IsIdentity()
00094 //      Bool_t    TGeoMatrix::IsTranslation()
00095 //      Bool_t    TGeoMatrix::IsRotation()
00096 //      Bool_t    TGeoMatrix::IsScale()
00097 //      Bool_t    TGeoMatrix::IsCombi() (translation + rotation)
00098 //      Bool_t    TGeoMatrix::IsGeneral() (translation + rotation + scale)
00099 //
00100 //   Combinations of basic transformations are represented by specific classes
00101 // deriving from TGeoMatrix. In order to define a matrix as a combination of several
00102 // others, a special class TGeoHMatrix is provided. Here is an example of matrix
00103 // creation :
00104 //
00105 // Matrix creation example:
00106 //
00107 //   root[0] TGeoRotation r1,r2;
00108 //           r1.SetAngles(90,0,30);        // rotation defined by Euler angles
00109 //           r2.SetAngles(90,90,90,180,0,0); // rotation defined by GEANT3 angles
00110 //           TGeoTranslation t1(-10,10,0);
00111 //           TGeoTranslation t2(10,-10,5);
00112 //           TGeoCombiTrans c1(t1,r1);
00113 //           TGeoCombiTrans c2(t2,r2);
00114 //           TGeoHMatrix h = c1 * c2; // composition is done via TGeoHMatrix class
00115 //   root[7] TGeoHMatrix *ph = new TGeoHMatrix(hm); // this is the one we want to
00116 //                                                // use for positioning a volume
00117 //   root[8] ph->Print();
00118 //           ...
00119 //           pVolume->AddNode(pVolDaughter,id,ph) // now ph is owned by the manager
00120 //
00121 // Rule for matrix creation:
00122 //  - unless explicitly used for positioning nodes (TGeoVolume::AddNode()) all
00123 // matrices deletion have to be managed by users. Matrices passed to geometry
00124 // have to be created by using new() operator and their deletion is done by 
00125 // TGeoManager class.
00126 //
00127 // Available geometrical transformations
00128 //
00129 //   1. TGeoTranslation - represent a (dx,dy,dz) translation. Data members: 
00130 // Double_t fTranslation[3]. Translations can be added/subtracted.
00131 //         TGeoTranslation t1;
00132 //         t1->SetTranslation(-5,10,4);
00133 //         TGeoTranslation *t2 = new TGeoTranslation(4,3,10);
00134 //         t2->Subtract(&t1);
00135 //
00136 //   2. Rotations - represent a pure rotation. Data members: Double_t fRotationMatrix[3*3].
00137 // Rotations can be defined either by Euler angles, either, by GEANT3 angles :
00138 //         TGeoRotation *r1 = new TGeoRotation();
00139 //         r1->SetAngles(phi, theta, psi); // all angles in degrees
00140 //      This represent the composition of : first a rotation about Z axis with
00141 //      angle phi, then a rotation with theta about the rotated X axis, and
00142 //      finally a rotation with psi about the new Z axis.
00143 //          
00144 //         r1->SetAngles(th1,phi1, th2,phi2, th3,phi3)
00145 //      This is a rotation defined in GEANT3 style. Theta and phi are the spherical
00146 //      angles of each axis of the rotated coordinate system with respect to the
00147 //      initial one. This construction allows definition of malformed rotations,
00148 //      e.g. not orthogonal. A check is performed and an error message is issued
00149 //      in this case.
00150 //
00151 //      Specific utilities : determinant, inverse.
00152 //
00153 //   3. Scale transformations - represent a scale shrinking/enlargement. Data
00154 //      members :Double_t fScale[3]. Not fully implemented yet.
00155 //
00156 //   4. Combined transformations - represent a rotation folowed by a translation.
00157 //      Data members: Double_t fTranslation[3], TGeoRotation *fRotation.
00158 //         TGeoRotation *rot = new TGeoRotation("rot",10,20,30);
00159 //         TGeoTranslation trans;
00160 //         ...
00161 //         TGeoCombiTrans *c1 = new TGeoCombiTrans(trans, rot);
00162 //         TGeoCombiTrans *c2 = new TGeoCombiTrans("somename",10,20,30,rot)
00163 //         
00164 //   5. TGeoGenTrans - combined transformations including a scale. Not implemented.
00165 //   6. TGeoIdentity - a generic singleton matrix representing a identity transformation
00166 //       NOTE: identified by the global variable gGeoIdentity.
00167 //  
00168 //     
00169 
00170 #include "Riostream.h"
00171 #include "TObjArray.h"
00172 
00173 #include "TGeoManager.h"
00174 #include "TGeoMatrix.h"
00175 #include "TMath.h"
00176 
00177 TGeoIdentity *gGeoIdentity = 0;
00178 const Int_t kN3 = 3*sizeof(Double_t);
00179 const Int_t kN9 = 9*sizeof(Double_t);
00180 
00181 // statics and globals
00182 
00183 ClassImp(TGeoMatrix)
00184 
00185 //_____________________________________________________________________________
00186 TGeoMatrix::TGeoMatrix()
00187 {
00188 // dummy constructor
00189 }
00190 
00191 //_____________________________________________________________________________
00192 TGeoMatrix::TGeoMatrix(const TGeoMatrix &other)
00193            :TNamed(other)
00194 {
00195 // copy constructor
00196    ResetBit(kGeoRegistered);
00197 }
00198 
00199 //_____________________________________________________________________________
00200 TGeoMatrix::TGeoMatrix(const char *name)
00201            :TNamed(name, "")
00202 {
00203 // Constructor
00204 }
00205 
00206 //_____________________________________________________________________________
00207 TGeoMatrix::~TGeoMatrix()
00208 {
00209 // Destructor
00210    if (IsRegistered() && gGeoManager) {
00211       if (gGeoManager->GetListOfVolumes()) {
00212          gGeoManager->GetListOfMatrices()->Remove(this);
00213          Warning("dtor", "Registered matrix %s was removed", GetName());
00214       }
00215    }
00216 }
00217 
00218 //_____________________________________________________________________________
00219 TGeoMatrix& TGeoMatrix::operator = (const TGeoMatrix &matrix)
00220 {
00221 // Assignment operator
00222    if (&matrix == this) return *this;
00223    Bool_t registered = TestBit(kGeoRegistered);
00224    TNamed::operator=(matrix);
00225    SetBit(kGeoRegistered,registered);
00226    return *this;
00227 }   
00228 
00229 //_____________________________________________________________________________
00230 TGeoMatrix &TGeoMatrix::operator*(const TGeoMatrix &right) const
00231 {
00232 // Multiplication
00233    static TGeoHMatrix h;
00234    h = *this;
00235    h.Multiply(&right);
00236    return h;
00237 }
00238 
00239 //_____________________________________________________________________________
00240 Bool_t TGeoMatrix::operator ==(const TGeoMatrix &other) const
00241 {
00242 // Is-equal operator
00243    if (&other == this) return kTRUE;
00244    Int_t i;
00245    Bool_t tr1 = IsTranslation();
00246    Bool_t tr2 = other.IsTranslation();
00247    if ((tr1 & !tr2) || (tr2 & !tr1)) return kFALSE; 
00248    Bool_t rr1 = IsRotation();
00249    Bool_t rr2 = other.IsRotation();
00250    if ((rr1 & !rr2) || (rr2 & !rr1)) return kFALSE; 
00251 
00252    if (tr1) {
00253       const Double_t *tr = GetTranslation();
00254       const Double_t *otr = other.GetTranslation();
00255       for (i=0; i<3; i++) if (TMath::Abs(tr[i]-otr[i])>1.E-10) return kFALSE;
00256    } 
00257    
00258    if (rr1) {
00259       const Double_t *rot = GetRotationMatrix();
00260       const Double_t *orot = other.GetRotationMatrix();
00261       for (i=0; i<9; i++) if (TMath::Abs(rot[i]-orot[i])>1.E-10) return kFALSE;
00262    }
00263    return kTRUE;
00264 }        
00265 
00266 //_____________________________________________________________________________
00267 Bool_t TGeoMatrix::IsRotAboutZ() const
00268 {
00269 // Returns true if no rotation or the rotation is about Z axis
00270    if (IsIdentity()) return kTRUE;
00271    const Double_t *rot = GetRotationMatrix();
00272    if (TMath::Abs(rot[6])>1E-9) return kFALSE;
00273    if (TMath::Abs(rot[7])>1E-9) return kFALSE;
00274    if ((1.-TMath::Abs(rot[8]))>1E-9) return kFALSE;
00275    return kTRUE;
00276 }   
00277 
00278 //_____________________________________________________________________________
00279 Int_t TGeoMatrix::GetByteCount() const
00280 {
00281 // Get total size in bytes of this
00282    Int_t count = 4+28+strlen(GetName())+strlen(GetTitle()); // fId + TNamed
00283    if (IsTranslation()) count += 12;
00284    if (IsScale()) count += 12;
00285    if (IsCombi() || IsGeneral()) count += 4 + 36;
00286    return count;
00287 }
00288 
00289 //_____________________________________________________________________________
00290 char *TGeoMatrix::GetPointerName() const
00291 {
00292 // Provide a pointer name containing uid.
00293    static TString name;
00294    name = TString::Format("pMatrix%d", GetUniqueID());
00295    return (char*)name.Data();
00296 }    
00297 
00298 //_____________________________________________________________________________
00299 void TGeoMatrix::GetHomogenousMatrix(Double_t *hmat) const
00300 {
00301 // The homogenous matrix associated with the transformation is used for
00302 // piling up's and visualization. A homogenous matrix is a 4*4 array
00303 // containing the translation, the rotation and the scale components
00304 //
00305 //          | R00*sx  R01    R02    dx |
00306 //          | R10    R11*sy  R12    dy |
00307 //          | R20     R21   R22*sz  dz |
00308 //          |  0       0      0      1 |
00309 //
00310 //   where Rij is the rotation matrix, (sx, sy, sz) is the scale 
00311 // transformation and (dx, dy, dz) is the translation.
00312    Double_t *hmatrix = hmat;
00313    const Double_t *mat = GetRotationMatrix();
00314    for (Int_t i=0; i<3; i++) {
00315       memcpy(hmatrix, mat, kN3);
00316       mat     += 3;
00317       hmatrix += 3;
00318       *hmatrix = 0.0;
00319       hmatrix++; 
00320    }
00321    memcpy(hmatrix, GetTranslation(), kN3);
00322    hmatrix = hmat;
00323    if (IsScale()) {
00324       for (Int_t i=0; i<3; i++) {
00325          *hmatrix *= GetScale()[i];
00326          hmatrix  += 5;
00327       }
00328    }
00329 }
00330 
00331 //_____________________________________________________________________________
00332 void TGeoMatrix::LocalToMaster(const Double_t *local, Double_t *master) const
00333 {
00334 // convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
00335    if (IsIdentity()) {
00336       memcpy(master, local, kN3);
00337       return;
00338    }
00339    Int_t i;   
00340    const Double_t *tr = GetTranslation();
00341    if (!IsRotation()) {
00342       for (i=0; i<3; i++) master[i] = tr[i] + local[i];
00343       return;
00344    }   
00345    const Double_t *rot = GetRotationMatrix();
00346    for (i=0; i<3; i++) {
00347       master[i] = tr[i] 
00348                 + local[0]*rot[3*i]
00349                 + local[1]*rot[3*i+1]
00350                 + local[2]*rot[3*i+2];
00351    }
00352 }
00353 
00354 //_____________________________________________________________________________
00355 void TGeoMatrix::LocalToMasterVect(const Double_t *local, Double_t *master) const
00356 {
00357 // convert a vector by multiplying its column vector (x, y, z, 1) to matrix inverse
00358    if (!IsRotation()) {
00359       memcpy(master, local, kN3);
00360       return;
00361    }
00362    const Double_t *rot = GetRotationMatrix();
00363    for (Int_t i=0; i<3; i++) {
00364       master[i] = local[0]*rot[3*i]
00365                 + local[1]*rot[3*i+1]
00366                 + local[2]*rot[3*i+2];
00367    }
00368 }
00369 
00370 //_____________________________________________________________________________
00371 void TGeoMatrix::LocalToMasterBomb(const Double_t *local, Double_t *master) const
00372 {
00373 // convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
00374    if (IsIdentity()) {
00375       memcpy(master, local, kN3);
00376       return;
00377    }   
00378    Int_t i;
00379    const Double_t *tr = GetTranslation();
00380    Double_t bombtr[3];
00381    gGeoManager->BombTranslation(tr, &bombtr[0]);
00382    if (!IsRotation()) {
00383       for (i=0; i<3; i++) master[i] = bombtr[i] + local[i];
00384       return;
00385    }   
00386    const Double_t *rot = GetRotationMatrix();
00387    for (i=0; i<3; i++) {
00388       master[i] = bombtr[i] 
00389                 + local[0]*rot[3*i]
00390                 + local[1]*rot[3*i+1]
00391                 + local[2]*rot[3*i+2];
00392    }
00393 }
00394 
00395 //_____________________________________________________________________________
00396 void TGeoMatrix::MasterToLocal(const Double_t *master, Double_t *local) const
00397 {
00398 // convert a point by multiplying its column vector (x, y, z, 1) to matrix
00399    if (IsIdentity()) {
00400       memcpy(local, master, kN3);
00401       return;
00402    }   
00403    const Double_t *tr  = GetTranslation();
00404    Double_t mt0  = master[0]-tr[0];
00405    Double_t mt1  = master[1]-tr[1];
00406    Double_t mt2  = master[2]-tr[2];
00407    if (!IsRotation()) {
00408       local[0] = mt0;
00409       local[1] = mt1;
00410       local[2] = mt2;
00411       return;
00412    }   
00413    const Double_t *rot = GetRotationMatrix();
00414    local[0] = mt0*rot[0] + mt1*rot[3] + mt2*rot[6];
00415    local[1] = mt0*rot[1] + mt1*rot[4] + mt2*rot[7];
00416    local[2] = mt0*rot[2] + mt1*rot[5] + mt2*rot[8];
00417 }
00418 
00419 //_____________________________________________________________________________
00420 void TGeoMatrix::MasterToLocalVect(const Double_t *master, Double_t *local) const
00421 {
00422 // convert a point by multiplying its column vector (x, y, z, 1) to matrix
00423    if (!IsRotation()) {
00424       memcpy(local, master, kN3);
00425       return;
00426    }   
00427    const Double_t *rot = GetRotationMatrix();
00428    for (Int_t i=0; i<3; i++) {
00429       local[i] = master[0]*rot[i]
00430                + master[1]*rot[i+3]
00431                + master[2]*rot[i+6];
00432    }
00433 }
00434 
00435 //_____________________________________________________________________________
00436 void TGeoMatrix::MasterToLocalBomb(const Double_t *master, Double_t *local) const
00437 {
00438 // convert a point by multiplying its column vector (x, y, z, 1) to matrix
00439    if (IsIdentity()) {
00440       memcpy(local, master, kN3);
00441       return;
00442    }   
00443    const Double_t *tr = GetTranslation();
00444    Double_t bombtr[3];
00445    Int_t i;
00446    gGeoManager->UnbombTranslation(tr, &bombtr[0]);
00447    if (!IsRotation()) {
00448       for (i=0; i<3; i++) local[i] = master[i]-bombtr[i];
00449       return;
00450    }   
00451    const Double_t *rot = GetRotationMatrix();
00452    for (i=0; i<3; i++) {
00453       local[i] = (master[0]-bombtr[0])*rot[i]
00454                + (master[1]-bombtr[1])*rot[i+3]
00455                + (master[2]-bombtr[2])*rot[i+6];
00456    }
00457 }
00458 
00459 //_____________________________________________________________________________
00460 void TGeoMatrix::Normalize(Double_t *vect)
00461 {
00462 // Normalize a vector.
00463    Double_t normfactor = vect[0]*vect[0] + vect[1]*vect[1] + vect[2]*vect[2];
00464    if (normfactor <= 1E-10) return;
00465    normfactor = 1./TMath::Sqrt(normfactor);
00466    vect[0] *= normfactor;
00467    vect[1] *= normfactor;
00468    vect[2] *= normfactor;
00469 }
00470 
00471 //_____________________________________________________________________________
00472 void TGeoMatrix::Print(Option_t *) const
00473 {
00474 // print the matrix in 4x4 format
00475    const Double_t *rot = GetRotationMatrix();
00476    const Double_t *tr  = GetTranslation();
00477    printf("matrix %s - tr=%d  rot=%d  refl=%d  scl=%d\n", GetName(),(Int_t)IsTranslation(),
00478           (Int_t)IsRotation(), (Int_t)IsReflection(), (Int_t)IsScale());
00479    printf("%10.6f%12.6f%12.6f    Tx = %10.6f\n", rot[0], rot[1], rot[2], tr[0]); 
00480    printf("%10.6f%12.6f%12.6f    Ty = %10.6f\n", rot[3], rot[4], rot[5], tr[1]); 
00481    printf("%10.6f%12.6f%12.6f    Tz = %10.6f\n", rot[6], rot[7], rot[8], tr[2]); 
00482    if (IsScale()) {
00483       const Double_t *scl  = GetScale();
00484       printf("Sx=%10.6fSy=%12.6fSz=%12.6f\n", scl[0], scl[1], scl[2]);
00485    }         
00486 }
00487 
00488 //_____________________________________________________________________________
00489 void TGeoMatrix::ReflectX(Bool_t, Bool_t)
00490 {
00491 // Multiply by a reflection respect to YZ.
00492 }
00493 
00494 //_____________________________________________________________________________
00495 void TGeoMatrix::ReflectY(Bool_t, Bool_t)
00496 {
00497 // Multiply by a reflection respect to ZX.
00498 }
00499 
00500 //_____________________________________________________________________________
00501 void TGeoMatrix::ReflectZ(Bool_t, Bool_t)
00502 {
00503 // Multiply by a reflection respect to XY.
00504 }
00505 
00506 //_____________________________________________________________________________
00507 void TGeoMatrix::RegisterYourself()
00508 {
00509 // Register the matrix in the current manager, which will become the owner.
00510    if (!gGeoManager) {
00511       Warning("RegisterYourself", "cannot register without geometry");
00512       return;
00513    }   
00514    if (!IsRegistered()) {
00515       gGeoManager->RegisterMatrix(this); 
00516       SetBit(kGeoRegistered);
00517    }   
00518 }
00519 
00520 //_____________________________________________________________________________
00521 void TGeoMatrix::SetDefaultName()
00522 {
00523 // If no name was supplied in the ctor, the type of transformation is checked.
00524 // A letter will be prepended to the name :
00525 //   t - translation
00526 //   r - rotation
00527 //   s - scale
00528 //   c - combi (translation + rotation)
00529 //   g - general (tr+rot+scale)
00530 // The index of the transformation in gGeoManager list of transformations will
00531 // be appended.
00532    if (!gGeoManager) return;
00533    if (strlen(GetName())) return;
00534    char type = 'n';
00535    if (IsTranslation()) type = 't'; 
00536    if (IsRotation()) type = 'r';
00537    if (IsScale()) type = 's';
00538    if (IsCombi()) type = 'c';
00539    if (IsGeneral()) type = 'g';
00540    TObjArray *matrices = gGeoManager->GetListOfMatrices();
00541    Int_t index = 0;
00542    if (matrices) index =matrices->GetEntriesFast() - 1;
00543    TString name = TString::Format("%c%d", type, index);
00544    SetName(name);
00545 }
00546 //=============================================================================
00547 
00548 ClassImp(TGeoTranslation)
00549 
00550 //_____________________________________________________________________________
00551 TGeoTranslation::TGeoTranslation()
00552 {
00553 // Default constructor
00554    for (Int_t i=0; i<3; i++) fTranslation[i] = 0;
00555 }
00556 
00557 //_____________________________________________________________________________
00558 TGeoTranslation::TGeoTranslation(const TGeoTranslation &other)
00559                 :TGeoMatrix(other)
00560 {
00561 // Copy ctor.
00562    SetTranslation(other);
00563 }
00564 
00565 //_____________________________________________________________________________
00566 TGeoTranslation::TGeoTranslation(const TGeoMatrix &other)
00567                 :TGeoMatrix(other)
00568 {
00569 // Ctor. based on a general matrix
00570    SetTranslation(other);
00571 }
00572 
00573 //_____________________________________________________________________________
00574 TGeoTranslation::TGeoTranslation(Double_t dx, Double_t dy, Double_t dz)
00575                 :TGeoMatrix("")
00576 {
00577 // Default constructor defining the translation
00578    if (dx || dy || dz) SetBit(kGeoTranslation);
00579    SetTranslation(dx, dy, dz);
00580 }
00581 
00582 //_____________________________________________________________________________
00583 TGeoTranslation::TGeoTranslation(const char *name, Double_t dx, Double_t dy, Double_t dz)
00584                 :TGeoMatrix(name)
00585 {
00586 // Default constructor defining the translation
00587    if (dx || dy || dz) SetBit(kGeoTranslation);
00588    SetTranslation(dx, dy, dz);
00589 }
00590 
00591 //_____________________________________________________________________________
00592 TGeoTranslation& TGeoTranslation::operator = (const TGeoMatrix &matrix)
00593 {
00594 // Assignment from a general matrix
00595    if (&matrix == this) return *this;
00596    TGeoMatrix::operator=(matrix);
00597    SetTranslation(matrix);
00598    return *this;
00599 }   
00600 
00601 //_____________________________________________________________________________
00602 TGeoMatrix& TGeoTranslation::Inverse() const
00603 {
00604 // Return a temporary inverse of this.
00605    static TGeoHMatrix h;
00606    h = *this;
00607    Double_t tr[3];
00608    tr[0] = -fTranslation[0];
00609    tr[1] = -fTranslation[1];
00610    tr[2] = -fTranslation[2];
00611    h.SetTranslation(tr);
00612    return h;
00613 }   
00614 
00615 //_____________________________________________________________________________
00616 void TGeoTranslation::Add(const TGeoTranslation *other)
00617 {
00618 // Adding a translation to this one
00619    const Double_t *trans = other->GetTranslation();
00620    for (Int_t i=0; i<3; i++) 
00621       fTranslation[i] += trans[i];
00622 }
00623 
00624 //_____________________________________________________________________________
00625 TGeoMatrix *TGeoTranslation::MakeClone() const
00626 {
00627 // Make a clone of this matrix.
00628    TGeoMatrix *matrix = new TGeoTranslation(*this);
00629    return matrix;
00630 }
00631 
00632 //_____________________________________________________________________________
00633 void TGeoTranslation::RotateX(Double_t /*angle*/)
00634 {
00635 // Rotate about X axis of the master frame with angle expressed in degrees.
00636    Warning("RotateX", "Not implemented. Use TGeoCombiTrans instead");
00637 }
00638 
00639 //_____________________________________________________________________________
00640 void TGeoTranslation::RotateY(Double_t /*angle*/)
00641 {
00642 // Rotate about Y axis of the master frame with angle expressed in degrees.
00643    Warning("RotateY", "Not implemented. Use TGeoCombiTrans instead");
00644 }
00645 
00646 //_____________________________________________________________________________
00647 void TGeoTranslation::RotateZ(Double_t /*angle*/)
00648 {
00649 // Rotate about Z axis of the master frame with angle expressed in degrees.
00650    Warning("RotateZ", "Not implemented. Use TGeoCombiTrans instead");
00651 }
00652 
00653 //_____________________________________________________________________________
00654 void TGeoTranslation::Subtract(const TGeoTranslation *other)
00655 {
00656 // Subtracting a translation from this one
00657    const Double_t *trans = other->GetTranslation();
00658    for (Int_t i=0; i<3; i++) 
00659       fTranslation[i] -= trans[i];
00660 }
00661 
00662 //_____________________________________________________________________________
00663 void TGeoTranslation::SetTranslation(Double_t dx, Double_t dy, Double_t dz)
00664 {
00665 // Set translation components
00666    fTranslation[0] = dx;
00667    fTranslation[1] = dy;
00668    fTranslation[2] = dz;
00669    if (dx || dy || dz) SetBit(kGeoTranslation);
00670    else                ResetBit(kGeoTranslation);
00671 }
00672 
00673 //_____________________________________________________________________________
00674 void TGeoTranslation::SetTranslation(const TGeoMatrix &other)
00675 {
00676 // Set translation components
00677    SetBit(kGeoTranslation, other.IsTranslation());
00678    const Double_t *transl = other.GetTranslation();
00679    memcpy(fTranslation, transl, kN3);
00680 }
00681 
00682 //_____________________________________________________________________________
00683 void TGeoTranslation::LocalToMaster(const Double_t *local, Double_t *master) const
00684 {
00685 // convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
00686    const Double_t *tr = GetTranslation();
00687    for (Int_t i=0; i<3; i++) 
00688       master[i] = tr[i] + local[i]; 
00689 }
00690 
00691 //_____________________________________________________________________________
00692 void TGeoTranslation::LocalToMasterVect(const Double_t *local, Double_t *master) const
00693 {
00694 // convert a vector to MARS
00695    memcpy(master, local, kN3);
00696 }
00697 
00698 //_____________________________________________________________________________
00699 void TGeoTranslation::LocalToMasterBomb(const Double_t *local, Double_t *master) const
00700 {
00701 // convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
00702    const Double_t *tr = GetTranslation();
00703    Double_t bombtr[3];
00704    gGeoManager->BombTranslation(tr, &bombtr[0]);
00705    for (Int_t i=0; i<3; i++) 
00706       master[i] = bombtr[i] + local[i]; 
00707 }
00708 
00709 //_____________________________________________________________________________
00710 void TGeoTranslation::MasterToLocal(const Double_t *master, Double_t *local) const
00711 {
00712 // convert a point by multiplying its column vector (x, y, z, 1) to matrix
00713    const Double_t *tr = GetTranslation();
00714    for (Int_t i=0; i<3; i++) 
00715       local[i] =  master[i]-tr[i];
00716 }
00717 
00718 //_____________________________________________________________________________
00719 void TGeoTranslation::MasterToLocalVect(const Double_t *master, Double_t *local) const
00720 {
00721 // convert a vector from MARS to local
00722    memcpy(local, master, kN3);
00723 }
00724 
00725 //_____________________________________________________________________________
00726 void TGeoTranslation::MasterToLocalBomb(const Double_t *master, Double_t *local) const
00727 {
00728 // convert a point by multiplying its column vector (x, y, z, 1) to matrix
00729    const Double_t *tr = GetTranslation();
00730    Double_t bombtr[3];
00731    gGeoManager->UnbombTranslation(tr, &bombtr[0]);
00732    for (Int_t i=0; i<3; i++) 
00733       local[i] =  master[i]-bombtr[i];
00734 }
00735 
00736 //_____________________________________________________________________________
00737 void TGeoTranslation::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
00738 {
00739 // Save a primitive as a C++ statement(s) on output stream "out".
00740    if (TestBit(kGeoSavePrimitive)) return;
00741    out << "   // Translation: " << GetName() << endl;
00742    out << "   dx = " << fTranslation[0] << ";" << endl;
00743    out << "   dy = " << fTranslation[1] << ";" << endl;
00744    out << "   dz = " << fTranslation[2] << ";" << endl;
00745    out << "   TGeoTranslation *" << GetPointerName() << " = new TGeoTranslation(\"" << GetName() << "\",dx,dy,dz);" << endl;
00746    TObject::SetBit(kGeoSavePrimitive);
00747 }
00748 
00749 //=============================================================================
00750 
00751 ClassImp(TGeoRotation)
00752 
00753 //_____________________________________________________________________________
00754 TGeoRotation::TGeoRotation()
00755 {
00756 // Default constructor.
00757    for (Int_t i=0; i<9; i++) {
00758       if (i%4) fRotationMatrix[i] = 0;
00759       else fRotationMatrix[i] = 1.0;
00760    }
00761 }
00762 
00763 //_____________________________________________________________________________
00764 TGeoRotation::TGeoRotation(const TGeoRotation &other)
00765              :TGeoMatrix(other)
00766 {
00767 // Copy ctor.
00768    SetRotation(other);
00769 }   
00770 
00771 //_____________________________________________________________________________
00772 TGeoRotation::TGeoRotation(const TGeoMatrix &other)
00773              :TGeoMatrix(other)
00774 {
00775 // Copy ctor.
00776    SetRotation(other);
00777 }   
00778 
00779 //_____________________________________________________________________________
00780 TGeoRotation::TGeoRotation(const char *name)
00781              :TGeoMatrix(name)
00782 {
00783 // Named rotation constructor
00784    for (Int_t i=0; i<9; i++) {
00785       if (i%4) fRotationMatrix[i] = 0;
00786       else fRotationMatrix[i] = 1.0;
00787    }
00788 }
00789 
00790 //_____________________________________________________________________________
00791 TGeoRotation::TGeoRotation(const char *name, Double_t phi, Double_t theta, Double_t psi)
00792              :TGeoMatrix(name)
00793 {
00794 // Default rotation constructor with Euler angles. Phi is the rotation angle about
00795 // Z axis  and is done first, theta is the rotation about new Y and is done
00796 // second, psi is the rotation angle about new Z and is done third. All angles are in
00797 // degrees.
00798    SetAngles(phi, theta, psi);
00799 }
00800 
00801 //_____________________________________________________________________________
00802 TGeoRotation::TGeoRotation(const char *name, Double_t theta1, Double_t phi1, Double_t theta2, Double_t phi2,
00803                            Double_t theta3, Double_t phi3)
00804              :TGeoMatrix(name)
00805 {
00806 // Rotation constructor a la GEANT3. Angles theta(i), phi(i) are the polar and azimuthal
00807 // angles of the (i) axis of the rotated system with respect to the initial non-rotated
00808 // system.
00809 //   Example : the identity matrix (no rotation) is composed by
00810 //      theta1=90, phi1=0, theta2=90, phi2=90, theta3=0, phi3=0
00811 //   SetBit(kGeoRotation);
00812    SetAngles(theta1, phi1, theta2, phi2, theta3, phi3);
00813 }
00814 
00815 //_____________________________________________________________________________
00816 TGeoRotation& TGeoRotation::operator = (const TGeoMatrix &other)
00817 {
00818 // Assignment from a general matrix
00819    if (&other == this) return *this;
00820    TGeoMatrix::operator=(other);
00821    SetRotation(other);
00822    return *this;
00823 }
00824  
00825 //_____________________________________________________________________________
00826 TGeoMatrix& TGeoRotation::Inverse() const
00827 {
00828 // Return a temporary inverse of this.
00829    static TGeoHMatrix h;
00830    h = *this;
00831    Double_t newrot[9];
00832    newrot[0] = fRotationMatrix[0];
00833    newrot[1] = fRotationMatrix[3];
00834    newrot[2] = fRotationMatrix[6];
00835    newrot[3] = fRotationMatrix[1];
00836    newrot[4] = fRotationMatrix[4];
00837    newrot[5] = fRotationMatrix[7];
00838    newrot[6] = fRotationMatrix[2];
00839    newrot[7] = fRotationMatrix[5];
00840    newrot[8] = fRotationMatrix[8];
00841    h.SetRotation(newrot);
00842    return h;
00843 }   
00844 
00845 //_____________________________________________________________________________
00846 Bool_t TGeoRotation::IsValid() const
00847 {
00848 // Perform orthogonality test for rotation.
00849    const Double_t *r = fRotationMatrix;
00850    Double_t cij;
00851    for (Int_t i=0; i<2; i++) {
00852       for (Int_t j=i+1; j<3; j++) {
00853          // check columns
00854          cij = TMath::Abs(r[i]*r[j]+r[i+3]*r[j+3]+r[i+6]*r[j+6]);
00855          if (cij>1E-4) return kFALSE;
00856          // check rows
00857          cij = TMath::Abs(r[3*i]*r[3*j]+r[3*i+1]*r[3*j+1]+r[3*i+2]*r[3*j+2]);
00858          if (cij>1E-4) return kFALSE;
00859       }
00860    }
00861    return kTRUE;   
00862 }
00863 
00864 //_____________________________________________________________________________
00865 void TGeoRotation::Clear(Option_t *)
00866 {
00867 // reset data members
00868    memcpy(fRotationMatrix,kIdentityMatrix,kN9);
00869    ResetBit(kGeoRotation);
00870 }
00871 
00872 //_____________________________________________________________________________
00873 void TGeoRotation::FastRotZ(Double_t *sincos)
00874 {
00875 // Perform a rotation about Z having the sine/cosine of the rotation angle.
00876    fRotationMatrix[0] = sincos[1];
00877    fRotationMatrix[1] = -sincos[0];
00878    fRotationMatrix[3] = sincos[0];
00879    fRotationMatrix[4] = sincos[1];
00880    SetBit(kGeoRotation);
00881 }
00882 
00883 //_____________________________________________________________________________
00884 Double_t TGeoRotation::GetPhiRotation(Bool_t fixX) const
00885 {
00886 //--- Returns rotation angle about Z axis in degrees. If the rotation is a pure
00887 //    rotation about Z, fixX parameter does not matter, otherwise its meaning is:
00888 //    - fixX = true  : result is the phi angle of the projection of the rotated X axis in the un-rotated XY
00889 //    - fixX = false : result is the phi angle of the projection of the rotated Y axis - 90 degrees
00890    Double_t phi;
00891    if (fixX) phi = 180.*TMath::ATan2(-fRotationMatrix[1],fRotationMatrix[4])/TMath::Pi();
00892    else      phi = 180.*TMath::ATan2(fRotationMatrix[3], fRotationMatrix[0])/TMath::Pi();
00893    return phi;
00894 }   
00895 
00896 //_____________________________________________________________________________
00897 void TGeoRotation::LocalToMaster(const Double_t *local, Double_t *master) const
00898 {
00899 // convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
00900    const Double_t *rot = GetRotationMatrix();
00901    for (Int_t i=0; i<3; i++) {
00902       master[i] = local[0]*rot[3*i]
00903                 + local[1]*rot[3*i+1]
00904                 + local[2]*rot[3*i+2];
00905    }
00906 }
00907 
00908 //_____________________________________________________________________________
00909 void TGeoRotation::MasterToLocal(const Double_t *master, Double_t *local) const
00910 {
00911 // convert a point by multiplying its column vector (x, y, z, 1) to matrix
00912    const Double_t *rot = GetRotationMatrix();
00913    for (Int_t i=0; i<3; i++) {
00914       local[i] = master[0]*rot[i]
00915                + master[1]*rot[i+3]
00916                + master[2]*rot[i+6];
00917    }
00918 }
00919 
00920 //_____________________________________________________________________________
00921 TGeoMatrix *TGeoRotation::MakeClone() const
00922 {
00923 // Make a clone of this matrix.
00924    TGeoMatrix *matrix = new TGeoRotation(*this);
00925    return matrix;
00926 }
00927 
00928 //_____________________________________________________________________________
00929 void TGeoRotation::RotateX(Double_t angle)
00930 {
00931 // Rotate about X axis of the master frame with angle expressed in degrees.
00932    SetBit(kGeoRotation);
00933    Double_t phi = angle*TMath::DegToRad();
00934    Double_t c = TMath::Cos(phi);
00935    Double_t s = TMath::Sin(phi);
00936    Double_t v[9];
00937    v[0] = fRotationMatrix[0];
00938    v[1] = fRotationMatrix[1];
00939    v[2] = fRotationMatrix[2];
00940    v[3] = c*fRotationMatrix[3]-s*fRotationMatrix[6];
00941    v[4] = c*fRotationMatrix[4]-s*fRotationMatrix[7];
00942    v[5] = c*fRotationMatrix[5]-s*fRotationMatrix[8];
00943    v[6] = s*fRotationMatrix[3]+c*fRotationMatrix[6];
00944    v[7] = s*fRotationMatrix[4]+c*fRotationMatrix[7];
00945    v[8] = s*fRotationMatrix[5]+c*fRotationMatrix[8];
00946    
00947    memcpy(fRotationMatrix, v, kN9);
00948 }
00949 
00950 //_____________________________________________________________________________
00951 void TGeoRotation::RotateY(Double_t angle)
00952 {
00953 // Rotate about Y axis of the master frame with angle expressed in degrees.
00954    SetBit(kGeoRotation);
00955    Double_t phi = angle*TMath::DegToRad();
00956    Double_t c = TMath::Cos(phi);
00957    Double_t s = TMath::Sin(phi);
00958    Double_t v[9];
00959    v[0] = c*fRotationMatrix[0]+s*fRotationMatrix[6];
00960    v[1] = c*fRotationMatrix[1]+s*fRotationMatrix[7];
00961    v[2] = c*fRotationMatrix[2]+s*fRotationMatrix[8];
00962    v[3] = fRotationMatrix[3];
00963    v[4] = fRotationMatrix[4];
00964    v[5] = fRotationMatrix[5];
00965    v[6] = -s*fRotationMatrix[0]+c*fRotationMatrix[6];
00966    v[7] = -s*fRotationMatrix[1]+c*fRotationMatrix[7];
00967    v[8] = -s*fRotationMatrix[2]+c*fRotationMatrix[8];
00968    
00969    memcpy(fRotationMatrix, v, kN9);
00970 }
00971 
00972 //_____________________________________________________________________________
00973 void TGeoRotation::RotateZ(Double_t angle)
00974 {
00975 // Rotate about Z axis of the master frame with angle expressed in degrees.
00976    SetBit(kGeoRotation);
00977    Double_t phi = angle*TMath::DegToRad();
00978    Double_t c = TMath::Cos(phi);
00979    Double_t s = TMath::Sin(phi);
00980    Double_t v[9];
00981    v[0] = c*fRotationMatrix[0]-s*fRotationMatrix[3];
00982    v[1] = c*fRotationMatrix[1]-s*fRotationMatrix[4];
00983    v[2] = c*fRotationMatrix[2]-s*fRotationMatrix[5];
00984    v[3] = s*fRotationMatrix[0]+c*fRotationMatrix[3];
00985    v[4] = s*fRotationMatrix[1]+c*fRotationMatrix[4];
00986    v[5] = s*fRotationMatrix[2]+c*fRotationMatrix[5];
00987    v[6] = fRotationMatrix[6];
00988    v[7] = fRotationMatrix[7];
00989    v[8] = fRotationMatrix[8];
00990    
00991    memcpy(&fRotationMatrix[0],v,kN9);
00992 }
00993 
00994 //_____________________________________________________________________________
00995 void TGeoRotation::ReflectX(Bool_t leftside, Bool_t)
00996 {
00997 // Multiply by a reflection respect to YZ.
00998    if (leftside) {
00999       fRotationMatrix[0]=-fRotationMatrix[0];
01000       fRotationMatrix[1]=-fRotationMatrix[1];
01001       fRotationMatrix[2]=-fRotationMatrix[2];
01002    } else {
01003       fRotationMatrix[0]=-fRotationMatrix[0];
01004       fRotationMatrix[3]=-fRotationMatrix[3];
01005       fRotationMatrix[6]=-fRotationMatrix[6];
01006    }   
01007    SetBit(kGeoRotation);
01008    SetBit(kGeoReflection, !IsReflection());
01009 }      
01010 
01011 //_____________________________________________________________________________
01012 void TGeoRotation::ReflectY(Bool_t leftside, Bool_t)
01013 {
01014 // Multiply by a reflection respect to ZX.
01015    if (leftside) {
01016       fRotationMatrix[3]=-fRotationMatrix[3];
01017       fRotationMatrix[4]=-fRotationMatrix[4];
01018       fRotationMatrix[5]=-fRotationMatrix[5];
01019    } else {
01020       fRotationMatrix[1]=-fRotationMatrix[1];
01021       fRotationMatrix[4]=-fRotationMatrix[4];
01022       fRotationMatrix[7]=-fRotationMatrix[7];
01023    }   
01024    SetBit(kGeoRotation);
01025    SetBit(kGeoReflection, !IsReflection());
01026 }      
01027 
01028 //_____________________________________________________________________________
01029 void TGeoRotation::ReflectZ(Bool_t leftside, Bool_t)
01030 {
01031 // Multiply by a reflection respect to XY.
01032    if (leftside) {
01033       fRotationMatrix[6]=-fRotationMatrix[6];
01034       fRotationMatrix[7]=-fRotationMatrix[7];
01035       fRotationMatrix[8]=-fRotationMatrix[8];
01036    } else {
01037       fRotationMatrix[2]=-fRotationMatrix[2];
01038       fRotationMatrix[5]=-fRotationMatrix[5];
01039       fRotationMatrix[8]=-fRotationMatrix[8];
01040    }   
01041    SetBit(kGeoRotation);
01042    SetBit(kGeoReflection, !IsReflection());
01043 }      
01044 
01045 //_____________________________________________________________________________
01046 void TGeoRotation::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
01047 {
01048 // Save a primitive as a C++ statement(s) on output stream "out".
01049    if (TestBit(kGeoSavePrimitive)) return;
01050    out << "   // Rotation: " << GetName() << endl;
01051    Double_t th1,ph1,th2,ph2,th3,ph3;
01052    GetAngles(th1,ph1,th2,ph2,th3,ph3);
01053    out << "   thx = " << th1 << ";    phx = " << ph1 << ";" << endl;
01054    out << "   thy = " << th2 << ";    phy = " << ph2 << ";" << endl;
01055    out << "   thz = " << th3 << ";    phz = " << ph3 << ";" << endl;
01056    out << "   TGeoRotation *" << GetPointerName() << " = new TGeoRotation(\"" << GetName() << "\",thx,phx,thy,phy,thz,phz);" << endl;
01057    TObject::SetBit(kGeoSavePrimitive);
01058 }
01059 
01060 //_____________________________________________________________________________
01061 void TGeoRotation::SetRotation(const TGeoMatrix &other)
01062 {
01063 // Copy rotation elements from other rotation matrix.
01064    SetBit(kGeoRotation, other.IsRotation());
01065    const Double_t *rot = other.GetRotationMatrix();
01066    SetMatrix(rot);
01067 }
01068 
01069 //_____________________________________________________________________________
01070 void TGeoRotation::SetAngles(Double_t phi, Double_t theta, Double_t psi)
01071 {
01072 // Set matrix elements according to Euler angles
01073    Double_t degrad = TMath::Pi()/180.;
01074    Double_t sinphi = TMath::Sin(degrad*phi);
01075    Double_t cosphi = TMath::Cos(degrad*phi);
01076    Double_t sinthe = TMath::Sin(degrad*theta);
01077    Double_t costhe = TMath::Cos(degrad*theta);
01078    Double_t sinpsi = TMath::Sin(degrad*psi);
01079    Double_t cospsi = TMath::Cos(degrad*psi);
01080 
01081    fRotationMatrix[0] =  cospsi*cosphi - costhe*sinphi*sinpsi;
01082    fRotationMatrix[1] = -sinpsi*cosphi - costhe*sinphi*cospsi;
01083    fRotationMatrix[2] =  sinthe*sinphi;
01084    fRotationMatrix[3] =  cospsi*sinphi + costhe*cosphi*sinpsi;
01085    fRotationMatrix[4] = -sinpsi*sinphi + costhe*cosphi*cospsi;
01086    fRotationMatrix[5] = -sinthe*cosphi;
01087    fRotationMatrix[6] =  sinpsi*sinthe;
01088    fRotationMatrix[7] =  cospsi*sinthe;
01089    fRotationMatrix[8] =  costhe;
01090 
01091    if (!IsValid()) Error("SetAngles", "invalid rotation (Euler angles : phi=%f theta=%f psi=%f)",phi,theta,psi);
01092    CheckMatrix();
01093 }
01094 
01095 //_____________________________________________________________________________
01096 void TGeoRotation::SetAngles(Double_t theta1, Double_t phi1, Double_t theta2, Double_t phi2,
01097                              Double_t theta3, Double_t phi3)
01098 {
01099 // Set matrix elements in the GEANT3 way
01100    Double_t degrad = TMath::Pi()/180.;
01101    fRotationMatrix[0] = TMath::Cos(degrad*phi1)*TMath::Sin(degrad*theta1);
01102    fRotationMatrix[3] = TMath::Sin(degrad*phi1)*TMath::Sin(degrad*theta1);
01103    fRotationMatrix[6] = TMath::Cos(degrad*theta1);
01104    fRotationMatrix[1] = TMath::Cos(degrad*phi2)*TMath::Sin(degrad*theta2);
01105    fRotationMatrix[4] = TMath::Sin(degrad*phi2)*TMath::Sin(degrad*theta2);
01106    fRotationMatrix[7] = TMath::Cos(degrad*theta2);
01107    fRotationMatrix[2] = TMath::Cos(degrad*phi3)*TMath::Sin(degrad*theta3);
01108    fRotationMatrix[5] = TMath::Sin(degrad*phi3)*TMath::Sin(degrad*theta3);
01109    fRotationMatrix[8] = TMath::Cos(degrad*theta3);
01110    // do the trick to eliminate most of the floating point errors
01111    for (Int_t i=0; i<9; i++) {
01112       if (TMath::Abs(fRotationMatrix[i])<1E-15) fRotationMatrix[i] = 0;
01113       if (TMath::Abs(fRotationMatrix[i]-1)<1E-15) fRotationMatrix[i] = 1;
01114       if (TMath::Abs(fRotationMatrix[i]+1)<1E-15) fRotationMatrix[i] = -1;
01115    }   
01116    if (!IsValid()) Error("SetAngles", "invalid rotation (G3 angles, th1=%f phi1=%f, th2=%f ph2=%f, th3=%f phi3=%f)",
01117                           theta1,phi1,theta2,phi2,theta3,phi3);
01118    CheckMatrix();
01119 }
01120 
01121 //_____________________________________________________________________________
01122 void TGeoRotation::GetAngles(Double_t &theta1, Double_t &phi1, Double_t &theta2, Double_t &phi2,
01123                              Double_t &theta3, Double_t &phi3) const
01124 {
01125 // Retreive rotation angles
01126    Double_t raddeg = 180./TMath::Pi();
01127    theta1 = raddeg*TMath::ACos(fRotationMatrix[6]);
01128    theta2 = raddeg*TMath::ACos(fRotationMatrix[7]);
01129    theta3 = raddeg*TMath::ACos(fRotationMatrix[8]);
01130    if (TMath::Abs(fRotationMatrix[0])<1E-6 && TMath::Abs(fRotationMatrix[3])<1E-6) phi1=0.;
01131    else phi1 = raddeg*TMath::ATan2(fRotationMatrix[3],fRotationMatrix[0]);
01132    if (phi1<0) phi1+=360.;
01133    if (TMath::Abs(fRotationMatrix[1])<1E-6 && TMath::Abs(fRotationMatrix[4])<1E-6) phi2=0.;
01134    else phi2 = raddeg*TMath::ATan2(fRotationMatrix[4],fRotationMatrix[1]);
01135    if (phi2<0) phi2+=360.;
01136    if (TMath::Abs(fRotationMatrix[2])<1E-6 && TMath::Abs(fRotationMatrix[5])<1E-6) phi3=0.;
01137    else phi3 = raddeg*TMath::ATan2(fRotationMatrix[5],fRotationMatrix[2]);
01138    if (phi3<0) phi3+=360.;
01139 }
01140 
01141 //_____________________________________________________________________________
01142 void TGeoRotation::GetAngles(Double_t &phi, Double_t &theta, Double_t &psi) const
01143 {
01144 // Retreive Euler angles.
01145    const Double_t *m = fRotationMatrix;
01146    // Check if theta is 0 or 180.
01147    if (TMath::Abs(1.-TMath::Abs(m[8]))<1.e-9) {      
01148       theta = TMath::ACos(m[8])*TMath::RadToDeg();
01149       phi = TMath::ATan2(-m[8]*m[1],m[0])*TMath::RadToDeg();
01150       psi = 0.; // convention, phi+psi matters
01151       return;
01152    }
01153    // sin(theta) != 0
01154    phi = TMath::ATan2(m[2],-m[5]);
01155    Double_t sphi = TMath::Sin(phi);
01156    if (TMath::Abs(sphi)<1.e-9) theta = -TMath::ASin(m[5]/TMath::Cos(phi))*TMath::RadToDeg();
01157    else theta = TMath::ASin(m[2]/sphi)*TMath::RadToDeg();
01158    phi *= TMath::RadToDeg();      
01159    psi = TMath::ATan2(m[6],m[7])*TMath::RadToDeg();
01160 }   
01161 
01162 //_____________________________________________________________________________
01163 Double_t TGeoRotation::Determinant() const
01164 {
01165 // computes determinant of the rotation matrix
01166    Double_t 
01167    det = fRotationMatrix[0]*fRotationMatrix[4]*fRotationMatrix[8] + 
01168          fRotationMatrix[3]*fRotationMatrix[7]*fRotationMatrix[2] +
01169          fRotationMatrix[6]*fRotationMatrix[1]*fRotationMatrix[5] - 
01170          fRotationMatrix[2]*fRotationMatrix[4]*fRotationMatrix[6] -
01171          fRotationMatrix[5]*fRotationMatrix[7]*fRotationMatrix[0] - 
01172          fRotationMatrix[8]*fRotationMatrix[1]*fRotationMatrix[3];
01173    return det;
01174 }
01175 
01176 //_____________________________________________________________________________
01177 void TGeoRotation::CheckMatrix()
01178 {
01179    // performes an orthogonality check and finds if the matrix is a reflection
01180 //   Warning("CheckMatrix", "orthogonality check not performed yet");
01181    if (Determinant() < 0) SetBit(kGeoReflection);
01182    Double_t dd = fRotationMatrix[0] + fRotationMatrix[4] + fRotationMatrix[8] - 3.;
01183    if (TMath::Abs(dd) < 1.E-12) ResetBit(kGeoRotation);
01184    else                         SetBit(kGeoRotation);
01185 }
01186 
01187 //_____________________________________________________________________________
01188 void TGeoRotation::GetInverse(Double_t *invmat) const
01189 {
01190 // Get the inverse rotation matrix (which is simply the transpose)
01191    if (!invmat) {
01192       Error("GetInverse", "no place to store the inverse matrix");
01193       return;
01194    }
01195    for (Int_t i=0; i<3; i++) {
01196       for (Int_t j=0; j<3; j++) {   
01197          invmat[3*i+j] = fRotationMatrix[3*j+i];
01198       }
01199    }
01200 }
01201 
01202 //_____________________________________________________________________________
01203 void TGeoRotation::MultiplyBy(TGeoRotation *rot, Bool_t after)
01204 {
01205 // Multiply this rotation with the one specified by ROT.
01206 // -   after=TRUE (default): THIS*ROT
01207 // -   after=FALSE         : ROT*THIS
01208    const Double_t *matleft, *matright;
01209    SetBit(kGeoRotation);
01210    Double_t  newmat[9] = {0};
01211    if (after) {
01212       matleft  = &fRotationMatrix[0];
01213       matright = rot->GetRotationMatrix();
01214    } else {
01215       matleft  = rot->GetRotationMatrix();
01216       matright = &fRotationMatrix[0];
01217    }
01218    for (Int_t i=0; i<3; i++) {
01219       for (Int_t j=0; j<3; j++) { 
01220          for (Int_t k=0; k<3; k++) {
01221             newmat[3*i+j] += matleft[3*i+k] * matright[3*k+j];
01222          }
01223       }
01224    }
01225    memcpy(&fRotationMatrix[0], &newmat[0], kN9);
01226 }
01227 //=============================================================================
01228 
01229 ClassImp(TGeoScale)
01230 
01231 //_____________________________________________________________________________
01232 TGeoScale::TGeoScale()
01233 {
01234 // default constructor
01235    SetBit(kGeoScale);
01236    for (Int_t i=0; i<3; i++) fScale[i] = 1.;
01237 }
01238 
01239 //_____________________________________________________________________________
01240 TGeoScale::TGeoScale(const TGeoScale &other)
01241           :TGeoMatrix(other)
01242 {
01243 // Copy constructor
01244    SetBit(kGeoScale);
01245    const Double_t *scl =  other.GetScale();
01246    memcpy(fScale, scl, kN3);
01247    if (fScale[0]*fScale[1]*fScale[2]<0) SetBit(kGeoReflection);
01248    else SetBit(kGeoReflection, kFALSE);
01249 }   
01250 
01251 //_____________________________________________________________________________
01252 TGeoScale::TGeoScale(Double_t sx, Double_t sy, Double_t sz)
01253           :TGeoMatrix("")
01254 {
01255 // default constructor
01256    SetBit(kGeoScale);
01257    SetScale(sx, sy, sz);
01258 }
01259 
01260 //_____________________________________________________________________________
01261 TGeoScale::TGeoScale(const char *name, Double_t sx, Double_t sy, Double_t sz)
01262           :TGeoMatrix(name)
01263 {
01264 // default constructor
01265    SetBit(kGeoScale);
01266    SetScale(sx, sy, sz);
01267 }
01268 
01269 //_____________________________________________________________________________
01270 TGeoScale::~TGeoScale()
01271 {
01272 // destructor
01273 }
01274 
01275 //_____________________________________________________________________________
01276 TGeoMatrix& TGeoScale::Inverse() const
01277 {
01278 // Return a temporary inverse of this.
01279    static TGeoHMatrix h;
01280    h = *this;
01281    Double_t scale[3];
01282    scale[0] = 1./fScale[0];
01283    scale[1] = 1./fScale[1];
01284    scale[2] = 1./fScale[2];
01285    h.SetScale(scale);
01286    return h;
01287 }   
01288 
01289 //_____________________________________________________________________________
01290 void TGeoScale::SetScale(Double_t sx, Double_t sy, Double_t sz)
01291 {
01292 // scale setter
01293    if (TMath::Abs(sx*sy*sz) < 1.E-10) {
01294       Error("SetScale", "Invalid scale %f, %f, %f for transformation %s",sx,sy,sx,GetName());
01295       return;
01296    }   
01297    fScale[0] = sx;
01298    fScale[1] = sy;
01299    fScale[2] = sz;
01300    if (sx*sy*sz<0) SetBit(kGeoReflection);
01301    else            SetBit(kGeoReflection, kFALSE);
01302 }
01303 
01304 //_____________________________________________________________________________
01305 void TGeoScale::LocalToMaster(const Double_t *local, Double_t *master) const
01306 {
01307 // Convert a local point to the master frame.
01308    master[0] = local[0]*fScale[0];
01309    master[1] = local[1]*fScale[1];
01310    master[2] = local[2]*fScale[2];
01311 }
01312 
01313 //_____________________________________________________________________________
01314 Double_t TGeoScale::LocalToMaster(Double_t dist, const Double_t *dir) const
01315 {
01316 // Convert the local distance along unit vector DIR to master frame. If DIR
01317 // is not specified perform a conversion such as the returned distance is the
01318 // the minimum for all possible directions.
01319    Double_t scale;
01320    if (!dir) {
01321       scale = TMath::Abs(fScale[0]);
01322       if (TMath::Abs(fScale[1])<scale) scale = TMath::Abs(fScale[1]);
01323       if (TMath::Abs(fScale[2])<scale) scale = TMath::Abs(fScale[2]);
01324    } else {
01325       scale = fScale[0]*fScale[0]*dir[0]*dir[0] +
01326               fScale[1]*fScale[1]*dir[1]*dir[1] +
01327               fScale[2]*fScale[2]*dir[2]*dir[2];
01328       scale = TMath::Sqrt(scale);        
01329    }   
01330    return scale*dist;   
01331 }   
01332 
01333 //_____________________________________________________________________________
01334 TGeoMatrix *TGeoScale::MakeClone() const
01335 {
01336 // Make a clone of this matrix.
01337    TGeoMatrix *matrix = new TGeoScale(*this);
01338    return matrix;
01339 }
01340       
01341 //_____________________________________________________________________________
01342 void TGeoScale::MasterToLocal(const Double_t *master, Double_t *local) const
01343 {
01344 // Convert a global point to local frame.
01345    local[0] = master[0]/fScale[0];
01346    local[1] = master[1]/fScale[1];
01347    local[2] = master[2]/fScale[2];
01348 }
01349 
01350 //_____________________________________________________________________________
01351 Double_t TGeoScale::MasterToLocal(Double_t dist, const Double_t *dir) const
01352 {
01353 // Convert the distance along unit vector DIR to local frame. If DIR
01354 // is not specified perform a conversion such as the returned distance is the
01355 // the minimum for all possible directions.
01356    Double_t scale;
01357    if (!dir) {
01358       scale = TMath::Abs(fScale[0]);
01359       if (TMath::Abs(fScale[1])>scale) scale = TMath::Abs(fScale[1]);
01360       if (TMath::Abs(fScale[2])>scale) scale = TMath::Abs(fScale[2]);
01361       scale = 1./scale;
01362    } else {
01363       scale = (dir[0]*dir[0])/(fScale[0]*fScale[0]) +
01364               (dir[1]*dir[1])/(fScale[1]*fScale[1]) +
01365               (dir[2]*dir[2])/(fScale[2]*fScale[2]);
01366       scale = TMath::Sqrt(scale);        
01367    }   
01368    return scale*dist;   
01369 }   
01370 
01371 //=============================================================================
01372 
01373 ClassImp(TGeoCombiTrans)
01374 
01375 //_____________________________________________________________________________
01376 TGeoCombiTrans::TGeoCombiTrans()
01377 {
01378 // dummy ctor
01379    for (Int_t i=0; i<3; i++) fTranslation[i] = 0.0;
01380    fRotation = 0;
01381 }
01382 
01383 //_____________________________________________________________________________
01384 TGeoCombiTrans::TGeoCombiTrans(const TGeoCombiTrans &other)
01385                :TGeoMatrix(other)
01386 {
01387 // Copy ctor
01388    Int_t i;
01389    if (other.IsTranslation()) {
01390       const Double_t *trans = other.GetTranslation();
01391       memcpy(fTranslation, trans, kN3);
01392    } else {
01393       for (i=0; i<3; i++) fTranslation[i] = 0.0;   
01394    }
01395    if (other.IsRotation()) {   
01396       const TGeoRotation rot = *other.GetRotation();
01397       fRotation = new TGeoRotation(rot); 
01398       SetBit(kGeoMatrixOwned);
01399    } 
01400    else fRotation = 0;  
01401 }   
01402 
01403 //_____________________________________________________________________________
01404 TGeoCombiTrans::TGeoCombiTrans(const TGeoMatrix &other)
01405                :TGeoMatrix(other)
01406 {
01407 // Copy ctor.
01408    Int_t i;
01409    if (other.IsTranslation()) {
01410       SetBit(kGeoTranslation);
01411       memcpy(fTranslation,other.GetTranslation(),kN3);
01412    } else {
01413       for (i=0; i<3; i++) fTranslation[i] = 0.0;   
01414    }
01415    if (other.IsRotation()) {
01416       SetBit(kGeoRotation);
01417       SetBit(kGeoMatrixOwned);
01418       fRotation = new TGeoRotation(other);
01419    }
01420    else fRotation = 0;
01421 }
01422 
01423 //_____________________________________________________________________________
01424 TGeoCombiTrans::TGeoCombiTrans(const TGeoTranslation &tr, const TGeoRotation &rot)
01425 {
01426 // Constructor from a translation and a rotation.
01427    if (tr.IsTranslation()) {
01428       SetBit(kGeoTranslation);
01429       const Double_t *trans = tr.GetTranslation();
01430       memcpy(fTranslation, trans, kN3);
01431    } else {
01432       for (Int_t i=0; i<3; i++) fTranslation[i] = 0.0;
01433    }   
01434    if (rot.IsRotation()) {
01435       SetBit(kGeoRotation);   
01436       SetBit(kGeoMatrixOwned);
01437       fRotation = new TGeoRotation(rot);
01438       SetBit(kGeoReflection, rot.TestBit(kGeoReflection));
01439    }
01440    else fRotation = 0;   
01441 }   
01442 
01443 //_____________________________________________________________________________
01444 TGeoCombiTrans::TGeoCombiTrans(const char *name)
01445                :TGeoMatrix(name)
01446 {
01447 // Named ctor.
01448    for (Int_t i=0; i<3; i++) fTranslation[i] = 0.0;
01449    fRotation = 0;
01450 }
01451 
01452 //_____________________________________________________________________________
01453 TGeoCombiTrans::TGeoCombiTrans(Double_t dx, Double_t dy, Double_t dz, TGeoRotation *rot)
01454                :TGeoMatrix("")
01455 {
01456 // Constructor from a translation specified by X,Y,Z and a pointer to a rotation. The rotation will not be owned by this.
01457    SetTranslation(dx, dy, dz);
01458    fRotation = 0;
01459    SetRotation(rot);
01460 }
01461 
01462 //_____________________________________________________________________________
01463 TGeoCombiTrans::TGeoCombiTrans(const char *name, Double_t dx, Double_t dy, Double_t dz, TGeoRotation *rot)
01464                :TGeoMatrix(name)
01465 {
01466 // Named ctor
01467    SetTranslation(dx, dy, dz);
01468    fRotation = 0;
01469    SetRotation(rot);
01470 }
01471 
01472 //_____________________________________________________________________________
01473 TGeoCombiTrans &TGeoCombiTrans::operator=(const TGeoMatrix &matrix)
01474 {
01475 // Assignment operator.
01476    if (&matrix == this) return *this;
01477    Clear();
01478    TGeoMatrix::operator=(matrix);
01479    
01480    if (matrix.IsTranslation()) {
01481       SetBit(kGeoTranslation);
01482       memcpy(fTranslation,matrix.GetTranslation(),kN3);
01483    }
01484    if (matrix.IsRotation()) {
01485       SetBit(kGeoRotation);
01486       if (!fRotation) {
01487          fRotation = new TGeoRotation();
01488          SetBit(kGeoMatrixOwned);
01489       } else {
01490          if (!TestBit(kGeoMatrixOwned)) {
01491             fRotation = new TGeoRotation(); 
01492             SetBit(kGeoMatrixOwned);
01493          }
01494       }        
01495       fRotation->SetMatrix(matrix.GetRotationMatrix());
01496       fRotation->SetBit(kGeoReflection, matrix.TestBit(kGeoReflection));
01497       fRotation->SetBit(kGeoRotation);
01498    } else {
01499       if (fRotation && TestBit(kGeoMatrixOwned)) delete fRotation;
01500       ResetBit(kGeoMatrixOwned);
01501       fRotation = 0;
01502    }   
01503    return *this;
01504 }
01505 
01506 //_____________________________________________________________________________
01507 TGeoCombiTrans::~TGeoCombiTrans()
01508 {
01509 // destructor
01510    if (fRotation) {
01511       if(TestBit(TGeoMatrix::kGeoMatrixOwned) && !fRotation->IsRegistered()) delete fRotation;
01512    }   
01513 }
01514 
01515 //_____________________________________________________________________________
01516 void TGeoCombiTrans::Clear(Option_t *)
01517 {
01518 // Reset translation/rotation to identity
01519    if (IsTranslation()) {
01520       ResetBit(kGeoTranslation);
01521       memset(fTranslation, 0, kN3);
01522    }
01523    if (fRotation) {
01524       if (TestBit(kGeoMatrixOwned)) delete fRotation;
01525       fRotation = 0;
01526    }
01527    ResetBit(kGeoRotation);
01528    ResetBit(kGeoReflection);
01529    ResetBit(kGeoMatrixOwned);
01530 }         
01531 
01532 //_____________________________________________________________________________
01533 TGeoMatrix& TGeoCombiTrans::Inverse() const
01534 {
01535 // Return a temporary inverse of this.
01536    static TGeoHMatrix h;
01537    h = *this;
01538    Bool_t is_tr = IsTranslation();
01539    Bool_t is_rot = IsRotation();
01540    Double_t tr[3];
01541    Double_t newrot[9];
01542    const Double_t *rot = GetRotationMatrix();
01543    tr[0] = -fTranslation[0]*rot[0] - fTranslation[1]*rot[3] - fTranslation[2]*rot[6];
01544    tr[1] = -fTranslation[0]*rot[1] - fTranslation[1]*rot[4] - fTranslation[2]*rot[7];
01545    tr[2] = -fTranslation[0]*rot[2] - fTranslation[1]*rot[5] - fTranslation[2]*rot[8];
01546    h.SetTranslation(tr);
01547    newrot[0] = rot[0];
01548    newrot[1] = rot[3];
01549    newrot[2] = rot[6];
01550    newrot[3] = rot[1];
01551    newrot[4] = rot[4];
01552    newrot[5] = rot[7];
01553    newrot[6] = rot[2];
01554    newrot[7] = rot[5];
01555    newrot[8] = rot[8];
01556    h.SetRotation(newrot);
01557    h.SetBit(kGeoTranslation,is_tr);
01558    h.SetBit(kGeoRotation,is_rot);
01559    return h;
01560 }   
01561 
01562 //_____________________________________________________________________________
01563 TGeoMatrix *TGeoCombiTrans::MakeClone() const
01564 {
01565 // Make a clone of this matrix.
01566    TGeoMatrix *matrix = new TGeoCombiTrans(*this);
01567    return matrix;
01568 }
01569 
01570 //_____________________________________________________________________________
01571 void TGeoCombiTrans::RegisterYourself()
01572 {
01573 // Register the matrix in the current manager, which will become the owner. 
01574    TGeoMatrix::RegisterYourself();
01575    if (fRotation && fRotation->IsRotation()) fRotation->RegisterYourself();
01576 }
01577 
01578 //_____________________________________________________________________________
01579 void TGeoCombiTrans::RotateX(Double_t angle)
01580 {
01581 // Rotate about X axis with angle expressed in degrees.
01582    if (!fRotation || !TestBit(kGeoMatrixOwned)) {
01583       if (fRotation) fRotation = new TGeoRotation(*fRotation);
01584       else fRotation = new TGeoRotation();
01585       SetBit(kGeoMatrixOwned);
01586    }   
01587    SetBit(kGeoRotation);
01588    const Double_t *rot = fRotation->GetRotationMatrix();
01589    Double_t phi = angle*TMath::DegToRad();
01590    Double_t c = TMath::Cos(phi);
01591    Double_t s = TMath::Sin(phi);
01592    Double_t v[9];
01593    v[0] = rot[0];
01594    v[1] = rot[1];
01595    v[2] = rot[2];
01596    v[3] = c*rot[3]-s*rot[6];
01597    v[4] = c*rot[4]-s*rot[7];
01598    v[5] = c*rot[5]-s*rot[8];
01599    v[6] = s*rot[3]+c*rot[6];
01600    v[7] = s*rot[4]+c*rot[7];
01601    v[8] = s*rot[5]+c*rot[8];
01602    fRotation->SetMatrix(v);
01603    fRotation->SetBit(kGeoRotation);
01604    if (!IsTranslation()) return;
01605    v[0] = fTranslation[0];
01606    v[1] = c*fTranslation[1]-s*fTranslation[2];
01607    v[2] = s*fTranslation[1]+c*fTranslation[2];   
01608    memcpy(fTranslation,v,kN3);
01609 }   
01610 
01611 //_____________________________________________________________________________
01612 void TGeoCombiTrans::RotateY(Double_t angle)
01613 {
01614 // Rotate about Y axis with angle expressed in degrees.
01615    if (!fRotation || !TestBit(kGeoMatrixOwned)) {
01616       if (fRotation) fRotation = new TGeoRotation(*fRotation);
01617       else fRotation = new TGeoRotation();
01618       SetBit(kGeoMatrixOwned);
01619    }   
01620    SetBit(kGeoRotation);
01621    const Double_t *rot = fRotation->GetRotationMatrix();
01622    Double_t phi = angle*TMath::DegToRad();
01623    Double_t c = TMath::Cos(phi);
01624    Double_t s = TMath::Sin(phi);
01625    Double_t v[9];
01626    v[0] = c*rot[0]+s*rot[6];
01627    v[1] = c*rot[1]+s*rot[7];
01628    v[2] = c*rot[2]+s*rot[8];
01629    v[3] = rot[3];
01630    v[4] = rot[4];
01631    v[5] = rot[5];
01632    v[6] = -s*rot[0]+c*rot[6];
01633    v[7] = -s*rot[1]+c*rot[7];
01634    v[8] = -s*rot[2]+c*rot[8];
01635    fRotation->SetMatrix(v);
01636    fRotation->SetBit(kGeoRotation);
01637    if (!IsTranslation()) return;
01638    v[0] = c*fTranslation[0]+s*fTranslation[2];
01639    v[1] = fTranslation[1];
01640    v[2] = -s*fTranslation[0]+c*fTranslation[2];
01641    memcpy(fTranslation,v,kN3);
01642 }   
01643 
01644 //_____________________________________________________________________________
01645 void TGeoCombiTrans::RotateZ(Double_t angle)
01646 {
01647 // Rotate about Z axis with angle expressed in degrees.
01648    if (!fRotation || !TestBit(kGeoMatrixOwned)) {
01649       if (fRotation) fRotation = new TGeoRotation(*fRotation);
01650       else fRotation = new TGeoRotation();
01651       SetBit(kGeoMatrixOwned);
01652    }   
01653    SetBit(kGeoRotation);
01654    const Double_t *rot = fRotation->GetRotationMatrix();
01655    Double_t phi = angle*TMath::DegToRad();
01656    Double_t c = TMath::Cos(phi);
01657    Double_t s = TMath::Sin(phi);
01658    Double_t v[9];
01659    v[0] = c*rot[0]-s*rot[3];
01660    v[1] = c*rot[1]-s*rot[4];
01661    v[2] = c*rot[2]-s*rot[5];
01662    v[3] = s*rot[0]+c*rot[3];
01663    v[4] = s*rot[1]+c*rot[4];
01664    v[5] = s*rot[2]+c*rot[5];
01665    v[6] = rot[6];
01666    v[7] = rot[7];
01667    v[8] = rot[8];
01668    fRotation->SetMatrix(v);
01669    fRotation->SetBit(kGeoRotation);
01670    if (!IsTranslation()) return;
01671    v[0] = c*fTranslation[0]-s*fTranslation[1];
01672    v[1] = s*fTranslation[0]+c*fTranslation[1];
01673    v[2] = fTranslation[2];
01674    memcpy(fTranslation,v,kN3);
01675 }   
01676 
01677 //_____________________________________________________________________________
01678 void TGeoCombiTrans::ReflectX(Bool_t leftside, Bool_t rotonly)
01679 {
01680 // Multiply by a reflection respect to YZ.
01681    if (leftside && !rotonly) fTranslation[0] = -fTranslation[0];
01682    if (!fRotation || !TestBit(kGeoMatrixOwned)) {
01683       if (fRotation) fRotation = new TGeoRotation(*fRotation);
01684       else fRotation = new TGeoRotation();
01685       SetBit(kGeoMatrixOwned);
01686    }
01687    SetBit(kGeoRotation);
01688    fRotation->ReflectX(leftside);
01689    SetBit(kGeoReflection, !IsReflection());
01690 }      
01691    
01692 //_____________________________________________________________________________
01693 void TGeoCombiTrans::ReflectY(Bool_t leftside, Bool_t rotonly)
01694 {
01695 // Multiply by a reflection respect to ZX.
01696    if (leftside && !rotonly) fTranslation[1] = -fTranslation[1];
01697    if (!fRotation || !TestBit(kGeoMatrixOwned)) {
01698       if (fRotation) fRotation = new TGeoRotation(*fRotation);
01699       else fRotation = new TGeoRotation();
01700       SetBit(kGeoMatrixOwned);
01701    }
01702    SetBit(kGeoRotation);
01703    fRotation->ReflectY(leftside);
01704    SetBit(kGeoReflection, !IsReflection());
01705 }      
01706 
01707 //_____________________________________________________________________________
01708 void TGeoCombiTrans::ReflectZ(Bool_t leftside, Bool_t rotonly)
01709 {
01710 // Multiply by a reflection respect to XY.
01711    if (leftside && !rotonly) fTranslation[2] = -fTranslation[2];
01712    if (!fRotation || !TestBit(kGeoMatrixOwned)) {
01713       if (fRotation) fRotation = new TGeoRotation(*fRotation);
01714       else fRotation = new TGeoRotation();
01715       SetBit(kGeoMatrixOwned);
01716    }
01717    SetBit(kGeoRotation);
01718    fRotation->ReflectZ(leftside);
01719    SetBit(kGeoReflection, !IsReflection());
01720 }      
01721 
01722 //_____________________________________________________________________________
01723 void TGeoCombiTrans::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
01724 {
01725 // Save a primitive as a C++ statement(s) on output stream "out".
01726    if (TestBit(kGeoSavePrimitive)) return;
01727    out << "   // Combi transformation: " << GetName() << endl;
01728    out << "   dx = " << fTranslation[0] << ";" << endl;
01729    out << "   dy = " << fTranslation[1] << ";" << endl;
01730    out << "   dz = " << fTranslation[2] << ";" << endl;
01731    if (fRotation && fRotation->IsRotation()) {
01732       fRotation->SavePrimitive(out,option);
01733       out << "   " << GetPointerName() << " = new TGeoCombiTrans(\"" << GetName() << "\", dx,dy,dz,";
01734       out << fRotation->GetPointerName() << ");" << endl;
01735    } else {   
01736       out << "   " << GetPointerName() << " = new TGeoCombiTrans(\"" << GetName() << "\");" << endl;
01737       out << "   " << GetPointerName() << "->SetTranslation(dx,dy,dz);" << endl;
01738    }   
01739    TObject::SetBit(kGeoSavePrimitive);
01740 }
01741 
01742 //_____________________________________________________________________________
01743 void TGeoCombiTrans::SetRotation(const TGeoRotation *rot)
01744 {
01745 // Assign a foreign rotation to the combi. The rotation is NOT owned by this.
01746    if (fRotation && TestBit(kGeoMatrixOwned)) delete fRotation;
01747    fRotation = 0;
01748    ResetBit(TGeoMatrix::kGeoMatrixOwned);      
01749    ResetBit(kGeoRotation);
01750    ResetBit(kGeoReflection);   
01751    if (!rot) return;
01752    if (!rot->IsRotation()) return;
01753          
01754    SetBit(kGeoRotation);
01755    SetBit(kGeoReflection, rot->TestBit(kGeoReflection));
01756    TGeoRotation *rr = (TGeoRotation*)rot;
01757    fRotation = rr;
01758 }
01759 
01760 //_____________________________________________________________________________
01761 void TGeoCombiTrans::SetRotation(const TGeoRotation &rot)
01762 {
01763 // Copy the rotation from another one.
01764    if (fRotation && TestBit(kGeoMatrixOwned)) delete fRotation;
01765    fRotation = 0;
01766    if (!rot.IsRotation()) {
01767       ResetBit(kGeoRotation);
01768       ResetBit(kGeoReflection);
01769       ResetBit(TGeoMatrix::kGeoMatrixOwned);
01770       return;
01771    }         
01772       
01773    SetBit(kGeoRotation);
01774    SetBit(kGeoReflection, rot.TestBit(kGeoReflection));
01775    fRotation = new TGeoRotation(rot);
01776    SetBit(kGeoMatrixOwned);
01777 }
01778 
01779 //_____________________________________________________________________________
01780 void TGeoCombiTrans::SetTranslation(const TGeoTranslation &tr)
01781 {
01782 // copy the translation component
01783    if (tr.IsTranslation()) {
01784       SetBit(kGeoTranslation);
01785       const Double_t *trans = tr.GetTranslation();
01786       memcpy(fTranslation, trans, kN3);
01787    } else {
01788       if (!IsTranslation()) return;
01789       memset(fTranslation, 0, kN3);
01790       ResetBit(kGeoTranslation);
01791    }      
01792 }   
01793 
01794 //_____________________________________________________________________________
01795 void TGeoCombiTrans::SetTranslation(Double_t dx, Double_t dy, Double_t dz)
01796 {
01797 // set the translation component
01798    fTranslation[0] = dx;
01799    fTranslation[1] = dy;
01800    fTranslation[2] = dz;
01801    if (fTranslation[0] || fTranslation[1] || fTranslation[2]) SetBit(kGeoTranslation);
01802    else ResetBit(kGeoTranslation);
01803 }
01804 
01805 //_____________________________________________________________________________
01806 void TGeoCombiTrans::SetTranslation(Double_t *vect)
01807 {
01808 // set the translation component
01809    fTranslation[0] = vect[0];
01810    fTranslation[1] = vect[1];
01811    fTranslation[2] = vect[2];
01812    if (fTranslation[0] || fTranslation[1] || fTranslation[2]) SetBit(kGeoTranslation);
01813    else ResetBit(kGeoTranslation);
01814 }
01815 
01816 //_____________________________________________________________________________
01817 const Double_t *TGeoCombiTrans::GetRotationMatrix() const
01818 {
01819 // get the rotation array
01820    if (!fRotation) return kIdentityMatrix;
01821    return fRotation->GetRotationMatrix();
01822 }
01823 //=============================================================================
01824 
01825 ClassImp(TGeoGenTrans)
01826 
01827 //_____________________________________________________________________________
01828 TGeoGenTrans::TGeoGenTrans()
01829 {
01830 // dummy ctor
01831    SetBit(kGeoGenTrans);
01832    for (Int_t i=0; i<3; i++) fTranslation[i] = 0.0;
01833    for (Int_t j=0; j<3; j++) fScale[j] = 1.0;
01834    fRotation = 0;
01835 }
01836 
01837 //_____________________________________________________________________________
01838 TGeoGenTrans::TGeoGenTrans(const char *name)
01839              :TGeoCombiTrans(name)
01840 {
01841 // constructor
01842    SetBit(kGeoGenTrans);
01843    for (Int_t i=0; i<3; i++) fTranslation[i] = 0.0;
01844    for (Int_t j=0; j<3; j++) fScale[j] = 1.0;
01845    fRotation = 0;
01846 }
01847 
01848 //_____________________________________________________________________________
01849 TGeoGenTrans::TGeoGenTrans(Double_t dx, Double_t dy, Double_t dz,
01850                            Double_t sx, Double_t sy, Double_t sz, TGeoRotation *rot)
01851              :TGeoCombiTrans("")
01852 {
01853 // constructor
01854    SetBit(kGeoGenTrans);
01855    SetTranslation(dx, dy, dz);
01856    SetScale(sx, sy, sz);
01857    SetRotation(rot);
01858 }
01859 
01860 //_____________________________________________________________________________
01861 TGeoGenTrans::TGeoGenTrans(const char *name, Double_t dx, Double_t dy, Double_t dz,
01862                            Double_t sx, Double_t sy, Double_t sz, TGeoRotation *rot)
01863              :TGeoCombiTrans(name)
01864 {
01865 // constructor
01866    SetBit(kGeoGenTrans);
01867    SetTranslation(dx, dy, dz);
01868    SetScale(sx, sy, sz);
01869    SetRotation(rot);
01870 }
01871 
01872 //_____________________________________________________________________________
01873 TGeoGenTrans::~TGeoGenTrans()
01874 {
01875 // destructor
01876 }
01877 
01878 //_____________________________________________________________________________
01879 void TGeoGenTrans::Clear(Option_t *)
01880 {
01881 // clear the fields of this transformation
01882    memset(&fTranslation[0], 0, kN3);
01883    memset(&fScale[0], 0, kN3);
01884    if (fRotation) fRotation->Clear();
01885 }
01886 
01887 //_____________________________________________________________________________
01888 void TGeoGenTrans::SetScale(Double_t sx, Double_t sy, Double_t sz)
01889 {
01890 // set the scale
01891    fScale[0] = sx;
01892    fScale[1] = sy;
01893    fScale[2] = sz;
01894    if (!(Normalize())) {
01895       Error("ctor", "Invalid scale");
01896       return;
01897    }
01898 }
01899 
01900 //_____________________________________________________________________________
01901 TGeoMatrix& TGeoGenTrans::Inverse() const
01902 {
01903 // Return a temporary inverse of this.
01904    Error("Inverse", "not implemented");
01905    static TGeoHMatrix h;
01906    h = *this;
01907    return h;
01908 }   
01909 
01910 //_____________________________________________________________________________
01911 Bool_t TGeoGenTrans::Normalize()
01912 {
01913 // A scale transformation should be normalized by sx*sy*sz factor
01914    Double_t normfactor = fScale[0]*fScale[1]*fScale[2];
01915    if (normfactor <= 1E-5) return kFALSE;
01916    for (Int_t i=0; i<3; i++)
01917       fScale[i] /= normfactor;
01918    return kTRUE;
01919 }
01920 //=============================================================================
01921 
01922 ClassImp(TGeoIdentity)
01923 
01924 //_____________________________________________________________________________
01925 TGeoIdentity::TGeoIdentity()
01926 {
01927 // dummy ctor
01928    if (!gGeoIdentity) gGeoIdentity = this;
01929    RegisterYourself();
01930 }
01931 
01932 //_____________________________________________________________________________
01933 TGeoIdentity::TGeoIdentity(const char *name)
01934              :TGeoMatrix(name)
01935 {
01936 // constructor
01937    if (!gGeoIdentity) gGeoIdentity = this;
01938    RegisterYourself();
01939 }
01940 
01941 //_____________________________________________________________________________
01942 TGeoMatrix &TGeoIdentity::Inverse() const
01943 {
01944 // Return a temporary inverse of this.
01945    return *gGeoIdentity;
01946 }
01947    
01948 /*************************************************************************
01949  * TGeoHMatrix - Matrix class used for computing global transformations  *
01950  *     Should NOT be used for node definition. An instance of this class *
01951  *     is generally used to pile-up local transformations starting from  *
01952  *     the top level physical node, down to the current node.            *
01953  *************************************************************************/
01954 
01955 //=============================================================================
01956 
01957 ClassImp(TGeoHMatrix)
01958    
01959 //_____________________________________________________________________________
01960 TGeoHMatrix::TGeoHMatrix()
01961 {
01962 // dummy ctor
01963    memset(&fTranslation[0], 0, kN3);
01964    memcpy(fRotationMatrix,kIdentityMatrix,kN9);
01965    memcpy(fScale,kUnitScale,kN3);
01966 }
01967 
01968 //_____________________________________________________________________________
01969 TGeoHMatrix::TGeoHMatrix(const char* name)
01970             :TGeoMatrix(name)
01971 {
01972 // constructor
01973    memset(&fTranslation[0], 0, kN3);
01974    memcpy(fRotationMatrix,kIdentityMatrix,kN9);
01975    memcpy(fScale,kUnitScale,kN3);
01976 }
01977 
01978 //_____________________________________________________________________________
01979 TGeoHMatrix::TGeoHMatrix(const TGeoMatrix &matrix)
01980             :TGeoMatrix(matrix)
01981 {
01982    // assignment
01983    if (matrix.IsTranslation()) {
01984       SetBit(kGeoTranslation);
01985       SetTranslation(matrix.GetTranslation());
01986    } else {
01987       memset(&fTranslation[0], 0, kN3);   
01988    }
01989    if (matrix.IsRotation()) {
01990       SetBit(kGeoRotation);
01991       memcpy(fRotationMatrix,matrix.GetRotationMatrix(),kN9);
01992    } else {
01993       memcpy(fRotationMatrix,kIdentityMatrix,kN9);   
01994    }
01995    if (matrix.IsScale()) {
01996       SetBit(kGeoScale);
01997       memcpy(fScale,matrix.GetScale(),kN3);
01998    } else {
01999       memcpy(fScale,kUnitScale,kN3);   
02000    }
02001 }
02002 
02003 //_____________________________________________________________________________
02004 TGeoHMatrix::~TGeoHMatrix()
02005 {
02006 // destructor
02007 }
02008 
02009 //_____________________________________________________________________________
02010 TGeoHMatrix &TGeoHMatrix::operator=(const TGeoMatrix *matrix)
02011 {
02012    // assignment
02013    if (matrix == this) return *this;
02014    Clear();
02015    if (matrix == 0) return *this;
02016    TGeoMatrix::operator=(*matrix);
02017    if (matrix->IsIdentity()) return *this;
02018    if (matrix->IsTranslation()) {
02019       SetBit(kGeoTranslation);
02020       memcpy(fTranslation,matrix->GetTranslation(),kN3);
02021    }
02022    if (matrix->IsRotation()) {
02023       SetBit(kGeoRotation);
02024       memcpy(fRotationMatrix,matrix->GetRotationMatrix(),kN9);
02025    }
02026    if (matrix->IsScale()) {
02027       SetBit(kGeoScale);
02028       memcpy(fScale,matrix->GetScale(),kN3);
02029    }
02030    return *this;
02031 }
02032 
02033 //_____________________________________________________________________________
02034 TGeoHMatrix &TGeoHMatrix::operator=(const TGeoMatrix &matrix)
02035 {
02036    // assignment
02037    if (&matrix == this) return *this;
02038    Clear();
02039    TGeoMatrix::operator=(matrix);
02040    if (matrix.IsIdentity()) return *this;
02041    if (matrix.IsTranslation()) {
02042       SetBit(kGeoTranslation);
02043       memcpy(fTranslation,matrix.GetTranslation(),kN3);
02044    } else {
02045       memcpy(fTranslation,kNullVector,kN3);
02046    }   
02047    if (matrix.IsRotation()) {
02048       SetBit(kGeoRotation);
02049       memcpy(fRotationMatrix,matrix.GetRotationMatrix(),kN9);
02050    } else {
02051       memcpy(fRotationMatrix,kIdentityMatrix,kN9);
02052    }   
02053    if (matrix.IsScale()) {
02054       SetBit(kGeoScale);
02055       memcpy(fScale,matrix.GetScale(),kN3);
02056    } else {
02057       memcpy(fScale,kUnitScale,kN3);
02058    }   
02059    return *this;
02060 }
02061 
02062 //_____________________________________________________________________________
02063 void TGeoHMatrix::CopyFrom(const TGeoMatrix *other)
02064 {
02065 // Fast copy method.
02066    SetBit(kGeoTranslation, other->IsTranslation());
02067    SetBit(kGeoRotation, other->IsRotation());
02068    SetBit(kGeoReflection, other->IsReflection());
02069    memcpy(fTranslation,other->GetTranslation(),kN3);
02070    memcpy(fRotationMatrix,other->GetRotationMatrix(),kN9);
02071 }   
02072 
02073 //_____________________________________________________________________________
02074 void TGeoHMatrix::Clear(Option_t *)
02075 {
02076 // clear the data for this matrix
02077    SetBit(kGeoReflection, kFALSE);
02078    if (IsIdentity()) return;
02079    if (IsTranslation()) {
02080       ResetBit(kGeoTranslation);
02081       memcpy(fTranslation,kNullVector,kN3);
02082    }
02083    if (IsRotation()) {
02084       ResetBit(kGeoRotation);
02085       memcpy(fRotationMatrix,kIdentityMatrix,kN9);
02086    }
02087    if (IsScale()) {      
02088       ResetBit(kGeoScale);
02089       memcpy(fScale,kUnitScale,kN3);
02090    }
02091 }
02092 
02093 //_____________________________________________________________________________
02094 TGeoMatrix *TGeoHMatrix::MakeClone() const
02095 {
02096 // Make a clone of this matrix.
02097    TGeoMatrix *matrix = new TGeoHMatrix(*this);
02098    return matrix;
02099 }
02100 
02101 //_____________________________________________________________________________
02102 TGeoMatrix& TGeoHMatrix::Inverse() const
02103 {
02104 // Return a temporary inverse of this.
02105    static TGeoHMatrix h;
02106    h = *this;
02107    if (IsTranslation()) {
02108       Double_t tr[3];
02109       tr[0] = -fTranslation[0]*fRotationMatrix[0] - fTranslation[1]*fRotationMatrix[3] - fTranslation[2]*fRotationMatrix[6];
02110       tr[1] = -fTranslation[0]*fRotationMatrix[1] - fTranslation[1]*fRotationMatrix[4] - fTranslation[2]*fRotationMatrix[7];
02111       tr[2] = -fTranslation[0]*fRotationMatrix[2] - fTranslation[1]*fRotationMatrix[5] - fTranslation[2]*fRotationMatrix[8];
02112       h.SetTranslation(tr);
02113    }
02114    if (IsRotation()) {
02115       Double_t newrot[9];
02116       newrot[0] = fRotationMatrix[0];
02117       newrot[1] = fRotationMatrix[3];
02118       newrot[2] = fRotationMatrix[6];
02119       newrot[3] = fRotationMatrix[1];
02120       newrot[4] = fRotationMatrix[4];
02121       newrot[5] = fRotationMatrix[7];
02122       newrot[6] = fRotationMatrix[2];
02123       newrot[7] = fRotationMatrix[5];
02124       newrot[8] = fRotationMatrix[8];
02125       h.SetRotation(newrot);
02126    }
02127    if (IsScale()) {
02128       Double_t sc[3];
02129       sc[0] = 1./fScale[0];
02130       sc[1] = 1./fScale[1];
02131       sc[2] = 1./fScale[2]; 
02132       h.SetScale(sc);  
02133    }
02134    return h;
02135 }   
02136 
02137 //_____________________________________________________________________________
02138 Double_t TGeoHMatrix::Determinant() const
02139 {
02140 // computes determinant of the rotation matrix
02141    Double_t 
02142    det = fRotationMatrix[0]*fRotationMatrix[4]*fRotationMatrix[8] + 
02143          fRotationMatrix[3]*fRotationMatrix[7]*fRotationMatrix[2] +
02144          fRotationMatrix[6]*fRotationMatrix[1]*fRotationMatrix[5] - 
02145          fRotationMatrix[2]*fRotationMatrix[4]*fRotationMatrix[6] -
02146          fRotationMatrix[5]*fRotationMatrix[7]*fRotationMatrix[0] - 
02147          fRotationMatrix[8]*fRotationMatrix[1]*fRotationMatrix[3];
02148    return det;
02149 }
02150 
02151 //_____________________________________________________________________________
02152 void TGeoHMatrix::Multiply(const TGeoMatrix *right)
02153 {
02154 // multiply to the right with an other transformation
02155    // if right is identity matrix, just return
02156    if (right->IsIdentity()) return;
02157    const Double_t *r_tra = right->GetTranslation();
02158    const Double_t *r_rot = right->GetRotationMatrix();
02159    const Double_t *r_scl = right->GetScale();
02160    if (IsIdentity()) {
02161       if (right->IsRotation()) {
02162          SetBit(kGeoRotation);
02163          memcpy(fRotationMatrix,r_rot,kN9);
02164          if (right->IsReflection()) SetBit(kGeoReflection, !TestBit(kGeoReflection));
02165       }
02166       if (right->IsScale()) {
02167          SetBit(kGeoScale);
02168          memcpy(fScale,r_scl,kN3);
02169       }
02170       if (right->IsTranslation()) {
02171          SetBit(kGeoTranslation);
02172          memcpy(fTranslation,r_tra,kN3);
02173       }
02174       return;
02175    }
02176    Int_t i, j;
02177    Double_t new_rot[9]; 
02178 
02179    if (right->IsRotation())    {
02180       SetBit(kGeoRotation);
02181       if (right->IsReflection()) SetBit(kGeoReflection, !TestBit(kGeoReflection));
02182    }   
02183    if (right->IsScale())       SetBit(kGeoScale);
02184    if (right->IsTranslation()) SetBit(kGeoTranslation);
02185 
02186    // new translation
02187    if (IsTranslation()) { 
02188       for (i=0; i<3; i++) {
02189          fTranslation[i] += fRotationMatrix[3*i]*r_tra[0]
02190                          + fRotationMatrix[3*i+1]*r_tra[1]
02191                          + fRotationMatrix[3*i+2]*r_tra[2];
02192       }
02193    }
02194    if (IsRotation()) {
02195       // new rotation
02196       for (i=0; i<3; i++) {
02197          for (j=0; j<3; j++) {
02198                new_rot[3*i+j] = fRotationMatrix[3*i]*r_rot[j] +
02199                                 fRotationMatrix[3*i+1]*r_rot[3+j] +
02200                                 fRotationMatrix[3*i+2]*r_rot[6+j];
02201          }
02202       }
02203       memcpy(fRotationMatrix,new_rot,kN9);
02204    }
02205    // new scale
02206    if (IsScale()) {
02207       for (i=0; i<3; i++) fScale[i] *= r_scl[i];
02208    }
02209 }
02210  
02211 //_____________________________________________________________________________
02212 void TGeoHMatrix::MultiplyLeft(const TGeoMatrix *left)
02213 {
02214 // multiply to the left with an other transformation
02215    // if right is identity matrix, just return
02216    if (left == gGeoIdentity) return;
02217    const Double_t *l_tra = left->GetTranslation();
02218    const Double_t *l_rot = left->GetRotationMatrix();
02219    const Double_t *l_scl = left->GetScale();
02220    if (IsIdentity()) {
02221       if (left->IsRotation()) {
02222          if (left->IsReflection()) SetBit(kGeoReflection, !TestBit(kGeoReflection));
02223          SetBit(kGeoRotation);
02224          memcpy(fRotationMatrix,l_rot,kN9);
02225       }
02226       if (left->IsScale()) {
02227          SetBit(kGeoScale);
02228          memcpy(fScale,l_scl,kN3);
02229       }
02230       if (left->IsTranslation()) {
02231          SetBit(kGeoTranslation);
02232          memcpy(fTranslation,l_tra,kN3);
02233       }
02234       return;
02235    }
02236    Int_t i, j;
02237    Double_t new_tra[3]; 
02238    Double_t new_rot[9]; 
02239 
02240    if (left->IsRotation()) {
02241       SetBit(kGeoRotation);
02242       if (left->IsReflection()) SetBit(kGeoReflection, !TestBit(kGeoReflection));
02243    }
02244    if (left->IsScale())       SetBit(kGeoScale);
02245    if (left->IsTranslation()) SetBit(kGeoTranslation);
02246 
02247    // new translation
02248    if (IsTranslation()) {  
02249       for (i=0; i<3; i++) {
02250          new_tra[i] = l_tra[i]
02251                       + l_rot[3*i]*  fTranslation[0]
02252                       + l_rot[3*i+1]*fTranslation[1]
02253                       + l_rot[3*i+2]*fTranslation[2];
02254       }
02255       memcpy(fTranslation,new_tra,kN3);
02256    }
02257    if (IsRotation()) {
02258       // new rotation
02259       for (i=0; i<3; i++) {
02260          for (j=0; j<3; j++) {
02261                new_rot[3*i+j] = l_rot[3*i]*fRotationMatrix[j] +
02262                                 l_rot[3*i+1]*fRotationMatrix[3+j] +
02263                                 l_rot[3*i+2]*fRotationMatrix[6+j];
02264          }
02265       }
02266       memcpy(fRotationMatrix,new_rot,kN9);
02267    }
02268    // new scale
02269    if (IsScale()) {
02270       for (i=0; i<3; i++) fScale[i] *= l_scl[i];
02271    }
02272 }
02273 
02274 //_____________________________________________________________________________
02275 void TGeoHMatrix::RotateX(Double_t angle)
02276 {
02277 // Rotate about X axis with angle expressed in degrees.
02278    SetBit(kGeoRotation);
02279    Double_t phi = angle*TMath::DegToRad();
02280    Double_t c = TMath::Cos(phi);
02281    Double_t s = TMath::Sin(phi);
02282    Double_t v[9];
02283    v[0] = fRotationMatrix[0];
02284    v[1] = fRotationMatrix[1];
02285    v[2] = fRotationMatrix[2];
02286    v[3] = c*fRotationMatrix[3]-s*fRotationMatrix[6];
02287    v[4] = c*fRotationMatrix[4]-s*fRotationMatrix[7];
02288    v[5] = c*fRotationMatrix[5]-s*fRotationMatrix[8];
02289    v[6] = s*fRotationMatrix[3]+c*fRotationMatrix[6];
02290    v[7] = s*fRotationMatrix[4]+c*fRotationMatrix[7];
02291    v[8] = s*fRotationMatrix[5]+c*fRotationMatrix[8];
02292    memcpy(fRotationMatrix, v, kN9);
02293 
02294    v[0] = fTranslation[0];
02295    v[1] = c*fTranslation[1]-s*fTranslation[2];
02296    v[2] = s*fTranslation[1]+c*fTranslation[2];
02297    memcpy(fTranslation,v,kN3);
02298 }
02299 
02300 //_____________________________________________________________________________
02301 void TGeoHMatrix::RotateY(Double_t angle)
02302 {
02303 // Rotate about Y axis with angle expressed in degrees.
02304    SetBit(kGeoRotation);
02305    Double_t phi = angle*TMath::DegToRad();
02306    Double_t c = TMath::Cos(phi);
02307    Double_t s = TMath::Sin(phi);
02308    Double_t v[9];
02309    v[0] = c*fRotationMatrix[0]+s*fRotationMatrix[6];
02310    v[1] = c*fRotationMatrix[1]+s*fRotationMatrix[7];
02311    v[2] = c*fRotationMatrix[2]+s*fRotationMatrix[8];
02312    v[3] = fRotationMatrix[3];
02313    v[4] = fRotationMatrix[4];
02314    v[5] = fRotationMatrix[5];
02315    v[6] = -s*fRotationMatrix[0]+c*fRotationMatrix[6];
02316    v[7] = -s*fRotationMatrix[1]+c*fRotationMatrix[7];
02317    v[8] = -s*fRotationMatrix[2]+c*fRotationMatrix[8];
02318    memcpy(fRotationMatrix, v, kN9);
02319 
02320    v[0] = c*fTranslation[0]+s*fTranslation[2];
02321    v[1] = fTranslation[1];
02322    v[2] = -s*fTranslation[0]+c*fTranslation[2];
02323    memcpy(fTranslation,v,kN3);
02324 }
02325 
02326 //_____________________________________________________________________________
02327 void TGeoHMatrix::RotateZ(Double_t angle)
02328 {
02329 // Rotate about Z axis with angle expressed in degrees.
02330    SetBit(kGeoRotation);
02331    Double_t phi = angle*TMath::DegToRad();
02332    Double_t c = TMath::Cos(phi);
02333    Double_t s = TMath::Sin(phi);
02334    Double_t v[9];
02335    v[0] = c*fRotationMatrix[0]-s*fRotationMatrix[3];
02336    v[1] = c*fRotationMatrix[1]-s*fRotationMatrix[4];
02337    v[2] = c*fRotationMatrix[2]-s*fRotationMatrix[5];
02338    v[3] = s*fRotationMatrix[0]+c*fRotationMatrix[3];
02339    v[4] = s*fRotationMatrix[1]+c*fRotationMatrix[4];
02340    v[5] = s*fRotationMatrix[2]+c*fRotationMatrix[5];
02341    v[6] = fRotationMatrix[6];
02342    v[7] = fRotationMatrix[7];
02343    v[8] = fRotationMatrix[8];
02344    memcpy(&fRotationMatrix[0],v,kN9);
02345 
02346    v[0] = c*fTranslation[0]-s*fTranslation[1];
02347    v[1] = s*fTranslation[0]+c*fTranslation[1];
02348    v[2] = fTranslation[2];
02349    memcpy(fTranslation,v,kN3);
02350 }
02351 
02352 //_____________________________________________________________________________
02353 void TGeoHMatrix::ReflectX(Bool_t leftside, Bool_t rotonly)
02354 {
02355 // Multiply by a reflection respect to YZ.
02356    if (leftside && !rotonly) fTranslation[0] = -fTranslation[0];
02357    if (leftside) {
02358       fRotationMatrix[0]=-fRotationMatrix[0];
02359       fRotationMatrix[1]=-fRotationMatrix[1];
02360       fRotationMatrix[2]=-fRotationMatrix[2];
02361    } else {
02362       fRotationMatrix[0]=-fRotationMatrix[0];
02363       fRotationMatrix[3]=-fRotationMatrix[3];
02364       fRotationMatrix[6]=-fRotationMatrix[6];
02365    }   
02366    SetBit(kGeoRotation);
02367    SetBit(kGeoReflection, !IsReflection());
02368 }      
02369 
02370 //_____________________________________________________________________________
02371 void TGeoHMatrix::ReflectY(Bool_t leftside, Bool_t rotonly)
02372 {
02373 // Multiply by a reflection respect to ZX.
02374    if (leftside && !rotonly) fTranslation[1] = -fTranslation[1];
02375    if (leftside) {
02376       fRotationMatrix[3]=-fRotationMatrix[3];
02377       fRotationMatrix[4]=-fRotationMatrix[4];
02378       fRotationMatrix[5]=-fRotationMatrix[5];
02379    } else {
02380       fRotationMatrix[1]=-fRotationMatrix[1];
02381       fRotationMatrix[4]=-fRotationMatrix[4];
02382       fRotationMatrix[7]=-fRotationMatrix[7];
02383    }   
02384    SetBit(kGeoRotation);
02385    SetBit(kGeoReflection, !IsReflection());
02386 }      
02387 
02388 //_____________________________________________________________________________
02389 void TGeoHMatrix::ReflectZ(Bool_t leftside, Bool_t rotonly)
02390 {
02391 // Multiply by a reflection respect to XY.
02392    if (leftside && !rotonly) fTranslation[2] = -fTranslation[2];
02393    if (leftside) {
02394       fRotationMatrix[6]=-fRotationMatrix[6];
02395       fRotationMatrix[7]=-fRotationMatrix[7];
02396       fRotationMatrix[8]=-fRotationMatrix[8];
02397    } else {
02398       fRotationMatrix[2]=-fRotationMatrix[2];
02399       fRotationMatrix[5]=-fRotationMatrix[5];
02400       fRotationMatrix[8]=-fRotationMatrix[8];
02401    }   
02402    SetBit(kGeoRotation);
02403    SetBit(kGeoReflection, !IsReflection());
02404 }      
02405 
02406 //_____________________________________________________________________________
02407 void TGeoHMatrix::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
02408 {
02409 // Save a primitive as a C++ statement(s) on output stream "out".
02410    if (TestBit(kGeoSavePrimitive)) return;
02411    const Double_t *tr = fTranslation;
02412    const Double_t *rot = fRotationMatrix;
02413    out << "   // HMatrix: " << GetName() << endl;
02414    out << "   tr[0]  = " << tr[0] << ";    " << "tr[1] = " << tr[1] << ";    " << "tr[2] = " << tr[2] << ";" << endl;
02415    out << "   rot[0] =" << rot[0] << ";    " << "rot[1] = " << rot[1] << ";    " << "rot[2] = " << rot[2] << ";" << endl; 
02416    out << "   rot[3] =" << rot[3] << ";    " << "rot[4] = " << rot[4] << ";    " << "rot[5] = " << rot[5] << ";" << endl; 
02417    out << "   rot[6] =" << rot[6] << ";    " << "rot[7] = " << rot[7] << ";    " << "rot[8] = " << rot[8] << ";" << endl; 
02418    char *name = GetPointerName();
02419    out << "   TGeoHMatrix *" << name << " = new TGeoHMatrix(\"" << GetName() << "\");" << endl;
02420    out << "   " << name << "->SetTranslation(tr);" << endl;
02421    out << "   " << name << "->SetRotation(rot);" << endl;
02422    if (IsTranslation()) out << "   " << name << "->SetBit(TGeoMatrix::kGeoTranslation);" << endl;
02423    if (IsRotation()) out << "   " << name << "->SetBit(TGeoMatrix::kGeoRotation);" << endl;
02424    if (IsReflection()) out << "   " << name << "->SetBit(TGeoMatrix::kGeoReflection);" << endl;
02425    TObject::SetBit(kGeoSavePrimitive);
02426 }

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