46 static Double_t gTolerance = TGeoShape::Tolerance();
47 const char *kGeoOutsidePath =
" ";
48 const Int_t kN3 = 3*
sizeof(Double_t);
50 ClassImp(TGeoNavigator);
55 TGeoNavigator::TGeoNavigator()
62 fNextDaughterIndex(0),
66 fSearchOverlaps(kFALSE),
67 fCurrentOverlapping(kFALSE),
71 fIsStepEntering(kFALSE),
72 fIsStepExiting(kFALSE),
74 fIsOnBoundary(kFALSE),
75 fIsSameLocation(kFALSE),
93 for (Int_t i=0; i<3; i++) {
96 fCldirChecked[i] = 0.;
106 TGeoNavigator::TGeoNavigator(TGeoManager* geom)
113 fNextDaughterIndex(-2),
117 fSearchOverlaps(kFALSE),
118 fCurrentOverlapping(kFALSE),
122 fIsStepEntering(kFALSE),
123 fIsStepExiting(kFALSE),
125 fIsOnBoundary(kFALSE),
126 fIsSameLocation(kTRUE),
144 fThreadId = TGeoManager::ThreadId();
146 for (Int_t i=0; i<3; i++) {
149 fCldirChecked[i] = 0;
154 fCurrentMatrix =
new TGeoHMatrix();
155 fCurrentMatrix->RegisterYourself();
156 fDivMatrix =
new TGeoHMatrix();
157 fDivMatrix->RegisterYourself();
158 fOverlapClusters =
new Int_t[fOverlapSize];
165 TGeoNavigator::TGeoNavigator(
const TGeoNavigator& gm)
169 fLastSafety(gm.fLastSafety),
173 fNextDaughterIndex(gm.fNextDaughterIndex),
174 fOverlapSize(gm.fOverlapSize),
175 fOverlapMark(gm.fOverlapMark),
176 fOverlapClusters(gm.fOverlapClusters),
177 fSearchOverlaps(gm.fSearchOverlaps),
178 fCurrentOverlapping(gm.fCurrentOverlapping),
179 fStartSafe(gm.fStartSafe),
180 fIsEntering(gm.fIsEntering),
181 fIsExiting(gm.fIsExiting),
182 fIsStepEntering(gm.fIsStepEntering),
183 fIsStepExiting(gm.fIsStepExiting),
184 fIsOutside(gm.fIsOutside),
185 fIsOnBoundary(gm.fIsOnBoundary),
186 fIsSameLocation(gm.fIsSameLocation),
187 fIsNullStep(gm.fIsNullStep),
188 fGeometry(gm.fGeometry),
190 fCurrentVolume(gm.fCurrentVolume),
191 fCurrentNode(gm.fCurrentNode),
192 fTopNode(gm.fTopNode),
193 fLastNode(gm.fLastNode),
194 fNextNode(gm.fNextNode),
195 fForcedNode(gm.fForcedNode),
196 fBackupState(gm.fBackupState),
197 fCurrentMatrix(gm.fCurrentMatrix),
198 fGlobalMatrix(gm.fGlobalMatrix),
201 fThreadId = TGeoManager::ThreadId();
202 for (Int_t i=0; i<3; i++) {
203 fNormal[i] = gm.fNormal[i];
204 fCldir[i] = gm.fCldir[i];
205 fCldirChecked[i] = gm.fCldirChecked[i];
206 fPoint[i] = gm.fPoint[i];
207 fDirection[i] = gm.fDirection[i];
208 fLastPoint[i] = gm.fLastPoint[i];
210 fDivMatrix =
new TGeoHMatrix();
211 fDivMatrix->RegisterYourself();
217 TGeoNavigator& TGeoNavigator::operator=(
const TGeoNavigator& gm)
220 TObject::operator=(gm);
222 fSafety = gm.fSafety;
223 fLastSafety = gm.fLastSafety;
224 fThreadId = TGeoManager::ThreadId();
227 fNextDaughterIndex = gm.fNextDaughterIndex;
228 fOverlapSize=gm.fOverlapSize;
229 fOverlapMark=gm.fOverlapMark;
230 fOverlapClusters=gm.fOverlapClusters;
231 fSearchOverlaps = gm.fSearchOverlaps;
232 fCurrentOverlapping = gm.fCurrentOverlapping;
233 fStartSafe = gm.fStartSafe;
234 fIsEntering = gm.fIsEntering;
235 fIsExiting = gm.fIsExiting;
236 fIsStepEntering = gm.fIsStepEntering;
237 fIsStepExiting = gm.fIsStepExiting;
238 fIsOutside = gm.fIsOutside;
239 fIsOnBoundary = gm.fIsOnBoundary;
240 fIsSameLocation = gm.fIsSameLocation;
241 fIsNullStep = gm.fIsNullStep;
242 fGeometry = gm.fGeometry;
244 fCurrentVolume = gm.fCurrentVolume;
245 fCurrentNode = gm.fCurrentNode;
246 fTopNode = gm.fTopNode;
247 fLastNode = gm.fLastNode;
248 fNextNode = gm.fNextNode;
249 fForcedNode = gm.fForcedNode;
250 fBackupState = gm.fBackupState;
251 fCurrentMatrix = gm.fCurrentMatrix;
252 fGlobalMatrix = gm.fGlobalMatrix;
254 for (Int_t i=0; i<3; i++) {
255 fNormal[i] = gm.fNormal[i];
256 fCldir[i] = gm.fCldir[i];
257 fCldirChecked[i] = gm.fCldirChecked[i];
258 fPoint[i] = gm.fPoint[i];
259 fDirection[i] = gm.fDirection[i];
260 fLastPoint[i] = gm.fLastPoint[i];
262 fDivMatrix =
new TGeoHMatrix();
263 fDivMatrix->RegisterYourself();
271 TGeoNavigator::~TGeoNavigator()
273 if (fCache)
delete fCache;
274 if (fBackupState)
delete fBackupState;
275 if (fOverlapClusters)
delete [] fOverlapClusters;
281 void TGeoNavigator::BuildCache(Bool_t , Bool_t nodeid)
283 static Bool_t first = kTRUE;
284 Int_t verbose = TGeoManager::GetVerboseLevel();
285 Int_t nlevel = fGeometry->GetMaxLevel();
286 if (nlevel<=0) nlevel = 100;
289 if (first && verbose>0) Info(
"BuildCache",
"--- Maximum geometry depth set to 100");
291 if (first && verbose>0) Info(
"BuildCache",
"--- Maximum geometry depth is %i", nlevel);
294 fCache =
new TGeoNodeCache(fGeometry->GetTopNode(), nodeid, nlevel+1);
295 fGlobalMatrix = fCache->GetCurrentMatrix();
296 fBackupState =
new TGeoCacheState(nlevel+1);
306 Bool_t TGeoNavigator::cd(
const char *path)
309 if (!path[0])
return kTRUE;
310 TString spath = path;
312 Int_t length = spath.Length();
313 Int_t ind1 = spath.Index(
"/");
314 if (ind1 == length-1) ind1 = -1;
317 Bool_t first = kTRUE;
321 ind2 = spath.Index(
"/", ind1+1);
322 if (ind2<0 || ind2==length-1) {
323 if (ind2<0) ind2 = length;
326 name = spath(ind1+1, ind2-ind1-1);
327 vol = fCurrentNode->GetVolume();
330 if (name.BeginsWith(vol->GetName())) {
335 node = vol->GetNode(name.Data());
337 Error(
"cd",
"Path %s not valid", path);
340 CdDown(vol->GetIndex(node));
349 Bool_t TGeoNavigator::CheckPath(
const char *path)
const
351 if (!path[0])
return kTRUE;
352 TGeoNode *crtnode = fGeometry->GetTopNode();
353 TString spath = path;
355 Int_t length = spath.Length();
356 Int_t ind1 = spath.Index(
"/");
357 if (ind1 == length-1) ind1 = -1;
360 Bool_t first = kTRUE;
364 ind2 = spath.Index(
"/", ind1+1);
365 if (ind2<0 || ind2==length-1) {
366 if (ind2<0) ind2 = length;
369 name = spath(ind1+1, ind2-ind1-1);
370 vol = crtnode->GetVolume();
373 if (name.BeginsWith(vol->GetName())) {
378 node = vol->GetNode(name.Data());
379 if (!node)
return kFALSE;
390 void TGeoNavigator::CdNode(Int_t nodeid)
393 fCache->CdNode(nodeid);
394 fGlobalMatrix = fCache->GetCurrentMatrix();
402 void TGeoNavigator::CdDown(Int_t index)
404 TGeoNode *node = fCurrentNode->GetDaughter(index);
405 Bool_t is_offset = node->IsOffset();
409 fCurrentOverlapping = node->IsOverlapping();
410 fCache->CdDown(index);
412 fGlobalMatrix = fCache->GetCurrentMatrix();
413 if (fCurrentOverlapping) fNmany++;
421 void TGeoNavigator::CdDown(TGeoNode *node)
423 Bool_t is_offset = node->IsOffset();
427 fCurrentOverlapping = node->IsOverlapping();
428 fCache->CdDown(node);
430 fGlobalMatrix = fCache->GetCurrentMatrix();
431 if (fCurrentOverlapping) fNmany++;
439 void TGeoNavigator::CdUp()
441 if (!fLevel || !fCache)
return;
448 if (fCurrentOverlapping) {
449 fLastNode = fCurrentNode;
452 fCurrentNode = fCache->GetNode();
453 fGlobalMatrix = fCache->GetCurrentMatrix();
454 if (!fCurrentNode->IsOffset()) {
455 fCurrentOverlapping = fCurrentNode->IsOverlapping();
458 Bool_t offset = kTRUE;
459 TGeoNode *mother = 0;
461 mother = GetMother(up++);
462 offset = mother->IsOffset();
464 fCurrentOverlapping = mother->IsOverlapping();
472 void TGeoNavigator::CdTop()
477 if (fCurrentOverlapping) fLastNode = fCurrentNode;
478 fCurrentNode = fGeometry->GetTopNode();
480 fGlobalMatrix = fCache->GetCurrentMatrix();
481 fCurrentOverlapping = fCurrentNode->IsOverlapping();
482 if (fCurrentOverlapping) fNmany++;
488 void TGeoNavigator::CdNext()
490 if (fNextDaughterIndex == -2 || !fCache)
return;
491 if (fNextDaughterIndex == -3) {
494 fNextDaughterIndex = -2;
497 if (fNextDaughterIndex == -1) {
499 while (fCurrentNode->GetVolume()->IsAssembly()) CdUp();
500 fNextDaughterIndex--;
503 if (fCurrentNode && fNextDaughterIndex<fCurrentNode->GetNdaughters()) {
504 CdDown(fNextDaughterIndex);
505 Int_t nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
506 while (nextindex>=0) {
508 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
511 fNextDaughterIndex = -2;
517 void TGeoNavigator::GetBranchNames(Int_t *names)
const
519 fCache->GetBranchNames(names);
525 void TGeoNavigator::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers)
const
527 fCache->GetBranchNumbers(copyNumbers, volumeNumbers);
533 void TGeoNavigator::GetBranchOnlys(Int_t *isonly)
const
535 fCache->GetBranchOnlys(isonly);
542 TGeoNode *TGeoNavigator::CrossDivisionCell()
544 TGeoPatternFinder *finder = fCurrentNode->GetFinder();
546 Fatal(
"CrossDivisionCell",
"Volume has no pattern finder");
550 TGeoNode *skip = fCurrentNode;
552 Double_t point[3], newpoint[3], dir[3];
553 fGlobalMatrix->MasterToLocal(fPoint, newpoint);
554 fGlobalMatrix->MasterToLocalVect(fDirection, dir);
556 Bool_t onbound = finder->IsOnBoundary(newpoint);
560 point[0] = newpoint[0] - dir[0]*fStep*(1.-gTolerance);
561 point[1] = newpoint[1] - dir[1]*fStep*(1.-gTolerance);
562 point[2] = newpoint[2] - dir[2]*fStep*(1.-gTolerance);
564 finder->FindNode(point, dir);
565 Int_t inext = finder->GetNext();
569 if (fCurrentNode->IsOffset()) {
570 Double_t dist = fCurrentNode->GetVolume()->GetShape()->DistFromInside(point,dir,3);
572 if (dist < fStep+2.*gTolerance) {
574 return CrossDivisionCell();
580 while (fCurrentNode->GetVolume()->IsAssembly()) {
586 return CrossBoundaryAndLocate(kFALSE, skip);
589 CdDown(inext+finder->GetDivIndex());
591 return CrossBoundaryAndLocate(kTRUE, skip);
594 if (fCurrentNode->IsOffset())
return CrossDivisionCell();
595 return CrossBoundaryAndLocate(kFALSE, skip);
602 TGeoNode *TGeoNavigator::CrossBoundaryAndLocate(Bool_t downwards, TGeoNode *skipnode)
605 Double_t *tr = fGlobalMatrix->GetTranslation();
606 Double_t trmax = 1.+TMath::Abs(tr[0])+TMath::Abs(tr[1])+TMath::Abs(tr[2]);
607 Double_t extra = 100.*(trmax+fStep)*gTolerance;
608 const Int_t idebug = TGeoManager::GetVerboseLevel();
609 TGeoNode *crtstate[10];
610 Int_t level = fLevel+1;
611 Bool_t samepath = kFALSE;
613 for (Int_t i=0; i<fLevel; ++i) {
614 crtstate[i] = GetMother(i);
618 fPoint[0] += extra*fDirection[0];
619 fPoint[1] += extra*fDirection[1];
620 fPoint[2] += extra*fDirection[2];
621 TGeoNode *current = SearchNode(downwards, skipnode);
623 fPoint[0] -= extra*fDirection[0];
624 fPoint[1] -= extra*fDirection[1];
625 fPoint[2] -= extra*fDirection[2];
626 if (!current)
return 0;
628 Int_t nextindex = current->GetVolume()->GetNextNodeIndex();
629 while (nextindex>=0) {
631 current = fCurrentNode;
632 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
635 printf(
"CrossBoundaryAndLocate: entered %s\n", GetPath());
641 if (current == skipnode) {
644 level = TMath::Min(level, 10);
645 for (Int_t i=1; i<level; i++) {
646 if (crtstate[i-1] != GetMother(i)) {
655 if (samepath || current->GetVolume()->IsAssembly()) {
659 printf(
"CrossBoundaryAndLocate: Exited geometry\n");
661 return fGeometry->GetCurrentNode();
664 while (fLevel && fCurrentNode->GetVolume()->IsAssembly()) CdUp();
665 if (!fLevel && fCurrentNode->GetVolume()->IsAssembly()) {
668 printf(
"CrossBoundaryAndLocate: Exited geometry\n");
671 printf(
"CrossBoundaryAndLocate: entered %s\n", GetPath());
678 printf(
"CrossBoundaryAndLocate: entered %s\n", GetPath());
697 TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax,
const char *path, Bool_t frombdr)
701 Int_t idebug = TGeoManager::GetVerboseLevel();
702 fNextDaughterIndex = -2;
703 fStep = TGeoShape::Big();
704 fIsStepEntering = kFALSE;
705 fIsStepExiting = kFALSE;
707 Bool_t computeGlobal = kFALSE;
708 fIsOnBoundary = frombdr;
710 TGeoNode *top_node = fGeometry->GetTopNode();
711 TGeoVolume *top_volume = top_node->GetVolume();
713 while (fCurrentNode->GetVolume()->IsAssembly() && fLevel) CdUp();
717 computeGlobal = kTRUE;
722 if (!frombdr && (fSafety>0) && IsSafeStep(stepmax+gTolerance, fSafety)) {
724 fNextNode = fCurrentNode;
727 fSafety = TMath::Abs(fSafety);
728 memcpy(fLastPoint, fPoint, kN3);
729 fLastSafety = fSafety;
730 if (fSafety<gTolerance) fIsOnBoundary = kTRUE;
731 else fIsOnBoundary = kFALSE;
733 if (stepmax+gTolerance<fSafety) {
734 fNextNode = fCurrentNode;
738 if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
739 Double_t snext = TGeoShape::Big();
744 printf(
"TGeoManager::FindNextBoundary: point=(%19.16f, %19.16f, %19.16f)\n",
745 fPoint[0],fPoint[1],fPoint[2]);
746 printf(
" dir= (%19.16f, %19.16f, %19.16f)\n",
747 fDirection[0], fDirection[1], fDirection[2]);
748 printf(
" pstep=%9.6g path=%s\n", stepmax, GetPath());
756 if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
757 fNextNode = fCurrentNode;
758 TGeoVolume *tvol=fCurrentNode->GetVolume();
759 fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
760 fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
762 printf(
"=== To path: %s\n", path);
763 printf(
"=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
764 tvol->GetName(), point[0],point[1],point[2],dir[0],dir[1],dir[2]);
766 if (tvol->Contains(point)) {
767 if (idebug>4) printf(
"=== volume %s contains point\n", tvol->GetName());
768 fStep=tvol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
770 fStep=tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, fStep, &safe);
772 printf(
"=== volume %s does not contain point\n", tvol->GetName());
773 printf(
"=== distance to path: %g\n", fStep);
774 tvol->InspectShape();
777 newpt[0] = point[0] + fStep*dir[0];
778 newpt[1] = point[1] + fStep*dir[1];
779 newpt[2] = point[2] + fStep*dir[2];
780 printf(
"=== Propagated point: (%19.16f, %19.16f, %19.16f)", newpt[0],newpt[1],newpt[2]);
784 tvol = fCurrentNode->GetVolume();
785 fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
786 fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
787 printf(
"=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
788 tvol->GetName(), point[0],point[1],point[2],dir[0],dir[1],dir[2]);
789 if (tvol->Contains(point)) {
790 printf(
"=== volume %s contains point\n", tvol->GetName());
792 printf(
"=== volume %s does not contain point\n", tvol->GetName());
793 snext = tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, 1.E30, &safe);
805 snext = top_volume->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep, &safe);
806 fNextNode = top_node;
807 if (snext < fStep-gTolerance) {
808 fIsStepEntering = kTRUE;
810 Int_t indnext = fNextNode->GetVolume()->GetNextNodeIndex();
811 fNextDaughterIndex = indnext;
813 fNextNode = fNextNode->GetDaughter(indnext);
814 if (computeGlobal) fCurrentMatrix->Multiply(fNextNode->GetMatrix());
815 indnext = fNextNode->GetVolume()->GetNextNodeIndex();
821 fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
822 fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
823 TGeoVolume *vol = fCurrentNode->GetVolume();
825 printf(
" -> from local=(%19.16f, %19.16f, %19.16f)\n",
826 point[0],point[1],point[2]);
827 printf(
" ldir =(%19.16f, %19.16f, %19.16f)\n",
828 dir[0],dir[1],dir[2]);
831 snext = vol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
833 printf(
" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
835 if (snext < fStep-gTolerance) {
836 fNextNode = fCurrentNode;
837 fNextDaughterIndex = -1;
838 fIsStepExiting = kTRUE;
840 fIsStepEntering = kFALSE;
841 if (fStep<1E-6)
return fCurrentNode;
843 fNextNode = (fStep<1E20)?fCurrentNode:0;
845 Int_t idaughter = -1;
846 FindNextDaughterBoundary(point,dir,idaughter,computeGlobal);
847 if (idaughter>=0) fNextDaughterIndex = idaughter;
848 TGeoNode *current = 0;
850 TGeoVolume *mother = 0;
855 Double_t dpt[3], dvec[3];
858 Int_t safelevel = GetSafeLevel();
859 PushPath(safelevel+1);
860 while (fCurrentOverlapping) {
861 Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
863 mother = fCurrentNode->GetVolume();
864 fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
865 fGlobalMatrix->MasterToLocalVect(fDirection, &vecpt[0]);
867 snext = TGeoShape::Big();
868 if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(&mothpt[0], &vecpt[0], iact, fStep, &safe);
869 if (snext<fStep-gTolerance) {
870 fIsStepExiting = kTRUE;
871 fIsStepEntering = kFALSE;
873 if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
874 fNextNode = fCurrentNode;
875 fNextDaughterIndex = -3;
879 for (Int_t i=0; i<novlps; i++) {
880 current = mother->GetNode(ovlps[i]);
881 if (!current->IsOverlapping()) {
883 current->MasterToLocal(&mothpt[0], &dpt[0]);
884 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
886 snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
887 if (snext<fStep-gTolerance) {
889 fCurrentMatrix->CopyFrom(fGlobalMatrix);
890 fCurrentMatrix->Multiply(current->GetMatrix());
892 fIsStepExiting = kTRUE;
893 fIsStepEntering = kFALSE;
896 fNextDaughterIndex = -3;
904 current->MasterToLocal(&mothpt[0], &dpt[0]);
905 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
906 if (current->GetVolume()->Contains(dpt)) {
907 if (current->GetVolume()->GetNdaughters()) {
909 fIsStepEntering = kFALSE;
910 fIsStepExiting = kTRUE;
911 dnode = FindNextDaughterBoundary(dpt,dvec,idovlp,computeGlobal);
914 fCurrentMatrix->CopyFrom(fGlobalMatrix);
915 fCurrentMatrix->Multiply(dnode->GetMatrix());
918 fNextDaughterIndex = -3;
920 Int_t indnext = fCurrentNode->GetVolume()->GetNextNodeIndex();
925 indnext = fCurrentNode->GetVolume()->GetNextNodeIndex();
937 snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
938 if (snext<fStep-gTolerance) {
940 fCurrentMatrix->CopyFrom(fGlobalMatrix);
941 fCurrentMatrix->Multiply(current->GetMatrix());
943 fIsStepExiting = kTRUE;
944 fIsStepEntering = kFALSE;
947 fNextDaughterIndex = -3;
961 Int_t nmany = fNmany;
962 Bool_t ovlp = kFALSE;
963 Bool_t nextovlp = kFALSE;
964 Bool_t offset = kFALSE;
965 TGeoNode *currentnode = fCurrentNode;
966 TGeoNode *mothernode, *mup;
969 mothernode = GetMother(up);
971 Fatal(
"FindNextBoundary",
"Cannot find mother node");
977 while (mup->IsOffset()) {
978 mup = GetMother(imother++);
981 nextovlp = mup->IsOverlapping();
984 if (nextovlp) nmany -= imother-up;
989 if (ovlp || nextovlp) {
990 matrix = GetMotherMatrix(up);
992 Fatal(
"FindNextBoundary",
"Cannot find mother matrix");
995 matrix->MasterToLocal(fPoint,dpt);
996 matrix->MasterToLocalVect(fDirection,dvec);
997 snext = TGeoShape::Big();
998 if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
999 if (snext<fStep-gTolerance) {
1000 fIsStepEntering = kFALSE;
1001 fIsStepExiting = kTRUE;
1003 fNextNode = mothernode;
1004 fNextDaughterIndex = -3;
1005 if (computeGlobal) fCurrentMatrix->CopyFrom(matrix);
1006 while (up--) CdUp();
1009 currentnode = fCurrentNode;
1010 ovlp = currentnode->IsOverlapping();
1014 currentnode = mothernode;
1022 Double_t parstep = TGeoShape::Big();
1023 if (fGeometry->IsParallelWorldNav()) {
1025 TGeoPhysicalNode *pnode = fGeometry->GetParallelWorld()->FindNextBoundary(fPoint, fDirection, parstep, fStep);
1029 fNextNode = pnode->GetNode();
1030 fNextDaughterIndex = -2;
1031 fIsStepEntering = kTRUE;
1032 fIsStepExiting = kFALSE;
1033 Int_t nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1034 while (nextindex>=0) {
1035 fNextNode = fNextNode->GetDaughter(nextindex);
1036 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1048 TGeoNode *TGeoNavigator::FindNextDaughterBoundary(Double_t *point, Double_t *dir, Int_t &idaughter, Bool_t compmatrix)
1050 Double_t snext = TGeoShape::Big();
1051 Int_t idebug = TGeoManager::GetVerboseLevel();
1053 TGeoNode *nodefound = 0;
1056 TGeoVolume *vol = fCurrentNode->GetVolume();
1057 Int_t nd = vol->GetNdaughters();
1059 if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters())
return 0;
1060 Double_t lpoint[3], ldir[3];
1061 TGeoNode *current = 0;
1065 TGeoPatternFinder *finder = vol->GetFinder();
1067 Int_t ifirst = finder->GetDivIndex();
1068 Int_t ilast = ifirst+finder->GetNdiv()-1;
1069 current = finder->FindNode(point);
1072 Int_t index = current->GetIndex();
1073 if ((index-1) >= ifirst) ifirst = index-1;
1075 if ((index+1) <= ilast) ilast = index+1;
1079 current = vol->GetNode(ifirst);
1081 current->MasterToLocal(&point[0], lpoint);
1082 current->MasterToLocalVect(&dir[0], ldir);
1083 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1084 if (snext<fStep-gTolerance) {
1086 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1087 fCurrentMatrix->Multiply(current->GetMatrix());
1089 fIsStepExiting = kFALSE;
1090 fIsStepEntering = kTRUE;
1092 fNextNode = current;
1093 nodefound = current;
1097 if (ilast==ifirst)
return nodefound;
1099 current = vol->GetNode(ilast);
1101 current->MasterToLocal(&point[0], lpoint);
1102 current->MasterToLocalVect(&dir[0], ldir);
1103 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1104 if (snext<fStep-gTolerance) {
1106 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1107 fCurrentMatrix->Multiply(current->GetMatrix());
1109 fIsStepExiting = kFALSE;
1110 fIsStepEntering = kTRUE;
1112 fNextNode = current;
1113 nodefound = current;
1120 TGeoVoxelFinder *voxels = vol->GetVoxels();
1122 if (idebug>4) printf(
" Checking distance to %d daughters...\n",nd);
1123 if (nd<5 || !voxels) {
1124 for (i=0; i<nd; i++) {
1125 current = vol->GetNode(i);
1126 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive())
continue;
1128 if (voxels && voxels->IsSafeVoxel(point, i, fStep))
continue;
1129 current->MasterToLocal(point, lpoint);
1130 current->MasterToLocalVect(dir, ldir);
1131 if (current->IsOverlapping() &&
1132 current->GetVolume()->Contains(lpoint) &&
1133 current->GetVolume()->GetShape()->Safety(lpoint, kTRUE) > gTolerance)
continue;
1134 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1135 if (snext<fStep-gTolerance) {
1137 printf(
" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1138 lpoint[0],lpoint[1],lpoint[2]);
1139 printf(
" ldir =(%19.16f, %19.16f, %19.16f)\n",
1140 ldir[0],ldir[1],ldir[2]);
1141 printf(
" -> to: %s shape %s snext=%g\n", current->GetName(),
1142 current->GetVolume()->GetShape()->ClassName(), snext);
1144 indnext = current->GetVolume()->GetNextNodeIndex();
1146 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1147 fCurrentMatrix->Multiply(current->GetMatrix());
1149 fIsStepExiting = kFALSE;
1150 fIsStepEntering = kTRUE;
1152 fNextNode = current;
1153 nodefound = fNextNode;
1155 while (indnext>=0) {
1156 current = current->GetDaughter(indnext);
1157 if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
1158 fNextNode = current;
1159 nodefound = current;
1160 indnext = current->GetVolume()->GetNextNodeIndex();
1164 if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
1169 Int_t sumchecked = 0;
1171 TGeoStateInfo &info = *fCache->GetInfo();
1172 voxels->SortCrossedVoxels(point, dir, info);
1173 while ((sumchecked<nd) && (vlist=voxels->GetNextVoxel(point, dir, ncheck, info))) {
1174 for (i=0; i<ncheck; i++) {
1175 current = vol->GetNode(vlist[i]);
1176 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive())
continue;
1178 current->MasterToLocal(point, lpoint);
1179 current->MasterToLocalVect(dir, ldir);
1180 if (current->IsOverlapping() && current->GetVolume()->Contains(lpoint) &&
1181 current->GetVolume()->GetShape()->Safety(lpoint, kTRUE) > gTolerance)
continue;
1182 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1185 if (snext<fStep-gTolerance) {
1187 printf(
" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1188 lpoint[0],lpoint[1],lpoint[2]);
1189 printf(
" ldir =(%19.16f, %19.16f, %19.16f)\n",
1190 ldir[0],ldir[1],ldir[2]);
1191 printf(
" -> to: %s shape %s snext=%g\n", current->GetName(),
1192 current->GetVolume()->GetShape()->ClassName(), snext);
1194 indnext = current->GetVolume()->GetNextNodeIndex();
1196 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1197 fCurrentMatrix->Multiply(current->GetMatrix());
1199 fIsStepExiting = kFALSE;
1200 fIsStepEntering = kTRUE;
1202 fNextNode = current;
1203 nodefound = fNextNode;
1204 idaughter = vlist[i];
1205 while (indnext>=0) {
1206 current = current->GetDaughter(indnext);
1207 if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
1208 fNextNode = current;
1209 nodefound = current;
1210 indnext = current->GetVolume()->GetNextNodeIndex();
1215 fCache->ReleaseInfo();
1216 if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
1226 TGeoNode *TGeoNavigator::FindNextBoundaryAndStep(Double_t stepmax, Bool_t compsafe)
1228 static Int_t icount = 0;
1231 Int_t idebug = TGeoManager::GetVerboseLevel();
1235 fIsStepExiting = kFALSE;
1237 fIsStepEntering = kFALSE;
1239 Double_t snext = TGeoShape::Big();
1241 while (fCurrentNode->GetVolume()->IsAssembly() && fLevel) CdUp();
1244 fIsOnBoundary = kFALSE;
1245 if (IsSafeStep(stepmax+gTolerance, fSafety)) {
1246 fPoint[0] += stepmax*fDirection[0];
1247 fPoint[1] += stepmax*fDirection[1];
1248 fPoint[2] += stepmax*fDirection[2];
1249 return fCurrentNode;
1252 fLastSafety = fSafety;
1253 memcpy(fLastPoint, fPoint, kN3);
1255 if (fSafety > stepmax+gTolerance) {
1256 fPoint[0] += stepmax*fDirection[0];
1257 fPoint[1] += stepmax*fDirection[1];
1258 fPoint[2] += stepmax*fDirection[2];
1259 return fCurrentNode;
1262 Double_t extra = (fIsOnBoundary)?gTolerance:0.0;
1263 fIsOnBoundary = kFALSE;
1264 fPoint[0] += extra*fDirection[0];
1265 fPoint[1] += extra*fDirection[1];
1266 fPoint[2] += extra*fDirection[2];
1267 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1269 printf(
"TGeoManager::FindNextBAndStep: point=(%19.16f, %19.16f, %19.16f)\n",
1270 fPoint[0],fPoint[1],fPoint[2]);
1271 printf(
" dir= (%19.16f, %19.16f, %19.16f)\n",
1272 fDirection[0], fDirection[1], fDirection[2]);
1273 printf(
" pstep=%9.6g path=%s\n", stepmax, GetPath());
1277 snext = fGeometry->GetTopVolume()->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep);
1278 if (snext < fStep-gTolerance) {
1282 fPoint[0] -= extra*fDirection[0];
1283 fPoint[1] -= extra*fDirection[1];
1284 fPoint[2] -= extra*fDirection[2];
1286 fStep = snext+extra;
1288 fIsStepEntering = kTRUE;
1289 fNextNode = fGeometry->GetTopNode();
1290 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1291 while (nextindex>=0) {
1293 fNextNode = fCurrentNode;
1294 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1295 if (nextindex<0) fCurrentMatrix->CopyFrom(fGlobalMatrix);
1298 fPoint[0] += snext*fDirection[0];
1299 fPoint[1] += snext*fDirection[1];
1300 fPoint[2] += snext*fDirection[2];
1301 fIsOnBoundary = kTRUE;
1302 fIsOutside = kFALSE;
1303 fForcedNode = fCurrentNode;
1304 return CrossBoundaryAndLocate(kTRUE, fCurrentNode);
1306 if (snext<TGeoShape::Big()) {
1308 fNextNode = fGeometry->GetTopNode();
1309 fPoint[0] += (fStep-extra)*fDirection[0];
1310 fPoint[1] += (fStep-extra)*fDirection[1];
1311 fPoint[2] += (fStep-extra)*fDirection[2];
1316 fIsOnBoundary = kFALSE;
1319 Double_t point[3],dir[3];
1320 Int_t icrossed = -2;
1321 fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
1322 fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
1323 TGeoVolume *vol = fCurrentNode->GetVolume();
1326 printf(
" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1327 point[0],point[1],point[2]);
1328 printf(
" ldir =(%19.16f, %19.16f, %19.16f)\n",
1329 dir[0],dir[1],dir[2]);
1332 snext = vol->GetShape()->DistFromInside(point, dir, iact, fStep);
1334 printf(
" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
1336 fNextNode = fCurrentNode;
1337 if (snext <= gTolerance) {
1341 fIsOnBoundary = kTRUE;
1342 fIsStepEntering = kFALSE;
1343 fIsStepExiting = kTRUE;
1344 skip = fCurrentNode;
1345 fPoint[0] += fStep*fDirection[0];
1346 fPoint[1] += fStep*fDirection[1];
1347 fPoint[2] += fStep*fDirection[2];
1348 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1349 if (!fLevel && !is_assembly) {
1353 if (fCurrentNode->IsOffset())
return CrossDivisionCell();
1356 return CrossBoundaryAndLocate(kFALSE, skip);
1359 if (snext < fStep-gTolerance) {
1363 fIsStepEntering = kFALSE;
1364 fIsStepExiting = kTRUE;
1367 Int_t idaughter = -1;
1368 TGeoNode *crossed = FindNextDaughterBoundary(point,dir, idaughter, kTRUE);
1370 fIsStepExiting = kFALSE;
1371 icrossed = idaughter;
1372 fIsStepEntering = kTRUE;
1374 TGeoNode *current = 0;
1375 TGeoNode *dnode = 0;
1376 TGeoVolume *mother = 0;
1381 Double_t dpt[3], dvec[3];
1383 Int_t safelevel = GetSafeLevel();
1384 PushPath(safelevel+1);
1385 while (fCurrentOverlapping) {
1386 Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
1388 mother = fCurrentNode->GetVolume();
1389 fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
1390 fGlobalMatrix->MasterToLocalVect(fDirection, &vecpt[0]);
1392 snext = TGeoShape::Big();
1393 if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(mothpt, vecpt, iact, fStep);
1394 if (snext<fStep-gTolerance) {
1398 PushPath(safelevel+1);
1399 fIsStepEntering = kFALSE;
1400 fIsStepExiting = kTRUE;
1402 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1403 fNextNode = fCurrentNode;
1406 for (Int_t i=0; i<novlps; i++) {
1407 current = mother->GetNode(ovlps[i]);
1408 if (!current->IsOverlapping()) {
1410 current->MasterToLocal(&mothpt[0], &dpt[0]);
1411 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1412 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1413 if (snext<fStep-gTolerance) {
1415 PushPath(safelevel+1);
1416 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1417 fCurrentMatrix->Multiply(current->GetMatrix());
1418 fIsStepEntering = kFALSE;
1419 fIsStepExiting = kTRUE;
1420 icrossed = ovlps[i];
1422 fNextNode = current;
1427 current->MasterToLocal(&mothpt[0], &dpt[0]);
1428 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1429 if (current->GetVolume()->Contains(dpt)) {
1430 if (current->GetVolume()->GetNdaughters()) {
1432 dnode = FindNextDaughterBoundary(dpt,dvec,idaughter,kFALSE);
1434 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1435 fCurrentMatrix->Multiply(dnode->GetMatrix());
1436 icrossed = idaughter;
1438 PushPath(safelevel+1);
1439 fIsStepEntering = kFALSE;
1440 fIsStepExiting = kTRUE;
1446 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1447 if (snext<fStep-gTolerance) {
1448 fCurrentMatrix->CopyFrom(fGlobalMatrix);
1449 fCurrentMatrix->Multiply(current->GetMatrix());
1450 fIsStepEntering = kFALSE;
1451 fIsStepExiting = kTRUE;
1453 fNextNode = current;
1454 icrossed = ovlps[i];
1456 PushPath(safelevel+1);
1467 Int_t nmany = fNmany;
1468 Bool_t ovlp = kFALSE;
1469 Bool_t nextovlp = kFALSE;
1470 Bool_t offset = kFALSE;
1471 TGeoNode *currentnode = fCurrentNode;
1472 TGeoNode *mothernode, *mup;
1473 TGeoHMatrix *matrix;
1475 mothernode = GetMother(up);
1479 while (mup->IsOffset()) {
1480 mup = GetMother(imother++);
1483 nextovlp = mup->IsOverlapping();
1486 if (nextovlp) nmany -= imother-up;
1491 if (ovlp || nextovlp) {
1492 matrix = GetMotherMatrix(up);
1493 matrix->MasterToLocal(fPoint,dpt);
1494 matrix->MasterToLocalVect(fDirection,dvec);
1495 snext = TGeoShape::Big();
1496 if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
1497 fIsStepEntering = kFALSE;
1498 fIsStepExiting = kTRUE;
1499 if (snext<fStep-gTolerance) {
1500 fNextNode = mothernode;
1501 fCurrentMatrix->CopyFrom(matrix);
1503 while (up--) CdUp();
1508 currentnode = fCurrentNode;
1509 ovlp = currentnode->IsOverlapping();
1513 currentnode = mothernode;
1521 Double_t parstep = TGeoShape::Big();
1522 TGeoPhysicalNode *pnode = 0;
1523 if (fGeometry->IsParallelWorldNav()) {
1524 pnode = fGeometry->GetParallelWorld()->FindNextBoundary(fPoint, fDirection, parstep, fStep);
1528 fPoint[0] += fStep*fDirection[0];
1529 fPoint[1] += fStep*fDirection[1];
1530 fPoint[2] += fStep*fDirection[2];
1531 fNextNode = pnode->GetNode();
1533 fIsStepEntering = kTRUE;
1534 fIsStepExiting = kFALSE;
1535 cd(pnode->GetName());
1536 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1537 while (nextindex>=0) {
1538 current = fCurrentNode;
1540 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1542 return fCurrentNode;
1545 fPoint[0] += fStep*fDirection[0];
1546 fPoint[1] += fStep*fDirection[1];
1547 fPoint[2] += fStep*fDirection[2];
1549 if (icrossed == -2) {
1551 fIsOnBoundary = kFALSE;
1552 return fCurrentNode;
1554 fIsOnBoundary = kTRUE;
1555 if (icrossed == -1) {
1557 skip = fCurrentNode;
1558 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1559 if (!fLevel && !is_assembly) {
1563 if (fCurrentNode->IsOffset())
return CrossDivisionCell();
1566 return CrossBoundaryAndLocate(kFALSE, skip);
1570 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1571 while (nextindex>=0) {
1572 current = fCurrentNode;
1574 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1576 fForcedNode = fCurrentNode;
1577 return CrossBoundaryAndLocate(kTRUE, current);
1583 TGeoNode *TGeoNavigator::FindNode(Bool_t safe_start)
1586 fSearchOverlaps = kFALSE;
1587 fIsOutside = kFALSE;
1588 fIsEntering = fIsExiting = kFALSE;
1589 fIsOnBoundary = kFALSE;
1590 fStartSafe = safe_start;
1591 fIsSameLocation = kTRUE;
1592 TGeoNode *last = fCurrentNode;
1593 TGeoNode *found = SearchNode();
1594 if (found != last) {
1595 fIsSameLocation = kFALSE;
1597 if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1605 TGeoNode *TGeoNavigator::FindNode(Double_t x, Double_t y, Double_t z)
1611 fSearchOverlaps = kFALSE;
1612 fIsOutside = kFALSE;
1613 fIsEntering = fIsExiting = kFALSE;
1614 fIsOnBoundary = kFALSE;
1616 fIsSameLocation = kTRUE;
1617 TGeoNode *last = fCurrentNode;
1618 TGeoNode *found = SearchNode();
1619 if (found != last) {
1620 fIsSameLocation = kFALSE;
1622 if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1631 Double_t *TGeoNavigator::FindNormalFast()
1633 if (!fNextNode)
return 0;
1637 fCurrentMatrix->MasterToLocal(fPoint, local);
1638 fCurrentMatrix->MasterToLocalVect(fDirection, ldir);
1639 fNextNode->GetVolume()->GetShape()->ComputeNormal(local, ldir,lnorm);
1640 fCurrentMatrix->LocalToMasterVect(lnorm, fNormal);
1650 Double_t *TGeoNavigator::FindNormal(Bool_t )
1652 return FindNormalFast();
1659 TGeoNode *TGeoNavigator::InitTrack(
const Double_t *point,
const Double_t *dir)
1661 SetCurrentPoint(point);
1662 SetCurrentDirection(dir);
1670 TGeoNode *TGeoNavigator::InitTrack(Double_t x, Double_t y, Double_t z, Double_t nx, Double_t ny, Double_t nz)
1672 SetCurrentPoint(x,y,z);
1673 SetCurrentDirection(nx,ny,nz);
1680 void TGeoNavigator::ResetState()
1682 fSearchOverlaps = kFALSE;
1683 fIsOutside = kFALSE;
1684 fIsEntering = fIsExiting = kFALSE;
1685 fIsOnBoundary = kFALSE;
1686 fIsStepEntering = fIsStepExiting = kFALSE;
1693 Double_t TGeoNavigator::Safety(Bool_t inside)
1695 if (fIsOnBoundary) {
1700 Double_t safpar = TGeoShape::Big();
1701 if (!inside) fSafety = TGeoShape::Big();
1703 if (fGeometry->IsParallelWorldNav()) {
1704 safpar = fGeometry->GetParallelWorld()->Safety(fPoint);
1708 fSafety = fGeometry->GetTopVolume()->GetShape()->Safety(fPoint,kFALSE);
1709 if (fSafety < gTolerance) {
1711 fIsOnBoundary = kTRUE;
1714 return TMath::Min(fSafety,safpar);
1717 fGlobalMatrix->MasterToLocal(fPoint, point);
1720 TGeoVolume *vol = fCurrentNode->GetVolume();
1722 fSafety = vol->GetShape()->Safety(point, kTRUE);
1724 if (fSafety < gTolerance) {
1726 fIsOnBoundary = kTRUE;
1732 if (safpar < fSafety) fSafety = safpar;
1735 TObjArray *nodes = vol->GetNodes();
1736 Int_t nd = fCurrentNode->GetNdaughters();
1737 if (!nd && !fCurrentOverlapping)
return fSafety;
1744 TGeoPatternFinder *finder = vol->GetFinder();
1746 Int_t ifirst = finder->GetDivIndex();
1747 node = (TGeoNode*)nodes->UncheckedAt(ifirst);
1749 safe = node->Safety(point, kFALSE);
1750 if (safe < gTolerance) {
1752 fIsOnBoundary = kTRUE;
1755 if (safe<fSafety) fSafety=safe;
1756 Int_t ilast = ifirst+finder->GetNdiv()-1;
1757 if (ilast==ifirst)
return fSafety;
1758 node = (TGeoNode*)nodes->UncheckedAt(ilast);
1760 safe = node->Safety(point, kFALSE);
1761 if (safe < gTolerance) {
1763 fIsOnBoundary = kTRUE;
1766 if (safe<fSafety) fSafety=safe;
1767 if (fCurrentOverlapping && !inside) SafetyOverlaps();
1772 TGeoVoxelFinder *voxels = vol->GetVoxels();
1774 for (
id=0;
id<nd;
id++) {
1775 node = (TGeoNode*)nodes->UncheckedAt(
id);
1776 safe = node->Safety(point, kFALSE);
1777 if (safe < gTolerance) {
1779 fIsOnBoundary = kTRUE;
1782 if (safe<fSafety) fSafety=safe;
1784 if (fNmany && !inside) SafetyOverlaps();
1787 if (voxels->NeedRebuild()) {
1789 vol->FindOverlaps();
1794 Double_t *boxes = voxels->GetBoxes();
1795 for (
id=0;
id<nd;
id++) {
1798 Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
1799 if (dxyz0 > fSafety)
continue;
1800 Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
1801 if (dxyz1 > fSafety)
continue;
1802 Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
1803 if (dxyz2 > fSafety)
continue;
1804 if (dxyz0>0) dxyz+=dxyz0*dxyz0;
1805 if (dxyz1>0) dxyz+=dxyz1*dxyz1;
1806 if (dxyz2>0) dxyz+=dxyz2*dxyz2;
1807 if (dxyz >= fSafety*fSafety)
continue;
1808 node = (TGeoNode*)nodes->UncheckedAt(
id);
1809 safe = node->Safety(point, kFALSE);
1810 if (safe<gTolerance) {
1812 fIsOnBoundary = kTRUE;
1815 if (safe<fSafety) fSafety = safe;
1817 if (fNmany && !inside) SafetyOverlaps();
1824 void TGeoNavigator::SafetyOverlaps()
1826 Double_t point[3], local[3];
1833 Int_t safelevel = GetSafeLevel();
1834 PushPath(safelevel+1);
1835 while (fCurrentOverlapping) {
1836 ovlp = fCurrentNode->GetOverlaps(novlp);
1838 vol = fCurrentNode->GetVolume();
1839 fGeometry->MasterToLocal(fPoint, point);
1840 contains = fCurrentNode->GetVolume()->Contains(point);
1841 safe = fCurrentNode->GetVolume()->GetShape()->Safety(point, contains);
1842 if (safe<fSafety && safe>=0) fSafety=safe;
1843 if (!novlp || !contains)
continue;
1845 for (io=0; io<novlp; io++) {
1846 nodeovlp = vol->GetNode(ovlp[io]);
1847 nodeovlp->GetMatrix()->MasterToLocal(point,local);
1848 contains = nodeovlp->GetVolume()->Contains(local);
1851 safe = Safety(kTRUE);
1854 safe = nodeovlp->GetVolume()->GetShape()->Safety(local, kFALSE);
1856 if (safe<fSafety && safe>=0) fSafety=safe;
1863 Int_t nmany = fNmany;
1864 Bool_t crtovlp = kFALSE;
1865 Bool_t nextovlp = kFALSE;
1866 TGeoNode *mother, *mup;
1867 TGeoHMatrix *matrix;
1869 mother = GetMother(up);
1872 while (mup->IsOffset()) mup = GetMother(imother++);
1873 nextovlp = mup->IsOverlapping();
1874 if (crtovlp) nmany--;
1875 if (crtovlp || nextovlp) {
1876 matrix = GetMotherMatrix(up);
1877 matrix->MasterToLocal(fPoint,local);
1878 safe = mother->GetVolume()->GetShape()->Safety(local,kTRUE);
1879 if (safe<fSafety) fSafety = safe;
1886 if (fSafety < gTolerance) {
1888 fIsOnBoundary = kTRUE;
1896 TGeoNode *TGeoNavigator::SearchNode(Bool_t downwards,
const TGeoNode *skipnode)
1898 if (fGeometry->IsParallelWorldNav()) {
1899 TGeoPhysicalNode *pnode = fGeometry->GetParallelWorld()->FindNode(fPoint);
1904 Int_t crtindex = fCurrentNode->GetVolume()->GetCurrentNodeIndex();
1905 while (crtindex>=0) {
1908 crtindex = fCurrentNode->GetVolume()->GetCurrentNodeIndex();
1910 return fCurrentNode;
1914 fNextDaughterIndex = -2;
1915 TGeoVolume *vol = 0;
1916 Int_t idebug = TGeoManager::GetVerboseLevel();
1917 Bool_t inside_current = (fCurrentNode==skipnode)?kTRUE:kFALSE;
1920 if (fGeometry->IsActivityEnabled() && !fCurrentNode->GetVolume()->IsActive()) {
1923 fIsSameLocation = kFALSE;
1924 return SearchNode(kFALSE, skipnode);
1927 vol=fCurrentNode->GetVolume();
1928 if (vol->IsAssembly()) inside_current=kTRUE;
1930 if (!inside_current) {
1931 fGlobalMatrix->MasterToLocal(fPoint, point);
1932 inside_current = vol->Contains(point);
1936 inside_current = GotoSafeLevel();
1938 if (!inside_current) {
1940 fIsSameLocation = kFALSE;
1941 TGeoNode *skip = fCurrentNode;
1948 return SearchNode(kFALSE, skip);
1951 vol = fCurrentNode->GetVolume();
1952 fGlobalMatrix->MasterToLocal(fPoint, point);
1953 if (!inside_current && downwards) {
1955 if (fCurrentNode == fForcedNode) inside_current = kTRUE;
1956 else inside_current = vol->Contains(point);
1957 if (!inside_current) {
1958 fIsSameLocation = kFALSE;
1962 fIsOutside = kFALSE;
1963 fIsSameLocation = kFALSE;
1966 printf(
"Search node local=(%19.16f, %19.16f, %19.16f) -> %s\n",
1967 point[0],point[1],point[2], fCurrentNode->GetName());
1975 if (!fCurrentOverlapping) {
1976 fSearchOverlaps = kFALSE;
1979 Int_t crtindex = vol->GetCurrentNodeIndex();
1980 while (crtindex>=0 && downwards) {
1983 vol = fCurrentNode->GetVolume();
1984 crtindex = vol->GetCurrentNodeIndex();
1985 if (crtindex<0) fGlobalMatrix->MasterToLocal(fPoint, point);
1988 Int_t nd = vol->GetNdaughters();
1990 if (!nd)
return fCurrentNode;
1991 if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters())
return fCurrentNode;
1993 TGeoPatternFinder *finder = vol->GetFinder();
1997 node=finder->FindNode(point);
1998 if (!node && fForcedNode) {
2001 fGlobalMatrix->MasterToLocalVect(fDirection, dir);
2002 finder->FindNode(point,dir);
2003 node = finder->CdNext();
2004 if (!node)
return fCurrentNode;
2006 if (node && node!=skipnode) {
2008 fIsSameLocation = kFALSE;
2009 CdDown(node->GetIndex());
2011 return SearchNode(kTRUE, node);
2015 while (fCurrentNode && fCurrentNode->IsOffset()) CdUp();
2016 return fCurrentNode;
2019 TGeoVoxelFinder *voxels = vol->GetVoxels();
2020 Int_t *check_list = 0;
2024 check_list = voxels->GetCheckList(&point[0], ncheck, *fCache->GetInfo());
2027 if (!fCurrentNode->GetVolume()->IsAssembly()) {
2028 fCache->ReleaseInfo();
2029 return fCurrentNode;
2032 node = fCurrentNode;
2035 fCache->ReleaseInfo();
2039 fCache->ReleaseInfo();
2040 return SearchNode(kFALSE,node);
2043 for (
id=0;
id<ncheck;
id++) {
2044 node = vol->GetNode(check_list[
id]);
2045 if (node==skipnode)
continue;
2046 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive())
continue;
2047 if ((
id<(ncheck-1)) && node->IsOverlapping()) {
2049 if (ncheck+fOverlapMark > fOverlapSize) {
2050 fOverlapSize = 2*(ncheck+fOverlapMark);
2051 delete [] fOverlapClusters;
2052 fOverlapClusters =
new Int_t[fOverlapSize];
2054 Int_t *cluster = fOverlapClusters + fOverlapMark;
2055 Int_t nc = GetTouchedCluster(
id, &point[0], check_list, ncheck, cluster);
2058 node = FindInCluster(cluster, nc);
2060 fCache->ReleaseInfo();
2064 CdDown(check_list[
id]);
2066 node = SearchNode(kTRUE);
2068 fIsSameLocation = kFALSE;
2069 fCache->ReleaseInfo();
2074 if (!fCurrentNode->GetVolume()->IsAssembly()) {
2075 fCache->ReleaseInfo();
2076 return fCurrentNode;
2078 node = fCurrentNode;
2081 fCache->ReleaseInfo();
2085 fCache->ReleaseInfo();
2086 return SearchNode(kFALSE,node);
2089 for (
id=0;
id<nd;
id++) {
2090 node=fCurrentNode->GetDaughter(
id);
2091 if (node==skipnode)
continue;
2092 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive())
continue;
2095 node = SearchNode(kTRUE);
2097 fIsSameLocation = kFALSE;
2103 if (fCurrentNode->GetVolume()->IsAssembly()) {
2104 node = fCurrentNode;
2110 return SearchNode(kFALSE,node);
2112 return fCurrentNode;
2119 TGeoNode *TGeoNavigator::FindInCluster(Int_t *cluster, Int_t nc)
2121 TGeoNode *clnode = 0;
2122 TGeoNode *priority = fLastNode;
2124 TGeoNode *current = fCurrentNode;
2125 TGeoNode *found = 0;
2127 Int_t ipop = PushPath();
2129 fSearchOverlaps = kTRUE;
2130 Int_t deepest = fLevel;
2131 Int_t deepest_virtual = fLevel-GetVirtualLevel();
2132 Int_t found_virtual = 0;
2133 Bool_t replace = kFALSE;
2134 Bool_t added = kFALSE;
2136 for (i=0; i<nc; i++) {
2137 clnode = current->GetDaughter(cluster[i]);
2139 Bool_t max_priority = (clnode==fNextNode)?kTRUE:kFALSE;
2140 found = SearchNode(kTRUE, clnode);
2141 if (!fSearchOverlaps || max_priority) {
2147 found_virtual = fLevel-GetVirtualLevel();
2150 if (found_virtual>deepest_virtual) {
2153 if (found_virtual==deepest_virtual) {
2154 if (fLevel>deepest) {
2157 if ((fLevel==deepest) && (clnode==priority)) replace=kTRUE;
2158 else replace = kFALSE;
2160 }
else replace = kFALSE;
2168 fCurrentOverlapping = PopPath();
2170 return fCurrentNode;
2179 deepest_virtual = found_virtual;
2182 fCurrentOverlapping = PopPath(ipop);
2188 deepest_virtual = found_virtual;
2190 fCurrentOverlapping = PopPath(ipop);
2194 return fCurrentNode;
2202 Int_t TGeoNavigator::GetTouchedCluster(Int_t start, Double_t *point,
2203 Int_t *check_list, Int_t ncheck, Int_t *result)
2206 TGeoNode *current = fCurrentNode->GetDaughter(check_list[start]);
2208 Int_t *ovlps = current->GetOverlaps(novlps);
2209 if (!ovlps)
return 0;
2213 current->MasterToLocal(point, &local[0]);
2214 if (current->GetVolume()->Contains(&local[0])) {
2215 result[ntotal++]=check_list[start];
2219 while ((jst<novlps) && (ovlps[jst]<=check_list[start])) jst++;
2220 if (jst==novlps)
return 0;
2221 for (i=start; i<ncheck; i++) {
2222 for (j=jst; j<novlps; j++) {
2223 if (check_list[i]==ovlps[j]) {
2225 current = fCurrentNode->GetDaughter(check_list[i]);
2226 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive())
continue;
2227 current->MasterToLocal(point, &local[0]);
2228 if (current->GetVolume()->Contains(&local[0])) {
2229 result[ntotal++]=check_list[i];
2244 TGeoNode *TGeoNavigator::Step(Bool_t is_geom, Bool_t cross)
2249 if (fStep<0) fStep = 0.;
2253 if (is_geom) epsil=(cross)?1E-6:-1E-6;
2254 TGeoNode *old = fCurrentNode;
2255 Int_t idold = GetNodeId();
2256 if (fIsOutside) old = 0;
2258 for (Int_t i=0; i<3; i++) fPoint[i]+=fStep*fDirection[i];
2259 TGeoNode *current = FindNode();
2261 fIsEntering = (current==old)?kFALSE:kTRUE;
2263 Int_t
id = GetNodeId();
2264 fIsEntering = (
id==idold)?kFALSE:kTRUE;
2266 fIsExiting = !fIsEntering;
2267 if (fIsEntering && fIsNullStep) fIsNullStep = kFALSE;
2268 fIsOnBoundary = kTRUE;
2270 fIsEntering = fIsExiting = kFALSE;
2271 fIsOnBoundary = kFALSE;
2280 Int_t TGeoNavigator::GetVirtualLevel()
2283 if (!fCurrentOverlapping)
return 0;
2284 Int_t new_media = 0;
2285 TGeoMedium *medium = fCurrentNode->GetMedium();
2286 Int_t virtual_level = 1;
2287 TGeoNode *mother = 0;
2289 while ((mother=GetMother(virtual_level))) {
2290 if (!mother->IsOverlapping() && !mother->IsOffset()) {
2291 if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2294 if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2297 return (new_media==0)?virtual_level:(new_media-1);
2303 Bool_t TGeoNavigator::GotoSafeLevel()
2305 while (fCurrentOverlapping && fLevel) CdUp();
2307 fGlobalMatrix->MasterToLocal(fPoint, point);
2308 if (!fCurrentNode->GetVolume()->Contains(point))
return kFALSE;
2313 Int_t nmany = fNmany;
2314 Bool_t ovlp = kFALSE;
2315 Bool_t nextovlp = kFALSE;
2316 TGeoNode *mother, *mup;
2317 TGeoHMatrix *matrix;
2319 mother = GetMother(up);
2320 if (!mother)
return kTRUE;
2323 while (mup->IsOffset()) mup = GetMother(imother++);
2324 nextovlp = mup->IsOverlapping();
2326 if (ovlp || nextovlp) {
2328 matrix = GetMotherMatrix(up);
2329 matrix->MasterToLocal(fPoint,point);
2330 if (!mother->GetVolume()->Contains(point)) {
2332 while (up--) CdUp();
2333 return GotoSafeLevel();
2346 Int_t TGeoNavigator::GetSafeLevel()
const
2348 Bool_t overlapping = fCurrentOverlapping;
2349 if (!overlapping)
return fLevel;
2350 Int_t level = fLevel;
2352 while (overlapping && level) {
2354 node = GetMother(fLevel-level);
2355 if (!node->IsOffset()) overlapping = node->IsOverlapping();
2363 void TGeoNavigator::InspectState()
const
2365 Info(
"InspectState",
"Current path is: %s",GetPath());
2368 Bool_t is_offset, is_overlapping;
2369 for (level=0; level<fLevel+1; level++) {
2370 node = GetMother(fLevel-level);
2371 if (!node)
continue;
2372 is_offset = node->IsOffset();
2373 is_overlapping = node->IsOverlapping();
2374 Info(
"InspectState",
"level %i: %s div=%i many=%i",level,node->GetName(),is_offset,is_overlapping);
2376 Info(
"InspectState",
"on_bound=%i entering=%i", fIsOnBoundary, fIsEntering);
2383 Bool_t TGeoNavigator::IsSameLocation(Double_t x, Double_t y, Double_t z, Bool_t change)
2386 if (fLastSafety>0) {
2387 Double_t dx = (x-fLastPoint[0]);
2388 Double_t dy = (y-fLastPoint[1]);
2389 Double_t dz = (z-fLastPoint[2]);
2390 Double_t dsq = dx*dx+dy*dy+dz*dz;
2391 if (dsq<fLastSafety*fLastSafety) {
2396 memcpy(fLastPoint, fPoint, 3*
sizeof(Double_t));
2397 fLastSafety -= TMath::Sqrt(dsq);
2401 if (change) fLastSafety = 0;
2403 if (fCurrentOverlapping) {
2405 Int_t cid = GetCurrentNodeId();
2406 if (!change) PushPoint();
2407 memcpy(oldpt, fPoint, kN3);
2408 SetCurrentPoint(x,y,z);
2410 memcpy(fPoint, oldpt, kN3);
2411 Bool_t same = (cid==GetCurrentNodeId())?kTRUE:kFALSE;
2412 if (!change) PopPoint();
2420 if (change) memcpy(fPoint, point, kN3);
2421 TGeoVolume *vol = fCurrentNode->GetVolume();
2423 if (vol->GetShape()->Contains(point)) {
2424 if (!change)
return kFALSE;
2432 fGlobalMatrix->MasterToLocal(point,local);
2434 if (!vol->GetShape()->Contains(local)) {
2435 if (!change)
return kFALSE;
2442 if (fGeometry->IsParallelWorldNav()) {
2443 TGeoPhysicalNode *pnode = fGeometry->GetParallelWorld()->FindNode(fPoint);
2445 if (!change)
return kFALSE;
2447 Int_t crtindex = fCurrentNode->GetVolume()->GetCurrentNodeIndex();
2448 while (crtindex>=0) {
2451 crtindex = fCurrentNode->GetVolume()->GetCurrentNodeIndex();
2457 Int_t nd = vol->GetNdaughters();
2458 if (!nd)
return kTRUE;
2461 TGeoPatternFinder *finder = vol->GetFinder();
2463 node=finder->FindNode(local);
2465 if (!change)
return kFALSE;
2466 CdDown(node->GetIndex());
2467 SearchNode(kTRUE,node);
2473 TGeoVoxelFinder *voxels = vol->GetVoxels();
2474 Int_t *check_list = 0;
2478 check_list = voxels->GetCheckList(local, ncheck, *fCache->GetInfo());
2480 fCache->ReleaseInfo();
2483 if (!change) PushPath();
2484 for (Int_t
id=0;
id<ncheck;
id++) {
2486 CdDown(check_list[
id]);
2487 fGlobalMatrix->MasterToLocal(point,local1);
2488 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2491 fCache->ReleaseInfo();
2495 fCache->ReleaseInfo();
2500 if (!change) PopPath();
2501 fCache->ReleaseInfo();
2505 if (!change) PushPath();
2506 while (fCurrentNode && fCurrentNode->GetDaughter(
id++)) {
2508 fGlobalMatrix->MasterToLocal(point,local1);
2509 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2519 if (!change) PopPath();
2523 if (!change) PopPath();
2532 Bool_t TGeoNavigator::IsSafeStep(Double_t proposed, Double_t &newsafety)
const
2535 if (fLastSafety < gTolerance)
return kFALSE;
2537 if (proposed < gTolerance) {
2538 newsafety = fLastSafety - proposed;
2542 Double_t dist = (fPoint[0]-fLastPoint[0])*(fPoint[0]-fLastPoint[0])+
2543 (fPoint[1]-fLastPoint[1])*(fPoint[1]-fLastPoint[1])+
2544 (fPoint[2]-fLastPoint[2])*(fPoint[2]-fLastPoint[2]);
2545 dist = TMath::Sqrt(dist);
2546 Double_t safe = fLastSafety - dist;
2547 if (safe < proposed)
return kFALSE;
2555 Bool_t TGeoNavigator::IsSamePoint(Double_t x, Double_t y, Double_t z)
const
2557 if (TMath::Abs(x-fLastPoint[0]) < 1.E-20) {
2558 if (TMath::Abs(y-fLastPoint[1]) < 1.E-20) {
2559 if (TMath::Abs(z-fLastPoint[2]) < 1.E-20)
return kTRUE;
2568 void TGeoNavigator::DoBackupState()
2570 if (fBackupState) fBackupState->SetState(fLevel,0, fNmany, fCurrentOverlapping);
2576 void TGeoNavigator::DoRestoreState()
2578 if (fBackupState && fCache) {
2579 fCurrentOverlapping = fCache->RestoreState(fNmany, fBackupState);
2580 fCurrentNode=fCache->GetNode();
2581 fGlobalMatrix = fCache->GetCurrentMatrix();
2582 fLevel=fCache->GetLevel();
2589 TGeoHMatrix *TGeoNavigator::GetHMatrix()
2591 if (!fCurrentMatrix) {
2592 fCurrentMatrix =
new TGeoHMatrix();
2593 fCurrentMatrix->RegisterYourself();
2595 return fCurrentMatrix;
2601 const char *TGeoNavigator::GetPath()
const
2603 if (fIsOutside)
return kGeoOutsidePath;
2604 return fCache->GetPath();
2610 void TGeoNavigator::MasterToTop(
const Double_t *master, Double_t *top)
const
2612 fCurrentMatrix->MasterToLocal(master, top);
2618 void TGeoNavigator::TopToMaster(
const Double_t *top, Double_t *master)
const
2620 fCurrentMatrix->LocalToMaster(top, master);
2626 void TGeoNavigator::ResetAll()
2629 *fCurrentMatrix = gGeoIdentity;
2630 fCurrentNode = fGeometry->GetTopNode();
2637 fNextDaughterIndex = -2;
2638 fCurrentOverlapping = kFALSE;
2639 fStartSafe = kFALSE;
2640 fIsSameLocation = kFALSE;
2641 fIsNullStep = kFALSE;
2642 fCurrentVolume = fGeometry->GetTopVolume();
2643 fCurrentNode = fGeometry->GetTopNode();
2648 Bool_t dummy=fCache->IsDummy();
2649 Bool_t nodeid = fCache->HasIdArray();
2651 delete fBackupState;
2653 BuildCache(dummy,nodeid);
2657 ClassImp(TGeoNavigatorArray);
2662 TGeoNavigator *TGeoNavigatorArray::AddNavigator()
2665 TGeoNavigator *nav =
new TGeoNavigator(fGeoManager);
2666 nav->BuildCache(kTRUE, kFALSE);
2668 SetCurrentNavigator(GetEntriesFast()-1);