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
52////////////////////////////////////////////////////////////////////////////////
53/// Constructor
54
56 :fStep(0.),
57 fSafety(0.),
58 fLastSafety(0.),
59 fThreadId(0),
60 fLevel(0),
61 fNmany(0),
62 fNextDaughterIndex(0),
63 fOverlapSize(0),
64 fOverlapMark(0),
65 fOverlapClusters(0),
66 fSearchOverlaps(kFALSE),
67 fCurrentOverlapping(kFALSE),
68 fStartSafe(kFALSE),
69 fIsEntering(kFALSE),
70 fIsExiting(kFALSE),
71 fIsStepEntering(kFALSE),
72 fIsStepExiting(kFALSE),
73 fIsOutside(kFALSE),
74 fIsOnBoundary(kFALSE),
75 fIsSameLocation(kFALSE),
76 fIsNullStep(kFALSE),
77 fGeometry(0),
78 fCache(0),
79 fCurrentVolume(0),
80 fCurrentNode(0),
81 fTopNode(0),
82 fLastNode(0),
83 fNextNode(0),
84 fForcedNode(0),
85 fBackupState(0),
86 fCurrentMatrix(0),
87 fGlobalMatrix(0),
88 fDivMatrix(0),
89 fPath()
90
91{
92// dummy constructor
93 for (Int_t i=0; i<3; i++) {
94 fNormal[i] = 0.;
95 fCldir[i] = 0.;
96 fCldirChecked[i] = 0.;
97 fPoint[i] = 0.;
98 fDirection[i] = 0.;
99 fLastPoint[i] = 0.;
100 }
101}
102
103////////////////////////////////////////////////////////////////////////////////
104/// Constructor
105
107 :fStep(0.),
108 fSafety(0.),
109 fLastSafety(0.),
110 fThreadId(0),
111 fLevel(0),
112 fNmany(0),
113 fNextDaughterIndex(-2),
114 fOverlapSize(1000),
115 fOverlapMark(0),
116 fOverlapClusters(0),
117 fSearchOverlaps(kFALSE),
118 fCurrentOverlapping(kFALSE),
119 fStartSafe(kTRUE),
120 fIsEntering(kFALSE),
121 fIsExiting(kFALSE),
122 fIsStepEntering(kFALSE),
123 fIsStepExiting(kFALSE),
124 fIsOutside(kFALSE),
125 fIsOnBoundary(kFALSE),
126 fIsSameLocation(kTRUE),
127 fIsNullStep(kFALSE),
128 fGeometry(geom),
129 fCache(0),
130 fCurrentVolume(0),
131 fCurrentNode(0),
132 fTopNode(0),
133 fLastNode(0),
134 fNextNode(0),
135 fForcedNode(0),
136 fBackupState(0),
137 fCurrentMatrix(0),
138 fGlobalMatrix(0),
139 fDivMatrix(0),
140 fPath()
141
142{
143// Default constructor.
145 // printf("Navigator: threadId=%d\n", fThreadId);
146 for (Int_t i=0; i<3; i++) {
147 fNormal[i] = 0.;
148 fCldir[i] = 0.;
149 fCldirChecked[i] = 0;
150 fPoint[i] = 0.;
151 fDirection[i] = 0.;
152 fLastPoint[i] = 0.;
153 }
156 fDivMatrix = new TGeoHMatrix();
159 ResetAll();
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// Destructor.
164
166{
167 if (fCache) delete fCache;
168 if (fBackupState) delete fBackupState;
169 if (fOverlapClusters) delete [] fOverlapClusters;
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// Builds the cache for physical nodes and global matrices.
174
176{
177 static Bool_t first = kTRUE;
179 Int_t nlevel = fGeometry->GetMaxLevel();
180 if (nlevel<=0) nlevel = 100;
181 if (!fCache) {
182 if (nlevel==100) {
183 if (first && verbose>0) Info("BuildCache","--- Maximum geometry depth set to 100");
184 } else {
185 if (first && verbose>0) Info("BuildCache","--- Maximum geometry depth is %i", nlevel);
186 }
187 // build cache
188 fCache = new TGeoNodeCache(fGeometry->GetTopNode(), nodeid, nlevel+1);
190 fBackupState = new TGeoCacheState(nlevel+1);
191 }
192 first = kFALSE;
193}
194
195////////////////////////////////////////////////////////////////////////////////
196/// Browse the tree of nodes starting from top node according to pathname.
197/// Changes the path accordingly. The path is changed to point to the top node
198/// in case of failure.
199
200Bool_t TGeoNavigator::cd(const char *path)
201{
202 CdTop();
203 if (!path[0]) return kTRUE;
204 TString spath = path;
205 TGeoVolume *vol;
206 Int_t length = spath.Length();
207 Int_t ind1 = spath.Index("/");
208 if (ind1 == length-1) ind1 = -1;
209 Int_t ind2 = 0;
210 Bool_t end = kFALSE;
213 TGeoNode *node;
214 while (!end) {
215 ind2 = spath.Index("/", ind1+1);
216 if (ind2<0 || ind2==length-1) {
217 if (ind2<0) ind2 = length;
218 end = kTRUE;
219 }
220 name = spath(ind1+1, ind2-ind1-1);
221 vol = fCurrentNode->GetVolume();
222 if (first) {
223 first = kFALSE;
224 if (name.BeginsWith(vol->GetName())) {
225 ind1 = ind2;
226 continue;
227 }
228 }
229 node = vol->GetNode(name.Data());
230 if (!node) {
231 Error("cd", "Path %s not valid", path);
232 return kFALSE;
233 }
234 CdDown(vol->GetIndex(node));
235 ind1 = ind2;
236 }
237 return kTRUE;
238}
239
240////////////////////////////////////////////////////////////////////////////////
241/// Check if a geometry path is valid without changing the state of the navigator.
242
243Bool_t TGeoNavigator::CheckPath(const char *path) const
244{
245 if (!path[0]) return kTRUE;
246 TGeoNode *crtnode = fGeometry->GetTopNode();
247 TString spath = path;
248 TGeoVolume *vol;
249 Int_t length = spath.Length();
250 Int_t ind1 = spath.Index("/");
251 if (ind1 == length-1) ind1 = -1;
252 Int_t ind2 = 0;
253 Bool_t end = kFALSE;
256 TGeoNode *node;
257 while (!end) {
258 ind2 = spath.Index("/", ind1+1);
259 if (ind2<0 || ind2==length-1) {
260 if (ind2<0) ind2 = length;
261 end = kTRUE;
262 }
263 name = spath(ind1+1, ind2-ind1-1);
264 vol = crtnode->GetVolume();
265 if (first) {
266 first = kFALSE;
267 if (name.BeginsWith(vol->GetName())) {
268 ind1 = ind2;
269 continue;
270 }
271 }
272 node = vol->GetNode(name.Data());
273 if (!node) return kFALSE;
274 crtnode = node;
275 ind1 = ind2;
276 }
277 return kTRUE;
278}
279
280////////////////////////////////////////////////////////////////////////////////
281/// Change current path to point to the node having this id.
282/// Node id has to be in range : 0 to fNNodes-1 (no check for performance reasons)
283
285{
286 if (fCache) {
287 fCache->CdNode(nodeid);
289 }
290}
291
292////////////////////////////////////////////////////////////////////////////////
293/// Make a daughter of current node current. Can be called only with a valid
294/// daughter index (no check). Updates cache accordingly.
295
297{
299 Bool_t is_offset = node->IsOffset();
300 if (is_offset)
301 node->cd();
302 else
305 fCurrentNode = node;
308 fLevel++;
309}
310
311////////////////////////////////////////////////////////////////////////////////
312/// Make a daughter of current node current. Can be called only with a valid
313/// daughter node (no check). Updates cache accordingly.
314
316{
317 Bool_t is_offset = node->IsOffset();
318 if (is_offset)
319 node->cd();
320 else
322 fCache->CdDown(node);
323 fCurrentNode = node;
326 fLevel++;
327}
328
329////////////////////////////////////////////////////////////////////////////////
330/// Go one level up in geometry. Updates cache accordingly.
331/// Determine the overlapping state of current node.
332
334{
335 if (!fLevel || !fCache) return;
336 fLevel--;
337 if (!fLevel) {
338 CdTop();
339 return;
340 }
341 fCache->CdUp();
344 fNmany--;
345 }
348 if (!fCurrentNode->IsOffset()) {
350 } else {
351 Int_t up = 1;
353 TGeoNode *mother = 0;
354 while (offset) {
355 mother = GetMother(up++);
356 offset = mother->IsOffset();
357 }
359 }
360}
361
362////////////////////////////////////////////////////////////////////////////////
363/// Make top level node the current node. Updates the cache accordingly.
364/// Determine the overlapping state of current node.
365
367{
368 if (!fCache) return;
369 fLevel = 0;
370 fNmany = 0;
373 fCache->CdTop();
377}
378
379////////////////////////////////////////////////////////////////////////////////
380/// Do a cd to the node found next by FindNextBoundary
381
383{
384 if (fNextDaughterIndex == -2 || !fCache) return;
385 if (fNextDaughterIndex == -3) {
386 // Next node is a many - restore it
389 return;
390 }
391 if (fNextDaughterIndex == -1) {
392 CdUp();
393 while (fCurrentNode->GetVolume()->IsAssembly()) CdUp();
395 return;
396 }
397 if (fCurrentNode && fNextDaughterIndex<fCurrentNode->GetNdaughters()) {
400 while (nextindex>=0) {
401 CdDown(nextindex);
402 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
403 }
404 }
406}
407
408////////////////////////////////////////////////////////////////////////////////
409/// Fill volume names of current branch into an array.
410
412{
413 fCache->GetBranchNames(names);
414}
415
416////////////////////////////////////////////////////////////////////////////////
417/// Fill node copy numbers of current branch into an array.
418
419void TGeoNavigator::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
420{
421 fCache->GetBranchNumbers(copyNumbers, volumeNumbers);
422}
423
424////////////////////////////////////////////////////////////////////////////////
425/// Fill node copy numbers of current branch into an array.
426
428{
429 fCache->GetBranchOnlys(isonly);
430}
431
432////////////////////////////////////////////////////////////////////////////////
433/// Cross a division cell. Distance to exit contained in fStep, current node
434/// points to the cell node.
435
437{
439 if (!finder) {
440 Fatal("CrossDivisionCell", "Volume has no pattern finder");
441 return 0;
442 }
443 // Mark current node and go up to the level of the divided volume
444 TGeoNode *skip = fCurrentNode;
445 CdUp();
446 Double_t point[3], newpoint[3], dir[3];
449 // Does step cross a boundary along division axis ?
450 Bool_t onbound = finder->IsOnBoundary(newpoint);
451 if (onbound) {
452 // Work along division axis
453 // Get the starting point
454 point[0] = newpoint[0] - dir[0]*fStep*(1.-gTolerance);
455 point[1] = newpoint[1] - dir[1]*fStep*(1.-gTolerance);
456 point[2] = newpoint[2] - dir[2]*fStep*(1.-gTolerance);
457 // Find which is the next crossed cell.
458 finder->FindNode(point, dir);
459 Int_t inext = finder->GetNext();
460 if (inext<0) {
461 // step fully exits the division along the division axis
462 // Do step exits in a mother cell ?
463 if (fCurrentNode->IsOffset()) {
464 Double_t dist = fCurrentNode->GetVolume()->GetShape()->DistFromInside(point,dir,3);
465 // Do step exit also from mother cell ?
466 if (dist < fStep+2.*gTolerance) {
467 // Step exits mother on its own division axis
468 return CrossDivisionCell();
469 }
470 // We end up here
471 return fCurrentNode;
472 }
473 // Exiting in a non-divided volume
474 while (fCurrentNode->GetVolume()->IsAssembly()) {
475 // Move always to mother for assemblies
476 skip = fCurrentNode;
477 if (!fLevel) break;
478 CdUp();
479 }
480 return CrossBoundaryAndLocate(kFALSE, skip);
481 }
482 // step enters a new cell
483 CdDown(inext+finder->GetDivIndex());
484 skip = fCurrentNode;
485 return CrossBoundaryAndLocate(kTRUE, skip);
486 }
487 // step exits on an axis other than the division axis -> get next slice
488 if (fCurrentNode->IsOffset()) return CrossDivisionCell();
489 return CrossBoundaryAndLocate(kFALSE, skip);
490}
491
492////////////////////////////////////////////////////////////////////////////////
493/// Cross next boundary and locate within current node
494/// The current point must be on the boundary of fCurrentNode.
495
497{
498// Extrapolate current point with estimated error.
500 Double_t trmax = 1.+TMath::Abs(tr[0])+TMath::Abs(tr[1])+TMath::Abs(tr[2]);
501 Double_t extra = 100.*(trmax+fStep)*gTolerance;
502 const Int_t idebug = TGeoManager::GetVerboseLevel();
503 TGeoNode *crtstate[10];
504 Int_t level = fLevel+1;
505 Bool_t samepath = kFALSE;
506 for (Int_t i=0; i<10; ++i)
507 crtstate[i] = nullptr;
508
509 if (!downwards) {
510 for (Int_t i=0; i<fLevel; ++i) {
511 crtstate[i] = GetMother(i);
512 if (i==9) break;
513 }
514 }
515 fPoint[0] += extra*fDirection[0];
516 fPoint[1] += extra*fDirection[1];
517 fPoint[2] += extra*fDirection[2];
518 TGeoNode *current = SearchNode(downwards, skipnode);
519 fForcedNode = 0;
520 fPoint[0] -= extra*fDirection[0];
521 fPoint[1] -= extra*fDirection[1];
522 fPoint[2] -= extra*fDirection[2];
523 if (!current) return 0;
524 if (downwards) {
525 Int_t nextindex = current->GetVolume()->GetNextNodeIndex();
526 while (nextindex>=0) {
527 CdDown(nextindex);
528 current = fCurrentNode;
529 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
530 }
531 if (idebug>4) {
532 printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
533 }
534 return current;
535 }
536
537 if (skipnode) {
538 if (current == skipnode) {
539 samepath = kTRUE;
540 if (!downwards) {
541 level = TMath::Min(level, 10);
542 for (Int_t i=1; i<level; i++) {
543 if (crtstate[i-1] != GetMother(i)) {
544 samepath = kFALSE;
545 break;
546 }
547 }
548 }
549 }
550 }
551
552 if (samepath || current->GetVolume()->IsAssembly()) {
553 if (!fLevel) {
555 if (idebug>4) {
556 printf("CrossBoundaryAndLocate: Exited geometry\n");
557 }
558 return fGeometry->GetCurrentNode();
559 }
560 CdUp();
561 while (fLevel && fCurrentNode->GetVolume()->IsAssembly()) CdUp();
562 if (!fLevel && fCurrentNode->GetVolume()->IsAssembly()) {
564 if (idebug>4) {
565 printf("CrossBoundaryAndLocate: Exited geometry\n");
566 }
567 if (idebug>4) {
568 printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
569 }
570 return fCurrentNode;
571 }
572 return fCurrentNode;
573 }
574 if (idebug>4) {
575 printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
576 }
577 return current;
578}
579
580////////////////////////////////////////////////////////////////////////////////
581/// Find distance to next boundary and store it in fStep. Returns node to which this
582/// boundary belongs. If PATH is specified, compute only distance to the node to which
583/// PATH points. If STEPMAX is specified, compute distance only in case fSafety is smaller
584/// than this value. STEPMAX represent the step to be made imposed by other reasons than
585/// geometry (usually physics processes). Therefore in this case this method provides the
586/// answer to the question : "Is STEPMAX a safe step ?" returning a NULL node and filling
587/// fStep with a big number.
588/// In case frombdr=kTRUE, the isotropic safety is set to zero.
589///
590/// Note : safety distance for the current point is computed ONLY in case STEPMAX is
591/// specified, otherwise users have to call explicitly TGeoManager::Safety() if
592/// they want this computed for the current point.
593
594TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax, const char *path, Bool_t frombdr)
595{
596 // convert current point and direction to local reference
597 Int_t iact = 3;
603 fForcedNode = 0;
604 Bool_t computeGlobal = kFALSE;
605 fIsOnBoundary = frombdr;
606 fSafety = 0.;
607 TGeoNode *top_node = fGeometry->GetTopNode();
608 TGeoVolume *top_volume = top_node->GetVolume();
609 // If inside an assembly, go logically up in the hierarchy
610 while (fCurrentNode->GetVolume()->IsAssembly() && fLevel) CdUp();
611 if (stepmax<1E29) {
612 if (stepmax <= 0) {
613 stepmax = - stepmax;
614 computeGlobal = kTRUE;
615 }
616// if (fLastSafety>0 && IsSamePoint(fPoint[0], fPoint[1], fPoint[2])) fSafety = fLastSafety;
617 fSafety = Safety();
618 // Try to get out easy if proposed step within safe region
619 if (!frombdr && (fSafety>0) && IsSafeStep(stepmax+gTolerance, fSafety)) {
620 fStep = stepmax;
622 return fCurrentNode;
623 }
625 memcpy(fLastPoint, fPoint, kN3);
628 else fIsOnBoundary = kFALSE;
629 fStep = stepmax;
630 if (stepmax+gTolerance<fSafety) {
632 return fCurrentNode;
633 }
634 }
635 if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
637 Double_t safe;
638 Double_t point[3];
639 Double_t dir[3];
640 if (idebug>4) {
641 printf("TGeoManager::FindNextBoundary: point=(%19.16f, %19.16f, %19.16f)\n",
642 fPoint[0],fPoint[1],fPoint[2]);
643 printf(" dir= (%19.16f, %19.16f, %19.16f)\n",
644 fDirection[0], fDirection[1], fDirection[2]);
645 printf(" pstep=%9.6g path=%s\n", stepmax, GetPath());
646 }
647 if (path[0]) {
648 PushPath();
649 if (!cd(path)) {
650 PopPath();
651 return 0;
652 }
653 if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
658 if (idebug>4) {
659 printf("=== To path: %s\n", path);
660 printf("=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
661 tvol->GetName(), point[0],point[1],point[2],dir[0],dir[1],dir[2]);
662 }
663 if (tvol->Contains(point)) {
664 if (idebug>4) printf("=== volume %s contains point\n", tvol->GetName());
665 fStep=tvol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
666 } else {
667 fStep=tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, fStep, &safe);
668 if (idebug>4) {
669 printf("=== volume %s does not contain point\n", tvol->GetName());
670 printf("=== distance to path: %g\n", fStep);
671 tvol->InspectShape();
672 if (fStep<1.E20) {
673 Double_t newpt[3];
674 newpt[0] = point[0] + fStep*dir[0];
675 newpt[1] = point[1] + fStep*dir[1];
676 newpt[2] = point[2] + fStep*dir[2];
677 printf("=== Propagated point: (%19.16f, %19.16f, %19.16f)", newpt[0],newpt[1],newpt[2]);
678 }
679 while (fLevel) {
680 CdUp();
681 tvol = fCurrentNode->GetVolume();
684 printf("=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
685 tvol->GetName(), point[0],point[1],point[2],dir[0],dir[1],dir[2]);
686 if (tvol->Contains(point)) {
687 printf("=== volume %s contains point\n", tvol->GetName());
688 } else {
689 printf("=== volume %s does not contain point\n", tvol->GetName());
690 snext = tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, 1.E30, &safe);
691 }
692 }
693 }
694 }
695 PopPath();
696 return fNextNode;
697 }
698 // compute distance to exit point from current node and the distance to its
699 // closest boundary
700 // if point is outside, just check the top node
701 if (fIsOutside) {
702 snext = top_volume->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep, &safe);
703 fNextNode = top_node;
704 if (snext < fStep-gTolerance) {
706 fStep = snext;
708 fNextDaughterIndex = indnext;
709 while (indnext>=0) {
710 fNextNode = fNextNode->GetDaughter(indnext);
711 if (computeGlobal) fCurrentMatrix->Multiply(fNextNode->GetMatrix());
712 indnext = fNextNode->GetVolume()->GetNextNodeIndex();
713 }
714 return fNextNode;
715 }
716 return 0;
717 }
721 if (idebug>4) {
722 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
723 point[0],point[1],point[2]);
724 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
725 dir[0],dir[1],dir[2]);
726 }
727 // find distance to exiting current node
728 snext = vol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
729 if (idebug>4) {
730 printf(" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
731 }
732 if (snext < fStep-gTolerance) {
736 fStep = snext;
738 if (fStep<1E-6) return fCurrentNode;
739 }
740 fNextNode = (fStep<1E20)?fCurrentNode:0;
741 // Find next daughter boundary for the current volume
742 Int_t idaughter = -1;
743 FindNextDaughterBoundary(point,dir,idaughter,computeGlobal);
744 if (idaughter>=0) fNextDaughterIndex = idaughter;
745 TGeoNode *current = 0;
746 TGeoNode *dnode = 0;
747 TGeoVolume *mother = 0;
748 // if we are in an overlapping node, check also the mother(s)
749 if (fNmany) {
750 Double_t mothpt[3];
751 Double_t vecpt[3];
752 Double_t dpt[3], dvec[3];
753 Int_t novlps;
754 Int_t idovlp = -1;
755 Int_t safelevel = GetSafeLevel();
756 PushPath(safelevel+1);
757 while (fCurrentOverlapping) {
758 Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
759 CdUp();
760 mother = fCurrentNode->GetVolume();
761 fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
763 // check distance to out
765 if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(&mothpt[0], &vecpt[0], iact, fStep, &safe);
766 if (snext<fStep-gTolerance) {
769 fStep = snext;
770 if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
774 }
775 // check overlapping nodes
776 for (Int_t i=0; i<novlps; i++) {
777 current = mother->GetNode(ovlps[i]);
778 if (!current->IsOverlapping()) {
779 current->cd();
780 current->MasterToLocal(&mothpt[0], &dpt[0]);
781 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
782 // Current point may be inside the other node - geometry error that we ignore
783 snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
784 if (snext<fStep-gTolerance) {
785 if (computeGlobal) {
787 fCurrentMatrix->Multiply(current->GetMatrix());
788 }
791 fStep = snext;
792 fNextNode = current;
794 CdDown(ovlps[i]);
796 CdUp();
797 }
798 } else {
799 // another many - check if point is in or out
800 current->cd();
801 current->MasterToLocal(&mothpt[0], &dpt[0]);
802 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
803 if (current->GetVolume()->Contains(dpt)) {
804 if (current->GetVolume()->GetNdaughters()) {
805 CdDown(ovlps[i]);
808 dnode = FindNextDaughterBoundary(dpt,dvec,idovlp,computeGlobal);
809 if (dnode) {
810 if (computeGlobal) {
813 }
814 fNextNode = dnode;
816 CdDown(idovlp);
818 Int_t iup=0;
819 while (indnext>=0) {
820 CdDown(indnext);
821 iup++;
823 }
825 while (iup>0) {
826 CdUp();
827 iup--;
828 }
829 CdUp();
830 }
831 CdUp();
832 }
833 } else {
834 snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
835 if (snext<fStep-gTolerance) {
836 if (computeGlobal) {
838 fCurrentMatrix->Multiply(current->GetMatrix());
839 }
842 fStep = snext;
843 fNextNode = current;
845 CdDown(ovlps[i]);
847 CdUp();
848 }
849 }
850 }
851 }
852 }
853 // Now we are in a non-overlapping node
854 if (fNmany) {
855 // We have overlaps up in the branch, check distance to exit
856 Int_t up = 1;
857 Int_t imother;
858 Int_t nmany = fNmany;
859 Bool_t ovlp = kFALSE;
860 Bool_t nextovlp = kFALSE;
862 TGeoNode *currentnode = fCurrentNode;
863 TGeoNode *mothernode, *mup;
864 TGeoHMatrix *matrix;
865 while (nmany) {
866 mothernode = GetMother(up);
867 if (!mothernode) {
868 Fatal("FindNextBoundary", "Cannot find mother node");
869 return 0;
870 }
871 mup = mothernode;
872 imother = up+1;
873 offset = kFALSE;
874 while (mup->IsOffset()) {
875 mup = GetMother(imother++);
876 offset = kTRUE;
877 }
878 nextovlp = mup->IsOverlapping();
879 if (offset) {
880 mothernode = mup;
881 if (nextovlp) nmany -= imother-up;
882 up = imother-1;
883 } else {
884 if (ovlp) nmany--;
885 }
886 if (ovlp || nextovlp) {
887 matrix = GetMotherMatrix(up);
888 if (!matrix) {
889 Fatal("FindNextBoundary", "Cannot find mother matrix");
890 return 0;
891 }
892 matrix->MasterToLocal(fPoint,dpt);
893 matrix->MasterToLocalVect(fDirection,dvec);
895 if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
896 if (snext<fStep-gTolerance) {
899 fStep = snext;
900 fNextNode = mothernode;
902 if (computeGlobal) fCurrentMatrix->CopyFrom(matrix);
903 while (up--) CdUp();
905 up = 1;
906 currentnode = fCurrentNode;
907 ovlp = currentnode->IsOverlapping();
908 continue;
909 }
910 }
911 currentnode = mothernode;
912 ovlp = nextovlp;
913 up++;
914 }
915 }
916 PopPath();
917 }
918 // Compute now the distance in case we have a parallel world
919 Double_t parstep = TGeoShape::Big();
921// printf("path: %s next node %s at %g\n", GetPath(), fNextNode->GetName(), fStep);
923 if (pnode) {
924 // A boundary is hit at less than fPStep
925 fStep = parstep;
926 fNextNode = pnode->GetNode();
927 fNextDaughterIndex = -2; // No way to store it for CdNext
930 Int_t nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
931 while (nextindex>=0) {
932 fNextNode = fNextNode->GetDaughter(nextindex);
933 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
934 }
935 }
936 }
937 return fNextNode;
938}
939
940////////////////////////////////////////////////////////////////////////////////
941/// Computes as fStep the distance to next daughter of the current volume.
942/// The point and direction must be converted in the coordinate system of the current volume.
943/// The proposed step limit is fStep.
944
946{
949 idaughter = -1; // nothing crossed
950 TGeoNode *nodefound = 0;
951 // Get number of daughters. If no daughters we are done.
952
954 Int_t nd = vol->GetNdaughters();
955 if (!nd) return 0; // No daughter
956 if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters()) return 0;
957 Double_t lpoint[3], ldir[3];
958 TGeoNode *current = 0;
959 Int_t i=0;
960 // if current volume is divided, we are in the non-divided region. We
961 // check first if we are inside a cell in which case compute distance to next cell
962 TGeoPatternFinder *finder = vol->GetFinder();
963 if (finder) {
964 Int_t ifirst = finder->GetDivIndex();
965 Int_t ilast = ifirst+finder->GetNdiv()-1;
966 current = finder->FindNode(point);
967 if (current) {
968 // Point inside a cell: find distance to next cell
969 Int_t index = current->GetIndex();
970 if ((index-1) >= ifirst) ifirst = index-1;
971 else ifirst = -1;
972 if ((index+1) <= ilast) ilast = index+1;
973 else ilast = -1;
974 }
975 if (ifirst>=0) {
976 current = vol->GetNode(ifirst);
977 current->cd();
978 current->MasterToLocal(&point[0], lpoint);
979 current->MasterToLocalVect(&dir[0], ldir);
980 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
981 if (snext<fStep-gTolerance) {
982 if (compmatrix) {
984 fCurrentMatrix->Multiply(current->GetMatrix());
985 }
988 fStep=snext;
989 fNextNode = current;
990 nodefound = current;
991 idaughter = ifirst;
992 }
993 }
994 if (ilast==ifirst) return nodefound;
995 if (ilast>=0) {
996 current = vol->GetNode(ilast);
997 current->cd();
998 current->MasterToLocal(&point[0], lpoint);
999 current->MasterToLocalVect(&dir[0], ldir);
1000 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1001 if (snext<fStep-gTolerance) {
1002 if (compmatrix) {
1004 fCurrentMatrix->Multiply(current->GetMatrix());
1005 }
1008 fStep=snext;
1009 fNextNode = current;
1010 nodefound = current;
1011 idaughter = ilast;
1012 }
1013 }
1014 return nodefound;
1015 }
1016 // if only few daughters, check all and exit
1017 TGeoVoxelFinder *voxels = vol->GetVoxels();
1018 Int_t indnext;
1019 if (idebug>4) printf(" Checking distance to %d daughters...\n",nd);
1020 if (nd<5 || !voxels) {
1021 for (i=0; i<nd; i++) {
1022 current = vol->GetNode(i);
1023 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
1024 current->cd();
1025 if (voxels && voxels->IsSafeVoxel(point, i, fStep)) continue;
1026 current->MasterToLocal(point, lpoint);
1027 current->MasterToLocalVect(dir, ldir);
1028 if (current->IsOverlapping() &&
1029 current->GetVolume()->Contains(lpoint) &&
1030 current->GetVolume()->GetShape()->Safety(lpoint, kTRUE) > gTolerance) continue;
1031 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1032 if (snext<fStep-gTolerance) {
1033 if (idebug>4) {
1034 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1035 lpoint[0],lpoint[1],lpoint[2]);
1036 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
1037 ldir[0],ldir[1],ldir[2]);
1038 printf(" -> to: %s shape %s snext=%g\n", current->GetName(),
1039 current->GetVolume()->GetShape()->ClassName(), snext);
1040 }
1041 indnext = current->GetVolume()->GetNextNodeIndex();
1042 if (compmatrix) {
1044 fCurrentMatrix->Multiply(current->GetMatrix());
1045 }
1048 fStep=snext;
1049 fNextNode = current;
1050 nodefound = fNextNode;
1051 idaughter = i;
1052 while (indnext>=0) {
1053 current = current->GetDaughter(indnext);
1054 if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
1055 fNextNode = current;
1056 nodefound = current;
1057 indnext = current->GetVolume()->GetNextNodeIndex();
1058 }
1059 }
1060 }
1061 if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
1062 return nodefound;
1063 }
1064 // if current volume is voxelized, first get current voxel
1065 Int_t ncheck = 0;
1066 Int_t sumchecked = 0;
1067 Int_t *vlist = 0;
1068 TGeoStateInfo &info = *fCache->GetInfo();
1069 voxels->SortCrossedVoxels(point, dir, info);
1070 while ((sumchecked<nd) && (vlist=voxels->GetNextVoxel(point, dir, ncheck, info))) {
1071 for (i=0; i<ncheck; i++) {
1072 current = vol->GetNode(vlist[i]);
1073 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
1074 current->cd();
1075 current->MasterToLocal(point, lpoint);
1076 current->MasterToLocalVect(dir, ldir);
1077 if (current->IsOverlapping() && current->GetVolume()->Contains(lpoint) &&
1078 current->GetVolume()->GetShape()->Safety(lpoint, kTRUE) > gTolerance) continue;
1079 snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1080 sumchecked++;
1081// printf("checked %d from %d : snext=%g\n", sumchecked, nd, snext);
1082 if (snext<fStep-gTolerance) {
1083 if (idebug>4) {
1084 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1085 lpoint[0],lpoint[1],lpoint[2]);
1086 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
1087 ldir[0],ldir[1],ldir[2]);
1088 printf(" -> to: %s shape %s snext=%g\n", current->GetName(),
1089 current->GetVolume()->GetShape()->ClassName(), snext);
1090 }
1091 indnext = current->GetVolume()->GetNextNodeIndex();
1092 if (compmatrix) {
1094 fCurrentMatrix->Multiply(current->GetMatrix());
1095 }
1098 fStep=snext;
1099 fNextNode = current;
1100 nodefound = fNextNode;
1101 idaughter = vlist[i];
1102 while (indnext>=0) {
1103 current = current->GetDaughter(indnext);
1104 if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
1105 fNextNode = current;
1106 nodefound = current;
1107 indnext = current->GetVolume()->GetNextNodeIndex();
1108 }
1109 }
1110 }
1111 }
1113 if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
1114 return nodefound;
1115}
1116
1117////////////////////////////////////////////////////////////////////////////////
1118/// Compute distance to next boundary within STEPMAX. If no boundary is found,
1119/// propagate current point along current direction with fStep=STEPMAX. Otherwise
1120/// propagate with fStep=SNEXT (distance to boundary) and locate/return the next
1121/// node.
1122
1124{
1125 Int_t iact = 3;
1127 Int_t nextindex;
1128 Bool_t is_assembly;
1129 fForcedNode = 0;
1131 TGeoNode *skip;
1133 fStep = stepmax;
1135 // If inside an assembly, go logically up in the hierarchy
1136 while (fCurrentNode->GetVolume()->IsAssembly() && fLevel) CdUp();
1137 if (compsafe) {
1138 // Try to get out easy if proposed step within safe region
1140 if (IsSafeStep(stepmax+gTolerance, fSafety)) {
1141 fPoint[0] += stepmax*fDirection[0];
1142 fPoint[1] += stepmax*fDirection[1];
1143 fPoint[2] += stepmax*fDirection[2];
1144 return fCurrentNode;
1145 }
1146 Safety();
1148 memcpy(fLastPoint, fPoint, kN3);
1149 // If proposed step less than safety, nothing to check
1150 if (fSafety > stepmax+gTolerance) {
1151 fPoint[0] += stepmax*fDirection[0];
1152 fPoint[1] += stepmax*fDirection[1];
1153 fPoint[2] += stepmax*fDirection[2];
1154 return fCurrentNode;
1155 }
1156 }
1157 Double_t extra = (fIsOnBoundary)?gTolerance:0.0;
1159 fPoint[0] += extra*fDirection[0];
1160 fPoint[1] += extra*fDirection[1];
1161 fPoint[2] += extra*fDirection[2];
1163 if (idebug>4) {
1164 printf("TGeoManager::FindNextBAndStep: point=(%19.16f, %19.16f, %19.16f)\n",
1165 fPoint[0],fPoint[1],fPoint[2]);
1166 printf(" dir= (%19.16f, %19.16f, %19.16f)\n",
1167 fDirection[0], fDirection[1], fDirection[2]);
1168 printf(" pstep=%9.6g path=%s\n", stepmax, GetPath());
1169 }
1170
1171 if (fIsOutside) {
1173 if (snext < fStep-gTolerance) {
1174 if (snext<=0) {
1175 snext = 0.0;
1176 fStep = snext;
1177 fPoint[0] -= extra*fDirection[0];
1178 fPoint[1] -= extra*fDirection[1];
1179 fPoint[2] -= extra*fDirection[2];
1180 } else {
1181 fStep = snext+extra;
1182 }
1185 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1186 while (nextindex>=0) {
1187 CdDown(nextindex);
1189 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1190 if (nextindex<0) fCurrentMatrix->CopyFrom(fGlobalMatrix);
1191 }
1192 // Update global point
1193 fPoint[0] += snext*fDirection[0];
1194 fPoint[1] += snext*fDirection[1];
1195 fPoint[2] += snext*fDirection[2];
1200 }
1201 if (snext<TGeoShape::Big()) {
1202 // New point still outside, but the top node is reachable
1204 fPoint[0] += (fStep-extra)*fDirection[0];
1205 fPoint[1] += (fStep-extra)*fDirection[1];
1206 fPoint[2] += (fStep-extra)*fDirection[2];
1207 return fNextNode;
1208 }
1209 // top node not reachable from current point/direction
1210 fNextNode = 0;
1212 return 0;
1213 }
1214 Double_t point[3],dir[3];
1215 Int_t icrossed = -2;
1216 fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
1219 // find distance to exiting current node
1220 if (idebug>4) {
1221 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1222 point[0],point[1],point[2]);
1223 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
1224 dir[0],dir[1],dir[2]);
1225 }
1226 // find distance to exiting current node
1227 snext = vol->GetShape()->DistFromInside(point, dir, iact, fStep);
1228 if (idebug>4) {
1229 printf(" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
1230 }
1232 if (snext <= gTolerance) {
1233 // Current point on the boundary while track exiting
1234 snext = gTolerance;
1235 fStep = snext;
1239 skip = fCurrentNode;
1240 fPoint[0] += fStep*fDirection[0];
1241 fPoint[1] += fStep*fDirection[1];
1242 fPoint[2] += fStep*fDirection[2];
1243 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1244 if (!fLevel && !is_assembly) {
1245 fIsOutside = kTRUE;
1246 return 0;
1247 }
1248 if (fCurrentNode->IsOffset()) return CrossDivisionCell();
1249 if (fLevel) CdUp();
1250 else skip = 0;
1251 return CrossBoundaryAndLocate(kFALSE, skip);
1252 }
1253
1254 if (snext < fStep-gTolerance) {
1255 // Currently the minimum step chosen is the exiting one
1256 icrossed = -1;
1257 fStep = snext;
1260 }
1261 // Find next daughter boundary for the current volume
1262 Int_t idaughter = -1;
1263 TGeoNode *crossed = FindNextDaughterBoundary(point,dir, idaughter, kTRUE);
1264 if (crossed) {
1266 icrossed = idaughter;
1268 }
1269 TGeoNode *current = 0;
1270 TGeoNode *dnode = 0;
1271 TGeoVolume *mother = 0;
1272 // if we are in an overlapping node, check also the mother(s)
1273 if (fNmany) {
1274 Double_t mothpt[3];
1275 Double_t vecpt[3];
1276 Double_t dpt[3], dvec[3];
1277 Int_t novlps;
1278 Int_t safelevel = GetSafeLevel();
1279 PushPath(safelevel+1);
1280 while (fCurrentOverlapping) {
1281 Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
1282 CdUp();
1283 mother = fCurrentNode->GetVolume();
1284 fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
1286 // check distance to out
1288 if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(mothpt, vecpt, iact, fStep);
1289 if (snext<fStep-gTolerance) {
1290 // exiting mother first (extrusion)
1291 icrossed = -1;
1292 PopDummy();
1293 PushPath(safelevel+1);
1296 fStep = snext;
1299 }
1300 // check overlapping nodes
1301 for (Int_t i=0; i<novlps; i++) {
1302 current = mother->GetNode(ovlps[i]);
1303 if (!current->IsOverlapping()) {
1304 current->cd();
1305 current->MasterToLocal(&mothpt[0], &dpt[0]);
1306 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1307 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1308 if (snext<fStep-gTolerance) {
1309 PopDummy();
1310 PushPath(safelevel+1);
1312 fCurrentMatrix->Multiply(current->GetMatrix());
1315 icrossed = ovlps[i];
1316 fStep = snext;
1317 fNextNode = current;
1318 }
1319 } else {
1320 // another many - check if point is in or out
1321 current->cd();
1322 current->MasterToLocal(&mothpt[0], &dpt[0]);
1323 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1324 if (current->GetVolume()->Contains(dpt)) {
1325 if (current->GetVolume()->GetNdaughters()) {
1326 CdDown(ovlps[i]);
1327 dnode = FindNextDaughterBoundary(dpt,dvec,idaughter,kFALSE);
1328 if (dnode) {
1331 icrossed = idaughter;
1332 PopDummy();
1333 PushPath(safelevel+1);
1336 fNextNode = dnode;
1337 }
1338 CdUp();
1339 }
1340 } else {
1341 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1342 if (snext<fStep-gTolerance) {
1344 fCurrentMatrix->Multiply(current->GetMatrix());
1347 fStep = snext;
1348 fNextNode = current;
1349 icrossed = ovlps[i];
1350 PopDummy();
1351 PushPath(safelevel+1);
1352 }
1353 }
1354 }
1355 }
1356 }
1357 // Now we are in a non-overlapping node
1358 if (fNmany) {
1359 // We have overlaps up in the branch, check distance to exit
1360 Int_t up = 1;
1361 Int_t imother;
1362 Int_t nmany = fNmany;
1363 Bool_t ovlp = kFALSE;
1364 Bool_t nextovlp = kFALSE;
1366 TGeoNode *currentnode = fCurrentNode;
1367 TGeoNode *mothernode, *mup;
1368 TGeoHMatrix *matrix;
1369 while (nmany) {
1370 mothernode = GetMother(up);
1371 mup = mothernode;
1372 imother = up+1;
1373 offset = kFALSE;
1374 while (mup->IsOffset()) {
1375 mup = GetMother(imother++);
1376 offset = kTRUE;
1377 }
1378 nextovlp = mup->IsOverlapping();
1379 if (offset) {
1380 mothernode = mup;
1381 if (nextovlp) nmany -= imother-up;
1382 up = imother-1;
1383 } else {
1384 if (ovlp) nmany--;
1385 }
1386 if (ovlp || nextovlp) {
1387 matrix = GetMotherMatrix(up);
1388 matrix->MasterToLocal(fPoint,dpt);
1389 matrix->MasterToLocalVect(fDirection,dvec);
1391 if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
1394 if (snext<fStep-gTolerance) {
1395 fNextNode = mothernode;
1396 fCurrentMatrix->CopyFrom(matrix);
1397 fStep = snext;
1398 while (up--) CdUp();
1399 PopDummy();
1400 PushPath();
1401 icrossed = -1;
1402 up = 1;
1403 currentnode = fCurrentNode;
1404 ovlp = currentnode->IsOverlapping();
1405 continue;
1406 }
1407 }
1408 currentnode = mothernode;
1409 ovlp = nextovlp;
1410 up++;
1411 }
1412 }
1413 PopPath();
1414 }
1415 // Compute now the distance in case we have a parallel world
1416 Double_t parstep = TGeoShape::Big();
1417 TGeoPhysicalNode *pnode = 0;
1420 if (pnode) {
1421 // A boundary is hit at less than fPStep
1422 fStep = parstep;
1423 fPoint[0] += fStep*fDirection[0];
1424 fPoint[1] += fStep*fDirection[1];
1425 fPoint[2] += fStep*fDirection[2];
1426 fNextNode = pnode->GetNode();
1427// icrossed = -4; //
1430 cd(pnode->GetName());
1431 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1432 while (nextindex>=0) {
1433 current = fCurrentNode;
1434 CdDown(nextindex);
1435 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1436 }
1437 return fCurrentNode;
1438 }
1439 }
1440 fPoint[0] += fStep*fDirection[0];
1441 fPoint[1] += fStep*fDirection[1];
1442 fPoint[2] += fStep*fDirection[2];
1443 fStep += extra;
1444 if (icrossed == -2) {
1445 // Nothing crossed within stepmax -> propagate and return same location
1447 return fCurrentNode;
1448 }
1450 if (icrossed == -1) {
1451 // Exiting current node.
1452 skip = fCurrentNode;
1453 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1454 if (!fLevel && !is_assembly) {
1455 fIsOutside = kTRUE;
1456 return 0;
1457 }
1458 if (fCurrentNode->IsOffset()) return CrossDivisionCell();
1459 if (fLevel) CdUp();
1460 else skip = 0;
1461 return CrossBoundaryAndLocate(kFALSE, skip);
1462 }
1463
1464 CdDown(icrossed);
1465 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1466 while (nextindex>=0) {
1467 current = fCurrentNode;
1468 CdDown(nextindex);
1469 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1470 }
1472 return CrossBoundaryAndLocate(kTRUE, current);
1473}
1474
1475////////////////////////////////////////////////////////////////////////////////
1476/// Returns deepest node containing current point.
1477
1479{
1480 fSafety = 0;
1485 fStartSafe = safe_start;
1487 TGeoNode *last = fCurrentNode;
1488 TGeoNode *found = SearchNode();
1489 if (found != last) {
1491 } else {
1492 if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1493 }
1494 return found;
1495}
1496
1497////////////////////////////////////////////////////////////////////////////////
1498/// Returns deepest node containing current point.
1499
1501{
1502 fPoint[0] = x;
1503 fPoint[1] = y;
1504 fPoint[2] = z;
1505 fSafety = 0;
1510 fStartSafe = kTRUE;
1512 TGeoNode *last = fCurrentNode;
1513 TGeoNode *found = SearchNode();
1514 if (found != last) {
1516 } else {
1517 if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1518 }
1519 return found;
1520}
1521
1522////////////////////////////////////////////////////////////////////////////////
1523/// Computes fast normal to next crossed boundary, assuming that the current point
1524/// is close enough to the boundary. Works only after calling FindNextBoundary.
1525
1527{
1528 if (!fNextNode) return 0;
1529 Double_t local[3];
1530 Double_t ldir[3];
1531 Double_t lnorm[3];
1534 fNextNode->GetVolume()->GetShape()->ComputeNormal(local, ldir,lnorm);
1536 return fNormal;
1537}
1538
1539////////////////////////////////////////////////////////////////////////////////
1540/// Computes normal vector to the next surface that will be or was already
1541/// crossed when propagating on a straight line from a given point/direction.
1542/// Returns the normal vector cosines in the MASTER coordinate system. The dot
1543/// product of the normal and the current direction is positive defined.
1544
1546{
1547 return FindNormalFast();
1548}
1549
1550////////////////////////////////////////////////////////////////////////////////
1551/// Initialize current point and current direction vector (normalized)
1552/// in MARS. Return corresponding node.
1553
1555{
1556 SetCurrentPoint(point);
1558 return FindNode();
1559}
1560
1561////////////////////////////////////////////////////////////////////////////////
1562/// Initialize current point and current direction vector (normalized)
1563/// in MARS. Return corresponding node.
1564
1566{
1567 SetCurrentPoint(x,y,z);
1568 SetCurrentDirection(nx,ny,nz);
1569 return FindNode();
1570}
1571
1572////////////////////////////////////////////////////////////////////////////////
1573/// Reset current state flags.
1574
1576{
1582}
1583
1584////////////////////////////////////////////////////////////////////////////////
1585/// Compute safe distance from the current point. This represent the distance
1586/// from POINT to the closest boundary.
1587
1589{
1590 if (fIsOnBoundary) {
1591 fSafety = 0;
1592 return fSafety;
1593 }
1594 Double_t point[3];
1595 Double_t safpar = TGeoShape::Big();
1596 if (!inside) fSafety = TGeoShape::Big();
1597 // Check if parallel navigation is enabled
1600 }
1601
1602 if (fIsOutside) {
1604 if (fSafety < gTolerance) {
1605 fSafety = 0;
1607 return fSafety;
1608 }
1609 return TMath::Min(fSafety,safpar);
1610 }
1611 //---> convert point to local reference frame of current node
1613
1614 //---> compute safety to current node
1616 if (!inside) {
1617 fSafety = vol->GetShape()->Safety(point, kTRUE);
1618 //---> if we were just entering, return this safety
1619 if (fSafety < gTolerance) {
1620 fSafety = 0;
1622 return fSafety;
1623 }
1624 }
1625
1626 //---> Check against the parallel geometry safety
1627 if (safpar < fSafety) fSafety = safpar;
1628
1629 //---> if we were just exiting, return this safety
1630 TObjArray *nodes = vol->GetNodes();
1632 if (!nd && !fCurrentOverlapping) return fSafety;
1633 TGeoNode *node;
1634 Double_t safe;
1635 Int_t id;
1636
1637 // if current volume is divided, we are in the non-divided region. We
1638 // check only the first and the last cell
1639 TGeoPatternFinder *finder = vol->GetFinder();
1640 if (finder) {
1641 Int_t ifirst = finder->GetDivIndex();
1642 node = (TGeoNode*)nodes->UncheckedAt(ifirst);
1643 node->cd();
1644 safe = node->Safety(point, kFALSE);
1645 if (safe < gTolerance) {
1646 fSafety=0;
1648 return fSafety;
1649 }
1650 if (safe<fSafety) fSafety=safe;
1651 Int_t ilast = ifirst+finder->GetNdiv()-1;
1652 if (ilast==ifirst) return fSafety;
1653 node = (TGeoNode*)nodes->UncheckedAt(ilast);
1654 node->cd();
1655 safe = node->Safety(point, kFALSE);
1656 if (safe < gTolerance) {
1657 fSafety=0;
1659 return fSafety;
1660 }
1661 if (safe<fSafety) fSafety=safe;
1662 if (fCurrentOverlapping && !inside) SafetyOverlaps();
1663 return fSafety;
1664 }
1665
1666 //---> If no voxels just loop daughters
1667 TGeoVoxelFinder *voxels = vol->GetVoxels();
1668 if (!voxels) {
1669 for (id=0; id<nd; id++) {
1670 node = (TGeoNode*)nodes->UncheckedAt(id);
1671 safe = node->Safety(point, kFALSE);
1672 if (safe < gTolerance) {
1673 fSafety=0;
1675 return fSafety;
1676 }
1677 if (safe<fSafety) fSafety=safe;
1678 }
1679 if (fNmany && !inside) SafetyOverlaps();
1680 return fSafety;
1681 } else {
1682 if (voxels->NeedRebuild()) {
1683 voxels->Voxelize();
1684 vol->FindOverlaps();
1685 }
1686 }
1687
1688 //---> check fast unsafe voxels
1689 Double_t *boxes = voxels->GetBoxes();
1690 for (id=0; id<nd; id++) {
1691 Int_t ist = 6*id;
1692 Double_t dxyz = 0.;
1693 Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
1694 if (dxyz0 > fSafety) continue;
1695 Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
1696 if (dxyz1 > fSafety) continue;
1697 Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
1698 if (dxyz2 > fSafety) continue;
1699 if (dxyz0>0) dxyz+=dxyz0*dxyz0;
1700 if (dxyz1>0) dxyz+=dxyz1*dxyz1;
1701 if (dxyz2>0) dxyz+=dxyz2*dxyz2;
1702 if (dxyz >= fSafety*fSafety) continue;
1703 node = (TGeoNode*)nodes->UncheckedAt(id);
1704 safe = node->Safety(point, kFALSE);
1705 if (safe<gTolerance) {
1706 fSafety=0;
1708 return fSafety;
1709 }
1710 if (safe<fSafety) fSafety = safe;
1711 }
1712 if (fNmany && !inside) SafetyOverlaps();
1713 return fSafety;
1714}
1715
1716////////////////////////////////////////////////////////////////////////////////
1717/// Compute safe distance from the current point within an overlapping node
1718
1720{
1721 Double_t point[3], local[3];
1722 Double_t safe;
1723 Bool_t contains;
1724 TGeoNode *nodeovlp;
1725 TGeoVolume *vol;
1726 Int_t novlp, io;
1727 Int_t *ovlp;
1728 Int_t safelevel = GetSafeLevel();
1729 PushPath(safelevel+1);
1730 while (fCurrentOverlapping) {
1731 ovlp = fCurrentNode->GetOverlaps(novlp);
1732 CdUp();
1733 vol = fCurrentNode->GetVolume();
1735 contains = fCurrentNode->GetVolume()->Contains(point);
1736 safe = fCurrentNode->GetVolume()->GetShape()->Safety(point, contains);
1737 if (safe<fSafety && safe>=0) fSafety=safe;
1738 if (!novlp || !contains) continue;
1739 // we are now in the container, check safety to all candidates
1740 for (io=0; io<novlp; io++) {
1741 nodeovlp = vol->GetNode(ovlp[io]);
1742 nodeovlp->GetMatrix()->MasterToLocal(point,local);
1743 contains = nodeovlp->GetVolume()->Contains(local);
1744 if (contains) {
1745 CdDown(ovlp[io]);
1746 safe = Safety(kTRUE);
1747 CdUp();
1748 } else {
1749 safe = nodeovlp->GetVolume()->GetShape()->Safety(local, kFALSE);
1750 }
1751 if (safe<fSafety && safe>=0) fSafety=safe;
1752 }
1753 }
1754 if (fNmany) {
1755 // We have overlaps up in the branch, check distance to exit
1756 Int_t up = 1;
1757 Int_t imother;
1758 Int_t nmany = fNmany;
1759 Bool_t crtovlp = kFALSE;
1760 Bool_t nextovlp = kFALSE;
1761 TGeoNode *mother, *mup;
1762 TGeoHMatrix *matrix;
1763 while (nmany) {
1764 mother = GetMother(up);
1765 mup = mother;
1766 imother = up+1;
1767 while (mup->IsOffset()) mup = GetMother(imother++);
1768 nextovlp = mup->IsOverlapping();
1769 if (crtovlp) nmany--;
1770 if (crtovlp || nextovlp) {
1771 matrix = GetMotherMatrix(up);
1772 matrix->MasterToLocal(fPoint,local);
1773 safe = mother->GetVolume()->GetShape()->Safety(local,kTRUE);
1774 if (safe<fSafety) fSafety = safe;
1775 crtovlp = nextovlp;
1776 }
1777 up++;
1778 }
1779 }
1780 PopPath();
1781 if (fSafety < gTolerance) {
1782 fSafety = 0.;
1784 }
1785}
1786
1787////////////////////////////////////////////////////////////////////////////////
1788/// Returns the deepest node containing fPoint, which must be set a priori.
1789/// Check if parallel world navigation is enabled
1790
1792{
1795 if (pnode) {
1796 // A node from the parallel world contains the point -> stop the search
1797 // and synchronize with navigation state
1798 pnode->cd();
1800 while (crtindex>=0) {
1801 // Make sure we did not end up in an assembly.
1802 CdDown(crtindex);
1804 }
1805 return fCurrentNode;
1806 }
1807 }
1808 Double_t point[3];
1809 fNextDaughterIndex = -2;
1810 TGeoVolume *vol = 0;
1812 Bool_t inside_current = (fCurrentNode==skipnode)?kTRUE:kFALSE;
1813 if (!downwards) {
1814 // we are looking upwards until inside current node or exit
1816 // We are inside an inactive volume-> go upwards
1817 CdUp();
1819 return SearchNode(kFALSE, skipnode);
1820 }
1821 // Check if the current point is still inside the current volume
1822 vol=fCurrentNode->GetVolume();
1823 if (vol->IsAssembly()) inside_current=kTRUE;
1824 // If the current node is not to be skipped
1825 if (!inside_current) {
1827 inside_current = vol->Contains(point);
1828 }
1829 // Point might be inside an overlapping node
1830 if (fNmany) {
1831 inside_current = GotoSafeLevel();
1832 }
1833 if (!inside_current) {
1834 // If not, go upwards
1836 TGeoNode *skip = fCurrentNode; // skip current node at next search
1837 // check if we can go up
1838 if (!fLevel) {
1839 fIsOutside = kTRUE;
1840 return 0;
1841 }
1842 CdUp();
1843 return SearchNode(kFALSE, skip);
1844 }
1845 }
1846 vol = fCurrentNode->GetVolume();
1848 if (!inside_current && downwards) {
1849 // we are looking downwards
1850 if (fCurrentNode == fForcedNode) inside_current = kTRUE;
1851 else inside_current = vol->Contains(point);
1852 if (!inside_current) {
1854 return 0;
1855 } else {
1856 if (fIsOutside) {
1859 }
1860 if (idebug>4) {
1861 printf("Search node local=(%19.16f, %19.16f, %19.16f) -> %s\n",
1862 point[0],point[1],point[2], fCurrentNode->GetName());
1863 }
1864 }
1865 }
1866 // point inside current (safe) node -> search downwards
1867 TGeoNode *node;
1868 Int_t ncheck = 0;
1869 // if inside an non-overlapping node, reset overlap searches
1870 if (!fCurrentOverlapping) {
1872 }
1873
1874 Int_t crtindex = vol->GetCurrentNodeIndex();
1875 while (crtindex>=0 && downwards) {
1876 // Make sure we did not end up in an assembly.
1877 CdDown(crtindex);
1878 vol = fCurrentNode->GetVolume();
1879 crtindex = vol->GetCurrentNodeIndex();
1880 if (crtindex<0) fGlobalMatrix->MasterToLocal(fPoint, point);
1881 }
1882
1883 Int_t nd = vol->GetNdaughters();
1884 // in case there are no daughters
1885 if (!nd) return fCurrentNode;
1887
1888 TGeoPatternFinder *finder = vol->GetFinder();
1889 // point is inside the current node
1890 // first check if inside a division
1891 if (finder) {
1892 node=finder->FindNode(point);
1893 if (!node && fForcedNode) {
1894 // Point *HAS* to be inside a cell
1895 Double_t dir[3];
1897 finder->FindNode(point,dir);
1898 node = finder->CdNext();
1899 if (!node) return fCurrentNode; // inside divided volume but not in a cell
1900 }
1901 if (node && node!=skipnode) {
1902 // go inside the division cell and search downwards
1904 CdDown(node->GetIndex());
1905 fForcedNode = 0;
1906 return SearchNode(kTRUE, node);
1907 }
1908 // point is not inside the division, but might be in other nodes
1909 // at the same level (NOT SUPPORTED YET)
1910 while (fCurrentNode && fCurrentNode->IsOffset()) CdUp();
1911 return fCurrentNode;
1912 }
1913 // second, look if current volume is voxelized
1914 TGeoVoxelFinder *voxels = vol->GetVoxels();
1915 Int_t *check_list = 0;
1916 Int_t id;
1917 if (voxels) {
1918 // get the list of nodes passing thorough the current voxel
1919 check_list = voxels->GetCheckList(&point[0], ncheck, *fCache->GetInfo());
1920 // if none in voxel, see if this is the last one
1921 if (!check_list) {
1922 if (!fCurrentNode->GetVolume()->IsAssembly()) {
1924 return fCurrentNode;
1925 }
1926 // Point in assembly - go up
1927 node = fCurrentNode;
1928 if (!fLevel) {
1929 fIsOutside = kTRUE;
1931 return 0;
1932 }
1933 CdUp();
1935 return SearchNode(kFALSE,node);
1936 }
1937 // loop all nodes in voxel
1938 for (id=0; id<ncheck; id++) {
1939 node = vol->GetNode(check_list[id]);
1940 if (node==skipnode) continue;
1941 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
1942 if ((id<(ncheck-1)) && node->IsOverlapping()) {
1943 // make the cluster of overlaps
1944 if (ncheck+fOverlapMark > fOverlapSize) {
1945 fOverlapSize = 2*(ncheck+fOverlapMark);
1946 delete [] fOverlapClusters;
1948 }
1949 Int_t *cluster = fOverlapClusters + fOverlapMark;
1950 Int_t nc = GetTouchedCluster(id, &point[0], check_list, ncheck, cluster);
1951 if (nc>1) {
1952 fOverlapMark += nc;
1953 node = FindInCluster(cluster, nc);
1954 fOverlapMark -= nc;
1956 return node;
1957 }
1958 }
1959 CdDown(check_list[id]);
1960 fForcedNode = 0;
1961 node = SearchNode(kTRUE);
1962 if (node) {
1965 return node;
1966 }
1967 CdUp();
1968 }
1969 if (!fCurrentNode->GetVolume()->IsAssembly()) {
1971 return fCurrentNode;
1972 }
1973 node = fCurrentNode;
1974 if (!fLevel) {
1975 fIsOutside = kTRUE;
1977 return 0;
1978 }
1979 CdUp();
1981 return SearchNode(kFALSE,node);
1982 }
1983 // if there are no voxels just loop all daughters
1984 for (id=0; id<nd; id++) {
1985 node=fCurrentNode->GetDaughter(id);
1986 if (node==skipnode) continue;
1987 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
1988 CdDown(id);
1989 fForcedNode = 0;
1990 node = SearchNode(kTRUE);
1991 if (node) {
1993 return node;
1994 }
1995 CdUp();
1996 }
1997 // point is not inside one of the daughters, so it is in the current vol
1998 if (fCurrentNode->GetVolume()->IsAssembly()) {
1999 node = fCurrentNode;
2000 if (!fLevel) {
2001 fIsOutside = kTRUE;
2002 return 0;
2003 }
2004 CdUp();
2005 return SearchNode(kFALSE,node);
2006 }
2007 return fCurrentNode;
2008}
2009
2010////////////////////////////////////////////////////////////////////////////////
2011/// Find a node inside a cluster of overlapping nodes. Current node must
2012/// be on top of all the nodes in cluster. Always nc>1.
2013
2015{
2016 TGeoNode *clnode = 0;
2017 TGeoNode *priority = fLastNode;
2018 // save current node
2019 TGeoNode *current = fCurrentNode;
2020 TGeoNode *found = 0;
2021 // save path
2022 Int_t ipop = PushPath();
2023 // mark this search
2025 Int_t deepest = fLevel;
2026 Int_t deepest_virtual = fLevel-GetVirtualLevel();
2027 Int_t found_virtual = 0;
2028 Bool_t replace = kFALSE;
2029 Bool_t added = kFALSE;
2030 Int_t i;
2031 for (i=0; i<nc; i++) {
2032 clnode = current->GetDaughter(cluster[i]);
2033 CdDown(cluster[i]);
2034 Bool_t max_priority = (clnode==fNextNode)?kTRUE:kFALSE;
2035 found = SearchNode(kTRUE, clnode);
2036 if (!fSearchOverlaps || max_priority) {
2037 // an only was found during the search -> exiting
2038 // The node given by FindNextBoundary returned -> exiting
2039 PopDummy(ipop);
2040 return found;
2041 }
2042 found_virtual = fLevel-GetVirtualLevel();
2043 if (added) {
2044 // we have put something in stack -> check it
2045 if (found_virtual>deepest_virtual) {
2046 replace = kTRUE;
2047 } else {
2048 if (found_virtual==deepest_virtual) {
2049 if (fLevel>deepest) {
2050 replace = kTRUE;
2051 } else {
2052 if ((fLevel==deepest) && (clnode==priority)) replace=kTRUE;
2053 else replace = kFALSE;
2054 }
2055 } else replace = kFALSE;
2056 }
2057 // if this was the last checked node
2058 if (i==(nc-1)) {
2059 if (replace) {
2060 PopDummy(ipop);
2061 return found;
2062 } else {
2064 PopDummy(ipop);
2065 return fCurrentNode;
2066 }
2067 }
2068 // we still have to go on
2069 if (replace) {
2070 // reset stack
2071 PopDummy();
2072 PushPath();
2073 deepest = fLevel;
2074 deepest_virtual = found_virtual;
2075 }
2076 // restore top of cluster
2078 } else {
2079 // the stack was clean, push new one
2080 PushPath();
2081 added = kTRUE;
2082 deepest = fLevel;
2083 deepest_virtual = found_virtual;
2084 // restore original path
2086 }
2087 }
2088 PopDummy(ipop);
2089 return fCurrentNode;
2090}
2091
2092////////////////////////////////////////////////////////////////////////////////
2093/// Make the cluster of overlapping nodes in a voxel, containing point in reference
2094/// of the mother. Returns number of nodes containing the point. Nodes should not be
2095/// offsets.
2096
2098 Int_t *check_list, Int_t ncheck, Int_t *result)
2099{
2100 // we are in the mother reference system
2101 TGeoNode *current = fCurrentNode->GetDaughter(check_list[start]);
2102 Int_t novlps = 0;
2103 Int_t *ovlps = current->GetOverlaps(novlps);
2104 if (!ovlps) return 0;
2105 Double_t local[3];
2106 // intersect check list with overlap list
2107 Int_t ntotal = 0;
2108 current->MasterToLocal(point, &local[0]);
2109 if (current->GetVolume()->Contains(&local[0])) {
2110 result[ntotal++]=check_list[start];
2111 }
2112
2113 Int_t jst=0, i, j;
2114 while ((jst<novlps) && (ovlps[jst]<=check_list[start])) jst++;
2115 if (jst==novlps) return 0;
2116 for (i=start; i<ncheck; i++) {
2117 for (j=jst; j<novlps; j++) {
2118 if (check_list[i]==ovlps[j]) {
2119 // overlapping node in voxel -> check if touched
2120 current = fCurrentNode->GetDaughter(check_list[i]);
2121 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
2122 current->MasterToLocal(point, &local[0]);
2123 if (current->GetVolume()->Contains(&local[0])) {
2124 result[ntotal++]=check_list[i];
2125 }
2126 }
2127 }
2128 }
2129 return ntotal;
2130}
2131
2132////////////////////////////////////////////////////////////////////////////////
2133/// Make a rectiliniar step of length fStep from current point (fPoint) on current
2134/// direction (fDirection). If the step is imposed by geometry, is_geom flag
2135/// must be true (default). The cross flag specifies if the boundary should be
2136/// crossed in case of a geometry step (default true). Returns new node after step.
2137/// Set also on boundary condition.
2138
2140{
2141 Double_t epsil = 0;
2142 if (fStep<1E-6) {
2144 if (fStep<0) fStep = 0.;
2145 } else {
2147 }
2148 if (is_geom) epsil=(cross)?1E-6:-1E-6;
2149 TGeoNode *old = fCurrentNode;
2150 Int_t idold = GetNodeId();
2151 if (fIsOutside) old = 0;
2152 fStep += epsil;
2153 for (Int_t i=0; i<3; i++) fPoint[i]+=fStep*fDirection[i];
2154 TGeoNode *current = FindNode();
2155 if (is_geom) {
2156 fIsEntering = (current==old)?kFALSE:kTRUE;
2157 if (!fIsEntering) {
2158 Int_t id = GetNodeId();
2159 fIsEntering = (id==idold)?kFALSE:kTRUE;
2160 }
2164 } else {
2167 }
2168 return current;
2169}
2170
2171////////////////////////////////////////////////////////////////////////////////
2172/// Find level of virtuality of current overlapping node (number of levels
2173/// up having the same tracking media.
2174
2176{
2177 // return if the current node is ONLY
2178 if (!fCurrentOverlapping) return 0;
2179 Int_t new_media = 0;
2180 TGeoMedium *medium = fCurrentNode->GetMedium();
2181 Int_t virtual_level = 1;
2182 TGeoNode *mother = 0;
2183
2184 while ((mother=GetMother(virtual_level))) {
2185 if (!mother->IsOverlapping() && !mother->IsOffset()) {
2186 if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2187 break;
2188 }
2189 if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2190 virtual_level++;
2191 }
2192 return (new_media==0)?virtual_level:(new_media-1);
2193}
2194
2195////////////////////////////////////////////////////////////////////////////////
2196/// Go upwards the tree until a non-overlapping node
2197
2199{
2200 while (fCurrentOverlapping && fLevel) CdUp();
2201 Double_t point[3];
2203 if (!fCurrentNode->GetVolume()->Contains(point)) return kFALSE;
2204 if (fNmany) {
2205 // We still have overlaps on the branch
2206 Int_t up = 1;
2207 Int_t imother;
2208 Int_t nmany = fNmany;
2209 Bool_t ovlp = kFALSE;
2210 Bool_t nextovlp = kFALSE;
2211 TGeoNode *mother, *mup;
2212 TGeoHMatrix *matrix;
2213 while (nmany) {
2214 mother = GetMother(up);
2215 if (!mother) return kTRUE;
2216 mup = mother;
2217 imother = up+1;
2218 while (mup->IsOffset()) mup = GetMother(imother++);
2219 nextovlp = mup->IsOverlapping();
2220 if (ovlp) nmany--;
2221 if (ovlp || nextovlp) {
2222 // check if the point is in the next node up
2223 matrix = GetMotherMatrix(up);
2224 matrix->MasterToLocal(fPoint,point);
2225 if (!mother->GetVolume()->Contains(point)) {
2226 up++;
2227 while (up--) CdUp();
2228 return GotoSafeLevel();
2229 }
2230 }
2231 ovlp = nextovlp;
2232 up++;
2233 }
2234 }
2235 return kTRUE;
2236}
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Go upwards the tree until a non-overlapping node
2240
2242{
2243 Bool_t overlapping = fCurrentOverlapping;
2244 if (!overlapping) return fLevel;
2245 Int_t level = fLevel;
2246 TGeoNode *node;
2247 while (overlapping && level) {
2248 level--;
2249 node = GetMother(fLevel-level);
2250 if (!node->IsOffset()) overlapping = node->IsOverlapping();
2251 }
2252 return level;
2253}
2254
2255////////////////////////////////////////////////////////////////////////////////
2256/// Inspects path and all flags for the current state.
2257
2259{
2260 Info("InspectState","Current path is: %s",GetPath());
2261 Int_t level;
2262 TGeoNode *node;
2263 Bool_t is_offset, is_overlapping;
2264 for (level=0; level<fLevel+1; level++) {
2265 node = GetMother(fLevel-level);
2266 if (!node) continue;
2267 is_offset = node->IsOffset();
2268 is_overlapping = node->IsOverlapping();
2269 Info("InspectState","level %i: %s div=%i many=%i",level,node->GetName(),is_offset,is_overlapping);
2270 }
2271 Info("InspectState","on_bound=%i entering=%i", fIsOnBoundary, fIsEntering);
2272}
2273
2274////////////////////////////////////////////////////////////////////////////////
2275/// Checks if point (x,y,z) is still in the current node.
2276/// check if this is an overlapping node
2277
2279{
2280 Double_t oldpt[3];
2281 if (fLastSafety>0) {
2282 Double_t dx = (x-fLastPoint[0]);
2283 Double_t dy = (y-fLastPoint[1]);
2284 Double_t dz = (z-fLastPoint[2]);
2285 Double_t dsq = dx*dx+dy*dy+dz*dz;
2286 if (dsq<fLastSafety*fLastSafety) {
2287 if (change) {
2288 fPoint[0] = x;
2289 fPoint[1] = y;
2290 fPoint[2] = z;
2291 memcpy(fLastPoint, fPoint, 3*sizeof(Double_t));
2292 fLastSafety -= TMath::Sqrt(dsq);
2293 }
2294 return kTRUE;
2295 }
2296 if (change) fLastSafety = 0;
2297 }
2298 if (fCurrentOverlapping) {
2299// TGeoNode *current = fCurrentNode;
2300 Int_t cid = GetCurrentNodeId();
2301 if (!change) PushPoint();
2302 memcpy(oldpt, fPoint, kN3);
2303 SetCurrentPoint(x,y,z);
2304 SearchNode();
2305 memcpy(fPoint, oldpt, kN3);
2306 Bool_t same = (cid==GetCurrentNodeId())?kTRUE:kFALSE;
2307 if (!change) PopPoint();
2308 return same;
2309 }
2310
2311 Double_t point[3];
2312 point[0] = x;
2313 point[1] = y;
2314 point[2] = z;
2315 if (change) memcpy(fPoint, point, kN3);
2317 if (fIsOutside) {
2318 if (vol->GetShape()->Contains(point)) {
2319 if (!change) return kFALSE;
2320 FindNode(x,y,z);
2321 return kFALSE;
2322 }
2323 return kTRUE;
2324 }
2325 Double_t local[3];
2326 // convert to local frame
2327 fGlobalMatrix->MasterToLocal(point,local);
2328 // check if still in current volume.
2329 if (!vol->GetShape()->Contains(local)) {
2330 if (!change) return kFALSE;
2331 CdUp();
2332 FindNode(x,y,z);
2333 return kFALSE;
2334 }
2335
2336 // Check if the point is in a parallel world volume
2339 if (pnode) {
2340 if (!change) return kFALSE;
2341 pnode->cd();
2343 while (crtindex>=0) {
2344 // Make sure we did not end up in an assembly.
2345 CdDown(crtindex);
2347 }
2348 return kFALSE;
2349 }
2350 }
2351 // check if there are daughters
2352 Int_t nd = vol->GetNdaughters();
2353 if (!nd) return kTRUE;
2354
2355 TGeoNode *node;
2356 TGeoPatternFinder *finder = vol->GetFinder();
2357 if (finder) {
2358 node=finder->FindNode(local);
2359 if (node) {
2360 if (!change) return kFALSE;
2361 CdDown(node->GetIndex());
2362 SearchNode(kTRUE,node);
2363 return kFALSE;
2364 }
2365 return kTRUE;
2366 }
2367 // if we are not allowed to do changes, save the current path
2368 TGeoVoxelFinder *voxels = vol->GetVoxels();
2369 Int_t *check_list = 0;
2370 Int_t ncheck = 0;
2371 Double_t local1[3];
2372 if (voxels) {
2373 check_list = voxels->GetCheckList(local, ncheck, *fCache->GetInfo());
2374 if (!check_list) {
2376 return kTRUE;
2377 }
2378 if (!change) PushPath();
2379 for (Int_t id=0; id<ncheck; id++) {
2380// node = vol->GetNode(check_list[id]);
2381 CdDown(check_list[id]);
2382 fGlobalMatrix->MasterToLocal(point,local1);
2383 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2384 if (!change) {
2385 PopPath();
2387 return kFALSE;
2388 }
2391 return kFALSE;
2392 }
2393 CdUp();
2394 }
2395 if (!change) PopPath();
2397 return kTRUE;
2398 }
2399 Int_t id = 0;
2400 if (!change) PushPath();
2401 while (fCurrentNode && fCurrentNode->GetDaughter(id++)) {
2402 CdDown(id-1);
2403 fGlobalMatrix->MasterToLocal(point,local1);
2404 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2405 if (!change) {
2406 PopPath();
2407 return kFALSE;
2408 }
2410 return kFALSE;
2411 }
2412 CdUp();
2413 if (id == nd) {
2414 if (!change) PopPath();
2415 return kTRUE;
2416 }
2417 }
2418 if (!change) PopPath();
2419 return kTRUE;
2420}
2421
2422////////////////////////////////////////////////////////////////////////////////
2423/// In case a previous safety value was computed, check if the safety region is
2424/// still safe for the current point and proposed step. Return value changed only
2425/// if proposed distance is safe.
2426
2428{
2429 // Last safety not computed.
2430 if (fLastSafety < gTolerance) return kFALSE;
2431 // Proposed step too small
2432 if (proposed < gTolerance) {
2433 newsafety = fLastSafety - proposed;
2434 return kTRUE;
2435 }
2436 // Normal step
2437 Double_t dist = (fPoint[0]-fLastPoint[0])*(fPoint[0]-fLastPoint[0])+
2438 (fPoint[1]-fLastPoint[1])*(fPoint[1]-fLastPoint[1])+
2439 (fPoint[2]-fLastPoint[2])*(fPoint[2]-fLastPoint[2]);
2440 dist = TMath::Sqrt(dist);
2441 Double_t safe = fLastSafety - dist;
2442 if (safe < proposed) return kFALSE;
2443 newsafety = safe;
2444 return kTRUE;
2445}
2446
2447////////////////////////////////////////////////////////////////////////////////
2448/// Check if a new point with given coordinates is the same as the last located one.
2449
2451{
2452 if (TMath::Abs(x-fLastPoint[0]) < 1.E-20) {
2453 if (TMath::Abs(y-fLastPoint[1]) < 1.E-20) {
2454 if (TMath::Abs(z-fLastPoint[2]) < 1.E-20) return kTRUE;
2455 }
2456 }
2457 return kFALSE;
2458}
2459
2460////////////////////////////////////////////////////////////////////////////////
2461/// Backup the current state without affecting the cache stack.
2462
2464{
2466}
2467
2468////////////////////////////////////////////////////////////////////////////////
2469/// Restore a backed-up state without affecting the cache stack.
2470
2472{
2473 if (fBackupState && fCache) {
2478 }
2479}
2480
2481////////////////////////////////////////////////////////////////////////////////
2482/// Return stored current matrix (global matrix of the next touched node).
2483
2485{
2486 if (!fCurrentMatrix) {
2489 }
2490 return fCurrentMatrix;
2491}
2492
2493////////////////////////////////////////////////////////////////////////////////
2494/// Get path to the current node in the form /node0/node1/...
2495
2496const char *TGeoNavigator::GetPath() const
2497{
2498 if (fIsOutside) return kGeoOutsidePath;
2499 return fCache->GetPath();
2500}
2501
2502////////////////////////////////////////////////////////////////////////////////
2503/// Convert coordinates from master volume frame to top.
2504
2505void TGeoNavigator::MasterToTop(const Double_t *master, Double_t *top) const
2506{
2507 fCurrentMatrix->MasterToLocal(master, top);
2508}
2509
2510////////////////////////////////////////////////////////////////////////////////
2511/// Convert coordinates from top volume frame to master.
2512
2513void TGeoNavigator::TopToMaster(const Double_t *top, Double_t *master) const
2514{
2515 fCurrentMatrix->LocalToMaster(top, master);
2516}
2517
2518////////////////////////////////////////////////////////////////////////////////
2519/// Reset the navigator.
2520
2522{
2523 GetHMatrix();
2526 ResetState();
2527 fStep = 0.;
2528 fSafety = 0.;
2529 fLastSafety = 0.;
2530 fLevel = 0;
2531 fNmany = 0;
2532 fNextDaughterIndex = -2;
2539 fLastNode = 0;
2540 fNextNode = 0;
2541 fPath = "";
2542 if (fCache) {
2543 Bool_t dummy=fCache->IsDummy();
2544 Bool_t nodeid = fCache->HasIdArray();
2545 delete fCache;
2546 fCache = nullptr;
2547 delete fBackupState;
2548 fBackupState = nullptr;
2549 BuildCache(dummy,nodeid);
2550 }
2551}
2552
2554
2555////////////////////////////////////////////////////////////////////////////////
2556/// Add a new navigator to the array.
2557
2559{
2560 SetOwner(kTRUE);
2562 nav->BuildCache(kTRUE, kFALSE);
2563 Add(nav);
2565 return nav;
2566}
int Int_t
Definition RtypesCore.h:45
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:377
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:478
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:29
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:421
void CopyFrom(const TGeoMatrix *other)
Fast copy method.
virtual const Double_t * GetTranslation() const
Definition TGeoMatrix.h:467
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:45
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:24
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
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...
TGeoHMatrix * GetHMatrix()
Return stored current matrix (global matrix of the next touched node).
virtual ~TGeoNavigator()
Destructor.
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.
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 point for which safety was computed
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
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()
path to current node
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
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:58
Bool_t IsDummy() const
Definition TGeoCache.h:117
TGeoNode * GetNode() const
Definition TGeoCache.h:107
void CdNode(Int_t nodeid)
Change current path to point to the node having this id.
void CdTop()
Definition TGeoCache.h:94
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:116
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:103
void ReleaseInfo()
Release last used state info pointer.
Int_t GetLevel() const
Definition TGeoCache.h:112
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition TGeoNode.h:41
TGeoMedium * GetMedium() const
Definition TGeoNode.h:91
Bool_t IsOverlapping() const
Definition TGeoNode.h:105
TGeoVolume * GetVolume() const
Definition TGeoNode.h:97
Bool_t IsOffset() const
Definition TGeoNode.h:103
Int_t GetNdaughters() const
Definition TGeoNode.h:93
TGeoNode * GetDaughter(Int_t ind) const
Definition TGeoNode.h:85
virtual TGeoMatrix * GetMatrix() const =0
virtual void cd() const
Definition TGeoNode.h:73
Int_t * GetOverlaps(Int_t &novlp) const
Definition TGeoNode.h:96
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:518
virtual Int_t GetIndex() const
Definition TGeoNode.h:89
virtual TGeoPatternFinder * GetFinder() const
Definition TGeoNode.h:90
virtual void MasterToLocalVect(const Double_t *master, Double_t *local) const
Convert a vector from mother reference to local reference system.
Definition TGeoNode.cxx:526
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:630
Double_t Safety(Double_t point[3], Double_t safmax=1.E30)
Compute safety for the parallel world.
TGeoPhysicalNode * FindNextBoundary(Double_t point[3], Double_t dir[3], Double_t &step, Double_t stepmax=1.E30)
Same functionality as TGeoNavigator::FindNextDaughterBoundary for the parallel world.
TGeoPhysicalNode * FindNode(Double_t point[3])
Finds physical node containing the point.
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:88
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:91
Volume assemblies.
Definition TGeoVolume.h:305
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:49
virtual Int_t GetNextNodeIndex() const
Definition TGeoVolume.h:167
Bool_t IsActiveDaughters() const
Definition TGeoVolume.h:145
Bool_t Contains(const Double_t *point) const
Definition TGeoVolume.h:109
Int_t GetNdaughters() const
Definition TGeoVolume.h:351
TObjArray * GetNodes()
Definition TGeoVolume.h:168
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:176
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
TGeoShape * GetShape() const
Definition TGeoVolume.h:189
virtual Int_t GetCurrentNodeIndex() const
Definition TGeoVolume.h:166
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.
Bool_t IsActive() const
Definition TGeoVolume.h:144
void InspectShape() const
Definition TGeoVolume.h:194
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:207
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:998
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:944
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
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:660
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
Definition first.py:1
Statefull info for the current geometry level.
#define snext(osub1, osub2)
Definition triangle.c:1168