TGeoNavigator.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoNavigator.cxx 35671 2010-09-23 14:57:00Z agheata $
00002 // Author: Mihaela Gheata   30/05/07
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  
00012 //_____________________________________________________________________________
00013 // TGeoNavigator
00014 //===============
00015 //
00016 //   Class providing navigation API for TGeo geometries. Several instances are 
00017 // allowed for a single geometry.
00018 // A default navigator is provided for any geometry but one may add several 
00019 // others for parallel navigation:
00020 //      
00021 //      TGeoNavigator *navig = new TGeoNavigator(gGeoManager);
00022 //      Int_t inav = gGeoManager->AddNavigator(navig);
00023 //      gGeoManager->SetCurrentNavigator(inav);
00024 //
00025 //      .... and then switch back to the default navigator:
00026 //
00027 //      gGeoManager->SetCurrentNavigator(0);
00028 //_____________________________________________________________________________
00029 
00030 #include "TGeoManager.h"
00031 #include "TGeoMatrix.h"
00032 #include "TGeoNode.h"
00033 #include "TGeoVolume.h"
00034 #include "TGeoPatternFinder.h"
00035 #include "TGeoVoxelFinder.h"
00036 #include "TMath.h"
00037 
00038 #include "TGeoNavigator.h"
00039 
00040 static Double_t gTolerance = TGeoShape::Tolerance();
00041 const char *kGeoOutsidePath = " ";
00042 const Int_t kN3 = 3*sizeof(Double_t);
00043 
00044 ClassImp(TGeoNavigator)
00045 
00046 //_____________________________________________________________________________
00047 TGeoNavigator::TGeoNavigator()
00048               :fStep(0.),
00049                fSafety(0.),
00050                fLastSafety(0.),
00051                fLevel(0),
00052                fNmany(0),
00053                fNextDaughterIndex(0),
00054                fOverlapSize(0),
00055                fOverlapMark(0),
00056                fOverlapClusters(0),
00057                fSearchOverlaps(kFALSE),
00058                fCurrentOverlapping(kFALSE),
00059                fStartSafe(kFALSE),
00060                fIsEntering(kFALSE),
00061                fIsExiting(kFALSE),
00062                fIsStepEntering(kFALSE),
00063                fIsStepExiting(kFALSE),
00064                fIsOutside(kFALSE),
00065                fIsOnBoundary(kFALSE),
00066                fIsSameLocation(kFALSE),
00067                fIsNullStep(kFALSE),
00068                fGeometry(0),
00069                fCache(0),
00070                fCurrentVolume(0),
00071                fCurrentNode(0),
00072                fTopNode(0),
00073                fLastNode(0),
00074                fNextNode(0),
00075                fForcedNode(0),
00076                fBackupState(0),
00077                fCurrentMatrix(0),
00078                fGlobalMatrix(0),
00079                fPath()
00080                 
00081 {
00082 // dummy constructor
00083    for (Int_t i=0; i<3; i++) {
00084       fNormal[i] = 0.;
00085       fCldir[i] = 0.;
00086       fCldirChecked[i] = 0.;
00087       fPoint[i] = 0.;
00088       fDirection[i] = 0.;
00089       fLastPoint[i] = 0.;
00090    }
00091 }
00092 
00093 //_____________________________________________________________________________
00094 TGeoNavigator::TGeoNavigator(TGeoManager* geom)
00095               :fStep(0.),
00096                fSafety(0.),
00097                fLastSafety(0.),
00098                fLevel(0),
00099                fNmany(0),
00100                fNextDaughterIndex(-2),
00101                fOverlapSize(1000),
00102                fOverlapMark(0),
00103                fOverlapClusters(0),
00104                fSearchOverlaps(kFALSE),
00105                fCurrentOverlapping(kFALSE),
00106                fStartSafe(kTRUE),
00107                fIsEntering(kFALSE),
00108                fIsExiting(kFALSE),
00109                fIsStepEntering(kFALSE),
00110                fIsStepExiting(kFALSE),
00111                fIsOutside(kFALSE),
00112                fIsOnBoundary(kFALSE),
00113                fIsSameLocation(kTRUE),
00114                fIsNullStep(kFALSE),
00115                fGeometry(geom),
00116                fCache(0),
00117                fCurrentVolume(0),
00118                fCurrentNode(0),
00119                fTopNode(0),
00120                fLastNode(0),
00121                fNextNode(0),
00122                fForcedNode(0),
00123                fBackupState(0),
00124                fCurrentMatrix(0),
00125                fGlobalMatrix(0),
00126                fPath()
00127                 
00128 {
00129 // Default constructor.
00130    for (Int_t i=0; i<3; i++) {
00131       fNormal[i] = 0.;
00132       fCldir[i] = 0.;
00133       fCldirChecked[i] = 0;
00134       fPoint[i] = 0.;
00135       fDirection[i] = 0.;
00136       fLastPoint[i] = 0.;
00137    }
00138    fCurrentMatrix = new TGeoHMatrix();
00139    fCurrentMatrix->RegisterYourself();
00140    fOverlapClusters = new Int_t[fOverlapSize];
00141 }      
00142 
00143 //_____________________________________________________________________________
00144 TGeoNavigator::TGeoNavigator(const TGeoNavigator& gm)
00145               :TObject(gm),
00146                fStep(gm.fStep),
00147                fSafety(gm.fSafety),
00148                fLastSafety(gm.fLastSafety),
00149                fLevel(gm.fLevel),
00150                fNmany(gm.fNmany),
00151                fNextDaughterIndex(gm.fNextDaughterIndex),
00152                fOverlapSize(gm.fOverlapSize),
00153                fOverlapMark(gm.fOverlapMark),
00154                fOverlapClusters(gm.fOverlapClusters),
00155                fSearchOverlaps(gm.fSearchOverlaps),
00156                fCurrentOverlapping(gm.fCurrentOverlapping),
00157                fStartSafe(gm.fStartSafe),
00158                fIsEntering(gm.fIsEntering),
00159                fIsExiting(gm.fIsExiting),
00160                fIsStepEntering(gm.fIsStepEntering),
00161                fIsStepExiting(gm.fIsStepExiting),
00162                fIsOutside(gm.fIsOutside),
00163                fIsOnBoundary(gm.fIsOnBoundary),
00164                fIsSameLocation(gm.fIsSameLocation),
00165                fIsNullStep(gm.fIsNullStep),
00166                fGeometry(gm.fGeometry),
00167                fCache(gm.fCache),
00168                fCurrentVolume(gm.fCurrentVolume),
00169                fCurrentNode(gm.fCurrentNode),
00170                fTopNode(gm.fTopNode),
00171                fLastNode(gm.fLastNode),
00172                fNextNode(gm.fNextNode),
00173                fForcedNode(gm.fForcedNode),
00174                fBackupState(gm.fBackupState),
00175                fCurrentMatrix(gm.fCurrentMatrix),
00176                fGlobalMatrix(gm.fGlobalMatrix),
00177                fPath(gm.fPath)               
00178 {
00179 // Copy constructor.
00180    for (Int_t i=0; i<3; i++) {
00181       fNormal[i] = gm.fNormal[i];
00182       fCldir[i] = gm.fCldir[i];
00183       fCldirChecked[i] = gm.fCldirChecked[i];
00184       fPoint[i] = gm.fPoint[i];
00185       fDirection[i] = gm.fDirection[i];
00186       fLastPoint[i] = gm.fLastPoint[i];
00187    }
00188 }      
00189 
00190 //_____________________________________________________________________________
00191 TGeoNavigator& TGeoNavigator::operator=(const TGeoNavigator& gm)
00192 {
00193    //assignment operator
00194    if(this!=&gm) {
00195       TObject::operator=(gm);
00196       fStep = gm.fStep;
00197       fSafety = gm.fSafety;
00198       fLastSafety = gm.fLastSafety;
00199       fLevel = gm.fLevel;
00200       fNmany = gm.fNmany;
00201       fNextDaughterIndex = gm.fNextDaughterIndex;
00202       fOverlapSize=gm.fOverlapSize;
00203       fOverlapMark=gm.fOverlapMark;
00204       fOverlapClusters=gm.fOverlapClusters;
00205       fSearchOverlaps = gm.fSearchOverlaps;
00206       fCurrentOverlapping = gm.fCurrentOverlapping;
00207       fStartSafe = gm.fStartSafe;
00208       fIsEntering = gm.fIsEntering;
00209       fIsExiting = gm.fIsExiting;
00210       fIsStepEntering = gm.fIsStepEntering;
00211       fIsStepExiting = gm.fIsStepExiting;
00212       fIsOutside = gm.fIsOutside;
00213       fIsOnBoundary = gm.fIsOnBoundary;
00214       fIsSameLocation = gm.fIsSameLocation;
00215       fIsNullStep = gm.fIsNullStep;
00216       fGeometry = gm.fGeometry;
00217       fCache = gm.fCache;
00218       fCurrentVolume = gm.fCurrentVolume;
00219       fCurrentNode = gm.fCurrentNode;
00220       fTopNode = gm.fTopNode;
00221       fLastNode = gm.fLastNode;
00222       fNextNode = gm.fNextNode;
00223       fForcedNode = gm.fForcedNode;
00224       fBackupState = gm.fBackupState;
00225       fCurrentMatrix = gm.fCurrentMatrix;
00226       fGlobalMatrix = gm.fGlobalMatrix;
00227       fPath = gm.fPath;
00228       for (Int_t i=0; i<3; i++) {
00229          fNormal[i] = gm.fNormal[i];
00230          fCldir[i] = gm.fCldir[i];
00231          fCldirChecked[i] = gm.fCldirChecked[i];
00232          fPoint[i] = gm.fPoint[i];
00233          fDirection[i] = gm.fDirection[i];
00234          fLastPoint[i] = gm.fLastPoint[i];
00235       }
00236    }
00237    return *this;   
00238 }
00239 
00240 //_____________________________________________________________________________
00241 TGeoNavigator::~TGeoNavigator()
00242 {
00243 // Destructor.
00244    if (fCache) delete fCache;
00245    if (fBackupState) delete fBackupState;
00246    if (fOverlapClusters) delete [] fOverlapClusters;
00247 }
00248    
00249 //_____________________________________________________________________________
00250 void TGeoNavigator::BuildCache(Bool_t /*dummy*/, Bool_t nodeid)
00251 {
00252 // Builds the cache for physical nodes and global matrices.
00253    static Bool_t first = kTRUE;
00254    Int_t nlevel = fGeometry->GetMaxLevel();
00255    if (nlevel<=0) nlevel = 100;
00256    if (!fCache) {
00257       if (nlevel==100) {
00258          if (first) Info("BuildCache","--- Maximum geometry depth set to 100");
00259       } else {
00260          if (first) Info("BuildCache","--- Maximum geometry depth is %i", nlevel);   
00261       }   
00262       // build cache
00263       fCache = new TGeoNodeCache(fGeometry->GetTopNode(), nodeid, nlevel+1);
00264       fGlobalMatrix = fCache->GetCurrentMatrix();
00265       fBackupState = new TGeoCacheState(nlevel+1);
00266    }
00267    first = kFALSE;
00268 }
00269 
00270 //_____________________________________________________________________________
00271 Bool_t TGeoNavigator::cd(const char *path)
00272 {
00273 // Browse the tree of nodes starting from top node according to pathname.
00274 // Changes the path accordingly.
00275    if (!strlen(path)) return kFALSE;
00276    CdTop();
00277    TString spath = path;
00278    TGeoVolume *vol;
00279    Int_t length = spath.Length();
00280    Int_t ind1 = spath.Index("/");
00281    Int_t ind2 = 0;
00282    Bool_t end = kFALSE;
00283    TString name;
00284    TGeoNode *node;
00285    while (!end) {
00286       ind2 = spath.Index("/", ind1+1);
00287       if (ind2<0) {
00288          ind2 = length;
00289          end  = kTRUE;
00290       }
00291       name = spath(ind1+1, ind2-ind1-1);
00292       if (name==fGeometry->GetTopNode()->GetName()) {
00293          ind1 = ind2;
00294          continue;
00295       }
00296       vol = fCurrentNode->GetVolume();
00297       if (vol) {
00298          node = vol->GetNode(name.Data());
00299       } else node = 0;
00300       if (!node) {
00301          Error("cd", "Path %s not valid", path);
00302          return kFALSE;
00303       }
00304       CdDown(fCurrentNode->GetVolume()->GetIndex(node));
00305       ind1 = ind2;
00306    }
00307    return kTRUE;
00308 }
00309 
00310 //_____________________________________________________________________________
00311 Bool_t TGeoNavigator::CheckPath(const char *path) const
00312 {
00313 // Check if a geometry path is valid without changing the state of the navigator.
00314    Int_t length = strlen(path);
00315    if (!length) return kFALSE;
00316    TString spath = path;
00317    TGeoVolume *vol;
00318    TGeoNode *top = fGeometry->GetTopNode();
00319    // Check first occurance of a '/'
00320    Int_t ind1 = spath.Index("/");
00321    if (ind1<0) {
00322       // No '/' so we check directly the path against the name of the top
00323       if (strcmp(path,top->GetName())) return kFALSE;
00324       return kTRUE;
00325    }   
00326    Int_t ind2 = ind1;
00327    Bool_t end = kFALSE;
00328    if (ind1>0) ind1 = -1;   // no trailing '/'
00329    else ind2 = spath.Index("/", ind1+1);
00330    if (ind2<0) ind2 = length;
00331    TString name(spath(ind1+1, ind2-ind1-1));
00332    if (name==top->GetName()) {
00333       if (ind2>=length-1) return kTRUE;
00334       ind1 = ind2;
00335    } else return kFALSE;  
00336    TGeoNode *node = top;
00337    // Deeper than just top level
00338    while (!end) {
00339       ind2 = spath.Index("/", ind1+1);
00340       if (ind2<0) {
00341          ind2 = length;
00342          end  = kTRUE;
00343       }
00344       vol = node->GetVolume();
00345       name = spath(ind1+1, ind2-ind1-1);
00346       node = vol->GetNode(name.Data());
00347       if (!node) return kFALSE;
00348       if (ind2>=length-1) return kTRUE;
00349       ind1 = ind2;
00350    }
00351    return kTRUE;
00352 }
00353 
00354 //_____________________________________________________________________________
00355 void TGeoNavigator::CdNode(Int_t nodeid)
00356 {
00357 // Change current path to point to the node having this id.
00358 // Node id has to be in range : 0 to fNNodes-1 (no check for performance reasons)
00359    if (fCache) {
00360       fCache->CdNode(nodeid);
00361       fGlobalMatrix = fCache->GetCurrentMatrix();
00362    }   
00363 }
00364 
00365 //_____________________________________________________________________________
00366 void TGeoNavigator::CdDown(Int_t index)
00367 {
00368 // Make a daughter of current node current. Can be called only with a valid
00369 // daughter index (no check). Updates cache accordingly.
00370    if (!fCache) return;
00371    TGeoNode *node = fCurrentNode->GetDaughter(index);
00372    Bool_t is_offset = node->IsOffset();
00373    if (is_offset)
00374       node->cd();
00375    else
00376       fCurrentOverlapping = node->IsOverlapping();
00377    fCache->CdDown(index);
00378    fCurrentNode = node;
00379    fGlobalMatrix = fCache->GetCurrentMatrix();
00380    if (fCurrentOverlapping) fNmany++;
00381    fLevel++;
00382 }
00383 
00384 
00385 //_____________________________________________________________________________
00386 void TGeoNavigator::CdUp()
00387 {
00388 // Go one level up in geometry. Updates cache accordingly.
00389 // Determine the overlapping state of current node.
00390    if (!fLevel || !fCache) return;
00391    fLevel--;
00392    if (!fLevel) {
00393       CdTop();
00394       return;
00395    }
00396    fCache->CdUp();
00397    if (fCurrentOverlapping) {
00398       fLastNode = fCurrentNode;
00399       fNmany--;
00400    }   
00401    fCurrentNode = fCache->GetNode();
00402    fGlobalMatrix = fCache->GetCurrentMatrix();
00403    if (!fCurrentNode->IsOffset()) {
00404       fCurrentOverlapping = fCurrentNode->IsOverlapping();
00405    } else {
00406       Int_t up = 1;
00407       Bool_t offset = kTRUE;
00408       TGeoNode *mother = 0;
00409       while  (offset) {
00410          mother = GetMother(up++);
00411          offset = mother->IsOffset();
00412       }
00413       fCurrentOverlapping = mother->IsOverlapping();
00414    }      
00415 }
00416 
00417 //_____________________________________________________________________________
00418 void TGeoNavigator::CdTop()
00419 {
00420 // Make top level node the current node. Updates the cache accordingly.
00421 // Determine the overlapping state of current node.
00422    if (!fCache) return;
00423    fLevel = 0;
00424    fNmany = 0;
00425    if (fCurrentOverlapping) fLastNode = fCurrentNode;
00426    fCurrentNode = fGeometry->GetTopNode();
00427    fCache->CdTop();
00428    fGlobalMatrix = fCache->GetCurrentMatrix();
00429    fCurrentOverlapping = fCurrentNode->IsOverlapping();
00430    if (fCurrentOverlapping) fNmany++;
00431 }
00432 
00433 //_____________________________________________________________________________
00434 void TGeoNavigator::CdNext()
00435 {
00436 // Do a cd to the node found next by FindNextBoundary
00437    if (fNextDaughterIndex == -2 || !fCache) return;
00438    if (fNextDaughterIndex ==  -3) {
00439       // Next node is a many - restore it
00440       DoRestoreState();
00441       fNextDaughterIndex = -2;
00442       return;
00443    }   
00444    if (fNextDaughterIndex == -1) {
00445       CdUp();
00446       while (fCurrentNode->GetVolume()->IsAssembly()) CdUp();
00447       fNextDaughterIndex--;
00448       return;
00449    }
00450    if (fCurrentNode && fNextDaughterIndex<fCurrentNode->GetNdaughters()) {
00451       CdDown(fNextDaughterIndex);
00452       Int_t nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
00453       while (nextindex>=0) {
00454          CdDown(nextindex);
00455          nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
00456       }   
00457    }
00458    fNextDaughterIndex = -2;
00459 }   
00460 
00461 //_____________________________________________________________________________
00462 void TGeoNavigator::GetBranchNames(Int_t *names) const
00463 {
00464 // Fill volume names of current branch into an array.
00465    fCache->GetBranchNames(names);
00466 }
00467 
00468 //_____________________________________________________________________________
00469 void TGeoNavigator::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
00470 {
00471 // Fill node copy numbers of current branch into an array.
00472    fCache->GetBranchNumbers(copyNumbers, volumeNumbers);
00473 }
00474 
00475 //_____________________________________________________________________________
00476 void TGeoNavigator::GetBranchOnlys(Int_t *isonly) const
00477 {
00478 // Fill node copy numbers of current branch into an array.
00479    fCache->GetBranchOnlys(isonly);
00480 }
00481 
00482 //_____________________________________________________________________________
00483 TGeoNode *TGeoNavigator::CrossDivisionCell()
00484 {
00485 // Cross a division cell. Distance to exit contained in fStep, current node
00486 // points to the cell node.
00487    TGeoPatternFinder *finder = fCurrentNode->GetFinder();
00488    if (!finder) {
00489       Fatal("CrossDivisionCell", "Volume has no pattern finder");
00490       return 0;
00491    }
00492    // Mark current node and go up to the level of the divided volume
00493    TGeoNode *skip = fCurrentNode;
00494    CdUp();
00495    Double_t point[3], newpoint[3], dir[3];
00496    fGlobalMatrix->MasterToLocal(fPoint, newpoint);
00497    fGlobalMatrix->MasterToLocalVect(fDirection, dir);
00498    // Does step cross a boundary along division axis ?
00499    Bool_t onbound = finder->IsOnBoundary(newpoint);
00500    if (onbound) {
00501       // Work along division axis
00502       // Get the starting point
00503       point[0] = newpoint[0] - dir[0]*fStep*(1.-gTolerance);
00504       point[1] = newpoint[1] - dir[1]*fStep*(1.-gTolerance);
00505       point[2] = newpoint[2] - dir[2]*fStep*(1.-gTolerance);
00506       // Find which is the next crossed cell.
00507       finder->FindNode(point, dir);
00508       Int_t inext = finder->GetNext();
00509       if (inext<0) {
00510          // step fully exits the division along the division axis
00511          // Do step exits in a mother cell ?
00512          if (fCurrentNode->IsOffset()) {
00513             Double_t dist = fCurrentNode->GetVolume()->GetShape()->DistFromInside(point,dir,3);
00514             // Do step exit also from mother cell ?
00515             if (dist < fStep+2.*gTolerance) {
00516                // Step exits mother on its own division axis
00517                return CrossDivisionCell();
00518             }
00519             // We end up here
00520             return fCurrentNode;
00521          }   
00522          // Exiting in a non-divided volume
00523          while (fCurrentNode->GetVolume()->IsAssembly()) {
00524             // Move always to mother for assemblies
00525             skip = fCurrentNode;
00526             if (!fLevel) break;
00527             CdUp();
00528          } 
00529          return CrossBoundaryAndLocate(kFALSE, skip);
00530       }
00531       // step enters a new cell
00532       CdDown(inext+finder->GetDivIndex());
00533       skip = fCurrentNode;
00534       return CrossBoundaryAndLocate(kTRUE, skip);
00535    }
00536    // step exits on an axis other than the division axis -> get next slice
00537    if (fCurrentNode->IsOffset()) return CrossDivisionCell();
00538    return CrossBoundaryAndLocate(kFALSE, skip);
00539 }
00540    
00541 //_____________________________________________________________________________
00542 TGeoNode *TGeoNavigator::CrossBoundaryAndLocate(Bool_t downwards, TGeoNode *skipnode)
00543 {
00544 // Cross next boundary and locate within current node
00545 // The current point must be on the boundary of fCurrentNode.
00546 
00547 // Extrapolate current point with estimated error.
00548    Double_t *tr = fGlobalMatrix->GetTranslation();
00549    Double_t trmax = 1.+TMath::Abs(tr[0])+TMath::Abs(tr[1])+TMath::Abs(tr[2]);
00550    Double_t extra = 100.*(trmax+fStep)*gTolerance;
00551    fPoint[0] += extra*fDirection[0];
00552    fPoint[1] += extra*fDirection[1];
00553    fPoint[2] += extra*fDirection[2];
00554    TGeoNode *current = SearchNode(downwards, skipnode);
00555    fForcedNode = 0;
00556    fPoint[0] -= extra*fDirection[0];
00557    fPoint[1] -= extra*fDirection[1];
00558    fPoint[2] -= extra*fDirection[2];
00559    if (!current) return 0;
00560    if (downwards) {
00561       Int_t nextindex = current->GetVolume()->GetNextNodeIndex();
00562       while (nextindex>=0) {
00563          CdDown(nextindex);
00564          current = fCurrentNode;
00565          nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
00566       }
00567       return current;   
00568    }   
00569      
00570    if ((skipnode && current == skipnode) || current->GetVolume()->IsAssembly()) {
00571       if (!fLevel) {
00572          fIsOutside = kTRUE;
00573          return fGeometry->GetCurrentNode();
00574       }
00575       CdUp();
00576       while (fLevel && fCurrentNode->GetVolume()->IsAssembly()) CdUp();
00577       if (!fLevel && fCurrentNode->GetVolume()->IsAssembly()) {
00578          fIsOutside = kTRUE;
00579          return fCurrentNode;
00580       }
00581       return fCurrentNode;
00582    }
00583    return current;
00584 }   
00585    
00586 //_____________________________________________________________________________
00587 TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax, const char *path, Bool_t frombdr)
00588 {
00589 // Find distance to next boundary and store it in fStep. Returns node to which this
00590 // boundary belongs. If PATH is specified, compute only distance to the node to which
00591 // PATH points. If STEPMAX is specified, compute distance only in case fSafety is smaller
00592 // than this value. STEPMAX represent the step to be made imposed by other reasons than
00593 // geometry (usually physics processes). Therefore in this case this method provides the
00594 // answer to the question : "Is STEPMAX a safe step ?" returning a NULL node and filling
00595 // fStep with a big number.
00596 // In case frombdr=kTRUE, the isotropic safety is set to zero.
00597 // Note : safety distance for the current point is computed ONLY in case STEPMAX is
00598 //        specified, otherwise users have to call explicitly TGeoManager::Safety() if
00599 //        they want this computed for the current point.
00600 
00601    // convert current point and direction to local reference
00602    Int_t iact = 3;
00603    Int_t idebug = TGeoManager::GetVerboseLevel();
00604    fNextDaughterIndex = -2;
00605    fStep = TGeoShape::Big();
00606    fIsStepEntering = kFALSE;
00607    fIsStepExiting = kFALSE;
00608    fForcedNode = 0;
00609    Bool_t computeGlobal = kFALSE;
00610    fIsOnBoundary = frombdr;
00611    fSafety = 0.;
00612    TGeoNode *top_node = fGeometry->GetTopNode();
00613    TGeoVolume *top_volume = top_node->GetVolume();
00614    if (stepmax<1E29) {
00615       if (stepmax <= 0) {
00616          stepmax = - stepmax;
00617          computeGlobal = kTRUE;
00618       }
00619       // Try to get out easy if proposed step within safe region
00620       if (!frombdr && IsSafeStep(stepmax+gTolerance, fSafety)) {
00621          fStep = stepmax;
00622          fNextNode = fCurrentNode;
00623          return fCurrentNode;
00624       }   
00625 //      if (fLastSafety>0 && IsSamePoint(fPoint[0], fPoint[1], fPoint[2])) fSafety = fLastSafety;
00626       fSafety = Safety();
00627       fSafety = TMath::Abs(fSafety);
00628       memcpy(fLastPoint, fPoint, kN3);
00629       fLastSafety = fSafety;
00630       if (fSafety<gTolerance) fIsOnBoundary = kTRUE;
00631       else fIsOnBoundary = kFALSE;
00632       fStep = stepmax;
00633       if (stepmax+gTolerance<fSafety) {
00634          fNextNode = fCurrentNode;
00635          return fCurrentNode;
00636       }   
00637    }
00638    if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
00639    Double_t snext  = TGeoShape::Big();
00640    Double_t safe;
00641    Double_t point[3];
00642    Double_t dir[3];
00643    if (idebug>4) {
00644       printf("TGeoManager::FindNextBoundary:  point=(%19.16f, %19.16f, %19.16f)\n",
00645              fPoint[0],fPoint[1],fPoint[2]);
00646       printf("                                dir=  (%19.16f, %19.16f, %19.16f)\n",
00647              fDirection[0], fDirection[1], fDirection[2]);
00648       printf("  pstep=%9.6g  path=%s\n", stepmax, GetPath());
00649    }   
00650    if (strlen(path)) {
00651       PushPath();
00652       if (!cd(path)) {
00653          PopPath();
00654          return 0;
00655       }
00656       if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
00657       fNextNode = fCurrentNode;
00658       TGeoVolume *tvol=fCurrentNode->GetVolume();
00659       fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
00660       fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
00661       if (tvol->Contains(&point[0])) {
00662          fStep=tvol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
00663       } else {
00664          fStep=tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, fStep, &safe);
00665       }
00666       PopPath();
00667       return fNextNode;
00668    }
00669    // compute distance to exit point from current node and the distance to its
00670    // closest boundary
00671    // if point is outside, just check the top node
00672    if (fIsOutside) {
00673       snext = top_volume->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep, &safe);
00674       fNextNode = top_node;
00675       if (snext < fStep-gTolerance) {
00676          fIsStepEntering = kTRUE;
00677          fStep = snext;
00678          Int_t indnext = fNextNode->GetVolume()->GetNextNodeIndex();
00679          fNextDaughterIndex = indnext;
00680          while (indnext>=0) {
00681             fNextNode = fNextNode->GetDaughter(indnext);
00682             if (computeGlobal) fCurrentMatrix->Multiply(fNextNode->GetMatrix());
00683             indnext = fNextNode->GetVolume()->GetNextNodeIndex();
00684          }
00685          return fNextNode;
00686       }
00687       return 0;
00688    }
00689    fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
00690    fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
00691    TGeoVolume *vol = fCurrentNode->GetVolume();
00692    if (idebug>4) {
00693       printf("   -> from local=(%19.16f, %19.16f, %19.16f)\n",
00694              point[0],point[1],point[2]);
00695       printf("           ldir =(%19.16f, %19.16f, %19.16f)\n",
00696              dir[0],dir[1],dir[2]);             
00697    }           
00698    // find distance to exiting current node
00699    snext = vol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
00700    if (idebug>4) {
00701       printf("      exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
00702    }   
00703    if (snext < fStep-gTolerance) {
00704       fNextNode = fCurrentNode;
00705       fNextDaughterIndex = -1;
00706       fIsStepExiting  = kTRUE;
00707       fStep = snext;
00708       fIsStepEntering = kFALSE;
00709       if (fStep<1E-6) return fCurrentNode;
00710    }
00711    fNextNode = (fStep<1E20)?fCurrentNode:0;
00712    // Find next daughter boundary for the current volume
00713    Int_t idaughter = -1;
00714    FindNextDaughterBoundary(point,dir,idaughter,computeGlobal);
00715    if (idaughter>=0) fNextDaughterIndex = idaughter;
00716    TGeoNode *current = 0;
00717    TGeoNode *dnode = 0;
00718    TGeoVolume *mother = 0;
00719    // if we are in an overlapping node, check also the mother(s)
00720    if (fNmany) {
00721       Double_t mothpt[3];
00722       Double_t vecpt[3];
00723       Double_t dpt[3], dvec[3];
00724       Int_t novlps;
00725       Int_t idovlp = -1;
00726       Int_t safelevel = GetSafeLevel();
00727       PushPath(safelevel+1);
00728       while (fCurrentOverlapping) {
00729          Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
00730          CdUp();
00731          mother = fCurrentNode->GetVolume();
00732          fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
00733          fGlobalMatrix->MasterToLocalVect(fDirection, &vecpt[0]);
00734          // check distance to out
00735          snext = TGeoShape::Big();
00736          if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(&mothpt[0], &vecpt[0], iact, fStep, &safe);
00737          if (snext<fStep-gTolerance) {
00738             fIsStepExiting  = kTRUE;
00739             fIsStepEntering = kFALSE;
00740             fStep = snext;
00741             if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
00742             fNextNode = fCurrentNode;
00743             fNextDaughterIndex = -3;
00744             DoBackupState();
00745          }
00746          // check overlapping nodes
00747          for (Int_t i=0; i<novlps; i++) {
00748             current = mother->GetNode(ovlps[i]);
00749             if (!current->IsOverlapping()) {
00750                current->cd();
00751                current->MasterToLocal(&mothpt[0], &dpt[0]);
00752                current->MasterToLocalVect(&vecpt[0], &dvec[0]);
00753                // Current point may be inside the other node - geometry error that we ignore
00754                snext = TGeoShape::Big();
00755                if (!current->GetVolume()->Contains(dpt))
00756                   snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
00757                if (snext<fStep-gTolerance) {
00758                   if (computeGlobal) {
00759                      fCurrentMatrix->CopyFrom(fGlobalMatrix);
00760                      fCurrentMatrix->Multiply(current->GetMatrix());
00761                   }
00762                   fIsStepExiting  = kTRUE;
00763                   fIsStepEntering = kFALSE;
00764                   fStep = snext;
00765                   fNextNode = current;
00766                   fNextDaughterIndex = -3;
00767                   CdDown(ovlps[i]);
00768                   DoBackupState();
00769                   CdUp();
00770                }
00771             } else {
00772                // another many - check if point is in or out
00773                current->cd();
00774                current->MasterToLocal(&mothpt[0], &dpt[0]);
00775                current->MasterToLocalVect(&vecpt[0], &dvec[0]);
00776                if (current->GetVolume()->Contains(dpt)) {
00777                   if (current->GetVolume()->GetNdaughters()) {
00778                      CdDown(ovlps[i]);
00779                      fIsStepEntering  = kFALSE;
00780                      fIsStepExiting  = kTRUE;
00781                      dnode = FindNextDaughterBoundary(dpt,dvec,idovlp,computeGlobal);
00782                      if (dnode) {
00783                         if (computeGlobal) {
00784                            fCurrentMatrix->CopyFrom(fGlobalMatrix);
00785                            fCurrentMatrix->Multiply(dnode->GetMatrix());
00786                         }   
00787                         fNextNode = dnode;
00788                         fNextDaughterIndex = -3;
00789                         CdDown(idovlp);
00790                         Int_t indnext = fCurrentNode->GetVolume()->GetNextNodeIndex();
00791                         Int_t iup=0;
00792                         while (indnext>=0) {
00793                            CdDown(indnext);
00794                            iup++;
00795                            indnext = fCurrentNode->GetVolume()->GetNextNodeIndex();
00796                         }   
00797                         DoBackupState();
00798                         while (iup>0) {
00799                            CdUp();
00800                            iup--;
00801                         }   
00802                         CdUp();
00803                      }
00804                      CdUp();
00805                   }   
00806                } else {
00807                   snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
00808                   if (snext<fStep-gTolerance) {
00809                      if (computeGlobal) {
00810                         fCurrentMatrix->CopyFrom(fGlobalMatrix);
00811                         fCurrentMatrix->Multiply(current->GetMatrix());
00812                      }
00813                      fIsStepExiting  = kTRUE;
00814                      fIsStepEntering = kFALSE;
00815                      fStep = snext;
00816                      fNextNode = current;
00817                      fNextDaughterIndex = -3;
00818                      CdDown(ovlps[i]);
00819                      DoBackupState();
00820                      CdUp();
00821                   }               
00822                }  
00823             }
00824          }
00825       }
00826       // Now we are in a non-overlapping node
00827       if (fNmany) {
00828       // We have overlaps up in the branch, check distance to exit
00829          Int_t up = 1;
00830          Int_t imother;
00831          Int_t nmany = fNmany;
00832          Bool_t ovlp = kFALSE;
00833          Bool_t nextovlp = kFALSE;
00834          Bool_t offset = kFALSE;
00835          TGeoNode *currentnode = fCurrentNode;
00836          TGeoNode *mothernode, *mup;
00837          TGeoHMatrix *matrix;
00838          while (nmany) {
00839             mothernode = GetMother(up);
00840             mup = mothernode;
00841             imother = up+1;
00842             offset = kFALSE;
00843             while (mup->IsOffset()) {
00844                mup = GetMother(imother++);
00845                offset = kTRUE;
00846             }   
00847             nextovlp = mup->IsOverlapping();
00848             if (offset) {
00849                mothernode = mup;
00850                if (nextovlp) nmany -= imother-up;
00851                up = imother-1;
00852             } else {    
00853                if (ovlp) nmany--;
00854             }   
00855             if (ovlp || nextovlp) {
00856                matrix = GetMotherMatrix(up);
00857                matrix->MasterToLocal(fPoint,dpt);
00858                matrix->MasterToLocalVect(fDirection,dvec);
00859                snext = TGeoShape::Big();
00860                if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
00861                if (snext<fStep-gTolerance) {
00862                   fIsStepEntering  = kFALSE;
00863                   fIsStepExiting  = kTRUE;
00864                   fStep = snext;
00865                   fNextNode = mothernode;
00866                   fNextDaughterIndex = -3;
00867                   if (computeGlobal) fCurrentMatrix->CopyFrom(matrix);
00868                   while (up--) CdUp();
00869                   DoBackupState();
00870                   up = 1;
00871                   currentnode = fCurrentNode;
00872                   ovlp = currentnode->IsOverlapping();
00873                   continue;
00874                }   
00875             }   
00876             currentnode = mothernode;
00877             ovlp = nextovlp;
00878             up++;            
00879          }
00880       }      
00881       PopPath();
00882    }
00883    return fNextNode;
00884 }
00885 
00886 //_____________________________________________________________________________
00887 TGeoNode *TGeoNavigator::FindNextDaughterBoundary(Double_t *point, Double_t *dir, Int_t &idaughter, Bool_t compmatrix)
00888 {
00889 // Computes as fStep the distance to next daughter of the current volume. 
00890 // The point and direction must be converted in the coordinate system of the current volume.
00891 // The proposed step limit is fStep.
00892 
00893    Double_t snext = TGeoShape::Big();
00894    Int_t idebug = TGeoManager::GetVerboseLevel();
00895    idaughter = -1; // nothing crossed
00896    TGeoNode *nodefound = 0;
00897    // Get number of daughters. If no daughters we are done.
00898 
00899    TGeoVolume *vol = fCurrentNode->GetVolume();
00900    Int_t nd = vol->GetNdaughters();
00901    if (!nd) return 0;  // No daughter 
00902    if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters()) return 0;
00903    Double_t lpoint[3], ldir[3];
00904    TGeoNode *current = 0;
00905    Int_t i=0;
00906    // if current volume is divided, we are in the non-divided region. We
00907    // check first if we are inside a cell in which case compute distance to next cell
00908    TGeoPatternFinder *finder = vol->GetFinder();
00909    if (finder) {
00910       Int_t ifirst = finder->GetDivIndex();
00911       Int_t ilast = ifirst+finder->GetNdiv()-1;
00912       current = finder->FindNode(point);
00913       if (current) {
00914          // Point inside a cell: find distance to next cell
00915          Int_t index = current->GetIndex();
00916          if ((index-1) >= ifirst) ifirst = index-1;
00917          else                     ifirst = -1;
00918          if ((index+1) <= ilast)  ilast  = index+1;
00919          else                     ilast  = -1;
00920       }
00921       if (ifirst>=0) {   
00922          current = vol->GetNode(ifirst);
00923          current->cd();
00924          current->MasterToLocal(&point[0], lpoint);
00925          current->MasterToLocalVect(&dir[0], ldir);
00926          snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
00927          if (snext<fStep-gTolerance) {
00928             if (compmatrix) {
00929                fCurrentMatrix->CopyFrom(fGlobalMatrix);
00930                fCurrentMatrix->Multiply(current->GetMatrix());
00931             }
00932             fIsStepExiting  = kFALSE;
00933             fIsStepEntering = kTRUE;
00934             fStep=snext;
00935             fNextNode = current;
00936             nodefound = current;
00937             idaughter = ifirst;
00938          }
00939       }   
00940       if (ilast==ifirst) return nodefound;
00941       if (ilast>=0) { 
00942          current = vol->GetNode(ilast);
00943          current->cd();
00944          current->MasterToLocal(&point[0], lpoint);
00945          current->MasterToLocalVect(&dir[0], ldir);
00946          snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
00947          if (snext<fStep-gTolerance) {
00948             if (compmatrix) {
00949                fCurrentMatrix->CopyFrom(fGlobalMatrix);
00950                fCurrentMatrix->Multiply(current->GetMatrix());
00951             }
00952             fIsStepExiting  = kFALSE;
00953             fIsStepEntering = kTRUE;
00954             fStep=snext;
00955             fNextNode = current;
00956             nodefound = current;
00957             idaughter = ilast;
00958          }
00959       }   
00960       return nodefound;
00961    }
00962    // if only few daughters, check all and exit
00963    TGeoVoxelFinder *voxels = vol->GetVoxels();
00964    Int_t indnext;
00965    if (idebug>4) printf("   Checking distance to %d daughters...\n",nd);
00966    if (nd<5 || !voxels) {
00967       for (i=0; i<nd; i++) {
00968          current = vol->GetNode(i);
00969          if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
00970          current->cd();
00971          if (voxels && voxels->IsSafeVoxel(point, i, fStep)) continue;
00972          current->MasterToLocal(point, lpoint);
00973          current->MasterToLocalVect(dir, ldir);
00974          if (current->IsOverlapping() && current->GetVolume()->Contains(lpoint)) continue;
00975          snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
00976          if (snext<fStep-gTolerance) {
00977             if (idebug>4) {
00978                printf("   -> from local=(%19.16f, %19.16f, %19.16f)\n",
00979                       lpoint[0],lpoint[1],lpoint[2]);
00980                printf("           ldir =(%19.16f, %19.16f, %19.16f)\n",
00981                       ldir[0],ldir[1],ldir[2]);             
00982                printf("   -> to: %s shape %s snext=%g\n", current->GetName(),
00983                       current->GetVolume()->GetShape()->ClassName(), snext);        
00984             }           
00985             indnext = current->GetVolume()->GetNextNodeIndex();
00986             if (compmatrix) {
00987                fCurrentMatrix->CopyFrom(fGlobalMatrix);
00988                fCurrentMatrix->Multiply(current->GetMatrix());
00989             }    
00990             fIsStepExiting  = kFALSE;
00991             fIsStepEntering = kTRUE;
00992             fStep=snext;
00993             fNextNode = current;
00994             nodefound = fNextNode;   
00995             idaughter = i;   
00996             while (indnext>=0) {
00997                current = current->GetDaughter(indnext);
00998                if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
00999                fNextNode = current;
01000                nodefound = current;
01001                indnext = current->GetVolume()->GetNextNodeIndex();
01002             }
01003          }
01004       }
01005       if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
01006       return nodefound;
01007    }
01008    // if current volume is voxelized, first get current voxel
01009    Int_t ncheck = 0;
01010    Int_t sumchecked = 0;
01011    Int_t *vlist = 0;
01012    voxels->SortCrossedVoxels(point, dir);
01013    while ((sumchecked<nd) && (vlist=voxels->GetNextVoxel(point, dir, ncheck))) {
01014       for (i=0; i<ncheck; i++) {
01015          current = vol->GetNode(vlist[i]);
01016          if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
01017          current->cd();
01018          current->MasterToLocal(point, lpoint);
01019          current->MasterToLocalVect(dir, ldir);
01020          if (current->IsOverlapping() && current->GetVolume()->Contains(lpoint)) continue;
01021          snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
01022          sumchecked++;
01023 //         printf("checked %d from %d : snext=%g\n", sumchecked, nd, snext);
01024          if (snext<fStep-gTolerance) {
01025             if (idebug>4) {
01026                printf("   -> from local=(%19.16f, %19.16f, %19.16f)\n",
01027                       lpoint[0],lpoint[1],lpoint[2]);
01028                printf("           ldir =(%19.16f, %19.16f, %19.16f)\n",
01029                       ldir[0],ldir[1],ldir[2]);             
01030                printf("   -> to: %s shape %s snext=%g\n", current->GetName(),
01031                       current->GetVolume()->GetShape()->ClassName(), snext);        
01032             }           
01033             indnext = current->GetVolume()->GetNextNodeIndex();
01034             if (compmatrix) {
01035                fCurrentMatrix->CopyFrom(fGlobalMatrix);
01036                fCurrentMatrix->Multiply(current->GetMatrix());
01037             }
01038             fIsStepExiting  = kFALSE;
01039             fIsStepEntering = kTRUE;
01040             fStep=snext;
01041             fNextNode = current;
01042             nodefound = fNextNode;
01043             idaughter = vlist[i];
01044             while (indnext>=0) {
01045                current = current->GetDaughter(indnext);
01046                if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
01047                fNextNode = current;
01048                nodefound = current;
01049                indnext = current->GetVolume()->GetNextNodeIndex();
01050             }
01051          }
01052       }
01053    }
01054    if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
01055    return nodefound;
01056 }
01057 
01058 //_____________________________________________________________________________
01059 TGeoNode *TGeoNavigator::FindNextBoundaryAndStep(Double_t stepmax, Bool_t compsafe)
01060 {
01061 // Compute distance to next boundary within STEPMAX. If no boundary is found,
01062 // propagate current point along current direction with fStep=STEPMAX. Otherwise
01063 // propagate with fStep=SNEXT (distance to boundary) and locate/return the next 
01064 // node.
01065    static Int_t icount = 0;
01066    icount++;
01067    Int_t iact = 3;
01068    Int_t idebug = TGeoManager::GetVerboseLevel();
01069    Int_t nextindex;
01070    Bool_t is_assembly;
01071    fForcedNode = 0;
01072    fIsStepExiting  = kFALSE;
01073    TGeoNode *skip;
01074    fIsStepEntering = kFALSE;
01075    fStep = stepmax;
01076    Double_t snext = TGeoShape::Big();
01077    if (compsafe) {
01078       // Try to get out easy if proposed step within safe region
01079       fIsOnBoundary = kFALSE;
01080       if (IsSafeStep(stepmax+gTolerance, fSafety)) {
01081          fPoint[0] += stepmax*fDirection[0];
01082          fPoint[1] += stepmax*fDirection[1];
01083          fPoint[2] += stepmax*fDirection[2];
01084          return fCurrentNode;
01085       }   
01086       Safety();
01087       fLastSafety = fSafety;
01088       memcpy(fLastPoint, fPoint, kN3);
01089       // If proposed step less than safety, nothing to check
01090       if (fSafety > stepmax+gTolerance) {
01091          fPoint[0] += stepmax*fDirection[0];
01092          fPoint[1] += stepmax*fDirection[1];
01093          fPoint[2] += stepmax*fDirection[2];
01094          return fCurrentNode;
01095       }   
01096    }   
01097    Double_t extra = (fIsOnBoundary)?gTolerance:0.0;
01098    fIsOnBoundary = kFALSE;
01099    fPoint[0] += extra*fDirection[0];
01100    fPoint[1] += extra*fDirection[1];
01101    fPoint[2] += extra*fDirection[2];
01102    fCurrentMatrix->CopyFrom(fGlobalMatrix);
01103    if (idebug>4) {
01104       printf("TGeoManager::FindNextBAndStep:  point=(%19.16f, %19.16f, %19.16f)\n",
01105              fPoint[0],fPoint[1],fPoint[2]);
01106       printf("                                dir=  (%19.16f, %19.16f, %19.16f)\n",
01107              fDirection[0], fDirection[1], fDirection[2]);
01108       printf("  pstep=%9.6g  path=%s\n", stepmax, GetPath());
01109    }   
01110    
01111    if (fIsOutside) {
01112       snext = fGeometry->GetTopVolume()->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep);
01113       if (snext < fStep-gTolerance) {
01114          if (snext<=0) {
01115             snext = 0.0;
01116             fStep = snext;
01117             fPoint[0] -= extra*fDirection[0];
01118             fPoint[1] -= extra*fDirection[1];
01119             fPoint[2] -= extra*fDirection[2];
01120          } else {
01121             fStep = snext+extra;
01122          }   
01123          fIsStepEntering = kTRUE;
01124          fNextNode = fGeometry->GetTopNode();
01125          nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
01126          while (nextindex>=0) {
01127             CdDown(nextindex);
01128             fNextNode = fCurrentNode;
01129             nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
01130             if (nextindex<0) fCurrentMatrix->CopyFrom(fGlobalMatrix);
01131          }   
01132          // Update global point
01133          fPoint[0] += snext*fDirection[0];
01134          fPoint[1] += snext*fDirection[1];
01135          fPoint[2] += snext*fDirection[2];
01136          fIsOnBoundary = kTRUE;
01137          fIsOutside = kFALSE;
01138          fForcedNode = fCurrentNode;
01139          return CrossBoundaryAndLocate(kTRUE, fCurrentNode);
01140       }
01141       if (snext<TGeoShape::Big()) {
01142          // New point still outside, but the top node is reachable
01143          fNextNode = fGeometry->GetTopNode();
01144          fPoint[0] += (fStep-extra)*fDirection[0];
01145          fPoint[1] += (fStep-extra)*fDirection[1];
01146          fPoint[2] += (fStep-extra)*fDirection[2];
01147          return fNextNode;
01148       }      
01149       // top node not reachable from current point/direction
01150       fNextNode = 0;
01151       fIsOnBoundary = kFALSE;
01152       return 0;
01153    }
01154    Double_t point[3],dir[3];
01155    Int_t icrossed = -2;
01156    fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
01157    fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
01158    TGeoVolume *vol = fCurrentNode->GetVolume();
01159    // find distance to exiting current node
01160    if (idebug>4) {
01161       printf("   -> from local=(%19.16f, %19.16f, %19.16f)\n",
01162              point[0],point[1],point[2]);
01163       printf("           ldir =(%19.16f, %19.16f, %19.16f)\n",
01164              dir[0],dir[1],dir[2]);             
01165    }           
01166    // find distance to exiting current node
01167    snext = vol->GetShape()->DistFromInside(point, dir, iact, fStep);
01168    if (idebug>4) {
01169       printf("      exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
01170    }   
01171    fNextNode = fCurrentNode;
01172    if (snext <= gTolerance) {
01173       // Current point on the boundary while track exiting
01174       snext = gTolerance;
01175       fStep = snext;
01176       fIsOnBoundary = kTRUE;
01177       fIsStepEntering = kFALSE;
01178       fIsStepExiting = kTRUE;
01179       skip = fCurrentNode;
01180       fPoint[0] += fStep*fDirection[0];
01181       fPoint[1] += fStep*fDirection[1];
01182       fPoint[2] += fStep*fDirection[2];
01183       is_assembly = fCurrentNode->GetVolume()->IsAssembly();
01184       if (!fLevel && !is_assembly) {
01185          fIsOutside = kTRUE;
01186          return 0;
01187       }
01188       if (fCurrentNode->IsOffset()) return CrossDivisionCell();   
01189       if (fLevel) CdUp();
01190       else        skip = 0;
01191       return CrossBoundaryAndLocate(kFALSE, skip);
01192    }   
01193 
01194    if (snext < fStep-gTolerance) {
01195       // Currently the minimum step chosen is the exiting one
01196       icrossed = -1;
01197       fStep = snext;
01198       fIsStepEntering = kFALSE;
01199       fIsStepExiting = kTRUE;
01200    }
01201    // Find next daughter boundary for the current volume
01202    Int_t idaughter = -1;
01203    TGeoNode *crossed = FindNextDaughterBoundary(point,dir, idaughter, kTRUE);
01204    if (crossed) {
01205       fIsStepExiting = kFALSE;
01206       icrossed = idaughter;
01207       fIsStepEntering = kTRUE;
01208    }   
01209    TGeoNode *current = 0;
01210    TGeoNode *dnode = 0;
01211    TGeoVolume *mother = 0;
01212    // if we are in an overlapping node, check also the mother(s)
01213    if (fNmany) {
01214       Double_t mothpt[3];
01215       Double_t vecpt[3];
01216       Double_t dpt[3], dvec[3];
01217       Int_t novlps;
01218       Int_t safelevel = GetSafeLevel();
01219       PushPath(safelevel+1);
01220       while (fCurrentOverlapping) {
01221          Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
01222          CdUp();
01223          mother = fCurrentNode->GetVolume();
01224          fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
01225          fGlobalMatrix->MasterToLocalVect(fDirection, &vecpt[0]);
01226          // check distance to out
01227          snext = TGeoShape::Big();
01228          if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(mothpt, vecpt, iact, fStep);
01229          if (snext<fStep-gTolerance) {
01230             // exiting mother first (extrusion)
01231             icrossed = -1;
01232             PopDummy();
01233             PushPath(safelevel+1);
01234             fIsStepEntering = kFALSE;
01235             fIsStepExiting = kTRUE;
01236             fStep = snext;
01237             fCurrentMatrix->CopyFrom(fGlobalMatrix);
01238             fNextNode = fCurrentNode;
01239          }
01240          // check overlapping nodes
01241          for (Int_t i=0; i<novlps; i++) {
01242             current = mother->GetNode(ovlps[i]);
01243             if (!current->IsOverlapping()) {
01244                current->cd();
01245                current->MasterToLocal(&mothpt[0], &dpt[0]);
01246                current->MasterToLocalVect(&vecpt[0], &dvec[0]);
01247                // Current point may be inside the other node - geometry error that we ignore
01248                snext = TGeoShape::Big();
01249                if (!current->GetVolume()->Contains(dpt))
01250                   snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
01251                if (snext<fStep-gTolerance) {
01252                   PopDummy();
01253                   PushPath(safelevel+1);
01254                   fCurrentMatrix->CopyFrom(fGlobalMatrix);
01255                   fCurrentMatrix->Multiply(current->GetMatrix());
01256                   fIsStepEntering = kFALSE;
01257                   fIsStepExiting = kTRUE;
01258                   icrossed = ovlps[i];
01259                   fStep = snext;
01260                   fNextNode = current;
01261                }
01262             } else {
01263                // another many - check if point is in or out
01264                current->cd();
01265                current->MasterToLocal(&mothpt[0], &dpt[0]);
01266                current->MasterToLocalVect(&vecpt[0], &dvec[0]);
01267                if (current->GetVolume()->Contains(dpt)) {
01268                   if (current->GetVolume()->GetNdaughters()) {
01269                      CdDown(ovlps[i]);
01270                      dnode = FindNextDaughterBoundary(dpt,dvec,idaughter,kFALSE);
01271                      if (dnode) {
01272                         fCurrentMatrix->CopyFrom(fGlobalMatrix);
01273                         fCurrentMatrix->Multiply(dnode->GetMatrix());
01274                         icrossed = idaughter;
01275                         PopDummy();
01276                         PushPath(safelevel+1);
01277                         fIsStepEntering = kFALSE;
01278                         fIsStepExiting = kTRUE;
01279                         fNextNode = dnode;
01280                      }   
01281                      CdUp();
01282                   }   
01283                } else {
01284                   snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
01285                   if (snext<fStep-gTolerance) {
01286                      fCurrentMatrix->CopyFrom(fGlobalMatrix);
01287                      fCurrentMatrix->Multiply(current->GetMatrix());
01288                      fIsStepEntering = kFALSE;
01289                      fIsStepExiting = kTRUE;
01290                      fStep = snext;
01291                      fNextNode = current;
01292                      icrossed = ovlps[i];
01293                      PopDummy();
01294                      PushPath(safelevel+1);
01295                   }               
01296                }  
01297             }
01298          }
01299       }
01300       // Now we are in a non-overlapping node
01301       if (fNmany) {
01302       // We have overlaps up in the branch, check distance to exit
01303          Int_t up = 1;
01304          Int_t imother;
01305          Int_t nmany = fNmany;
01306          Bool_t ovlp = kFALSE;
01307          Bool_t nextovlp = kFALSE;
01308          Bool_t offset = kFALSE;
01309          TGeoNode *currentnode = fCurrentNode;
01310          TGeoNode *mothernode, *mup;
01311          TGeoHMatrix *matrix;
01312          while (nmany) {
01313             mothernode = GetMother(up);
01314             mup = mothernode;
01315             imother = up+1;
01316             offset = kFALSE;
01317             while (mup->IsOffset()) {
01318                mup = GetMother(imother++);
01319                offset = kTRUE;
01320             }   
01321             nextovlp = mup->IsOverlapping();
01322             if (offset) {
01323                mothernode = mup;
01324                if (nextovlp) nmany -= imother-up;
01325                up = imother-1;
01326             } else {    
01327                if (ovlp) nmany--;
01328             }
01329             if (ovlp || nextovlp) {
01330                matrix = GetMotherMatrix(up);
01331                matrix->MasterToLocal(fPoint,dpt);
01332                matrix->MasterToLocalVect(fDirection,dvec);
01333                snext = TGeoShape::Big();
01334                if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
01335                   fIsStepEntering = kFALSE;
01336                   fIsStepExiting  = kTRUE;
01337                if (snext<fStep-gTolerance) {
01338                   fNextNode = mothernode;
01339                   fCurrentMatrix->CopyFrom(matrix);
01340                   fStep = snext;
01341                   while (up--) CdUp();
01342                   PopDummy();
01343                   PushPath();
01344                   icrossed = -1;
01345                   up = 1;
01346                   currentnode = fCurrentNode;
01347                   ovlp = currentnode->IsOverlapping();
01348                   continue;
01349                }   
01350             }   
01351             currentnode = mothernode;
01352             ovlp = nextovlp;
01353             up++;            
01354          }
01355       }      
01356       PopPath();
01357    }
01358    fPoint[0] += fStep*fDirection[0];
01359    fPoint[1] += fStep*fDirection[1];
01360    fPoint[2] += fStep*fDirection[2];
01361    fStep += extra;
01362    if (icrossed == -2) {
01363       // Nothing crossed within stepmax -> propagate and return same location   
01364       fIsOnBoundary = kFALSE;
01365       return fCurrentNode;
01366    }
01367    fIsOnBoundary = kTRUE;
01368    if (icrossed == -1) {
01369       // Exiting current node.
01370       skip = fCurrentNode;
01371       is_assembly = fCurrentNode->GetVolume()->IsAssembly();
01372       if (!fLevel && !is_assembly) {
01373          fIsOutside = kTRUE;
01374          return 0;
01375       }   
01376       if (fCurrentNode->IsOffset()) return CrossDivisionCell();   
01377       if (fLevel) CdUp();
01378       else        skip = 0;
01379       return CrossBoundaryAndLocate(kFALSE, skip);
01380    }   
01381    current = fCurrentNode;   
01382    CdDown(icrossed);
01383    nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
01384    while (nextindex>=0) {
01385       current = fCurrentNode;
01386       CdDown(nextindex);
01387       nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
01388    }   
01389    fForcedNode = fCurrentNode;
01390    return CrossBoundaryAndLocate(kTRUE, current);
01391 }   
01392 
01393 //_____________________________________________________________________________
01394 TGeoNode *TGeoNavigator::FindNode(Bool_t safe_start)
01395 {
01396 // Returns deepest node containing current point.
01397    fSafety = 0;
01398    fSearchOverlaps = kFALSE;
01399    fIsOutside = kFALSE;
01400    fIsEntering = fIsExiting = kFALSE;
01401    fIsOnBoundary = kFALSE;
01402    fStartSafe = safe_start;
01403    fIsSameLocation = kTRUE;
01404    TGeoNode *last = fCurrentNode;
01405    TGeoNode *found = SearchNode();
01406    if (found != last) {
01407       fIsSameLocation = kFALSE;
01408    } else {   
01409       if (last->IsOverlapping()) fIsSameLocation = kTRUE;
01410    }   
01411    return found;
01412 }
01413 
01414 //_____________________________________________________________________________
01415 TGeoNode *TGeoNavigator::FindNode(Double_t x, Double_t y, Double_t z)
01416 {
01417 // Returns deepest node containing current point.
01418    fPoint[0] = x;
01419    fPoint[1] = y;
01420    fPoint[2] = z;
01421    fSafety = 0;
01422    fSearchOverlaps = kFALSE;
01423    fIsOutside = kFALSE;
01424    fIsEntering = fIsExiting = kFALSE;
01425    fIsOnBoundary = kFALSE;
01426    fStartSafe = kTRUE;
01427    fIsSameLocation = kTRUE;
01428    TGeoNode *last = fCurrentNode;
01429    TGeoNode *found = SearchNode();
01430    if (found != last) {
01431       fIsSameLocation = kFALSE;
01432    } else {   
01433       if (last->IsOverlapping()) fIsSameLocation = kTRUE;
01434    }   
01435    return found;
01436 }
01437 
01438 //_____________________________________________________________________________
01439 Double_t *TGeoNavigator::FindNormalFast()
01440 {
01441 // Computes fast normal to next crossed boundary, assuming that the current point
01442 // is close enough to the boundary. Works only after calling FindNextBoundary.
01443    if (!fNextNode) return 0;
01444    Double_t local[3];
01445    Double_t ldir[3];
01446    Double_t lnorm[3];
01447    fCurrentMatrix->MasterToLocal(fPoint, local);
01448    fCurrentMatrix->MasterToLocalVect(fDirection, ldir);
01449    fNextNode->GetVolume()->GetShape()->ComputeNormal(local, ldir,lnorm);
01450    fCurrentMatrix->LocalToMasterVect(lnorm, fNormal);
01451    return fNormal;
01452 }
01453 
01454 //_____________________________________________________________________________
01455 Double_t *TGeoNavigator::FindNormal(Bool_t /*forward*/)
01456 {
01457 // Computes normal vector to the next surface that will be or was already
01458 // crossed when propagating on a straight line from a given point/direction.
01459 // Returns the normal vector cosines in the MASTER coordinate system. The dot
01460 // product of the normal and the current direction is positive defined.
01461    return FindNormalFast();
01462 }
01463 
01464 //_____________________________________________________________________________
01465 TGeoNode *TGeoNavigator::InitTrack(const Double_t *point, const Double_t *dir)
01466 {
01467 // Initialize current point and current direction vector (normalized)
01468 // in MARS. Return corresponding node.
01469    SetCurrentPoint(point);
01470    SetCurrentDirection(dir);
01471    return FindNode();
01472 }
01473 
01474 //_____________________________________________________________________________
01475 TGeoNode *TGeoNavigator::InitTrack(Double_t x, Double_t y, Double_t z, Double_t nx, Double_t ny, Double_t nz)
01476 {
01477 // Initialize current point and current direction vector (normalized)
01478 // in MARS. Return corresponding node.
01479    SetCurrentPoint(x,y,z);
01480    SetCurrentDirection(nx,ny,nz);
01481    return FindNode();
01482 }
01483 
01484 //_____________________________________________________________________________
01485 void TGeoNavigator::ResetState()
01486 {
01487 // Reset current state flags.
01488    fSearchOverlaps = kFALSE;
01489    fIsOutside = kFALSE;
01490    fIsEntering = fIsExiting = kFALSE;
01491    fIsOnBoundary = kFALSE;
01492    fIsStepEntering = fIsStepExiting = kFALSE;
01493 }
01494 
01495 //_____________________________________________________________________________
01496 Double_t TGeoNavigator::Safety(Bool_t inside)
01497 {
01498 // Compute safe distance from the current point. This represent the distance
01499 // from POINT to the closest boundary.
01500 
01501    if (fIsOnBoundary) {
01502       fSafety = 0;
01503       return fSafety;
01504    }
01505    Double_t point[3];
01506    if (!inside) fSafety = TGeoShape::Big();
01507    if (fIsOutside) {
01508       fSafety = fGeometry->GetTopVolume()->GetShape()->Safety(fPoint,kFALSE);
01509       if (fSafety < gTolerance) {
01510          fSafety = 0;
01511          fIsOnBoundary = kTRUE;
01512       }   
01513       return fSafety;
01514    }
01515    //---> convert point to local reference frame of current node
01516    fGlobalMatrix->MasterToLocal(fPoint, point);
01517 
01518    //---> compute safety to current node
01519    TGeoVolume *vol = fCurrentNode->GetVolume();
01520    if (!inside) {
01521       fSafety = vol->GetShape()->Safety(point, kTRUE);
01522       //---> if we were just entering, return this safety
01523       if (fSafety < gTolerance) {
01524          fSafety = 0;
01525          fIsOnBoundary = kTRUE;
01526          return fSafety;
01527       }
01528    }
01529 
01530    //---> now check the safety to the last node
01531 
01532    //---> if we were just exiting, return this safety
01533    TObjArray *nodes = vol->GetNodes();
01534    Int_t nd = fCurrentNode->GetNdaughters();
01535    if (!nd && !fCurrentOverlapping) return fSafety;
01536    TGeoNode *node;
01537    Double_t safe;
01538    Int_t id;
01539 
01540    // if current volume is divided, we are in the non-divided region. We
01541    // check only the first and the last cell
01542    TGeoPatternFinder *finder = vol->GetFinder();
01543    if (finder) {
01544       Int_t ifirst = finder->GetDivIndex();
01545       node = (TGeoNode*)nodes->UncheckedAt(ifirst);
01546       node->cd();
01547       safe = node->Safety(point, kFALSE);
01548       if (safe < gTolerance) {
01549          fSafety=0;
01550          fIsOnBoundary = kTRUE;
01551          return fSafety;
01552       }
01553       if (safe<fSafety) fSafety=safe;
01554       Int_t ilast = ifirst+finder->GetNdiv()-1;
01555       if (ilast==ifirst) return fSafety;
01556       node = (TGeoNode*)nodes->UncheckedAt(ilast);
01557       node->cd();
01558       safe = node->Safety(point, kFALSE);
01559       if (safe < gTolerance) {
01560          fSafety=0;
01561          fIsOnBoundary = kTRUE;
01562          return fSafety;
01563       }
01564       if (safe<fSafety) fSafety=safe;
01565       if (fCurrentOverlapping  && !inside) SafetyOverlaps();
01566       return fSafety;
01567    }
01568 
01569    //---> If no voxels just loop daughters
01570    TGeoVoxelFinder *voxels = vol->GetVoxels();
01571    if (!voxels) {
01572       for (id=0; id<nd; id++) {
01573          node = (TGeoNode*)nodes->UncheckedAt(id);
01574          safe = node->Safety(point, kFALSE);
01575          if (safe < gTolerance) {
01576             fSafety=0;
01577             fIsOnBoundary = kTRUE;
01578             return fSafety;
01579          }
01580          if (safe<fSafety) fSafety=safe;
01581       }
01582       if (fNmany && !inside) SafetyOverlaps();
01583       return fSafety;
01584    } else {
01585       if (voxels->NeedRebuild()) {
01586          voxels->Voxelize();
01587          vol->FindOverlaps();
01588       }
01589    }      
01590 
01591    //---> check fast unsafe voxels
01592    Double_t *boxes = voxels->GetBoxes();
01593    for (id=0; id<nd; id++) {
01594       Int_t ist = 6*id;
01595       Double_t dxyz = 0.;
01596       Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
01597       if (dxyz0 > fSafety) continue;
01598       Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
01599       if (dxyz1 > fSafety) continue;
01600       Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
01601       if (dxyz2 > fSafety) continue;
01602       if (dxyz0>0) dxyz+=dxyz0*dxyz0;
01603       if (dxyz1>0) dxyz+=dxyz1*dxyz1;
01604       if (dxyz2>0) dxyz+=dxyz2*dxyz2;
01605       if (dxyz >= fSafety*fSafety) continue;
01606       node = (TGeoNode*)nodes->UncheckedAt(id);
01607       safe = node->Safety(point, kFALSE);
01608       if (safe<gTolerance) {
01609          fSafety=0;
01610          fIsOnBoundary = kTRUE;
01611          return fSafety;
01612       }
01613       if (safe<fSafety) fSafety = safe;
01614    }
01615    if (fNmany  && !inside) SafetyOverlaps();
01616    return fSafety;
01617 }
01618 
01619 //_____________________________________________________________________________
01620 void TGeoNavigator::SafetyOverlaps()
01621 {
01622 // Compute safe distance from the current point within an overlapping node
01623    Double_t point[3], local[3];
01624    Double_t safe;
01625    Bool_t contains;
01626    TGeoNode *nodeovlp;
01627    TGeoVolume *vol;
01628    Int_t novlp, io;
01629    Int_t *ovlp;
01630    Int_t safelevel = GetSafeLevel();
01631    PushPath(safelevel+1);
01632    while (fCurrentOverlapping) {
01633       ovlp = fCurrentNode->GetOverlaps(novlp);
01634       CdUp();
01635       vol = fCurrentNode->GetVolume();
01636       fGeometry->MasterToLocal(fPoint, point);
01637       contains = fCurrentNode->GetVolume()->Contains(point);
01638       safe = fCurrentNode->GetVolume()->GetShape()->Safety(point, contains);
01639       if (safe<fSafety && safe>=0) fSafety=safe;
01640       if (!novlp || !contains) continue;
01641       // we are now in the container, check safety to all candidates
01642       for (io=0; io<novlp; io++) {
01643          nodeovlp = vol->GetNode(ovlp[io]);
01644          nodeovlp->GetMatrix()->MasterToLocal(point,local);
01645          contains = nodeovlp->GetVolume()->Contains(local);
01646          if (contains) {
01647             CdDown(ovlp[io]);
01648             safe = Safety(kTRUE);
01649             CdUp();
01650          } else {
01651             safe = nodeovlp->GetVolume()->GetShape()->Safety(local, kFALSE);
01652          }
01653          if (safe<fSafety && safe>=0) fSafety=safe;
01654       }
01655    }
01656    if (fNmany) {
01657    // We have overlaps up in the branch, check distance to exit
01658       Int_t up = 1;
01659       Int_t imother;
01660       Int_t nmany = fNmany;
01661       Bool_t crtovlp = kFALSE;
01662       Bool_t nextovlp = kFALSE;
01663       TGeoNode *current = fCurrentNode;
01664       TGeoNode *mother, *mup;
01665       TGeoHMatrix *matrix;
01666       while (nmany) {
01667          mother = GetMother(up);
01668          mup = mother;
01669          imother = up+1;
01670          while (mup->IsOffset()) mup = GetMother(imother++);
01671          nextovlp = mup->IsOverlapping();
01672          if (crtovlp) nmany--;
01673          if (crtovlp || nextovlp) {
01674             matrix = GetMotherMatrix(up);
01675             matrix->MasterToLocal(fPoint,local);
01676             safe = mother->GetVolume()->GetShape()->Safety(local,kTRUE);
01677             if (safe<fSafety) fSafety = safe;
01678             current = mother;
01679             crtovlp = nextovlp;
01680          }
01681          up++;
01682       }      
01683    }
01684    PopPath();
01685    if (fSafety < gTolerance) {
01686       fSafety = 0.;
01687       fIsOnBoundary = kTRUE;
01688    }   
01689 }
01690 
01691 //_____________________________________________________________________________
01692 TGeoNode *TGeoNavigator::SearchNode(Bool_t downwards, const TGeoNode *skipnode)
01693 {
01694 // Returns the deepest node containing fPoint, which must be set a priori.
01695    Double_t point[3];
01696    fNextDaughterIndex = -2;
01697    TGeoVolume *vol = 0;
01698    Int_t idebug = TGeoManager::GetVerboseLevel();
01699    Bool_t inside_current = (fCurrentNode==skipnode)?kTRUE:kFALSE;
01700    if (!downwards) {
01701    // we are looking upwards until inside current node or exit
01702       if (fGeometry->IsActivityEnabled() && !fCurrentNode->GetVolume()->IsActive()) {
01703          // We are inside an inactive volume-> go upwards
01704          CdUp();
01705          fIsSameLocation = kFALSE;
01706          return SearchNode(kFALSE, skipnode);
01707       }
01708       // Check if the current point is still inside the current volume
01709       vol=fCurrentNode->GetVolume();
01710       if (vol->IsAssembly()) inside_current=kTRUE;
01711       // If the current node is not to be skipped
01712       if (!inside_current) {
01713          fGlobalMatrix->MasterToLocal(fPoint, point);
01714          inside_current = vol->Contains(point);
01715       }   
01716       // Point might be inside an overlapping node
01717       if (fNmany) {
01718          inside_current = GotoSafeLevel();
01719       }   
01720       if (!inside_current) {
01721          // If not, go upwards
01722          fIsSameLocation = kFALSE;
01723          TGeoNode *skip = fCurrentNode;  // skip current node at next search
01724          // check if we can go up
01725          if (!fLevel) {
01726             fIsOutside = kTRUE;
01727             return 0;
01728          }
01729          CdUp();
01730          return SearchNode(kFALSE, skip);
01731       }
01732    }
01733    vol = fCurrentNode->GetVolume();
01734    fGlobalMatrix->MasterToLocal(fPoint, point);
01735    if (!inside_current && downwards) {
01736    // we are looking downwards
01737       if (fCurrentNode == fForcedNode) inside_current = kTRUE;
01738       else inside_current = vol->Contains(point);
01739       if (!inside_current) {
01740          fIsSameLocation = kFALSE;
01741          return 0;
01742       } else {
01743          if (fIsOutside) {
01744             fIsOutside = kFALSE;
01745             fIsSameLocation = kFALSE;
01746          }
01747          if (idebug>4) {
01748             printf("Search node local=(%19.16f, %19.16f, %19.16f) -> %s\n",
01749                    point[0],point[1],point[2], fCurrentNode->GetName());
01750          }                    
01751       }      
01752    }
01753    // point inside current (safe) node -> search downwards
01754    TGeoNode *node;
01755    Int_t ncheck = 0;
01756    // if inside an non-overlapping node, reset overlap searches
01757    if (!fCurrentOverlapping) {
01758       fSearchOverlaps = kFALSE;
01759    }
01760 
01761    Int_t crtindex = vol->GetCurrentNodeIndex();
01762    while (crtindex>=0 && downwards) {
01763       // Make sure we did not end up in an assembly.
01764       CdDown(crtindex);
01765       vol = fCurrentNode->GetVolume();
01766       crtindex = vol->GetCurrentNodeIndex();
01767       if (crtindex<0) fGlobalMatrix->MasterToLocal(fPoint, point);
01768    }   
01769       
01770    Int_t nd = vol->GetNdaughters();
01771    // in case there are no daughters
01772    if (!nd) return fCurrentNode;
01773    if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters()) return fCurrentNode;
01774 
01775    TGeoPatternFinder *finder = vol->GetFinder();
01776    // point is inside the current node
01777    // first check if inside a division
01778    if (finder) {
01779       node=finder->FindNode(point);
01780       if (!node && fForcedNode) {
01781          // Point *HAS* to be inside a cell
01782          Double_t dir[3];
01783          fGlobalMatrix->MasterToLocalVect(fDirection, dir);
01784          finder->FindNode(point,dir);
01785          node = finder->CdNext();
01786          if (!node) return fCurrentNode;  // inside divided volume but not in a cell
01787       }   
01788       if (node && node!=skipnode) {
01789          // go inside the division cell and search downwards
01790          fIsSameLocation = kFALSE;
01791          CdDown(node->GetIndex());
01792          fForcedNode = 0;
01793          return SearchNode(kTRUE, node);
01794       }
01795       // point is not inside the division, but might be in other nodes
01796       // at the same level (NOT SUPPORTED YET)
01797       while (fCurrentNode && fCurrentNode->IsOffset()) CdUp();
01798       return fCurrentNode;
01799    }
01800    // second, look if current volume is voxelized
01801    TGeoVoxelFinder *voxels = vol->GetVoxels();
01802    Int_t *check_list = 0;
01803    Int_t id;
01804    if (voxels) {
01805       // get the list of nodes passing thorough the current voxel
01806       check_list = voxels->GetCheckList(&point[0], ncheck);
01807       // if none in voxel, see if this is the last one
01808       if (!check_list) {
01809          if (!fCurrentNode->GetVolume()->IsAssembly()) return fCurrentNode;
01810          // Point in assembly - go up
01811          node = fCurrentNode;
01812          if (!fLevel) {
01813             fIsOutside = kTRUE;
01814             return 0;
01815          }
01816          CdUp();
01817          return SearchNode(kFALSE,node);
01818       }   
01819       // loop all nodes in voxel
01820       for (id=0; id<ncheck; id++) {
01821          node = vol->GetNode(check_list[id]);
01822          if (node==skipnode) continue;
01823          if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
01824          if ((id<(ncheck-1)) && node->IsOverlapping()) {
01825          // make the cluster of overlaps
01826             if (ncheck+fOverlapMark > fOverlapSize) {
01827                fOverlapSize = 2*(ncheck+fOverlapMark);
01828                delete [] fOverlapClusters;
01829                fOverlapClusters = new Int_t[fOverlapSize];
01830             }
01831             Int_t *cluster = fOverlapClusters + fOverlapMark;
01832             Int_t nc = GetTouchedCluster(id, &point[0], check_list, ncheck, cluster);
01833             if (nc>1) {
01834                fOverlapMark += nc;
01835                node = FindInCluster(cluster, nc);
01836                fOverlapMark -= nc;
01837                return node;
01838             }
01839          }
01840          CdDown(check_list[id]);
01841          fForcedNode = 0;
01842          node = SearchNode(kTRUE);
01843          if (node) {
01844             fIsSameLocation = kFALSE;
01845             return node;
01846          }
01847          CdUp();
01848       }
01849       if (!fCurrentNode->GetVolume()->IsAssembly()) return fCurrentNode;
01850       node = fCurrentNode;
01851       if (!fLevel) {
01852          fIsOutside = kTRUE;
01853          return 0;
01854       }
01855       CdUp();
01856       return SearchNode(kFALSE,node);
01857    }
01858    // if there are no voxels just loop all daughters
01859    for (id=0; id<nd; id++) {
01860       node=fCurrentNode->GetDaughter(id);
01861       if (node==skipnode) continue;  
01862       if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
01863       CdDown(id);
01864       fForcedNode = 0;
01865       node = SearchNode(kTRUE);
01866       if (node) {
01867          fIsSameLocation = kFALSE;
01868          return node;
01869       }
01870       CdUp();
01871    }      
01872    // point is not inside one of the daughters, so it is in the current vol
01873    if (fCurrentNode->GetVolume()->IsAssembly()) {
01874       node = fCurrentNode;
01875       if (!fLevel) {
01876          fIsOutside = kTRUE;
01877          return 0;
01878       }
01879       CdUp();
01880       return SearchNode(kFALSE,node);
01881    }      
01882    return fCurrentNode;
01883 }
01884 
01885 //_____________________________________________________________________________
01886 TGeoNode *TGeoNavigator::FindInCluster(Int_t *cluster, Int_t nc)
01887 {
01888 // Find a node inside a cluster of overlapping nodes. Current node must
01889 // be on top of all the nodes in cluster. Always nc>1.
01890    TGeoNode *clnode = 0;
01891    TGeoNode *priority = fLastNode;
01892    // save current node
01893    TGeoNode *current = fCurrentNode;
01894    TGeoNode *found = 0;
01895    // save path
01896    Int_t ipop = PushPath();
01897    // mark this search
01898    fSearchOverlaps = kTRUE;
01899    Int_t deepest = fLevel;
01900    Int_t deepest_virtual = fLevel-GetVirtualLevel();
01901    Int_t found_virtual = 0;
01902    Bool_t replace = kFALSE;
01903    Bool_t added = kFALSE;
01904    Int_t i;
01905    for (i=0; i<nc; i++) {
01906       clnode = current->GetDaughter(cluster[i]);
01907       CdDown(cluster[i]);
01908       Bool_t max_priority = (clnode==fNextNode)?kTRUE:kFALSE;
01909       found = SearchNode(kTRUE, clnode);
01910       if (!fSearchOverlaps || max_priority) {
01911       // an only was found during the search -> exiting
01912       // The node given by FindNextBoundary returned -> exiting
01913          PopDummy(ipop);
01914          return found;
01915       }
01916       found_virtual = fLevel-GetVirtualLevel();
01917       if (added) {
01918       // we have put something in stack -> check it
01919          if (found_virtual>deepest_virtual) {
01920             replace = kTRUE;
01921          } else {
01922             if (found_virtual==deepest_virtual) {
01923                if (fLevel>deepest) {
01924                   replace = kTRUE;
01925                } else {
01926                   if ((fLevel==deepest) && (clnode==priority)) replace=kTRUE;
01927                   else                                          replace = kFALSE;
01928                }
01929             } else                 replace = kFALSE;
01930          }
01931          // if this was the last checked node
01932          if (i==(nc-1)) {
01933             if (replace) {
01934                PopDummy(ipop);
01935                return found;
01936             } else {
01937                fCurrentOverlapping = PopPath();
01938                PopDummy(ipop);
01939                return fCurrentNode;
01940             }
01941          }
01942          // we still have to go on
01943          if (replace) {
01944             // reset stack
01945             PopDummy();
01946             PushPath();
01947             deepest = fLevel;
01948             deepest_virtual = found_virtual;
01949          }
01950          // restore top of cluster
01951          fCurrentOverlapping = PopPath(ipop);
01952       } else {
01953       // the stack was clean, push new one
01954          PushPath();
01955          added = kTRUE;
01956          deepest = fLevel;
01957          deepest_virtual = found_virtual;
01958          // restore original path
01959          fCurrentOverlapping = PopPath(ipop);
01960       }
01961    }
01962    PopDummy(ipop);
01963    return fCurrentNode;
01964 }
01965 
01966 //_____________________________________________________________________________
01967 Int_t TGeoNavigator::GetTouchedCluster(Int_t start, Double_t *point,
01968                               Int_t *check_list, Int_t ncheck, Int_t *result)
01969 {
01970 // Make the cluster of overlapping nodes in a voxel, containing point in reference
01971 // of the mother. Returns number of nodes containing the point. Nodes should not be
01972 // offsets.
01973 
01974    // we are in the mother reference system
01975    TGeoNode *current = fCurrentNode->GetDaughter(check_list[start]);
01976    Int_t novlps = 0;
01977    Int_t *ovlps = current->GetOverlaps(novlps);
01978    if (!ovlps) return 0;
01979    Double_t local[3];
01980    // intersect check list with overlap list
01981    Int_t ntotal = 0;
01982    current->MasterToLocal(point, &local[0]);
01983    if (current->GetVolume()->Contains(&local[0])) {
01984       result[ntotal++]=check_list[start];
01985    }
01986 
01987    Int_t jst=0, i, j;
01988    while ((ovlps[jst]<=check_list[start]) && (jst<novlps))  jst++;
01989    if (jst==novlps) return 0;
01990    for (i=start; i<ncheck; i++) {
01991       for (j=jst; j<novlps; j++) {
01992          if (check_list[i]==ovlps[j]) {
01993          // overlapping node in voxel -> check if touched
01994             current = fCurrentNode->GetDaughter(check_list[i]);
01995             if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
01996             current->MasterToLocal(point, &local[0]);
01997             if (current->GetVolume()->Contains(&local[0])) {
01998                result[ntotal++]=check_list[i];
01999             }
02000          }
02001       }
02002    }
02003    return ntotal;
02004 }
02005 
02006 //_____________________________________________________________________________
02007 TGeoNode *TGeoNavigator::Step(Bool_t is_geom, Bool_t cross)
02008 {
02009 // Make a rectiliniar step of length fStep from current point (fPoint) on current
02010 // direction (fDirection). If the step is imposed by geometry, is_geom flag
02011 // must be true (default). The cross flag specifies if the boundary should be
02012 // crossed in case of a geometry step (default true). Returns new node after step.
02013 // Set also on boundary condition.
02014    Double_t epsil = 0;
02015    if (fStep<1E-6) {
02016       fIsNullStep=kTRUE;
02017       if (fStep<0) fStep = 0.;
02018    } else {
02019       fIsNullStep=kFALSE;
02020    }
02021    if (is_geom) epsil=(cross)?1E-6:-1E-6;
02022    TGeoNode *old = fCurrentNode;
02023    Int_t idold = GetNodeId();
02024    if (fIsOutside) old = 0;
02025    fStep += epsil;
02026    for (Int_t i=0; i<3; i++) fPoint[i]+=fStep*fDirection[i];
02027    TGeoNode *current = FindNode();
02028    if (is_geom) {
02029       fIsEntering = (current==old)?kFALSE:kTRUE;
02030       if (!fIsEntering) {
02031          Int_t id = GetNodeId();
02032          fIsEntering = (id==idold)?kFALSE:kTRUE;
02033       }
02034       fIsExiting  = !fIsEntering;
02035       if (fIsEntering && fIsNullStep) fIsNullStep = kFALSE;
02036       fIsOnBoundary = kTRUE;
02037    } else {
02038       fIsEntering = fIsExiting = kFALSE;
02039       fIsOnBoundary = kFALSE;
02040    }
02041    return current;
02042 }
02043 
02044 //_____________________________________________________________________________
02045 Int_t TGeoNavigator::GetVirtualLevel()
02046 {
02047 // Find level of virtuality of current overlapping node (number of levels
02048 // up having the same tracking media.
02049 
02050    // return if the current node is ONLY
02051    if (!fCurrentOverlapping) return 0;
02052    Int_t new_media = 0;
02053    TGeoMedium *medium = fCurrentNode->GetMedium();
02054    Int_t virtual_level = 1;
02055    TGeoNode *mother = 0;
02056 
02057    while ((mother=GetMother(virtual_level))) {
02058       if (!mother->IsOverlapping() && !mother->IsOffset()) {
02059          if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
02060          break;
02061       }
02062       if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
02063       virtual_level++;
02064    }
02065    return (new_media==0)?virtual_level:(new_media-1);
02066 }
02067 
02068 //_____________________________________________________________________________
02069 Bool_t TGeoNavigator::GotoSafeLevel()
02070 {
02071 // Go upwards the tree until a non-overlaping node
02072    while (fCurrentOverlapping && fLevel) CdUp();
02073    Double_t point[3];
02074    fGlobalMatrix->MasterToLocal(fPoint, point);
02075    if (!fCurrentNode->GetVolume()->Contains(point)) return kFALSE;
02076    if (fNmany) {
02077    // We still have overlaps on the branch
02078       Int_t up = 1;
02079       Int_t imother;
02080       Int_t nmany = fNmany;
02081       Bool_t ovlp = kFALSE;
02082       Bool_t nextovlp = kFALSE;
02083       TGeoNode *current = fCurrentNode;
02084       TGeoNode *mother, *mup;
02085       TGeoHMatrix *matrix;
02086       while (nmany) {
02087          mother = GetMother(up);
02088          if (!mother) return kTRUE;
02089          mup = mother;
02090          imother = up+1;
02091          while (mup->IsOffset()) mup = GetMother(imother++);
02092          nextovlp = mup->IsOverlapping();
02093          if (ovlp) nmany--;
02094          if (ovlp || nextovlp) {
02095          // check if the point is in the next node up
02096             matrix = GetMotherMatrix(up);
02097             matrix->MasterToLocal(fPoint,point);
02098             if (!mother->GetVolume()->Contains(point)) {
02099                up++;
02100                while (up--) CdUp();
02101                return GotoSafeLevel();
02102             }
02103          }   
02104          current = mother;
02105          ovlp = nextovlp;
02106          up++;
02107       }            
02108    }      
02109    return kTRUE;         
02110 }
02111 
02112 //_____________________________________________________________________________
02113 Int_t TGeoNavigator::GetSafeLevel() const
02114 {
02115 // Go upwards the tree until a non-overlaping node
02116    Bool_t overlapping = fCurrentOverlapping;
02117    if (!overlapping) return fLevel;
02118    Int_t level = fLevel;
02119    TGeoNode *node;
02120    while (overlapping && level) {
02121       level--;
02122       node = GetMother(fLevel-level);
02123       if (!node->IsOffset()) overlapping = node->IsOverlapping();
02124    }
02125    return level;
02126 }
02127 
02128 //_____________________________________________________________________________
02129 void TGeoNavigator::InspectState() const
02130 {
02131 // Inspects path and all flags for the current state.
02132    Info("InspectState","Current path is: %s",GetPath());
02133    Int_t level;
02134    TGeoNode *node;
02135    Bool_t is_offset, is_overlapping;
02136    for (level=0; level<fLevel+1; level++) {
02137       node = GetMother(fLevel-level);
02138       if (!node) continue;
02139       is_offset = node->IsOffset();
02140       is_overlapping = node->IsOverlapping();
02141       Info("InspectState","level %i: %s  div=%i  many=%i",level,node->GetName(),is_offset,is_overlapping);
02142    }
02143    Info("InspectState","on_bound=%i   entering=%i", fIsOnBoundary, fIsEntering);
02144 }      
02145 
02146 //_____________________________________________________________________________
02147 Bool_t TGeoNavigator::IsSameLocation(Double_t x, Double_t y, Double_t z, Bool_t change)
02148 {
02149 // Checks if point (x,y,z) is still in the current node.
02150    // check if this is an overlapping node
02151    Double_t oldpt[3];
02152    if (fLastSafety>0) {
02153       Double_t dx = (x-fLastPoint[0]);
02154       Double_t dy = (y-fLastPoint[1]);
02155       Double_t dz = (z-fLastPoint[2]);
02156       Double_t dsq = dx*dx+dy*dy+dz*dz;
02157       if (dsq<fLastSafety*fLastSafety) return kTRUE;
02158    }
02159    if (fCurrentOverlapping) {
02160 //      TGeoNode *current = fCurrentNode;
02161       Int_t cid = GetCurrentNodeId();
02162       if (!change) PushPoint();
02163       memcpy(oldpt, fPoint, kN3);
02164       SetCurrentPoint(x,y,z);
02165       SearchNode();
02166       memcpy(fPoint, oldpt, kN3);
02167       Bool_t same = (cid==GetCurrentNodeId())?kTRUE:kFALSE;
02168       if (!change) PopPoint();
02169       return same;
02170    }
02171 
02172    Double_t point[3];
02173    point[0] = x;
02174    point[1] = y;
02175    point[2] = z;
02176    if (change) memcpy(fPoint, point, kN3);
02177    TGeoVolume *vol = fCurrentNode->GetVolume();
02178    if (fIsOutside) {
02179       if (vol->GetShape()->Contains(point)) {
02180          if (!change) return kFALSE;
02181          FindNode(x,y,z);
02182          return kFALSE;
02183       }
02184       return kTRUE;
02185    }
02186    Double_t local[3];
02187    // convert to local frame
02188    fGlobalMatrix->MasterToLocal(point,local);
02189    // check if still in current volume.
02190    if (!vol->GetShape()->Contains(local)) {
02191       if (!change) return kFALSE;
02192       CdUp();
02193       FindNode(x,y,z);
02194       return kFALSE;
02195    }
02196 
02197    // check if there are daughters
02198    Int_t nd = vol->GetNdaughters();
02199    if (!nd) return kTRUE;
02200 
02201    TGeoNode *node;
02202    TGeoPatternFinder *finder = vol->GetFinder();
02203    if (finder) {
02204       node=finder->FindNode(local);
02205       if (node) {
02206          if (!change) return kFALSE;
02207          CdDown(node->GetIndex());
02208          SearchNode(kTRUE,node);
02209          return kFALSE;
02210       }
02211       return kTRUE;
02212    }
02213    // if we are not allowed to do changes, save the current path
02214    TGeoVoxelFinder *voxels = vol->GetVoxels();
02215    Int_t *check_list = 0;
02216    Int_t ncheck = 0;
02217    Double_t local1[3];
02218    if (voxels) {
02219       check_list = voxels->GetCheckList(local, ncheck);
02220       if (!check_list) return kTRUE;
02221       if (!change) PushPath();
02222       for (Int_t id=0; id<ncheck; id++) {
02223 //         node = vol->GetNode(check_list[id]);
02224          CdDown(check_list[id]);
02225          fGlobalMatrix->MasterToLocal(point,local1);
02226          if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
02227             if (!change) {
02228                PopPath();
02229                return kFALSE;
02230             }
02231             SearchNode(kTRUE);
02232             return kFALSE;
02233          }
02234          CdUp();
02235       }
02236       if (!change) PopPath();
02237       return kTRUE;
02238    }
02239    Int_t id = 0;
02240    if (!change) PushPath();
02241    while (fCurrentNode && fCurrentNode->GetDaughter(id++)) {
02242       CdDown(id-1);
02243       fGlobalMatrix->MasterToLocal(point,local1);
02244       if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
02245          if (!change) {
02246             PopPath();
02247             return kFALSE;
02248          }
02249          SearchNode(kTRUE);
02250          return kFALSE;
02251       }
02252       CdUp();
02253       if (id == nd) {
02254          if (!change) PopPath();
02255          return kTRUE;
02256       }
02257    }
02258    if (!change) PopPath();
02259    return kTRUE;
02260 }
02261 
02262 //_____________________________________________________________________________
02263 Bool_t TGeoNavigator::IsSafeStep(Double_t proposed, Double_t &newsafety) const
02264 {
02265 // In case a previous safety value was computed, check if the safety region is
02266 // still safe for the current point and proposed step. Return value changed only
02267 // if proposed distance is safe.
02268 
02269    // Last safety not computed.
02270    if (fLastSafety < gTolerance) return kFALSE;
02271    // Proposed step too small
02272    if (proposed < gTolerance) {
02273       newsafety = fLastSafety - proposed;
02274       return kTRUE;
02275    }
02276    // Normal step
02277    Double_t dist = (fPoint[0]-fLastPoint[0])*(fPoint[0]-fLastPoint[0])+
02278                    (fPoint[1]-fLastPoint[1])*(fPoint[1]-fLastPoint[1])+
02279                    (fPoint[2]-fLastPoint[2])*(fPoint[2]-fLastPoint[2]);
02280    dist = TMath::Sqrt(dist);
02281    Double_t safe =  fLastSafety - dist;
02282    if (safe < proposed) return kFALSE;
02283    newsafety = safe;
02284    return kTRUE;
02285 }
02286 
02287 //_____________________________________________________________________________
02288 Bool_t TGeoNavigator::IsSamePoint(Double_t x, Double_t y, Double_t z) const
02289 {
02290 // Check if a new point with given coordinates is the same as the last located one.
02291    if (TMath::Abs(x-fLastPoint[0]) < 1.E-20) {
02292       if (TMath::Abs(y-fLastPoint[1]) < 1.E-20) {
02293          if (TMath::Abs(z-fLastPoint[2]) < 1.E-20) return kTRUE;
02294       }
02295    }
02296    return kFALSE;
02297 }
02298   
02299 //_____________________________________________________________________________
02300 void TGeoNavigator::DoBackupState()
02301 {
02302 // Backup the current state without affecting the cache stack.
02303    if (fBackupState) fBackupState->SetState(fLevel,0, fNmany, fCurrentOverlapping);
02304 }
02305 
02306 //_____________________________________________________________________________
02307 void TGeoNavigator::DoRestoreState()
02308 {
02309 // Restore a backed-up state without affecting the cache stack.
02310    if (fBackupState && fCache) {
02311       fCurrentOverlapping = fCache->RestoreState(fNmany, fBackupState);
02312       fCurrentNode=fCache->GetNode();
02313       fGlobalMatrix = fCache->GetCurrentMatrix();
02314       fLevel=fCache->GetLevel();
02315    }   
02316 }
02317 
02318 //_____________________________________________________________________________
02319 TGeoHMatrix *TGeoNavigator::GetHMatrix()
02320 {
02321 // Return stored current matrix (global matrix of the next touched node).
02322    if (!fCurrentMatrix) {
02323       fCurrentMatrix = new TGeoHMatrix();
02324       fCurrentMatrix->RegisterYourself();
02325    }   
02326    return fCurrentMatrix;
02327 }
02328 
02329 //_____________________________________________________________________________
02330 const char *TGeoNavigator::GetPath() const
02331 {
02332 // Get path to the current node in the form /node0/node1/...
02333    if (fIsOutside) return kGeoOutsidePath;
02334    return fCache->GetPath();
02335 }
02336 
02337 //______________________________________________________________________________
02338 void TGeoNavigator::MasterToTop(const Double_t *master, Double_t *top) const
02339 {
02340 // Convert coordinates from master volume frame to top.
02341    fCurrentMatrix->MasterToLocal(master, top);
02342 }
02343 
02344 //______________________________________________________________________________
02345 void TGeoNavigator::TopToMaster(const Double_t *top, Double_t *master) const
02346 {
02347 // Convert coordinates from top volume frame to master.
02348    fCurrentMatrix->LocalToMaster(top, master);
02349 }
02350 
02351 //______________________________________________________________________________
02352 void TGeoNavigator::ResetAll()
02353 {
02354 // Reset the navigator.
02355    GetHMatrix();
02356    *fCurrentMatrix = gGeoIdentity;
02357    fCurrentNode = fGeometry->GetTopNode();
02358    ResetState();
02359    fStep = 0.;
02360    fSafety = 0.;
02361    fLastSafety = 0.;
02362    fLevel = 0;
02363    fNmany = 0;
02364    fNextDaughterIndex = -2;
02365    fCurrentOverlapping = kFALSE;
02366    fStartSafe = kFALSE;
02367    fIsSameLocation = kFALSE;
02368    fIsNullStep = kFALSE;
02369    fCurrentVolume = fGeometry->GetTopVolume();
02370    fCurrentNode = fGeometry->GetTopNode();
02371    fLastNode = 0;
02372    fNextNode = 0;
02373    fPath = "";
02374    if (fCache) {
02375       Bool_t dummy=fCache->IsDummy();
02376       Bool_t nodeid = fCache->HasIdArray();
02377       delete fCache;
02378       delete fBackupState;
02379       fCache = 0;
02380       BuildCache(dummy,nodeid);
02381    }
02382 }

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