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 }