00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011  
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #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 
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 
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 
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    
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 
00244    if (fCache) delete fCache;
00245    if (fBackupState) delete fBackupState;
00246    if (fOverlapClusters) delete [] fOverlapClusters;
00247 }
00248    
00249 
00250 void TGeoNavigator::BuildCache(Bool_t , Bool_t nodeid)
00251 {
00252 
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       
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 
00274 
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 
00314    Int_t length = strlen(path);
00315    if (!length) return kFALSE;
00316    TString spath = path;
00317    TGeoVolume *vol;
00318    TGeoNode *top = fGeometry->GetTopNode();
00319    
00320    Int_t ind1 = spath.Index("/");
00321    if (ind1<0) {
00322       
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;   
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    
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 
00358 
00359    if (fCache) {
00360       fCache->CdNode(nodeid);
00361       fGlobalMatrix = fCache->GetCurrentMatrix();
00362    }   
00363 }
00364 
00365 
00366 void TGeoNavigator::CdDown(Int_t index)
00367 {
00368 
00369 
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 
00389 
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 
00421 
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 
00437    if (fNextDaughterIndex == -2 || !fCache) return;
00438    if (fNextDaughterIndex ==  -3) {
00439       
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 
00465    fCache->GetBranchNames(names);
00466 }
00467 
00468 
00469 void TGeoNavigator::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
00470 {
00471 
00472    fCache->GetBranchNumbers(copyNumbers, volumeNumbers);
00473 }
00474 
00475 
00476 void TGeoNavigator::GetBranchOnlys(Int_t *isonly) const
00477 {
00478 
00479    fCache->GetBranchOnlys(isonly);
00480 }
00481 
00482 
00483 TGeoNode *TGeoNavigator::CrossDivisionCell()
00484 {
00485 
00486 
00487    TGeoPatternFinder *finder = fCurrentNode->GetFinder();
00488    if (!finder) {
00489       Fatal("CrossDivisionCell", "Volume has no pattern finder");
00490       return 0;
00491    }
00492    
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    
00499    Bool_t onbound = finder->IsOnBoundary(newpoint);
00500    if (onbound) {
00501       
00502       
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       
00507       finder->FindNode(point, dir);
00508       Int_t inext = finder->GetNext();
00509       if (inext<0) {
00510          
00511          
00512          if (fCurrentNode->IsOffset()) {
00513             Double_t dist = fCurrentNode->GetVolume()->GetShape()->DistFromInside(point,dir,3);
00514             
00515             if (dist < fStep+2.*gTolerance) {
00516                
00517                return CrossDivisionCell();
00518             }
00519             
00520             return fCurrentNode;
00521          }   
00522          
00523          while (fCurrentNode->GetVolume()->IsAssembly()) {
00524             
00525             skip = fCurrentNode;
00526             if (!fLevel) break;
00527             CdUp();
00528          } 
00529          return CrossBoundaryAndLocate(kFALSE, skip);
00530       }
00531       
00532       CdDown(inext+finder->GetDivIndex());
00533       skip = fCurrentNode;
00534       return CrossBoundaryAndLocate(kTRUE, skip);
00535    }
00536    
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 
00545 
00546 
00547 
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 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601    
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       
00620       if (!frombdr && IsSafeStep(stepmax+gTolerance, fSafety)) {
00621          fStep = stepmax;
00622          fNextNode = fCurrentNode;
00623          return fCurrentNode;
00624       }   
00625 
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    
00670    
00671    
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    
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    
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    
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          
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          
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                
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                
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       
00827       if (fNmany) {
00828       
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 
00890 
00891 
00892 
00893    Double_t snext = TGeoShape::Big();
00894    Int_t idebug = TGeoManager::GetVerboseLevel();
00895    idaughter = -1; 
00896    TGeoNode *nodefound = 0;
00897    
00898 
00899    TGeoVolume *vol = fCurrentNode->GetVolume();
00900    Int_t nd = vol->GetNdaughters();
00901    if (!nd) return 0;  
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    
00907    
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          
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    
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    
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 
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 
01062 
01063 
01064 
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       
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       
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          
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          
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       
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    
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    
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       
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       
01196       icrossed = -1;
01197       fStep = snext;
01198       fIsStepEntering = kFALSE;
01199       fIsStepExiting = kTRUE;
01200    }
01201    
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    
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          
01227          snext = TGeoShape::Big();
01228          if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(mothpt, vecpt, iact, fStep);
01229          if (snext<fStep-gTolerance) {
01230             
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          
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                
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                
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       
01301       if (fNmany) {
01302       
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       
01364       fIsOnBoundary = kFALSE;
01365       return fCurrentNode;
01366    }
01367    fIsOnBoundary = kTRUE;
01368    if (icrossed == -1) {
01369       
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 
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 
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 
01442 
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 )
01456 {
01457 
01458 
01459 
01460 
01461    return FindNormalFast();
01462 }
01463 
01464 
01465 TGeoNode *TGeoNavigator::InitTrack(const Double_t *point, const Double_t *dir)
01466 {
01467 
01468 
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 
01478 
01479    SetCurrentPoint(x,y,z);
01480    SetCurrentDirection(nx,ny,nz);
01481    return FindNode();
01482 }
01483 
01484 
01485 void TGeoNavigator::ResetState()
01486 {
01487 
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 
01499 
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    
01516    fGlobalMatrix->MasterToLocal(fPoint, point);
01517 
01518    
01519    TGeoVolume *vol = fCurrentNode->GetVolume();
01520    if (!inside) {
01521       fSafety = vol->GetShape()->Safety(point, kTRUE);
01522       
01523       if (fSafety < gTolerance) {
01524          fSafety = 0;
01525          fIsOnBoundary = kTRUE;
01526          return fSafety;
01527       }
01528    }
01529 
01530    
01531 
01532    
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    
01541    
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    
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    
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 
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       
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    
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 
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    
01702       if (fGeometry->IsActivityEnabled() && !fCurrentNode->GetVolume()->IsActive()) {
01703          
01704          CdUp();
01705          fIsSameLocation = kFALSE;
01706          return SearchNode(kFALSE, skipnode);
01707       }
01708       
01709       vol=fCurrentNode->GetVolume();
01710       if (vol->IsAssembly()) inside_current=kTRUE;
01711       
01712       if (!inside_current) {
01713          fGlobalMatrix->MasterToLocal(fPoint, point);
01714          inside_current = vol->Contains(point);
01715       }   
01716       
01717       if (fNmany) {
01718          inside_current = GotoSafeLevel();
01719       }   
01720       if (!inside_current) {
01721          
01722          fIsSameLocation = kFALSE;
01723          TGeoNode *skip = fCurrentNode;  
01724          
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    
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    
01754    TGeoNode *node;
01755    Int_t ncheck = 0;
01756    
01757    if (!fCurrentOverlapping) {
01758       fSearchOverlaps = kFALSE;
01759    }
01760 
01761    Int_t crtindex = vol->GetCurrentNodeIndex();
01762    while (crtindex>=0 && downwards) {
01763       
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    
01772    if (!nd) return fCurrentNode;
01773    if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters()) return fCurrentNode;
01774 
01775    TGeoPatternFinder *finder = vol->GetFinder();
01776    
01777    
01778    if (finder) {
01779       node=finder->FindNode(point);
01780       if (!node && fForcedNode) {
01781          
01782          Double_t dir[3];
01783          fGlobalMatrix->MasterToLocalVect(fDirection, dir);
01784          finder->FindNode(point,dir);
01785          node = finder->CdNext();
01786          if (!node) return fCurrentNode;  
01787       }   
01788       if (node && node!=skipnode) {
01789          
01790          fIsSameLocation = kFALSE;
01791          CdDown(node->GetIndex());
01792          fForcedNode = 0;
01793          return SearchNode(kTRUE, node);
01794       }
01795       
01796       
01797       while (fCurrentNode && fCurrentNode->IsOffset()) CdUp();
01798       return fCurrentNode;
01799    }
01800    
01801    TGeoVoxelFinder *voxels = vol->GetVoxels();
01802    Int_t *check_list = 0;
01803    Int_t id;
01804    if (voxels) {
01805       
01806       check_list = voxels->GetCheckList(&point[0], ncheck);
01807       
01808       if (!check_list) {
01809          if (!fCurrentNode->GetVolume()->IsAssembly()) return fCurrentNode;
01810          
01811          node = fCurrentNode;
01812          if (!fLevel) {
01813             fIsOutside = kTRUE;
01814             return 0;
01815          }
01816          CdUp();
01817          return SearchNode(kFALSE,node);
01818       }   
01819       
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          
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    
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    
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 
01889 
01890    TGeoNode *clnode = 0;
01891    TGeoNode *priority = fLastNode;
01892    
01893    TGeoNode *current = fCurrentNode;
01894    TGeoNode *found = 0;
01895    
01896    Int_t ipop = PushPath();
01897    
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       
01912       
01913          PopDummy(ipop);
01914          return found;
01915       }
01916       found_virtual = fLevel-GetVirtualLevel();
01917       if (added) {
01918       
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          
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          
01943          if (replace) {
01944             
01945             PopDummy();
01946             PushPath();
01947             deepest = fLevel;
01948             deepest_virtual = found_virtual;
01949          }
01950          
01951          fCurrentOverlapping = PopPath(ipop);
01952       } else {
01953       
01954          PushPath();
01955          added = kTRUE;
01956          deepest = fLevel;
01957          deepest_virtual = found_virtual;
01958          
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 
01971 
01972 
01973 
01974    
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    
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          
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 
02010 
02011 
02012 
02013 
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 
02048 
02049 
02050    
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 
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    
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          
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 
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 
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 
02150    
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 
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    
02188    fGlobalMatrix->MasterToLocal(point,local);
02189    
02190    if (!vol->GetShape()->Contains(local)) {
02191       if (!change) return kFALSE;
02192       CdUp();
02193       FindNode(x,y,z);
02194       return kFALSE;
02195    }
02196 
02197    
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    
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 
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 
02266 
02267 
02268 
02269    
02270    if (fLastSafety < gTolerance) return kFALSE;
02271    
02272    if (proposed < gTolerance) {
02273       newsafety = fLastSafety - proposed;
02274       return kTRUE;
02275    }
02276    
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 
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 
02303    if (fBackupState) fBackupState->SetState(fLevel,0, fNmany, fCurrentOverlapping);
02304 }
02305 
02306 
02307 void TGeoNavigator::DoRestoreState()
02308 {
02309 
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 
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 
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 
02341    fCurrentMatrix->MasterToLocal(master, top);
02342 }
02343 
02344 
02345 void TGeoNavigator::TopToMaster(const Double_t *top, Double_t *master) const
02346 {
02347 
02348    fCurrentMatrix->LocalToMaster(top, master);
02349 }
02350 
02351 
02352 void TGeoNavigator::ResetAll()
02353 {
02354 
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 }