Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGeoNavigator.cxx
Go to the documentation of this file.
1// @(#)root/geom:$Id$
2// Author: Mihaela Gheata 30/05/07
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TGeoNavigator
13\ingroup Geometry_classes
14
15 Class providing navigation API for TGeo geometries. Several instances are
16allowed for a single geometry.
17A default navigator is provided for any geometry but one may add several
18others for parallel navigation:
19
20~~~ {.cpp}
21TGeoNavigator *navig = new TGeoNavigator(gGeoManager);
22Int_t inav = gGeoManager->AddNavigator(navig);
23gGeoManager->SetCurrentNavigator(inav);
24~~~
25
26.... and then switch back to the default navigator:
27
28~~~ {.cpp}
29gGeoManager->SetCurrentNavigator(0);
30~~~
31
32*/
33
34#include "TGeoNavigator.h"
35
36#include "TGeoManager.h"
37#include "TGeoMatrix.h"
38#include "TGeoNode.h"
39#include "TGeoVolume.h"
40#include "TGeoPatternFinder.h"
41#include "TGeoVoxelFinder.h"
42#include "TMath.h"
43#include "TGeoParallelWorld.h"
44#include "TGeoPhysicalNode.h"
45
47const char *kGeoOutsidePath = " ";
48const Int_t kN3 = 3 * sizeof(Double_t);
49
51
53
54////////////////////////////////////////////////////////////////////////////////
55/// Constructor
56
58 : fStep(0.),
59 fSafety(0.),
60 fLastSafety(0.),
61 fLastPWSafety(-1.),
62 fThreadId(0),
63 fLevel(0),
64 fNmany(0),
65 fNextDaughterIndex(0),
66 fOverlapSize(0),
67 fOverlapMark(0),
68 fOverlapClusters(nullptr),
69 fSearchOverlaps(kFALSE),
70 fCurrentOverlapping(kFALSE),
71 fStartSafe(kFALSE),
72 fIsEntering(kFALSE),
73 fIsExiting(kFALSE),
74 fIsStepEntering(kFALSE),
75 fIsStepExiting(kFALSE),
76 fIsOutside(kFALSE),
77 fIsOnBoundary(kFALSE),
78 fIsSameLocation(kFALSE),
79 fIsNullStep(kFALSE),
80 fGeometry(nullptr),
81 fCache(nullptr),
82 fCurrentVolume(nullptr),
83 fCurrentNode(nullptr),
84 fTopNode(nullptr),
85 fLastNode(nullptr),
86 fNextNode(nullptr),
87 fForcedNode(nullptr),
88 fBackupState(nullptr),
89 fCurrentMatrix(nullptr),
90 fGlobalMatrix(nullptr),
91 fDivMatrix(nullptr),
92 fPath()
93
94{
95 // dummy constructor
96 for (Int_t i = 0; i < 3; i++) {
97 fNormal[i] = 0.;
98 fCldir[i] = 0.;
99 fCldirChecked[i] = 0.;
100 fPoint[i] = 0.;
101 fDirection[i] = 0.;
102 fLastPoint[i] = 0.;
103 }
104}
105
106////////////////////////////////////////////////////////////////////////////////
107/// Constructor
108
110 : fStep(0.),
111 fSafety(0.),
112 fLastSafety(0.),
113 fLastPWSafety(-1.),
114 fThreadId(0),
115 fLevel(0),
116 fNmany(0),
117 fNextDaughterIndex(-2),
118 fOverlapSize(1000),
119 fOverlapMark(0),
120 fOverlapClusters(nullptr),
121 fSearchOverlaps(kFALSE),
122 fCurrentOverlapping(kFALSE),
123 fStartSafe(kTRUE),
124 fIsEntering(kFALSE),
125 fIsExiting(kFALSE),
126 fIsStepEntering(kFALSE),
127 fIsStepExiting(kFALSE),
128 fIsOutside(kFALSE),
129 fIsOnBoundary(kFALSE),
130 fIsSameLocation(kTRUE),
131 fIsNullStep(kFALSE),
132 fGeometry(geom),
133 fCache(nullptr),
134 fCurrentVolume(nullptr),
135 fCurrentNode(nullptr),
136 fTopNode(nullptr),
137 fLastNode(nullptr),
138 fNextNode(nullptr),
139 fForcedNode(nullptr),
140 fBackupState(nullptr),
141 fCurrentMatrix(nullptr),
142 fGlobalMatrix(nullptr),
143 fDivMatrix(nullptr),
144 fPath()
145
146{
147 // Default constructor.
149 // printf("Navigator: threadId=%d\n", fThreadId);
150 for (Int_t i = 0; i < 3; i++) {
151 fNormal[i] = 0.;
152 fCldir[i] = 0.;
153 fCldirChecked[i] = 0;
154 fPoint[i] = 0.;
155 fDirection[i] = 0.;
156 fLastPoint[i] = 0.;
157 }
160 fDivMatrix = new TGeoHMatrix();
163 ResetAll();
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// Destructor.
168
170{
171 if (fCache)
172 delete fCache;
173 if (fBackupState)
174 delete fBackupState;
176 delete[] fOverlapClusters;
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// Builds the cache for physical nodes and global matrices.
181
183{
184 static Bool_t first = kTRUE;
186 Int_t nlevel = fGeometry->GetMaxLevel();
187 if (nlevel <= 0)
188 nlevel = 100;
189 if (!fCache) {
190 if (nlevel == 100) {
191 if (first && verbose > 0)
192 Info("BuildCache", "--- Maximum geometry depth set to 100");
193 } else {
194 if (first && verbose > 0)
195 Info("BuildCache", "--- Maximum geometry depth is %i", nlevel);
196 }
197 // build cache
198 fCache = new TGeoNodeCache(fGeometry->GetTopNode(), nodeid, nlevel + 1);
200 fBackupState = new TGeoCacheState(nlevel + 1);
201 }
202 first = kFALSE;
203}
204
205////////////////////////////////////////////////////////////////////////////////
206/// Browse the tree of nodes starting from top node according to pathname.
207/// Changes the path accordingly. The path is changed to point to the top node
208/// in case of failure.
209
210Bool_t TGeoNavigator::cd(const char *path)
211{
212 CdTop();
213 if (!path[0])
214 return kTRUE;
215 TString spath = path;
216 TGeoVolume *vol;
217 Int_t length = spath.Length();
218 Int_t ind1 = spath.Index("/");
219 if (ind1 == length - 1)
220 ind1 = -1;
221 Int_t ind2 = 0;
222 Bool_t end = kFALSE;
223 Bool_t first = kTRUE;
225 TGeoNode *node;
226 while (!end) {
227 ind2 = spath.Index("/", ind1 + 1);
228 if (ind2 < 0 || ind2 == length - 1) {
229 if (ind2 < 0)
230 ind2 = length;
231 end = kTRUE;
232 }
233 name = spath(ind1 + 1, ind2 - ind1 - 1);
234 vol = fCurrentNode->GetVolume();
235 if (first) {
236 first = kFALSE;
237 if (name.BeginsWith(vol->GetName())) {
238 ind1 = ind2;
239 continue;
240 }
241 }
242 node = vol->GetNode(name.Data());
243 if (!node) {
244 Error("cd", "Path %s not valid", path);
245 return kFALSE;
246 }
247 CdDown(vol->GetIndex(node));
248 ind1 = ind2;
249 }
250 return kTRUE;
251}
252
253////////////////////////////////////////////////////////////////////////////////
254/// Check if a geometry path is valid without changing the state of the navigator.
255
256Bool_t TGeoNavigator::CheckPath(const char *path) const
257{
258 if (!path[0])
259 return kTRUE;
260 TGeoNode *crtnode = fGeometry->GetTopNode();
261 TString spath = path;
262 TGeoVolume *vol;
263 Int_t length = spath.Length();
264 Int_t ind1 = spath.Index("/");
265 if (ind1 == length - 1)
266 ind1 = -1;
267 Int_t ind2 = 0;
268 Bool_t end = kFALSE;
269 Bool_t first = kTRUE;
271 TGeoNode *node;
272 while (!end) {
273 ind2 = spath.Index("/", ind1 + 1);
274 if (ind2 < 0 || ind2 == length - 1) {
275 if (ind2 < 0)
276 ind2 = length;
277 end = kTRUE;
278 }
279 name = spath(ind1 + 1, ind2 - ind1 - 1);
280 vol = crtnode->GetVolume();
281 if (first) {
282 first = kFALSE;
283 if (name.BeginsWith(vol->GetName())) {
284 ind1 = ind2;
285 continue;
286 }
287 }
288 node = vol->GetNode(name.Data());
289 if (!node)
290 return kFALSE;
291 crtnode = node;
292 ind1 = ind2;
293 }
294 return kTRUE;
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// Change current path to point to the node having this id.
299/// Node id has to be in range : 0 to fNNodes-1 (no check for performance reasons)
300
302{
303 if (fCache) {
304 fCache->CdNode(nodeid);
306 }
307}
308
309////////////////////////////////////////////////////////////////////////////////
310/// Make a daughter of current node current. Can be called only with a valid
311/// daughter index (no check). Updates cache accordingly.
312
314{
316 Bool_t is_offset = node->IsOffset();
317 if (is_offset)
318 node->cd();
319 else
322 fCurrentNode = node;
325 fNmany++;
326 fLevel++;
327}
328
329////////////////////////////////////////////////////////////////////////////////
330/// Make a daughter of current node current. Can be called only with a valid
331/// daughter node (no check). Updates cache accordingly.
332
334{
335 Bool_t is_offset = node->IsOffset();
336 if (is_offset)
337 node->cd();
338 else
340 fCache->CdDown(node);
341 fCurrentNode = node;
344 fNmany++;
345 fLevel++;
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Go one level up in geometry. Updates cache accordingly.
350/// Determine the overlapping state of current node.
351
353{
354 if (!fLevel || !fCache)
355 return;
356 fLevel--;
357 if (!fLevel) {
358 CdTop();
359 return;
360 }
361 fCache->CdUp();
364 fNmany--;
365 }
368 if (!fCurrentNode->IsOffset()) {
370 } else {
371 Int_t up = 1;
373 TGeoNode *mother = nullptr;
374 while (offset) {
375 mother = GetMother(up++);
376 offset = mother->IsOffset();
377 }
379 }
380}
381
382////////////////////////////////////////////////////////////////////////////////
383/// Make top level node the current node. Updates the cache accordingly.
384/// Determine the overlapping state of current node.
385
387{
388 if (!fCache)
389 return;
390 fLevel = 0;
391 fNmany = 0;
395 fCache->CdTop();
399 fNmany++;
400}
401
402////////////////////////////////////////////////////////////////////////////////
403/// Do a cd to the node found next by FindNextBoundary
404
406{
407 if (fNextDaughterIndex == -2 || !fCache)
408 return;
409 if (fNextDaughterIndex == -3) {
410 // Next node is a many - restore it
413 return;
414 }
415 if (fNextDaughterIndex == -1) {
416 CdUp();
417 while (fCurrentNode->GetVolume()->IsAssembly())
418 CdUp();
420 return;
421 }
422 if (fCurrentNode && fNextDaughterIndex < fCurrentNode->GetNdaughters()) {
425 while (nextindex >= 0) {
426 CdDown(nextindex);
427 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
428 }
429 }
431}
432
433////////////////////////////////////////////////////////////////////////////////
434/// Fill volume names of current branch into an array.
435
437{
438 fCache->GetBranchNames(names);
439}
440
441////////////////////////////////////////////////////////////////////////////////
442/// Fill node copy numbers of current branch into an array.
443
444void TGeoNavigator::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
445{
446 fCache->GetBranchNumbers(copyNumbers, volumeNumbers);
447}
448
449////////////////////////////////////////////////////////////////////////////////
450/// Fill node copy numbers of current branch into an array.
451
453{
454 fCache->GetBranchOnlys(isonly);
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// Cross a division cell. Distance to exit contained in fStep, current node
459/// points to the cell node.
460
462{
464 if (!finder) {
465 Fatal("CrossDivisionCell", "Volume has no pattern finder");
466 return nullptr;
467 }
468 // Mark current node and go up to the level of the divided volume
469 TGeoNode *skip = fCurrentNode;
470 CdUp();
471 Double_t point[3], newpoint[3], dir[3];
474 // Does step cross a boundary along division axis ?
475 Bool_t onbound = finder->IsOnBoundary(newpoint);
476 if (onbound) {
477 // Work along division axis
478 // Get the starting point
479 point[0] = newpoint[0] - dir[0] * fStep * (1. - gTolerance);
480 point[1] = newpoint[1] - dir[1] * fStep * (1. - gTolerance);
481 point[2] = newpoint[2] - dir[2] * fStep * (1. - gTolerance);
482 // Find which is the next crossed cell.
483 finder->FindNode(point, dir);
484 Int_t inext = finder->GetNext();
485 if (inext < 0) {
486 // step fully exits the division along the division axis
487 // Do step exits in a mother cell ?
488 if (fCurrentNode->IsOffset()) {
489 Double_t dist = fCurrentNode->GetVolume()->GetShape()->DistFromInside(point, dir, 3);
490 // Do step exit also from mother cell ?
491 if (dist < fStep + 2. * gTolerance) {
492 // Step exits mother on its own division axis
493 return CrossDivisionCell();
494 }
495 // We end up here
496 return fCurrentNode;
497 }
498 // Exiting in a non-divided volume
499 while (fCurrentNode->GetVolume()->IsAssembly()) {
500 // Move always to mother for assemblies
501 skip = fCurrentNode;
502 if (!fLevel)
503 break;
504 CdUp();
505 }
506 return CrossBoundaryAndLocate(kFALSE, skip);
507 }
508 // step enters a new cell
509 CdDown(inext + finder->GetDivIndex());
510 skip = fCurrentNode;
511 return CrossBoundaryAndLocate(kTRUE, skip);
512 }
513 // step exits on an axis other than the division axis -> get next slice
514 if (fCurrentNode->IsOffset())
515 return CrossDivisionCell();
516 return CrossBoundaryAndLocate(kFALSE, skip);
517}
518
519////////////////////////////////////////////////////////////////////////////////
520/// Cross next boundary and locate within current node
521/// The current point must be on the boundary of fCurrentNode.
522
524{
525 // Extrapolate current point with estimated error.
527 Double_t trmax = 1. + TMath::Abs(tr[0]) + TMath::Abs(tr[1]) + TMath::Abs(tr[2]);
528 Double_t extra = 100. * (trmax + fStep) * gTolerance;
529 const Int_t idebug = TGeoManager::GetVerboseLevel();
530 TGeoNode *crtstate[10];
531 Int_t level = fLevel + 1;
532 Bool_t samepath = kFALSE;
533 for (Int_t i = 0; i < 10; ++i)
534 crtstate[i] = nullptr;
535
536 if (!downwards) {
537 for (Int_t i = 0; i < fLevel; ++i) {
538 crtstate[i] = GetMother(i);
539 if (i == 9)
540 break;
541 }
542 }
543 fPoint[0] += extra * fDirection[0];
544 fPoint[1] += extra * fDirection[1];
545 fPoint[2] += extra * fDirection[2];
546 TGeoNode *current = SearchNode(downwards, skipnode);
547 fForcedNode = nullptr;
548 fPoint[0] -= extra * fDirection[0];
549 fPoint[1] -= extra * fDirection[1];
550 fPoint[2] -= extra * fDirection[2];
551 if (!current)
552 return nullptr;
553 if (downwards) {
554 Int_t nextindex = current->GetVolume()->GetNextNodeIndex();
555 while (nextindex >= 0) {
556 CdDown(nextindex);
557 current = fCurrentNode;
558 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
559 }
560 if (idebug > 4) {
561 printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
562 }
563 return current;
564 }
565
566 if (skipnode) {
567 if (current == skipnode) {
568 samepath = kTRUE;
569 if (!downwards) {
570 level = TMath::Min(level, 10);
571 for (Int_t i = 1; i < level; i++) {
572 if (crtstate[i - 1] != GetMother(i)) {
573 samepath = kFALSE;
574 break;
575 }
576 }
577 }
578 }
579 }
580
581 if (samepath || current->GetVolume()->IsAssembly()) {
582 if (!fLevel) {
584 if (idebug > 4) {
585 printf("CrossBoundaryAndLocate: Exited geometry\n");
586 }
587 return fGeometry->GetCurrentNode();
588 }
589 CdUp();
590 while (fLevel && fCurrentNode->GetVolume()->IsAssembly())
591 CdUp();
592 if (!fLevel && fCurrentNode->GetVolume()->IsAssembly()) {
594 if (idebug > 4) {
595 printf("CrossBoundaryAndLocate: Exited geometry\n");
596 }
597 if (idebug > 4) {
598 printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
599 }
600 return fCurrentNode;
601 }
602 return fCurrentNode;
603 }
604 if (idebug > 4) {
605 printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
606 }
607 return current;
608}
609
610////////////////////////////////////////////////////////////////////////////////
611/// Find distance to next boundary and store it in fStep. Returns node to which this
612/// boundary belongs. If PATH is specified, compute only distance to the node to which
613/// PATH points. If STEPMAX is specified, compute distance only in case fSafety is smaller
614/// than this value. STEPMAX represent the step to be made imposed by other reasons than
615/// geometry (usually physics processes). Therefore in this case this method provides the
616/// answer to the question : "Is STEPMAX a safe step ?" returning a NULL node and filling
617/// fStep with a big number.
618/// In case frombdr=kTRUE, the isotropic safety is set to zero.
619///
620/// Note : safety distance for the current point is computed ONLY in case STEPMAX is
621/// specified, otherwise users have to call explicitly TGeoManager::Safety() if
622/// they want this computed for the current point.
623
624TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax, const char *path, Bool_t frombdr)
625{
626 // convert current point and direction to local reference
627 Int_t iact = 3;
633 fForcedNode = nullptr;
634 Bool_t computeGlobal = kFALSE;
635 fIsOnBoundary = frombdr;
636 fSafety = 0.;
637 TGeoNode *top_node = fGeometry->GetTopNode();
638 TGeoVolume *top_volume = top_node->GetVolume();
639 // If inside an assembly, go logically up in the hierarchy
640 while (fCurrentNode->GetVolume()->IsAssembly() && fLevel)
641 CdUp();
642 if (stepmax < 1E29) {
643 if (stepmax <= 0) {
644 stepmax = -stepmax;
645 computeGlobal = kTRUE;
646 }
647 // if (fLastSafety>0 && IsSamePoint(fPoint[0], fPoint[1], fPoint[2])) fSafety = fLastSafety;
648 fSafety = Safety();
649 // Try to get out easy if proposed step within safe region
650 if (!frombdr && (fSafety > 0) && IsSafeStep(stepmax + gTolerance, fSafety)) {
651 fStep = stepmax;
653 return fCurrentNode;
654 }
656 memcpy(fLastPoint, fPoint, kN3);
658 if (fSafety < gTolerance)
660 else
662 fStep = stepmax;
663 if (stepmax + gTolerance < fSafety) {
665 return fCurrentNode;
666 }
667 }
668 if (computeGlobal)
670 Double_t snext = TGeoShape::Big();
671 Double_t safe;
672 Double_t point[3];
673 Double_t dir[3];
674 if (idebug > 4) {
675 printf("TGeoManager::FindNextBoundary: point=(%19.16f, %19.16f, %19.16f)\n", fPoint[0], fPoint[1], fPoint[2]);
676 printf(" dir= (%19.16f, %19.16f, %19.16f)\n", fDirection[0], fDirection[1],
677 fDirection[2]);
678 printf(" pstep=%9.6g path=%s\n", stepmax, GetPath());
679 }
680 if (path[0]) {
681 PushPath();
682 if (!cd(path)) {
683 PopPath();
684 return nullptr;
685 }
686 if (computeGlobal)
692 if (idebug > 4) {
693 printf("=== To path: %s\n", path);
694 printf("=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n", tvol->GetName(), point[0],
695 point[1], point[2], dir[0], dir[1], dir[2]);
696 }
697 if (tvol->Contains(point)) {
698 if (idebug > 4)
699 printf("=== volume %s contains point\n", tvol->GetName());
700 fStep = tvol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
701 } else {
702 fStep = tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, fStep, &safe);
703 if (idebug > 4) {
704 printf("=== volume %s does not contain point\n", tvol->GetName());
705 printf("=== distance to path: %g\n", fStep);
706 tvol->InspectShape();
707 if (fStep < 1.E20) {
708 Double_t newpt[3];
709 newpt[0] = point[0] + fStep * dir[0];
710 newpt[1] = point[1] + fStep * dir[1];
711 newpt[2] = point[2] + fStep * dir[2];
712 printf("=== Propagated point: (%19.16f, %19.16f, %19.16f)", newpt[0], newpt[1], newpt[2]);
713 }
714 while (fLevel) {
715 CdUp();
716 tvol = fCurrentNode->GetVolume();
719 printf("=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n", tvol->GetName(),
720 point[0], point[1], point[2], dir[0], dir[1], dir[2]);
721 if (tvol->Contains(point)) {
722 printf("=== volume %s contains point\n", tvol->GetName());
723 } else {
724 printf("=== volume %s does not contain point\n", tvol->GetName());
725 snext = tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, 1.E30, &safe);
726 }
727 }
728 }
729 }
730 PopPath();
731 return fNextNode;
732 }
733 // compute distance to exit point from current node and the distance to its
734 // closest boundary
735 // if point is outside, just check the top node
736 if (fIsOutside) {
737 snext = top_volume->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep, &safe);
738 fNextNode = top_node;
739 if (snext < fStep - gTolerance) {
741 fStep = snext;
743 fNextDaughterIndex = indnext;
744 while (indnext >= 0) {
745 fNextNode = fNextNode->GetDaughter(indnext);
746 if (computeGlobal)
748 indnext = fNextNode->GetVolume()->GetNextNodeIndex();
749 }
750 return fNextNode;
751 }
752 return nullptr;
753 }
757 if (idebug > 4) {
758 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n", point[0], point[1], point[2]);
759 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n", dir[0], dir[1], dir[2]);
760 }
761 // find distance to exiting current node
762 snext = vol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
763 if (idebug > 4) {
764 printf(" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(), snext);
765 }
766 if (snext < fStep - gTolerance) {
770 fStep = snext;
772 if (fStep < 1E-6)
773 return fCurrentNode;
774 }
775 fNextNode = (fStep < 1E20) ? fCurrentNode : nullptr;
776 // Find next daughter boundary for the current volume
777 Int_t idaughter = -1;
778 FindNextDaughterBoundary(point, dir, idaughter, computeGlobal);
779 if (idaughter >= 0)
780 fNextDaughterIndex = idaughter;
781 TGeoNode *current = nullptr;
782 TGeoNode *dnode = nullptr;
783 TGeoVolume *mother = nullptr;
784 // if we are in an overlapping node, check also the mother(s)
785 if (fNmany) {
786 Double_t mothpt[3];
787 Double_t vecpt[3];
788 Double_t dpt[3], dvec[3];
789 Int_t novlps;
790 Int_t idovlp = -1;
791 Int_t safelevel = GetSafeLevel();
792 PushPath(safelevel + 1);
793 while (fCurrentOverlapping) {
794 Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
795 CdUp();
796 mother = fCurrentNode->GetVolume();
797 fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
799 // check distance to out
800 snext = TGeoShape::Big();
801 if (!mother->IsAssembly())
802 snext = mother->GetShape()->DistFromInside(&mothpt[0], &vecpt[0], iact, fStep, &safe);
803 if (snext < fStep - gTolerance) {
806 fStep = snext;
807 if (computeGlobal)
812 }
813 // check overlapping nodes
814 for (Int_t i = 0; i < novlps; i++) {
815 current = mother->GetNode(ovlps[i]);
816 if (!current->IsOverlapping()) {
817 current->cd();
818 current->MasterToLocal(&mothpt[0], &dpt[0]);
819 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
820 // Current point may be inside the other node - geometry error that we ignore
821 snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
822 if (snext < fStep - gTolerance) {
823 if (computeGlobal) {
825 fCurrentMatrix->Multiply(current->GetMatrix());
826 }
829 fStep = snext;
830 fNextNode = current;
832 CdDown(ovlps[i]);
834 CdUp();
835 }
836 } else {
837 // another many - check if point is in or out
838 current->cd();
839 current->MasterToLocal(&mothpt[0], &dpt[0]);
840 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
841 if (current->GetVolume()->Contains(dpt)) {
842 if (current->GetVolume()->GetNdaughters()) {
843 CdDown(ovlps[i]);
846 dnode = FindNextDaughterBoundary(dpt, dvec, idovlp, computeGlobal);
847 if (dnode) {
848 if (computeGlobal) {
851 }
852 fNextNode = dnode;
854 CdDown(idovlp);
856 Int_t iup = 0;
857 while (indnext >= 0) {
858 CdDown(indnext);
859 iup++;
861 }
863 while (iup > 0) {
864 CdUp();
865 iup--;
866 }
867 CdUp();
868 }
869 CdUp();
870 }
871 } else {
872 snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
873 if (snext < fStep - gTolerance) {
874 if (computeGlobal) {
876 fCurrentMatrix->Multiply(current->GetMatrix());
877 }
880 fStep = snext;
881 fNextNode = current;
883 CdDown(ovlps[i]);
885 CdUp();
886 }
887 }
888 }
889 }
890 }
891 // Now we are in a non-overlapping node
892 if (fNmany) {
893 // We have overlaps up in the branch, check distance to exit
894 Int_t up = 1;
895 Int_t imother;
896 Int_t nmany = fNmany;
897 Bool_t ovlp = kFALSE;
898 Bool_t nextovlp = kFALSE;
900 TGeoNode *currentnode = fCurrentNode;
901 TGeoNode *mothernode, *mup;
902 TGeoHMatrix *matrix;
903 while (nmany) {
904 mothernode = GetMother(up);
905 if (!mothernode) {
906 Fatal("FindNextBoundary", "Cannot find mother node");
907 return nullptr;
908 }
909 mup = mothernode;
910 imother = up + 1;
911 offset = kFALSE;
912 while (mup->IsOffset()) {
913 mup = GetMother(imother++);
914 offset = kTRUE;
915 }
916 nextovlp = mup->IsOverlapping();
917 if (offset) {
918 mothernode = mup;
919 if (nextovlp)
920 nmany -= imother - up;
921 up = imother - 1;
922 } else {
923 if (ovlp)
924 nmany--;
925 }
926 if (ovlp || nextovlp) {
927 matrix = GetMotherMatrix(up);
928 if (!matrix) {
929 Fatal("FindNextBoundary", "Cannot find mother matrix");
930 return nullptr;
931 }
932 matrix->MasterToLocal(fPoint, dpt);
933 matrix->MasterToLocalVect(fDirection, dvec);
934 snext = TGeoShape::Big();
935 if (!mothernode->GetVolume()->IsAssembly())
936 snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt, dvec, iact, fStep);
937 if (snext < fStep - gTolerance) {
940 fStep = snext;
941 fNextNode = mothernode;
943 if (computeGlobal)
944 fCurrentMatrix->CopyFrom(matrix);
945 while (up--)
946 CdUp();
948 up = 1;
949 currentnode = fCurrentNode;
950 ovlp = currentnode->IsOverlapping();
951 continue;
952 }
953 }
954 currentnode = mothernode;
955 ovlp = nextovlp;
956 up++;
957 }
958 }
959 PopPath();
960 }
961 // Compute now the distance in case we have a parallel world
962 Double_t parstep = TGeoShape::Big();
964 // printf("path: %s next node %s at %g\n", GetPath(), fNextNode->GetName(), fStep);
966 if (pnode) {
967 // A boundary is hit at less than fPStep
968 fStep = parstep;
969 fNextNode = pnode->GetNode();
970 fNextDaughterIndex = -2; // No way to store it for CdNext
973 Int_t nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
974 while (nextindex >= 0) {
975 fNextNode = fNextNode->GetDaughter(nextindex);
976 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
977 }
978 }
979 }
980 return fNextNode;
981}
982
983////////////////////////////////////////////////////////////////////////////////
984/// Computes as fStep the distance to next daughter of the current volume.
985/// The point and direction must be converted in the coordinate system of the current volume.
986/// The proposed step limit is fStep.
987
989{
990 Double_t snext = TGeoShape::Big();
992 idaughter = -1; // nothing crossed
993 TGeoNode *nodefound = nullptr;
994 // Get number of daughters. If no daughters we are done.
995
997 Int_t nd = vol->GetNdaughters();
998 if (!nd)
999 return nullptr; // No daughter
1001 return nullptr;
1002 Double_t lpoint[3], ldir[3];
1003 TGeoNode *current = nullptr;
1004 Int_t i = 0;
1005 // if current volume is divided, we are in the non-divided region. We
1006 // check first if we are inside a cell in which case compute distance to next cell
1007 TGeoPatternFinder *finder = vol->GetFinder();
1008 if (finder) {
1009 Int_t ifirst = finder->GetDivIndex();
1010 Int_t ilast = ifirst + finder->GetNdiv() - 1;
1011 current = finder->FindNode(point);
1012 if (current) {
1013 // Point inside a cell: find distance to next cell
1014 Int_t index = current->GetIndex();
1015 if ((index - 1) >= ifirst)
1016 ifirst = index - 1;
1017 else
1018 ifirst = -1;
1019 if ((index + 1) <= ilast)
1020 ilast = index + 1;
1021 else
1022 ilast = -1;
1023 }
1024 if (ifirst >= 0) {
1025 current = vol->GetNode(ifirst);
1026 current->cd();
1027 current->MasterToLocal(&point[0], lpoint);
1028 current->MasterToLocalVect(&dir[0], ldir);
1029 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1030 if (snext < fStep - gTolerance) {
1031 if (compmatrix) {
1033 fCurrentMatrix->Multiply(current->GetMatrix());
1034 }
1037 fStep = snext;
1038 fNextNode = current;
1039 nodefound = current;
1040 idaughter = ifirst;
1041 }
1042 }
1043 if (ilast == ifirst)
1044 return nodefound;
1045 if (ilast >= 0) {
1046 current = vol->GetNode(ilast);
1047 current->cd();
1048 current->MasterToLocal(&point[0], lpoint);
1049 current->MasterToLocalVect(&dir[0], ldir);
1050 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1051 if (snext < fStep - gTolerance) {
1052 if (compmatrix) {
1054 fCurrentMatrix->Multiply(current->GetMatrix());
1055 }
1058 fStep = snext;
1059 fNextNode = current;
1060 nodefound = current;
1061 idaughter = ilast;
1062 }
1063 }
1064 return nodefound;
1065 }
1066 // if only few daughters, check all and exit
1067 TGeoVoxelFinder *voxels = vol->GetVoxels();
1068 Int_t indnext;
1069 if (idebug > 4)
1070 printf(" Checking distance to %d daughters...\n", nd);
1071 if (nd < 5 || !voxels) {
1072 for (i = 0; i < nd; i++) {
1073 current = vol->GetNode(i);
1074 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive())
1075 continue;
1076 current->cd();
1077 if (voxels && voxels->IsSafeVoxel(point, i, fStep))
1078 continue;
1079 current->MasterToLocal(point, lpoint);
1080 current->MasterToLocalVect(dir, ldir);
1081 if (current->IsOverlapping() && current->GetVolume()->Contains(lpoint) &&
1082 current->GetVolume()->GetShape()->Safety(lpoint, kTRUE) > gTolerance)
1083 continue;
1084 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1085 if (snext < fStep - gTolerance) {
1086 if (idebug > 4) {
1087 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n", lpoint[0], lpoint[1], lpoint[2]);
1088 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n", ldir[0], ldir[1], ldir[2]);
1089 printf(" -> to: %s shape %s snext=%g\n", current->GetName(),
1090 current->GetVolume()->GetShape()->ClassName(), snext);
1091 }
1092 indnext = current->GetVolume()->GetNextNodeIndex();
1093 if (compmatrix) {
1095 fCurrentMatrix->Multiply(current->GetMatrix());
1096 }
1099 fStep = snext;
1100 fNextNode = current;
1101 nodefound = fNextNode;
1102 idaughter = i;
1103 while (indnext >= 0) {
1104 current = current->GetDaughter(indnext);
1105 if (compmatrix)
1106 fCurrentMatrix->Multiply(current->GetMatrix());
1107 fNextNode = current;
1108 nodefound = current;
1109 indnext = current->GetVolume()->GetNextNodeIndex();
1110 }
1111 }
1112 }
1113 if (vol->IsAssembly())
1114 ((TGeoVolumeAssembly *)vol)->SetNextNodeIndex(idaughter);
1115 return nodefound;
1116 }
1117 // if current volume is voxelized, first get current voxel
1118 Int_t ncheck = 0;
1119 Int_t sumchecked = 0;
1120 Int_t *vlist = nullptr;
1121 TGeoStateInfo &info = *fCache->GetInfo();
1122 voxels->SortCrossedVoxels(point, dir, info);
1123 while ((sumchecked < nd) && (vlist = voxels->GetNextVoxel(point, dir, ncheck, info))) {
1124 for (i = 0; i < ncheck; i++) {
1125 current = vol->GetNode(vlist[i]);
1126 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive())
1127 continue;
1128 current->cd();
1129 current->MasterToLocal(point, lpoint);
1130 current->MasterToLocalVect(dir, ldir);
1131 if (current->IsOverlapping() && current->GetVolume()->Contains(lpoint) &&
1132 current->GetVolume()->GetShape()->Safety(lpoint, kTRUE) > gTolerance)
1133 continue;
1134 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1135 sumchecked++;
1136 // printf("checked %d from %d : snext=%g\n", sumchecked, nd, snext);
1137 if (snext < fStep - gTolerance) {
1138 if (idebug > 4) {
1139 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n", lpoint[0], lpoint[1], lpoint[2]);
1140 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n", ldir[0], ldir[1], ldir[2]);
1141 printf(" -> to: %s shape %s snext=%g\n", current->GetName(),
1142 current->GetVolume()->GetShape()->ClassName(), snext);
1143 }
1144 indnext = current->GetVolume()->GetNextNodeIndex();
1145 if (compmatrix) {
1147 fCurrentMatrix->Multiply(current->GetMatrix());
1148 }
1151 fStep = snext;
1152 fNextNode = current;
1153 nodefound = fNextNode;
1154 idaughter = vlist[i];
1155 while (indnext >= 0) {
1156 current = current->GetDaughter(indnext);
1157 if (compmatrix)
1158 fCurrentMatrix->Multiply(current->GetMatrix());
1159 fNextNode = current;
1160 nodefound = current;
1161 indnext = current->GetVolume()->GetNextNodeIndex();
1162 }
1163 }
1164 }
1165 }
1167 if (vol->IsAssembly())
1168 ((TGeoVolumeAssembly *)vol)->SetNextNodeIndex(idaughter);
1169 return nodefound;
1170}
1171
1172////////////////////////////////////////////////////////////////////////////////
1173/// Compute distance to next boundary within STEPMAX. If no boundary is found,
1174/// propagate current point along current direction with fStep=STEPMAX. Otherwise
1175/// propagate with fStep=SNEXT (distance to boundary) and locate/return the next
1176/// node.
1177
1179{
1180 Int_t iact = 3;
1182 Int_t nextindex;
1183 Bool_t is_assembly;
1184 fForcedNode = nullptr;
1186 TGeoNode *skip;
1188 fStep = stepmax;
1189 Double_t snext = TGeoShape::Big();
1190 // If inside an assembly, go logically up in the hierarchy
1191 while (fCurrentNode->GetVolume()->IsAssembly() && fLevel)
1192 CdUp();
1193 if (compsafe) {
1194 // Try to get out easy if proposed step within safe region
1196 if (IsSafeStep(stepmax + gTolerance, fSafety)) {
1197 fPoint[0] += stepmax * fDirection[0];
1198 fPoint[1] += stepmax * fDirection[1];
1199 fPoint[2] += stepmax * fDirection[2];
1200 return fCurrentNode;
1201 }
1202 Safety();
1204 memcpy(fLastPoint, fPoint, kN3);
1205 // If proposed step less than safety, nothing to check
1206 if (fSafety > stepmax + gTolerance) {
1207 fPoint[0] += stepmax * fDirection[0];
1208 fPoint[1] += stepmax * fDirection[1];
1209 fPoint[2] += stepmax * fDirection[2];
1210 return fCurrentNode;
1211 }
1212 }
1213 Double_t extra = (fIsOnBoundary) ? gTolerance : 0.0;
1215 fPoint[0] += extra * fDirection[0];
1216 fPoint[1] += extra * fDirection[1];
1217 fPoint[2] += extra * fDirection[2];
1219 if (idebug > 4) {
1220 printf("TGeoManager::FindNextBAndStep: point=(%19.16f, %19.16f, %19.16f)\n", fPoint[0], fPoint[1], fPoint[2]);
1221 printf(" dir= (%19.16f, %19.16f, %19.16f)\n", fDirection[0], fDirection[1],
1222 fDirection[2]);
1223 printf(" pstep=%9.6g path=%s\n", stepmax, GetPath());
1224 }
1225
1226 if (fIsOutside) {
1228 if (snext < fStep - gTolerance) {
1229 if (snext <= 0) {
1230 snext = 0.0;
1231 fStep = snext;
1232 fPoint[0] -= extra * fDirection[0];
1233 fPoint[1] -= extra * fDirection[1];
1234 fPoint[2] -= extra * fDirection[2];
1235 } else {
1236 fStep = snext + extra;
1237 }
1240 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1241 while (nextindex >= 0) {
1242 CdDown(nextindex);
1244 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1245 if (nextindex < 0)
1247 }
1248 // Update global point
1249 fPoint[0] += snext * fDirection[0];
1250 fPoint[1] += snext * fDirection[1];
1251 fPoint[2] += snext * fDirection[2];
1256 }
1257 if (snext < TGeoShape::Big()) {
1258 // New point still outside, but the top node is reachable
1260 fPoint[0] += (fStep - extra) * fDirection[0];
1261 fPoint[1] += (fStep - extra) * fDirection[1];
1262 fPoint[2] += (fStep - extra) * fDirection[2];
1263 return fNextNode;
1264 }
1265 // top node not reachable from current point/direction
1266 fNextNode = nullptr;
1268 return nullptr;
1269 }
1270 Double_t point[3], dir[3];
1271 Int_t icrossed = -2;
1272 fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
1275 // find distance to exiting current node
1276 if (idebug > 4) {
1277 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n", point[0], point[1], point[2]);
1278 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n", dir[0], dir[1], dir[2]);
1279 }
1280 // find distance to exiting current node
1281 snext = vol->GetShape()->DistFromInside(point, dir, iact, fStep);
1282 if (idebug > 4) {
1283 printf(" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(), snext);
1284 }
1286 if (snext <= gTolerance) {
1287 // Current point on the boundary while track exiting
1288 snext = gTolerance;
1289 fStep = snext;
1293 skip = fCurrentNode;
1294 fPoint[0] += fStep * fDirection[0];
1295 fPoint[1] += fStep * fDirection[1];
1296 fPoint[2] += fStep * fDirection[2];
1297 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1298 if (!fLevel && !is_assembly) {
1299 fIsOutside = kTRUE;
1300 return nullptr;
1301 }
1302 if (fCurrentNode->IsOffset())
1303 return CrossDivisionCell();
1304 if (fLevel)
1305 CdUp();
1306 else
1307 skip = nullptr;
1308 return CrossBoundaryAndLocate(kFALSE, skip);
1309 }
1310
1311 if (snext < fStep - gTolerance) {
1312 // Currently the minimum step chosen is the exiting one
1313 icrossed = -1;
1314 fStep = snext;
1317 }
1318 // Find next daughter boundary for the current volume
1319 Int_t idaughter = -1;
1320 TGeoNode *crossed = FindNextDaughterBoundary(point, dir, idaughter, kTRUE);
1321 if (crossed) {
1323 icrossed = idaughter;
1325 }
1326 TGeoNode *current = nullptr;
1327 TGeoNode *dnode = nullptr;
1328 TGeoVolume *mother = nullptr;
1329 // if we are in an overlapping node, check also the mother(s)
1330 if (fNmany) {
1331 Double_t mothpt[3];
1332 Double_t vecpt[3];
1333 Double_t dpt[3], dvec[3];
1334 Int_t novlps;
1335 Int_t safelevel = GetSafeLevel();
1336 PushPath(safelevel + 1);
1337 while (fCurrentOverlapping) {
1338 Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
1339 CdUp();
1340 mother = fCurrentNode->GetVolume();
1341 fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
1343 // check distance to out
1344 snext = TGeoShape::Big();
1345 if (!mother->IsAssembly())
1346 snext = mother->GetShape()->DistFromInside(mothpt, vecpt, iact, fStep);
1347 if (snext < fStep - gTolerance) {
1348 // exiting mother first (extrusion)
1349 icrossed = -1;
1350 PopDummy();
1351 PushPath(safelevel + 1);
1354 fStep = snext;
1357 }
1358 // check overlapping nodes
1359 for (Int_t i = 0; i < novlps; i++) {
1360 current = mother->GetNode(ovlps[i]);
1361 if (!current->IsOverlapping()) {
1362 current->cd();
1363 current->MasterToLocal(&mothpt[0], &dpt[0]);
1364 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1365 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1366 if (snext < fStep - gTolerance) {
1367 PopDummy();
1368 PushPath(safelevel + 1);
1370 fCurrentMatrix->Multiply(current->GetMatrix());
1373 icrossed = ovlps[i];
1374 fStep = snext;
1375 fNextNode = current;
1376 }
1377 } else {
1378 // another many - check if point is in or out
1379 current->cd();
1380 current->MasterToLocal(&mothpt[0], &dpt[0]);
1381 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1382 if (current->GetVolume()->Contains(dpt)) {
1383 if (current->GetVolume()->GetNdaughters()) {
1384 CdDown(ovlps[i]);
1385 dnode = FindNextDaughterBoundary(dpt, dvec, idaughter, kFALSE);
1386 if (dnode) {
1389 icrossed = idaughter;
1390 PopDummy();
1391 PushPath(safelevel + 1);
1394 fNextNode = dnode;
1395 }
1396 CdUp();
1397 }
1398 } else {
1399 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1400 if (snext < fStep - gTolerance) {
1402 fCurrentMatrix->Multiply(current->GetMatrix());
1405 fStep = snext;
1406 fNextNode = current;
1407 icrossed = ovlps[i];
1408 PopDummy();
1409 PushPath(safelevel + 1);
1410 }
1411 }
1412 }
1413 }
1414 }
1415 // Now we are in a non-overlapping node
1416 if (fNmany) {
1417 // We have overlaps up in the branch, check distance to exit
1418 Int_t up = 1;
1419 Int_t imother;
1420 Int_t nmany = fNmany;
1421 Bool_t ovlp = kFALSE;
1422 Bool_t nextovlp = kFALSE;
1424 TGeoNode *currentnode = fCurrentNode;
1425 TGeoNode *mothernode, *mup;
1426 TGeoHMatrix *matrix;
1427 while (nmany) {
1428 mothernode = GetMother(up);
1429 mup = mothernode;
1430 imother = up + 1;
1431 offset = kFALSE;
1432 while (mup->IsOffset()) {
1433 mup = GetMother(imother++);
1434 offset = kTRUE;
1435 }
1436 nextovlp = mup->IsOverlapping();
1437 if (offset) {
1438 mothernode = mup;
1439 if (nextovlp)
1440 nmany -= imother - up;
1441 up = imother - 1;
1442 } else {
1443 if (ovlp)
1444 nmany--;
1445 }
1446 if (ovlp || nextovlp) {
1447 matrix = GetMotherMatrix(up);
1448 matrix->MasterToLocal(fPoint, dpt);
1449 matrix->MasterToLocalVect(fDirection, dvec);
1450 snext = TGeoShape::Big();
1451 if (!mothernode->GetVolume()->IsAssembly())
1452 snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt, dvec, iact, fStep);
1455 if (snext < fStep - gTolerance) {
1456 fNextNode = mothernode;
1457 fCurrentMatrix->CopyFrom(matrix);
1458 fStep = snext;
1459 while (up--)
1460 CdUp();
1461 PopDummy();
1462 PushPath();
1463 icrossed = -1;
1464 up = 1;
1465 currentnode = fCurrentNode;
1466 ovlp = currentnode->IsOverlapping();
1467 continue;
1468 }
1469 }
1470 currentnode = mothernode;
1471 ovlp = nextovlp;
1472 up++;
1473 }
1474 }
1475 PopPath();
1476 }
1477 // Compute now the distance in case we have a parallel world
1478 Double_t parstep = TGeoShape::Big();
1479 TGeoPhysicalNode *pnode = nullptr;
1482 if (pnode) {
1483 // A boundary is hit at less than fPStep
1484 fStep = parstep;
1485 fPoint[0] += fStep * fDirection[0];
1486 fPoint[1] += fStep * fDirection[1];
1487 fPoint[2] += fStep * fDirection[2];
1488 fNextNode = pnode->GetNode();
1489 // icrossed = -4; //
1492 cd(pnode->GetName());
1493 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1494 while (nextindex >= 0) {
1495 current = fCurrentNode;
1496 CdDown(nextindex);
1497 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1498 }
1499 return fCurrentNode;
1500 }
1501 }
1502 fPoint[0] += fStep * fDirection[0];
1503 fPoint[1] += fStep * fDirection[1];
1504 fPoint[2] += fStep * fDirection[2];
1505 fStep += extra;
1506 if (icrossed == -2) {
1507 // Nothing crossed within stepmax -> propagate and return same location
1509 return fCurrentNode;
1510 }
1512 if (icrossed == -1) {
1513 // Exiting current node.
1514 skip = fCurrentNode;
1515 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1516 if (!fLevel && !is_assembly) {
1517 fIsOutside = kTRUE;
1518 return nullptr;
1519 }
1520 if (fCurrentNode->IsOffset())
1521 return CrossDivisionCell();
1522 if (fLevel)
1523 CdUp();
1524 else
1525 skip = nullptr;
1526 return CrossBoundaryAndLocate(kFALSE, skip);
1527 }
1528
1529 CdDown(icrossed);
1530 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1531 while (nextindex >= 0) {
1532 current = fCurrentNode;
1533 CdDown(nextindex);
1534 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1535 }
1537 return CrossBoundaryAndLocate(kTRUE, current);
1538}
1539
1540////////////////////////////////////////////////////////////////////////////////
1541/// Returns deepest node containing current point.
1542
1544{
1545 fSafety = 0;
1550 fStartSafe = safe_start;
1552 TGeoNode *last = fCurrentNode;
1553 TGeoNode *found = SearchNode();
1554 if (found != last) {
1556 } else {
1557 if (last->IsOverlapping())
1559 }
1560 return found;
1561}
1562
1563////////////////////////////////////////////////////////////////////////////////
1564/// Returns deepest node containing current point.
1565
1567{
1568 fPoint[0] = x;
1569 fPoint[1] = y;
1570 fPoint[2] = z;
1571 fSafety = 0;
1576 fStartSafe = kTRUE;
1578 TGeoNode *last = fCurrentNode;
1579 TGeoNode *found = SearchNode();
1580 if (found != last) {
1582 } else {
1583 if (last->IsOverlapping())
1585 }
1586 return found;
1587}
1588
1589////////////////////////////////////////////////////////////////////////////////
1590/// Computes fast normal to next crossed boundary, assuming that the current point
1591/// is close enough to the boundary. Works only after calling FindNextBoundary.
1592
1594{
1595 if (!fNextNode)
1596 return nullptr;
1597 Double_t local[3];
1598 Double_t ldir[3];
1599 Double_t lnorm[3];
1602 fNextNode->GetVolume()->GetShape()->ComputeNormal(local, ldir, lnorm);
1604 return fNormal;
1605}
1606
1607////////////////////////////////////////////////////////////////////////////////
1608/// Computes normal vector to the next surface that will be or was already
1609/// crossed when propagating on a straight line from a given point/direction.
1610/// Returns the normal vector cosines in the MASTER coordinate system. The dot
1611/// product of the normal and the current direction is positive defined.
1612
1614{
1615 return FindNormalFast();
1616}
1617
1618////////////////////////////////////////////////////////////////////////////////
1619/// Initialize current point and current direction vector (normalized)
1620/// in MARS. Return corresponding node.
1621
1623{
1624 SetCurrentPoint(point);
1626 return FindNode();
1627}
1628
1629////////////////////////////////////////////////////////////////////////////////
1630/// Initialize current point and current direction vector (normalized)
1631/// in MARS. Return corresponding node.
1632
1634{
1635 SetCurrentPoint(x, y, z);
1636 SetCurrentDirection(nx, ny, nz);
1637 return FindNode();
1638}
1639
1640////////////////////////////////////////////////////////////////////////////////
1641/// Reset current state flags.
1642
1644{
1650}
1651
1652//////////////////////////////////////////////////////////////////////////////////
1653/// Wrapper for getting the safety from the parallel world. Takes care of
1654/// caching mechanics + talking to the parallel world.
1655
1657{
1658 if (!IsPWSafetyCaching()) {
1659 return fGeometry->GetParallelWorld()->Safety(cpoint, saf_max);
1660 }
1661 const auto cached = GetPWSafetyEstimateFromCache(cpoint);
1662 if (cached > 0) {
1663 // if cache is valid, just use it
1664 return cached;
1665 }
1666 // otherwise we need to evaluate it and update the cache
1667 // we evaluate this with saf_max = infinity to get the best
1668 // possible safety value
1669 auto pw = fGeometry->GetParallelWorld();
1670 const auto newsafety = pw->Safety(cpoint /*saf_max*/);
1671
1672 // we need to be a bit careful: A returned safety value of TGeoShape::Big()
1673 // is not the actual safety and should not be cached
1674 if (newsafety < TGeoShape::Big()) {
1675 fLastPWSafety = newsafety;
1676 fLastPWSaftyPnt[0] = cpoint[0];
1677 fLastPWSaftyPnt[1] = cpoint[1];
1678 fLastPWSaftyPnt[2] = cpoint[2];
1679 } else {
1680 fLastPWSafety = -1;
1681 }
1682 return newsafety;
1683}
1684
1685////////////////////////////////////////////////////////////////////////////////
1686/// Compute safe distance from the current point. This represent the distance
1687/// from POINT to the closest boundary.
1688
1690{
1691 if (fIsOnBoundary) {
1692 fSafety = 0;
1693 return fSafety;
1694 }
1695 Double_t point[3];
1696 Double_t safpar = TGeoShape::Big(); // safety from parallel world
1697 if (!inside)
1699
1700 // Check if parallel navigation is enabled
1701 const bool have_PW = fGeometry->IsParallelWorldNav();
1702
1703 if (fIsOutside) {
1705 if (fSafety < gTolerance) {
1706 fSafety = 0;
1708 return fSafety;
1709 }
1710
1711 // cross-check against the parallel world safety, using fSafety as limit
1712 if (have_PW) {
1713 safpar = GetPWSafety(fPoint, fSafety);
1714 }
1715 return TMath::Min(fSafety, safpar);
1716 }
1717 //---> convert point to local reference frame of current node
1719
1720 //---> compute safety to current node
1722 if (!inside) {
1723 fSafety = vol->GetShape()->Safety(point, kTRUE);
1724 //---> if we were just entering, return this safety
1725 if (fSafety < gTolerance) {
1726 fSafety = 0;
1728 return fSafety;
1729 }
1730 }
1731
1732 //---> Check against the parallel geometry safety
1733 // cross-check against the parallel world safety, using fSafety as limit
1734 if (have_PW) {
1735 safpar = GetPWSafety(fPoint, fSafety);
1736 }
1737 if (safpar < fSafety)
1738 fSafety = safpar;
1739
1740 //---> if we were just exiting, return this safety
1741 TObjArray *nodes = vol->GetNodes();
1743 if (!nd && !fCurrentOverlapping)
1744 return fSafety;
1745 TGeoNode *node;
1746 Double_t safe;
1747 Int_t id;
1748
1749 // if current volume is divided, we are in the non-divided region. We
1750 // check only the first and the last cell
1751 TGeoPatternFinder *finder = vol->GetFinder();
1752 if (finder) {
1753 Int_t ifirst = finder->GetDivIndex();
1754 node = (TGeoNode *)nodes->UncheckedAt(ifirst);
1755 node->cd();
1756 safe = node->Safety(point, kFALSE);
1757 if (safe < gTolerance) {
1758 fSafety = 0;
1760 return fSafety;
1761 }
1762 if (safe < fSafety)
1763 fSafety = safe;
1764 Int_t ilast = ifirst + finder->GetNdiv() - 1;
1765 if (ilast == ifirst)
1766 return fSafety;
1767 node = (TGeoNode *)nodes->UncheckedAt(ilast);
1768 node->cd();
1769 safe = node->Safety(point, kFALSE);
1770 if (safe < gTolerance) {
1771 fSafety = 0;
1773 return fSafety;
1774 }
1775 if (safe < fSafety)
1776 fSafety = safe;
1777 if (fCurrentOverlapping && !inside)
1779 return fSafety;
1780 }
1781
1782 //---> If no voxels just loop daughters
1783 TGeoVoxelFinder *voxels = vol->GetVoxels();
1784 if (!voxels) {
1785 for (id = 0; id < nd; id++) {
1786 node = (TGeoNode *)nodes->UncheckedAt(id);
1787 safe = node->Safety(point, kFALSE);
1788 if (safe < gTolerance) {
1789 fSafety = 0;
1791 return fSafety;
1792 }
1793 if (safe < fSafety)
1794 fSafety = safe;
1795 }
1796 if (fNmany && !inside)
1798 return fSafety;
1799 } else {
1800 if (voxels->NeedRebuild()) {
1801 voxels->Voxelize();
1802 vol->FindOverlaps();
1803 }
1804 }
1805
1806 //---> check fast unsafe voxels
1807 Double_t *boxes = voxels->GetBoxes();
1808 for (id = 0; id < nd; id++) {
1809 Int_t ist = 6 * id;
1810 Double_t dxyz = 0.;
1811 Double_t dxyz0 = TMath::Abs(point[0] - boxes[ist + 3]) - boxes[ist];
1812 if (dxyz0 > fSafety)
1813 continue;
1814 Double_t dxyz1 = TMath::Abs(point[1] - boxes[ist + 4]) - boxes[ist + 1];
1815 if (dxyz1 > fSafety)
1816 continue;
1817 Double_t dxyz2 = TMath::Abs(point[2] - boxes[ist + 5]) - boxes[ist + 2];
1818 if (dxyz2 > fSafety)
1819 continue;
1820 if (dxyz0 > 0)
1821 dxyz += dxyz0 * dxyz0;
1822 if (dxyz1 > 0)
1823 dxyz += dxyz1 * dxyz1;
1824 if (dxyz2 > 0)
1825 dxyz += dxyz2 * dxyz2;
1826 if (dxyz >= fSafety * fSafety)
1827 continue;
1828 node = (TGeoNode *)nodes->UncheckedAt(id);
1829 safe = node->Safety(point, kFALSE);
1830 if (safe < gTolerance) {
1831 fSafety = 0;
1833 return fSafety;
1834 }
1835 if (safe < fSafety)
1836 fSafety = safe;
1837 }
1838 if (fNmany && !inside)
1840 return fSafety;
1841}
1842
1843////////////////////////////////////////////////////////////////////////////////
1844/// Compute safe distance from the current point within an overlapping node
1845
1847{
1848 Double_t point[3], local[3];
1849 Double_t safe;
1850 Bool_t contains;
1851 TGeoNode *nodeovlp;
1852 TGeoVolume *vol;
1853 Int_t novlp, io;
1854 Int_t *ovlp;
1855 Int_t safelevel = GetSafeLevel();
1856 PushPath(safelevel + 1);
1857 while (fCurrentOverlapping) {
1858 ovlp = fCurrentNode->GetOverlaps(novlp);
1859 CdUp();
1860 vol = fCurrentNode->GetVolume();
1862 contains = fCurrentNode->GetVolume()->Contains(point);
1863 safe = fCurrentNode->GetVolume()->GetShape()->Safety(point, contains);
1864 if (safe < fSafety && safe >= 0)
1865 fSafety = safe;
1866 if (!novlp || !contains)
1867 continue;
1868 // we are now in the container, check safety to all candidates
1869 for (io = 0; io < novlp; io++) {
1870 nodeovlp = vol->GetNode(ovlp[io]);
1871 nodeovlp->GetMatrix()->MasterToLocal(point, local);
1872 contains = nodeovlp->GetVolume()->Contains(local);
1873 if (contains) {
1874 CdDown(ovlp[io]);
1875 safe = Safety(kTRUE);
1876 CdUp();
1877 } else {
1878 safe = nodeovlp->GetVolume()->GetShape()->Safety(local, kFALSE);
1879 }
1880 if (safe < fSafety && safe >= 0)
1881 fSafety = safe;
1882 }
1883 }
1884 if (fNmany) {
1885 // We have overlaps up in the branch, check distance to exit
1886 Int_t up = 1;
1887 Int_t imother;
1888 Int_t nmany = fNmany;
1889 Bool_t crtovlp = kFALSE;
1890 Bool_t nextovlp = kFALSE;
1891 TGeoNode *mother, *mup;
1892 TGeoHMatrix *matrix;
1893 while (nmany) {
1894 mother = GetMother(up);
1895 mup = mother;
1896 imother = up + 1;
1897 while (mup->IsOffset())
1898 mup = GetMother(imother++);
1899 nextovlp = mup->IsOverlapping();
1900 if (crtovlp)
1901 nmany--;
1902 if (crtovlp || nextovlp) {
1903 matrix = GetMotherMatrix(up);
1904 matrix->MasterToLocal(fPoint, local);
1905 safe = mother->GetVolume()->GetShape()->Safety(local, kTRUE);
1906 if (safe < fSafety)
1907 fSafety = safe;
1908 crtovlp = nextovlp;
1909 }
1910 up++;
1911 }
1912 }
1913 PopPath();
1914 if (fSafety < gTolerance) {
1915 fSafety = 0.;
1917 }
1918}
1919
1920////////////////////////////////////////////////////////////////////////////////
1921/// Returns the deepest node containing fPoint, which must be set a priori.
1922/// Check if parallel world navigation is enabled
1923
1925{
1928 if (pnode) {
1929 // A node from the parallel world contains the point -> stop the search
1930 // and synchronize with navigation state
1931 pnode->cd();
1933 while (crtindex >= 0) {
1934 // Make sure we did not end up in an assembly.
1935 CdDown(crtindex);
1937 }
1938 return fCurrentNode;
1939 }
1940 }
1941 Double_t point[3];
1942 fNextDaughterIndex = -2;
1943 TGeoVolume *vol = nullptr;
1945 Bool_t inside_current = (fCurrentNode == skipnode) ? kTRUE : kFALSE;
1946 if (!downwards) {
1947 // we are looking upwards until inside current node or exit
1949 // We are inside an inactive volume-> go upwards
1950 CdUp();
1952 return SearchNode(kFALSE, skipnode);
1953 }
1954 // Check if the current point is still inside the current volume
1955 vol = fCurrentNode->GetVolume();
1956 if (vol->IsAssembly())
1957 inside_current = kTRUE;
1958 // If the current node is not to be skipped
1959 if (!inside_current) {
1961 inside_current = vol->Contains(point);
1962 }
1963 // Point might be inside an overlapping node
1964 if (fNmany) {
1965 inside_current = GotoSafeLevel();
1966 }
1967 if (!inside_current) {
1968 // If not, go upwards
1970 TGeoNode *skip = fCurrentNode; // skip current node at next search
1971 // check if we can go up
1972 if (!fLevel) {
1973 fIsOutside = kTRUE;
1974 return nullptr;
1975 }
1976 CdUp();
1977 return SearchNode(kFALSE, skip);
1978 }
1979 }
1980 vol = fCurrentNode->GetVolume();
1982 if (!inside_current && downwards) {
1983 // we are looking downwards
1985 inside_current = kTRUE;
1986 else
1987 inside_current = vol->Contains(point);
1988 if (!inside_current) {
1990 return nullptr;
1991 } else {
1992 if (fIsOutside) {
1995 }
1996 if (idebug > 4) {
1997 printf("Search node local=(%19.16f, %19.16f, %19.16f) -> %s\n", point[0], point[1], point[2],
1999 }
2000 }
2001 }
2002 // point inside current (safe) node -> search downwards
2003 TGeoNode *node;
2004 Int_t ncheck = 0;
2005 // if inside an non-overlapping node, reset overlap searches
2006 if (!fCurrentOverlapping) {
2008 }
2009
2010 Int_t crtindex = vol->GetCurrentNodeIndex();
2011 while (crtindex >= 0 && downwards) {
2012 // Make sure we did not end up in an assembly.
2013 CdDown(crtindex);
2014 vol = fCurrentNode->GetVolume();
2015 crtindex = vol->GetCurrentNodeIndex();
2016 if (crtindex < 0)
2018 }
2019
2020 Int_t nd = vol->GetNdaughters();
2021 // in case there are no daughters
2022 if (!nd)
2023 return fCurrentNode;
2025 return fCurrentNode;
2026
2027 TGeoPatternFinder *finder = vol->GetFinder();
2028 // point is inside the current node
2029 // first check if inside a division
2030 if (finder) {
2031 node = finder->FindNode(point);
2032 if (!node && fForcedNode) {
2033 // Point *HAS* to be inside a cell
2034 Double_t dir[3];
2036 finder->FindNode(point, dir);
2037 node = finder->CdNext();
2038 if (!node)
2039 return fCurrentNode; // inside divided volume but not in a cell
2040 }
2041 if (node && node != skipnode) {
2042 // go inside the division cell and search downwards
2044 CdDown(node->GetIndex());
2045 fForcedNode = nullptr;
2046 return SearchNode(kTRUE, node);
2047 }
2048 // point is not inside the division, but might be in other nodes
2049 // at the same level (NOT SUPPORTED YET)
2050 while (fCurrentNode && fCurrentNode->IsOffset())
2051 CdUp();
2052 return fCurrentNode;
2053 }
2054 // second, look if current volume is voxelized
2055 TGeoVoxelFinder *voxels = vol->GetVoxels();
2056 Int_t *check_list = nullptr;
2057 Int_t id;
2058 if (voxels) {
2059 // get the list of nodes passing thorough the current voxel
2060 check_list = voxels->GetCheckList(&point[0], ncheck, *fCache->GetInfo());
2061 // if none in voxel, see if this is the last one
2062 if (!check_list) {
2063 if (!fCurrentNode->GetVolume()->IsAssembly()) {
2065 return fCurrentNode;
2066 }
2067 // Point in assembly - go up
2068 node = fCurrentNode;
2069 if (!fLevel) {
2070 fIsOutside = kTRUE;
2072 return nullptr;
2073 }
2074 CdUp();
2076 return SearchNode(kFALSE, node);
2077 }
2078 // loop all nodes in voxel
2079 for (id = 0; id < ncheck; id++) {
2080 node = vol->GetNode(check_list[id]);
2081 if (node == skipnode)
2082 continue;
2083 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive())
2084 continue;
2085 if ((id < (ncheck - 1)) && node->IsOverlapping()) {
2086 // make the cluster of overlaps
2087 if (ncheck + fOverlapMark > fOverlapSize) {
2088 fOverlapSize = 2 * (ncheck + fOverlapMark);
2089 delete[] fOverlapClusters;
2091 }
2092 Int_t *cluster = fOverlapClusters + fOverlapMark;
2093 Int_t nc = GetTouchedCluster(id, &point[0], check_list, ncheck, cluster);
2094 if (nc > 1) {
2095 fOverlapMark += nc;
2096 node = FindInCluster(cluster, nc);
2097 fOverlapMark -= nc;
2099 return node;
2100 }
2101 }
2102 CdDown(check_list[id]);
2103 fForcedNode = nullptr;
2104 node = SearchNode(kTRUE);
2105 if (node) {
2108 return node;
2109 }
2110 CdUp();
2111 }
2112 if (!fCurrentNode->GetVolume()->IsAssembly()) {
2114 return fCurrentNode;
2115 }
2116 node = fCurrentNode;
2117 if (!fLevel) {
2118 fIsOutside = kTRUE;
2120 return nullptr;
2121 }
2122 CdUp();
2124 return SearchNode(kFALSE, node);
2125 }
2126 // if there are no voxels just loop all daughters
2127 for (id = 0; id < nd; id++) {
2128 node = fCurrentNode->GetDaughter(id);
2129 if (node == skipnode)
2130 continue;
2131 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive())
2132 continue;
2133 CdDown(id);
2134 fForcedNode = nullptr;
2135 node = SearchNode(kTRUE);
2136 if (node) {
2138 return node;
2139 }
2140 CdUp();
2141 }
2142 // point is not inside one of the daughters, so it is in the current vol
2143 if (fCurrentNode->GetVolume()->IsAssembly()) {
2144 node = fCurrentNode;
2145 if (!fLevel) {
2146 fIsOutside = kTRUE;
2147 return nullptr;
2148 }
2149 CdUp();
2150 return SearchNode(kFALSE, node);
2151 }
2152 return fCurrentNode;
2153}
2154
2155////////////////////////////////////////////////////////////////////////////////
2156/// Find a node inside a cluster of overlapping nodes. Current node must
2157/// be on top of all the nodes in cluster. Always nc>1.
2158
2160{
2161 TGeoNode *clnode = nullptr;
2162 TGeoNode *priority = fLastNode;
2163 // save current node
2164 TGeoNode *current = fCurrentNode;
2165 TGeoNode *found = nullptr;
2166 // save path
2167 Int_t ipop = PushPath();
2168 // mark this search
2170 Int_t deepest = fLevel;
2171 Int_t deepest_virtual = fLevel - GetVirtualLevel();
2172 Int_t found_virtual = 0;
2173 Bool_t replace = kFALSE;
2174 Bool_t added = kFALSE;
2175 Int_t i;
2176 for (i = 0; i < nc; i++) {
2177 clnode = current->GetDaughter(cluster[i]);
2178 CdDown(cluster[i]);
2179 Bool_t max_priority = (clnode == fNextNode) ? kTRUE : kFALSE;
2180 found = SearchNode(kTRUE, clnode);
2181 if (!fSearchOverlaps || max_priority) {
2182 // an only was found during the search -> exiting
2183 // The node given by FindNextBoundary returned -> exiting
2184 PopDummy(ipop);
2185 return found;
2186 }
2187 found_virtual = fLevel - GetVirtualLevel();
2188 if (added) {
2189 // we have put something in stack -> check it
2190 if (found_virtual > deepest_virtual) {
2191 replace = kTRUE;
2192 } else {
2193 if (found_virtual == deepest_virtual) {
2194 if (fLevel > deepest) {
2195 replace = kTRUE;
2196 } else {
2197 if ((fLevel == deepest) && (clnode == priority))
2198 replace = kTRUE;
2199 else
2200 replace = kFALSE;
2201 }
2202 } else
2203 replace = kFALSE;
2204 }
2205 // if this was the last checked node
2206 if (i == (nc - 1)) {
2207 if (replace) {
2208 PopDummy(ipop);
2209 return found;
2210 } else {
2212 PopDummy(ipop);
2213 return fCurrentNode;
2214 }
2215 }
2216 // we still have to go on
2217 if (replace) {
2218 // reset stack
2219 PopDummy();
2220 PushPath();
2221 deepest = fLevel;
2222 deepest_virtual = found_virtual;
2223 }
2224 // restore top of cluster
2226 } else {
2227 // the stack was clean, push new one
2228 PushPath();
2229 added = kTRUE;
2230 deepest = fLevel;
2231 deepest_virtual = found_virtual;
2232 // restore original path
2234 }
2235 }
2236 PopDummy(ipop);
2237 return fCurrentNode;
2238}
2239
2240////////////////////////////////////////////////////////////////////////////////
2241/// Make the cluster of overlapping nodes in a voxel, containing point in reference
2242/// of the mother. Returns number of nodes containing the point. Nodes should not be
2243/// offsets.
2244
2246{
2247 // we are in the mother reference system
2248 TGeoNode *current = fCurrentNode->GetDaughter(check_list[start]);
2249 Int_t novlps = 0;
2250 Int_t *ovlps = current->GetOverlaps(novlps);
2251 if (!ovlps)
2252 return 0;
2253 Double_t local[3];
2254 // intersect check list with overlap list
2255 Int_t ntotal = 0;
2256 current->MasterToLocal(point, &local[0]);
2257 if (current->GetVolume()->Contains(&local[0])) {
2258 result[ntotal++] = check_list[start];
2259 }
2260
2261 Int_t jst = 0, i, j;
2262 while ((jst < novlps) && (ovlps[jst] <= check_list[start]))
2263 jst++;
2264 if (jst == novlps)
2265 return 0;
2266 for (i = start; i < ncheck; i++) {
2267 for (j = jst; j < novlps; j++) {
2268 if (check_list[i] == ovlps[j]) {
2269 // overlapping node in voxel -> check if touched
2270 current = fCurrentNode->GetDaughter(check_list[i]);
2271 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive())
2272 continue;
2273 current->MasterToLocal(point, &local[0]);
2274 if (current->GetVolume()->Contains(&local[0])) {
2275 result[ntotal++] = check_list[i];
2276 }
2277 }
2278 }
2279 }
2280 return ntotal;
2281}
2282
2283////////////////////////////////////////////////////////////////////////////////
2284/// Make a rectiliniar step of length fStep from current point (fPoint) on current
2285/// direction (fDirection). If the step is imposed by geometry, is_geom flag
2286/// must be true (default). The cross flag specifies if the boundary should be
2287/// crossed in case of a geometry step (default true). Returns new node after step.
2288/// Set also on boundary condition.
2289
2291{
2292 Double_t epsil = 0;
2293 if (fStep < 1E-6) {
2295 if (fStep < 0)
2296 fStep = 0.;
2297 } else {
2299 }
2300 if (is_geom)
2301 epsil = (cross) ? 1E-6 : -1E-6;
2302 TGeoNode *old = fCurrentNode;
2303 Int_t idold = GetNodeId();
2304 if (fIsOutside)
2305 old = nullptr;
2306 fStep += epsil;
2307 for (Int_t i = 0; i < 3; i++)
2308 fPoint[i] += fStep * fDirection[i];
2309 TGeoNode *current = FindNode();
2310 if (is_geom) {
2311 fIsEntering = (current == old) ? kFALSE : kTRUE;
2312 if (!fIsEntering) {
2313 Int_t id = GetNodeId();
2314 fIsEntering = (id == idold) ? kFALSE : kTRUE;
2315 }
2317 if (fIsEntering && fIsNullStep)
2320 } else {
2323 }
2324 return current;
2325}
2326
2327////////////////////////////////////////////////////////////////////////////////
2328/// Find level of virtuality of current overlapping node (number of levels
2329/// up having the same tracking media.
2330
2332{
2333 // return if the current node is ONLY
2335 return 0;
2336 Int_t new_media = 0;
2337 TGeoMedium *medium = fCurrentNode->GetMedium();
2338 Int_t virtual_level = 1;
2339 TGeoNode *mother = nullptr;
2340
2341 while ((mother = GetMother(virtual_level))) {
2342 if (!mother->IsOverlapping() && !mother->IsOffset()) {
2343 if (!new_media)
2344 new_media = (mother->GetMedium() == medium) ? 0 : virtual_level;
2345 break;
2346 }
2347 if (!new_media)
2348 new_media = (mother->GetMedium() == medium) ? 0 : virtual_level;
2349 virtual_level++;
2350 }
2351 return (new_media == 0) ? virtual_level : (new_media - 1);
2352}
2353
2354////////////////////////////////////////////////////////////////////////////////
2355/// Go upwards the tree until a non-overlapping node
2356
2358{
2359 while (fCurrentOverlapping && fLevel)
2360 CdUp();
2361 Double_t point[3];
2363 if (!fCurrentNode->GetVolume()->Contains(point))
2364 return kFALSE;
2365 if (fNmany) {
2366 // We still have overlaps on the branch
2367 Int_t up = 1;
2368 Int_t imother;
2369 Int_t nmany = fNmany;
2370 Bool_t ovlp = kFALSE;
2371 Bool_t nextovlp = kFALSE;
2372 TGeoNode *mother, *mup;
2373 TGeoHMatrix *matrix;
2374 while (nmany) {
2375 mother = GetMother(up);
2376 if (!mother)
2377 return kTRUE;
2378 mup = mother;
2379 imother = up + 1;
2380 while (mup->IsOffset())
2381 mup = GetMother(imother++);
2382 nextovlp = mup->IsOverlapping();
2383 if (ovlp)
2384 nmany--;
2385 if (ovlp || nextovlp) {
2386 // check if the point is in the next node up
2387 matrix = GetMotherMatrix(up);
2388 matrix->MasterToLocal(fPoint, point);
2389 if (!mother->GetVolume()->Contains(point)) {
2390 up++;
2391 while (up--)
2392 CdUp();
2393 return GotoSafeLevel();
2394 }
2395 }
2396 ovlp = nextovlp;
2397 up++;
2398 }
2399 }
2400 return kTRUE;
2401}
2402
2403////////////////////////////////////////////////////////////////////////////////
2404/// Go upwards the tree until a non-overlapping node
2405
2407{
2408 Bool_t overlapping = fCurrentOverlapping;
2409 if (!overlapping)
2410 return fLevel;
2411 Int_t level = fLevel;
2412 TGeoNode *node;
2413 while (overlapping && level) {
2414 level--;
2415 node = GetMother(fLevel - level);
2416 if (!node->IsOffset())
2417 overlapping = node->IsOverlapping();
2418 }
2419 return level;
2420}
2421
2422////////////////////////////////////////////////////////////////////////////////
2423/// Inspects path and all flags for the current state.
2424
2426{
2427 Info("InspectState", "Current path is: %s", GetPath());
2428 Int_t level;
2429 TGeoNode *node;
2430 Bool_t is_offset, is_overlapping;
2431 for (level = 0; level < fLevel + 1; level++) {
2432 node = GetMother(fLevel - level);
2433 if (!node)
2434 continue;
2435 is_offset = node->IsOffset();
2436 is_overlapping = node->IsOverlapping();
2437 Info("InspectState", "level %i: %s div=%i many=%i", level, node->GetName(), is_offset, is_overlapping);
2438 }
2439 Info("InspectState", "on_bound=%i entering=%i", fIsOnBoundary, fIsEntering);
2440}
2441
2442////////////////////////////////////////////////////////////////////////////////
2443/// Checks if point (x,y,z) is still in the current node.
2444/// check if this is an overlapping node
2445
2447{
2448 Double_t oldpt[3];
2449 if (fLastSafety > 0) {
2450 Double_t dx = (x - fLastPoint[0]);
2451 Double_t dy = (y - fLastPoint[1]);
2452 Double_t dz = (z - fLastPoint[2]);
2453 Double_t dsq = dx * dx + dy * dy + dz * dz;
2454 if (dsq < fLastSafety * fLastSafety) {
2455 if (change) {
2456 fPoint[0] = x;
2457 fPoint[1] = y;
2458 fPoint[2] = z;
2459 memcpy(fLastPoint, fPoint, 3 * sizeof(Double_t));
2460 fLastSafety -= TMath::Sqrt(dsq);
2461 }
2462 return kTRUE;
2463 }
2464 if (change)
2465 fLastSafety = 0;
2466 }
2467 if (fCurrentOverlapping) {
2468 // TGeoNode *current = fCurrentNode;
2469 Int_t cid = GetCurrentNodeId();
2470 if (!change)
2471 PushPoint();
2472 memcpy(oldpt, fPoint, kN3);
2473 SetCurrentPoint(x, y, z);
2474 SearchNode();
2475 memcpy(fPoint, oldpt, kN3);
2476 Bool_t same = (cid == GetCurrentNodeId()) ? kTRUE : kFALSE;
2477 if (!change)
2478 PopPoint();
2479 return same;
2480 }
2481
2482 Double_t point[3];
2483 point[0] = x;
2484 point[1] = y;
2485 point[2] = z;
2486 if (change)
2487 memcpy(fPoint, point, kN3);
2489 if (fIsOutside) {
2490 if (vol->GetShape()->Contains(point)) {
2491 if (!change)
2492 return kFALSE;
2493 FindNode(x, y, z);
2494 return kFALSE;
2495 }
2496 return kTRUE;
2497 }
2498 Double_t local[3];
2499 // convert to local frame
2500 fGlobalMatrix->MasterToLocal(point, local);
2501 // check if still in current volume.
2502 if (!vol->GetShape()->Contains(local)) {
2503 if (!change)
2504 return kFALSE;
2505 CdUp();
2506 FindNode(x, y, z);
2507 return kFALSE;
2508 }
2509
2510 // Check if the point is in a parallel world volume
2513 if (pnode) {
2514 if (!change)
2515 return kFALSE;
2516 pnode->cd();
2518 while (crtindex >= 0) {
2519 // Make sure we did not end up in an assembly.
2520 CdDown(crtindex);
2522 }
2523 return kFALSE;
2524 }
2525 }
2526 // check if there are daughters
2527 Int_t nd = vol->GetNdaughters();
2528 if (!nd)
2529 return kTRUE;
2530
2531 TGeoNode *node;
2532 TGeoPatternFinder *finder = vol->GetFinder();
2533 if (finder) {
2534 node = finder->FindNode(local);
2535 if (node) {
2536 if (!change)
2537 return kFALSE;
2538 CdDown(node->GetIndex());
2539 SearchNode(kTRUE, node);
2540 return kFALSE;
2541 }
2542 return kTRUE;
2543 }
2544 // if we are not allowed to do changes, save the current path
2545 TGeoVoxelFinder *voxels = vol->GetVoxels();
2546 Int_t *check_list = nullptr;
2547 Int_t ncheck = 0;
2548 Double_t local1[3];
2549 if (voxels) {
2550 check_list = voxels->GetCheckList(local, ncheck, *fCache->GetInfo());
2551 if (!check_list) {
2553 return kTRUE;
2554 }
2555 if (!change)
2556 PushPath();
2557 for (Int_t id = 0; id < ncheck; id++) {
2558 // node = vol->GetNode(check_list[id]);
2559 CdDown(check_list[id]);
2560 fGlobalMatrix->MasterToLocal(point, local1);
2561 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2562 if (!change) {
2563 PopPath();
2565 return kFALSE;
2566 }
2569 return kFALSE;
2570 }
2571 CdUp();
2572 }
2573 if (!change)
2574 PopPath();
2576 return kTRUE;
2577 }
2578 Int_t id = 0;
2579 if (!change)
2580 PushPath();
2581 while (fCurrentNode && fCurrentNode->GetDaughter(id++)) {
2582 CdDown(id - 1);
2583 fGlobalMatrix->MasterToLocal(point, local1);
2584 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2585 if (!change) {
2586 PopPath();
2587 return kFALSE;
2588 }
2590 return kFALSE;
2591 }
2592 CdUp();
2593 if (id == nd) {
2594 if (!change)
2595 PopPath();
2596 return kTRUE;
2597 }
2598 }
2599 if (!change)
2600 PopPath();
2601 return kTRUE;
2602}
2603
2604////////////////////////////////////////////////////////////////////////////////
2605/// In case a previous safety value was computed, check if the safety region is
2606/// still safe for the current point and proposed step. Return value changed only
2607/// if proposed distance is safe.
2608
2610{
2611 // Last safety not computed.
2612 if (fLastSafety < gTolerance)
2613 return kFALSE;
2614 // Proposed step too small
2615 if (proposed < gTolerance) {
2616 newsafety = fLastSafety - proposed;
2617 return kTRUE;
2618 }
2619 // Normal step
2620 Double_t dist = (fPoint[0] - fLastPoint[0]) * (fPoint[0] - fLastPoint[0]) +
2621 (fPoint[1] - fLastPoint[1]) * (fPoint[1] - fLastPoint[1]) +
2622 (fPoint[2] - fLastPoint[2]) * (fPoint[2] - fLastPoint[2]);
2623 dist = TMath::Sqrt(dist);
2624 Double_t safe = fLastSafety - dist;
2625 if (safe < proposed)
2626 return kFALSE;
2627 newsafety = safe;
2628 return kTRUE;
2629}
2630
2631////////////////////////////////////////////////////////////////////////////////
2632/// Check if a new point with given coordinates is the same as the last located one.
2633
2635{
2636 if (TMath::Abs(x - fLastPoint[0]) < 1.E-20) {
2637 if (TMath::Abs(y - fLastPoint[1]) < 1.E-20) {
2638 if (TMath::Abs(z - fLastPoint[2]) < 1.E-20)
2639 return kTRUE;
2640 }
2641 }
2642 return kFALSE;
2643}
2644
2645////////////////////////////////////////////////////////////////////////////////
2646/// Backup the current state without affecting the cache stack.
2647
2649{
2650 if (fBackupState)
2652}
2653
2654////////////////////////////////////////////////////////////////////////////////
2655/// Restore a backed-up state without affecting the cache stack.
2656
2658{
2659 if (fBackupState && fCache) {
2663 fLevel = fCache->GetLevel();
2664 }
2665}
2666
2667////////////////////////////////////////////////////////////////////////////////
2668/// Return stored current matrix (global matrix of the next touched node).
2669
2671{
2672 if (!fCurrentMatrix) {
2675 }
2676 return fCurrentMatrix;
2677}
2678
2679////////////////////////////////////////////////////////////////////////////////
2680/// Get path to the current node in the form /node0/node1/...
2681
2682const char *TGeoNavigator::GetPath() const
2683{
2684 if (fIsOutside)
2685 return kGeoOutsidePath;
2686 return fCache->GetPath();
2687}
2688
2689////////////////////////////////////////////////////////////////////////////////
2690/// Convert coordinates from master volume frame to top.
2691
2692void TGeoNavigator::MasterToTop(const Double_t *master, Double_t *top) const
2693{
2694 fCurrentMatrix->MasterToLocal(master, top);
2695}
2696
2697////////////////////////////////////////////////////////////////////////////////
2698/// Convert coordinates from top volume frame to master.
2699
2700void TGeoNavigator::TopToMaster(const Double_t *top, Double_t *master) const
2701{
2702 fCurrentMatrix->LocalToMaster(top, master);
2703}
2704
2705////////////////////////////////////////////////////////////////////////////////
2706/// Reset the navigator.
2707
2709{
2710 GetHMatrix();
2713 ResetState();
2714 fStep = 0.;
2715 fSafety = 0.;
2716 fLastSafety = 0.;
2717 fLevel = 0;
2718 fNmany = 0;
2719 fNextDaughterIndex = -2;
2726 fLastNode = nullptr;
2727 fNextNode = nullptr;
2728 fPath = "";
2729 if (fCache) {
2730 Bool_t dummy = fCache->IsDummy();
2731 Bool_t nodeid = fCache->HasIdArray();
2732 delete fCache;
2733 fCache = nullptr;
2734 delete fBackupState;
2735 fBackupState = nullptr;
2736 BuildCache(dummy, nodeid);
2737 }
2738}
2739
2741
2742////////////////////////////////////////////////////////////////////////////////
2743/// Add a new navigator to the array.
2744
2746{
2747 SetOwner(kTRUE);
2749 nav->BuildCache(kTRUE, kFALSE);
2750 Add(nav);
2752 return nav;
2753}
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
#define ClassImp(name)
Definition Rtypes.h:382
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
char name[80]
Definition TGX11.cxx:110
const Int_t kN3
R__EXTERN TGeoIdentity * gGeoIdentity
Definition TGeoMatrix.h:537
const Int_t kN3
const char * kGeoOutsidePath
static Double_t gTolerance
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Class storing the state of the cache at a given moment.
Definition TGeoCache.h:28
void SetState(Int_t level, Int_t startlevel, Int_t nmany, Bool_t ovlp, Double_t *point=nullptr)
Fill current modeller state.
Matrix class used for computing global transformations Should NOT be used for node definition.
Definition TGeoMatrix.h:458
void CopyFrom(const TGeoMatrix *other)
Fast copy method.
const Double_t * GetTranslation() const override
Definition TGeoMatrix.h:527
void Multiply(const TGeoMatrix *right)
multiply to the right with an other transformation if right is identity matrix, just return
The manager class for any TGeo geometry.
Definition TGeoManager.h:44
TGeoNode * GetCurrentNode() const
TGeoParallelWorld * GetParallelWorld() const
Int_t GetMaxLevel() const
Bool_t IsParallelWorldNav() const
Bool_t IsActivityEnabled() const
TGeoNode * GetTopNode() const
static Int_t GetVerboseLevel()
Set verbosity level (static function).
void MasterToLocal(const Double_t *master, Double_t *local) const
TGeoVolume * GetTopVolume() const
static Int_t ThreadId()
Translates the current thread id to an ordinal number.
virtual void LocalToMasterVect(const Double_t *local, Double_t *master) const
convert a vector by multiplying its column vector (x, y, z, 1) to matrix inverse
virtual void MasterToLocal(const Double_t *master, Double_t *local) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix
virtual void MasterToLocalVect(const Double_t *master, Double_t *local) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix
virtual void RegisterYourself()
Register the matrix in the current manager, which will become the owner.
virtual void LocalToMaster(const Double_t *local, Double_t *master) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
Media are used to store properties related to tracking and which are useful only when using geometry ...
Definition TGeoMedium.h:23
TGeoNavigator * AddNavigator()
Add a new navigator to the array.
TGeoManager * fGeoManager
TGeoNavigator * SetCurrentNavigator(Int_t inav)
Class providing navigation API for TGeo geometries.
void CdUp()
Go one level up in geometry.
void DoBackupState()
Backup the current state without affecting the cache stack.
TGeoNode * GetMother(Int_t up=1) const
Double_t fLastPWSaftyPnt[3]
last point for which safety was computed
void DoRestoreState()
Restore a backed-up state without affecting the cache stack.
Double_t fPoint[3]
unit vector to current checked shape
Bool_t fSearchOverlaps
internal array for overlaps
Bool_t fIsExiting
flag if current step just got into a new node
TString fPath
current local matrix of the selected division cell
TGeoHMatrix * fDivMatrix
current pointer to cached global matrix
TGeoNode * CrossBoundaryAndLocate(Bool_t downwards, TGeoNode *skipnode)
Cross next boundary and locate within current node The current point must be on the boundary of fCurr...
Double_t fLastPWSafety
last point for which parallel world safety was "evaluated"
TGeoHMatrix * GetHMatrix()
Return stored current matrix (global matrix of the next touched node).
TGeoNodeCache * fCache
current geometry
Bool_t fStartSafe
flags the type of the current node
void CdNext()
Do a cd to the node found next by FindNextBoundary.
Double_t Safety(Bool_t inside=kFALSE)
Compute safe distance from the current point.
Bool_t GotoSafeLevel()
Go upwards the tree until a non-overlapping node.
Double_t fNormal[3]
last computed safety radius
Bool_t cd(const char *path="")
Browse the tree of nodes starting from top node according to pathname.
Double_t fLastPoint[3]
current direction
Bool_t IsSameLocation() const
Double_t fCldir[3]
cosine of incident angle on current checked surface
Bool_t fIsStepEntering
flag that current track is about to leave current node
Int_t GetNodeId() const
Int_t GetVirtualLevel()
Find level of virtuality of current overlapping node (number of levels up having the same tracking me...
Bool_t PopPoint()
Int_t fOverlapSize
next daughter index after FindNextBoundary
TGeoNode * InitTrack(const Double_t *point, const Double_t *dir)
Initialize current point and current direction vector (normalized) in MARS.
void InspectState() const
Inspects path and all flags for the current state.
Int_t PushPoint(Int_t startlevel=0)
TGeoNode * Step(Bool_t is_geom=kTRUE, Bool_t cross=kTRUE)
Make a rectiliniar step of length fStep from current point (fPoint) on current direction (fDirection)...
TGeoNode * FindInCluster(Int_t *cluster, Int_t nc)
Find a node inside a cluster of overlapping nodes.
void SafetyOverlaps()
Compute safe distance from the current point within an overlapping node.
TGeoNode * CrossDivisionCell()
Cross a division cell.
void ResetState()
Reset current state flags.
static Bool_t IsPWSafetyCaching()
TGeoNode * FindNextDaughterBoundary(Double_t *point, Double_t *dir, Int_t &idaughter, Bool_t compmatrix=kFALSE)
Computes as fStep the distance to next daughter of the current volume.
Bool_t fIsSameLocation
flag that current point is on some boundary
void GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
Fill node copy numbers of current branch into an array.
Bool_t CheckPath(const char *path) const
Check if a geometry path is valid without changing the state of the navigator.
TGeoHMatrix * GetMotherMatrix(Int_t up=1) const
TGeoVolume * fCurrentVolume
cache of states
TGeoNode * fLastNode
top physical node
Int_t fThreadId
last safety returned from parallel world (negative if invalid)
Double_t GetPWSafetyEstimateFromCache(Double_t cpoint[3]) const
Double_t fDirection[3]
current point
void PopDummy(Int_t ipop=9999)
Int_t GetTouchedCluster(Int_t start, Double_t *point, Int_t *check_list, Int_t ncheck, Int_t *result)
Make the cluster of overlapping nodes in a voxel, containing point in reference of the mother.
TGeoNode * FindNextBoundary(Double_t stepmax=TGeoShape::Big(), const char *path="", Bool_t frombdr=kFALSE)
Find distance to next boundary and store it in fStep.
TGeoNode * FindNode(Bool_t safe_start=kTRUE)
Returns deepest node containing current point.
Int_t fOverlapMark
current size of fOverlapClusters
TGeoNode * FindNextBoundaryAndStep(Double_t stepmax=TGeoShape::Big(), Bool_t compsafe=kFALSE)
Compute distance to next boundary within STEPMAX.
void CdTop()
Make top level node the current node.
Int_t fNmany
current geometry level;
TGeoManager * fGeometry
flag that last geometric step was null
TGeoHMatrix * fGlobalMatrix
current stored global matrix
void MasterToTop(const Double_t *master, Double_t *top) const
Convert coordinates from master volume frame to top.
Int_t GetCurrentNodeId() const
Double_t * FindNormalFast()
Computes fast normal to next crossed boundary, assuming that the current point is close enough to the...
Int_t PushPath(Int_t startlevel=0)
Bool_t fIsStepExiting
flag that next geometric step will enter new volume
Bool_t fIsOnBoundary
flag that current point is outside geometry
static Bool_t fgUsePWSafetyCaching
path to current node
void GetBranchOnlys(Int_t *isonly) const
Fill node copy numbers of current branch into an array.
void TopToMaster(const Double_t *top, Double_t *master) const
Convert coordinates from top volume frame to master.
void SetCurrentPoint(const Double_t *point)
TGeoHMatrix * fCurrentMatrix
backup state
Int_t * fOverlapClusters
current recursive position in fOverlapClusters
Bool_t IsSafeStep(Double_t proposed, Double_t &newsafety) const
In case a previous safety value was computed, check if the safety region is still safe for the curren...
TGeoNode * SearchNode(Bool_t downwards=kFALSE, const TGeoNode *skipnode=nullptr)
Returns the deepest node containing fPoint, which must be set a priori.
Double_t fLastSafety
safety radius from current point
~TGeoNavigator() override
Destructor.
TGeoNavigator()
global mode is caching enabled for parallel world safety calls
void SetCurrentDirection(const Double_t *dir)
void BuildCache(Bool_t dummy=kFALSE, Bool_t nodeid=kFALSE)
Builds the cache for physical nodes and global matrices.
Int_t fNextDaughterIndex
number of overlapping nodes on current branch
Bool_t fIsNullStep
flag that a new point is in the same node as previous
void CdNode(Int_t nodeid)
Change current path to point to the node having this id.
TGeoNode * fNextNode
last searched node
Double_t fCldirChecked[3]
unit vector to current closest shape
Int_t fLevel
thread id for this navigator
Double_t GetPWSafety(Double_t cpoint[3], Double_t saf_max)
Wrapper for getting the safety from the parallel world.
void ResetAll()
Reset the navigator.
TGeoCacheState * fBackupState
current point is supposed to be inside this node
Bool_t IsSamePoint(Double_t x, Double_t y, Double_t z) const
Check if a new point with given coordinates is the same as the last located one.
Bool_t fCurrentOverlapping
flag set when an overlapping cluster is searched
Bool_t fIsOutside
flag that next geometric step will exit current volume
void CdDown(Int_t index)
Make a daughter of current node current.
Bool_t fIsEntering
flag a safe start for point classification
TGeoNode * fForcedNode
next node that will be crossed
const char * GetPath() const
Get path to the current node in the form /node0/node1/...
Int_t GetSafeLevel() const
Go upwards the tree until a non-overlapping node.
TGeoNode * fCurrentNode
current volume
Double_t fSafety
step to be done from current point and direction
Double_t * FindNormal(Bool_t forward=kTRUE)
Computes normal vector to the next surface that will be or was already crossed when propagating on a ...
void GetBranchNames(Int_t *names) const
Fill volume names of current branch into an array.
Special pool of reusable nodes.
Definition TGeoCache.h:56
Bool_t IsDummy() const
Definition TGeoCache.h:126
TGeoNode * GetNode() const
Definition TGeoCache.h:116
void CdNode(Int_t nodeid)
Change current path to point to the node having this id.
void CdTop()
Definition TGeoCache.h:92
void GetBranchOnlys(Int_t *isonly) const
Fill copy numbers of current branch nodes.
const char * GetPath()
Returns the current geometry path.
void GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
Fill copy numbers of current branch nodes.
TGeoStateInfo * GetInfo()
Get next state info pointer.
Bool_t HasIdArray() const
Definition TGeoCache.h:125
Bool_t CdDown(Int_t index)
Make daughter INDEX of current node the active state. Compute global matrix.
Bool_t RestoreState(Int_t &nmany, TGeoCacheState *state, Double_t *point=nullptr)
Pop next state/point from a backed-up state.
void CdUp()
Make mother of current node the active state.
void GetBranchNames(Int_t *names) const
Fill names with current branch volume names (4 char - used by GEANT3 interface).
TGeoHMatrix * GetCurrentMatrix() const
Definition TGeoCache.h:109
void ReleaseInfo()
Release last used state info pointer.
Int_t GetLevel() const
Definition TGeoCache.h:121
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition TGeoNode.h:39
TGeoMedium * GetMedium() const
Definition TGeoNode.h:89
Bool_t IsOverlapping() const
Definition TGeoNode.h:107
TGeoVolume * GetVolume() const
Definition TGeoNode.h:99
Bool_t IsOffset() const
Definition TGeoNode.h:105
Int_t GetNdaughters() const
Definition TGeoNode.h:91
TGeoNode * GetDaughter(Int_t ind) const
Definition TGeoNode.h:83
virtual TGeoMatrix * GetMatrix() const =0
virtual void cd() const
Definition TGeoNode.h:71
Int_t * GetOverlaps(Int_t &novlp) const
Definition TGeoNode.h:94
virtual void MasterToLocal(const Double_t *master, Double_t *local) const
Convert the point coordinates from mother reference to local reference system.
Definition TGeoNode.cxx:568
virtual Int_t GetIndex() const
Definition TGeoNode.h:87
virtual TGeoPatternFinder * GetFinder() const
Definition TGeoNode.h:88
virtual void MasterToLocalVect(const Double_t *master, Double_t *local) const
Convert a vector from mother reference to local reference system.
Definition TGeoNode.cxx:576
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
computes the closest distance from given point to this shape
Definition TGeoNode.cxx:684
Double_t Safety(Double_t point[3], Double_t safmax=1.E30)
TGeoPhysicalNode * FindNextBoundary(Double_t point[3], Double_t dir[3], Double_t &step, Double_t stepmax=1.E30)
TGeoPhysicalNode * FindNode(Double_t point[3])
Base finder class for patterns.
virtual TGeoNode * CdNext()
Make next node (if any) current.
virtual TGeoNode * FindNode(Double_t *, const Double_t *=nullptr)
virtual Bool_t IsOnBoundary(const Double_t *) const
Int_t GetNdiv() const
Int_t GetNext() const
Get index of next division.
Physical nodes are the actual 'touchable' objects in the geometry, representing a path of positioned ...
TGeoNode * GetNode(Int_t level=-1) const
Return node in branch at LEVEL. If not specified, return last leaf.
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)=0
static Double_t Big()
Definition TGeoShape.h:87
virtual Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const =0
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const =0
virtual Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const =0
virtual Bool_t Contains(const Double_t *point) const =0
static Double_t Tolerance()
Definition TGeoShape.h:90
Volume assemblies.
Definition TGeoVolume.h:316
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:43
virtual Int_t GetNextNodeIndex() const
Definition TGeoVolume.h:168
Bool_t IsActiveDaughters() const
Definition TGeoVolume.h:146
Bool_t Contains(const Double_t *point) const
Definition TGeoVolume.h:104
Int_t GetNdaughters() const
Definition TGeoVolume.h:362
TObjArray * GetNodes()
Definition TGeoVolume.h:169
void FindOverlaps() const
loop all nodes marked as overlaps and find overlapping brothers
TGeoNode * GetNode(const char *name) const
get the pointer to a daughter node
Int_t GetIndex(const TGeoNode *node) const
get index number for a given daughter
TGeoPatternFinder * GetFinder() const
Definition TGeoVolume.h:177
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
TGeoShape * GetShape() const
Definition TGeoVolume.h:190
virtual Int_t GetCurrentNodeIndex() const
Definition TGeoVolume.h:167
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.
Bool_t IsActive() const
Definition TGeoVolume.h:145
void InspectShape() const
Definition TGeoVolume.h:195
Finder class handling voxels.
Double_t * GetBoxes() const
virtual Int_t * GetCheckList(const Double_t *point, Int_t &nelem, TGeoStateInfo &td)
get the list of daughter indices for which point is inside their bbox
virtual Int_t * GetNextVoxel(const Double_t *point, const Double_t *dir, Int_t &ncheck, TGeoStateInfo &td)
get the list of new candidates for the next voxel crossed by current ray printf("### GetNextVoxel\n")...
virtual void Voxelize(Option_t *option="")
Voxelize attached volume according to option If the volume is an assembly, make sure the bbox is comp...
Bool_t IsSafeVoxel(const Double_t *point, Int_t inode, Double_t minsafe) const
Computes squared distance from POINT to the voxel(s) containing node INODE.
Bool_t NeedRebuild() const
virtual void SortCrossedVoxels(const Double_t *point, const Double_t *dir, TGeoStateInfo &td)
get the list in the next voxel crossed by a ray
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
void Add(TObject *obj) override
Definition TObjArray.h:68
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1005
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1033
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:979
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:666
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
Statefull info for the current geometry level.