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{
298 TGeoNode *node = fCurrentNode->GetDaughter(index);
299 Bool_t is_offset = node->IsOffset();
300 if (is_offset)
301 node->cd();
302 else
304 fCache->CdDown(index);
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;
352 Bool_t offset = kTRUE;
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;
861 Bool_t offset = 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 static Int_t icount = 0;
1126 icount++;
1127 Int_t iact = 3;
1129 Int_t nextindex;
1130 Bool_t is_assembly;
1131 fForcedNode = 0;
1133 TGeoNode *skip;
1135 fStep = stepmax;
1137 // If inside an assembly, go logically up in the hierarchy
1138 while (fCurrentNode->GetVolume()->IsAssembly() && fLevel) CdUp();
1139 if (compsafe) {
1140 // Try to get out easy if proposed step within safe region
1142 if (IsSafeStep(stepmax+gTolerance, fSafety)) {
1143 fPoint[0] += stepmax*fDirection[0];
1144 fPoint[1] += stepmax*fDirection[1];
1145 fPoint[2] += stepmax*fDirection[2];
1146 return fCurrentNode;
1147 }
1148 Safety();
1150 memcpy(fLastPoint, fPoint, kN3);
1151 // If proposed step less than safety, nothing to check
1152 if (fSafety > stepmax+gTolerance) {
1153 fPoint[0] += stepmax*fDirection[0];
1154 fPoint[1] += stepmax*fDirection[1];
1155 fPoint[2] += stepmax*fDirection[2];
1156 return fCurrentNode;
1157 }
1158 }
1159 Double_t extra = (fIsOnBoundary)?gTolerance:0.0;
1161 fPoint[0] += extra*fDirection[0];
1162 fPoint[1] += extra*fDirection[1];
1163 fPoint[2] += extra*fDirection[2];
1165 if (idebug>4) {
1166 printf("TGeoManager::FindNextBAndStep: point=(%19.16f, %19.16f, %19.16f)\n",
1167 fPoint[0],fPoint[1],fPoint[2]);
1168 printf(" dir= (%19.16f, %19.16f, %19.16f)\n",
1169 fDirection[0], fDirection[1], fDirection[2]);
1170 printf(" pstep=%9.6g path=%s\n", stepmax, GetPath());
1171 }
1172
1173 if (fIsOutside) {
1175 if (snext < fStep-gTolerance) {
1176 if (snext<=0) {
1177 snext = 0.0;
1178 fStep = snext;
1179 fPoint[0] -= extra*fDirection[0];
1180 fPoint[1] -= extra*fDirection[1];
1181 fPoint[2] -= extra*fDirection[2];
1182 } else {
1183 fStep = snext+extra;
1184 }
1187 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1188 while (nextindex>=0) {
1189 CdDown(nextindex);
1191 nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1192 if (nextindex<0) fCurrentMatrix->CopyFrom(fGlobalMatrix);
1193 }
1194 // Update global point
1195 fPoint[0] += snext*fDirection[0];
1196 fPoint[1] += snext*fDirection[1];
1197 fPoint[2] += snext*fDirection[2];
1202 }
1203 if (snext<TGeoShape::Big()) {
1204 // New point still outside, but the top node is reachable
1206 fPoint[0] += (fStep-extra)*fDirection[0];
1207 fPoint[1] += (fStep-extra)*fDirection[1];
1208 fPoint[2] += (fStep-extra)*fDirection[2];
1209 return fNextNode;
1210 }
1211 // top node not reachable from current point/direction
1212 fNextNode = 0;
1214 return 0;
1215 }
1216 Double_t point[3],dir[3];
1217 Int_t icrossed = -2;
1218 fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
1221 // find distance to exiting current node
1222 if (idebug>4) {
1223 printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1224 point[0],point[1],point[2]);
1225 printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
1226 dir[0],dir[1],dir[2]);
1227 }
1228 // find distance to exiting current node
1229 snext = vol->GetShape()->DistFromInside(point, dir, iact, fStep);
1230 if (idebug>4) {
1231 printf(" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
1232 }
1234 if (snext <= gTolerance) {
1235 // Current point on the boundary while track exiting
1236 snext = gTolerance;
1237 fStep = snext;
1241 skip = fCurrentNode;
1242 fPoint[0] += fStep*fDirection[0];
1243 fPoint[1] += fStep*fDirection[1];
1244 fPoint[2] += fStep*fDirection[2];
1245 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1246 if (!fLevel && !is_assembly) {
1247 fIsOutside = kTRUE;
1248 return 0;
1249 }
1250 if (fCurrentNode->IsOffset()) return CrossDivisionCell();
1251 if (fLevel) CdUp();
1252 else skip = 0;
1253 return CrossBoundaryAndLocate(kFALSE, skip);
1254 }
1255
1256 if (snext < fStep-gTolerance) {
1257 // Currently the minimum step chosen is the exiting one
1258 icrossed = -1;
1259 fStep = snext;
1262 }
1263 // Find next daughter boundary for the current volume
1264 Int_t idaughter = -1;
1265 TGeoNode *crossed = FindNextDaughterBoundary(point,dir, idaughter, kTRUE);
1266 if (crossed) {
1268 icrossed = idaughter;
1270 }
1271 TGeoNode *current = 0;
1272 TGeoNode *dnode = 0;
1273 TGeoVolume *mother = 0;
1274 // if we are in an overlapping node, check also the mother(s)
1275 if (fNmany) {
1276 Double_t mothpt[3];
1277 Double_t vecpt[3];
1278 Double_t dpt[3], dvec[3];
1279 Int_t novlps;
1280 Int_t safelevel = GetSafeLevel();
1281 PushPath(safelevel+1);
1282 while (fCurrentOverlapping) {
1283 Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
1284 CdUp();
1285 mother = fCurrentNode->GetVolume();
1286 fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
1288 // check distance to out
1290 if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(mothpt, vecpt, iact, fStep);
1291 if (snext<fStep-gTolerance) {
1292 // exiting mother first (extrusion)
1293 icrossed = -1;
1294 PopDummy();
1295 PushPath(safelevel+1);
1298 fStep = snext;
1301 }
1302 // check overlapping nodes
1303 for (Int_t i=0; i<novlps; i++) {
1304 current = mother->GetNode(ovlps[i]);
1305 if (!current->IsOverlapping()) {
1306 current->cd();
1307 current->MasterToLocal(&mothpt[0], &dpt[0]);
1308 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1309 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1310 if (snext<fStep-gTolerance) {
1311 PopDummy();
1312 PushPath(safelevel+1);
1314 fCurrentMatrix->Multiply(current->GetMatrix());
1317 icrossed = ovlps[i];
1318 fStep = snext;
1319 fNextNode = current;
1320 }
1321 } else {
1322 // another many - check if point is in or out
1323 current->cd();
1324 current->MasterToLocal(&mothpt[0], &dpt[0]);
1325 current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1326 if (current->GetVolume()->Contains(dpt)) {
1327 if (current->GetVolume()->GetNdaughters()) {
1328 CdDown(ovlps[i]);
1329 dnode = FindNextDaughterBoundary(dpt,dvec,idaughter,kFALSE);
1330 if (dnode) {
1333 icrossed = idaughter;
1334 PopDummy();
1335 PushPath(safelevel+1);
1338 fNextNode = dnode;
1339 }
1340 CdUp();
1341 }
1342 } else {
1343 snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1344 if (snext<fStep-gTolerance) {
1346 fCurrentMatrix->Multiply(current->GetMatrix());
1349 fStep = snext;
1350 fNextNode = current;
1351 icrossed = ovlps[i];
1352 PopDummy();
1353 PushPath(safelevel+1);
1354 }
1355 }
1356 }
1357 }
1358 }
1359 // Now we are in a non-overlapping node
1360 if (fNmany) {
1361 // We have overlaps up in the branch, check distance to exit
1362 Int_t up = 1;
1363 Int_t imother;
1364 Int_t nmany = fNmany;
1365 Bool_t ovlp = kFALSE;
1366 Bool_t nextovlp = kFALSE;
1367 Bool_t offset = kFALSE;
1368 TGeoNode *currentnode = fCurrentNode;
1369 TGeoNode *mothernode, *mup;
1370 TGeoHMatrix *matrix;
1371 while (nmany) {
1372 mothernode = GetMother(up);
1373 mup = mothernode;
1374 imother = up+1;
1375 offset = kFALSE;
1376 while (mup->IsOffset()) {
1377 mup = GetMother(imother++);
1378 offset = kTRUE;
1379 }
1380 nextovlp = mup->IsOverlapping();
1381 if (offset) {
1382 mothernode = mup;
1383 if (nextovlp) nmany -= imother-up;
1384 up = imother-1;
1385 } else {
1386 if (ovlp) nmany--;
1387 }
1388 if (ovlp || nextovlp) {
1389 matrix = GetMotherMatrix(up);
1390 matrix->MasterToLocal(fPoint,dpt);
1391 matrix->MasterToLocalVect(fDirection,dvec);
1393 if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
1396 if (snext<fStep-gTolerance) {
1397 fNextNode = mothernode;
1398 fCurrentMatrix->CopyFrom(matrix);
1399 fStep = snext;
1400 while (up--) CdUp();
1401 PopDummy();
1402 PushPath();
1403 icrossed = -1;
1404 up = 1;
1405 currentnode = fCurrentNode;
1406 ovlp = currentnode->IsOverlapping();
1407 continue;
1408 }
1409 }
1410 currentnode = mothernode;
1411 ovlp = nextovlp;
1412 up++;
1413 }
1414 }
1415 PopPath();
1416 }
1417 // Compute now the distance in case we have a parallel world
1418 Double_t parstep = TGeoShape::Big();
1419 TGeoPhysicalNode *pnode = 0;
1422 if (pnode) {
1423 // A boundary is hit at less than fPStep
1424 fStep = parstep;
1425 fPoint[0] += fStep*fDirection[0];
1426 fPoint[1] += fStep*fDirection[1];
1427 fPoint[2] += fStep*fDirection[2];
1428 fNextNode = pnode->GetNode();
1429// icrossed = -4; //
1432 cd(pnode->GetName());
1433 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1434 while (nextindex>=0) {
1435 current = fCurrentNode;
1436 CdDown(nextindex);
1437 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1438 }
1439 return fCurrentNode;
1440 }
1441 }
1442 fPoint[0] += fStep*fDirection[0];
1443 fPoint[1] += fStep*fDirection[1];
1444 fPoint[2] += fStep*fDirection[2];
1445 fStep += extra;
1446 if (icrossed == -2) {
1447 // Nothing crossed within stepmax -> propagate and return same location
1449 return fCurrentNode;
1450 }
1452 if (icrossed == -1) {
1453 // Exiting current node.
1454 skip = fCurrentNode;
1455 is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1456 if (!fLevel && !is_assembly) {
1457 fIsOutside = kTRUE;
1458 return 0;
1459 }
1460 if (fCurrentNode->IsOffset()) return CrossDivisionCell();
1461 if (fLevel) CdUp();
1462 else skip = 0;
1463 return CrossBoundaryAndLocate(kFALSE, skip);
1464 }
1465
1466 CdDown(icrossed);
1467 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1468 while (nextindex>=0) {
1469 current = fCurrentNode;
1470 CdDown(nextindex);
1471 nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1472 }
1474 return CrossBoundaryAndLocate(kTRUE, current);
1475}
1476
1477////////////////////////////////////////////////////////////////////////////////
1478/// Returns deepest node containing current point.
1479
1481{
1482 fSafety = 0;
1487 fStartSafe = safe_start;
1489 TGeoNode *last = fCurrentNode;
1490 TGeoNode *found = SearchNode();
1491 if (found != last) {
1493 } else {
1494 if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1495 }
1496 return found;
1497}
1498
1499////////////////////////////////////////////////////////////////////////////////
1500/// Returns deepest node containing current point.
1501
1503{
1504 fPoint[0] = x;
1505 fPoint[1] = y;
1506 fPoint[2] = z;
1507 fSafety = 0;
1512 fStartSafe = kTRUE;
1514 TGeoNode *last = fCurrentNode;
1515 TGeoNode *found = SearchNode();
1516 if (found != last) {
1518 } else {
1519 if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1520 }
1521 return found;
1522}
1523
1524////////////////////////////////////////////////////////////////////////////////
1525/// Computes fast normal to next crossed boundary, assuming that the current point
1526/// is close enough to the boundary. Works only after calling FindNextBoundary.
1527
1529{
1530 if (!fNextNode) return 0;
1531 Double_t local[3];
1532 Double_t ldir[3];
1533 Double_t lnorm[3];
1536 fNextNode->GetVolume()->GetShape()->ComputeNormal(local, ldir,lnorm);
1538 return fNormal;
1539}
1540
1541////////////////////////////////////////////////////////////////////////////////
1542/// Computes normal vector to the next surface that will be or was already
1543/// crossed when propagating on a straight line from a given point/direction.
1544/// Returns the normal vector cosines in the MASTER coordinate system. The dot
1545/// product of the normal and the current direction is positive defined.
1546
1548{
1549 return FindNormalFast();
1550}
1551
1552////////////////////////////////////////////////////////////////////////////////
1553/// Initialize current point and current direction vector (normalized)
1554/// in MARS. Return corresponding node.
1555
1557{
1558 SetCurrentPoint(point);
1560 return FindNode();
1561}
1562
1563////////////////////////////////////////////////////////////////////////////////
1564/// Initialize current point and current direction vector (normalized)
1565/// in MARS. Return corresponding node.
1566
1568{
1569 SetCurrentPoint(x,y,z);
1570 SetCurrentDirection(nx,ny,nz);
1571 return FindNode();
1572}
1573
1574////////////////////////////////////////////////////////////////////////////////
1575/// Reset current state flags.
1576
1578{
1584}
1585
1586////////////////////////////////////////////////////////////////////////////////
1587/// Compute safe distance from the current point. This represent the distance
1588/// from POINT to the closest boundary.
1589
1591{
1592 if (fIsOnBoundary) {
1593 fSafety = 0;
1594 return fSafety;
1595 }
1596 Double_t point[3];
1597 Double_t safpar = TGeoShape::Big();
1598 if (!inside) fSafety = TGeoShape::Big();
1599 // Check if parallel navigation is enabled
1602 }
1603
1604 if (fIsOutside) {
1606 if (fSafety < gTolerance) {
1607 fSafety = 0;
1609 return fSafety;
1610 }
1611 return TMath::Min(fSafety,safpar);
1612 }
1613 //---> convert point to local reference frame of current node
1615
1616 //---> compute safety to current node
1618 if (!inside) {
1619 fSafety = vol->GetShape()->Safety(point, kTRUE);
1620 //---> if we were just entering, return this safety
1621 if (fSafety < gTolerance) {
1622 fSafety = 0;
1624 return fSafety;
1625 }
1626 }
1627
1628 //---> Check against the parallel geometry safety
1629 if (safpar < fSafety) fSafety = safpar;
1630
1631 //---> if we were just exiting, return this safety
1632 TObjArray *nodes = vol->GetNodes();
1634 if (!nd && !fCurrentOverlapping) return fSafety;
1635 TGeoNode *node;
1636 Double_t safe;
1637 Int_t id;
1638
1639 // if current volume is divided, we are in the non-divided region. We
1640 // check only the first and the last cell
1641 TGeoPatternFinder *finder = vol->GetFinder();
1642 if (finder) {
1643 Int_t ifirst = finder->GetDivIndex();
1644 node = (TGeoNode*)nodes->UncheckedAt(ifirst);
1645 node->cd();
1646 safe = node->Safety(point, kFALSE);
1647 if (safe < gTolerance) {
1648 fSafety=0;
1650 return fSafety;
1651 }
1652 if (safe<fSafety) fSafety=safe;
1653 Int_t ilast = ifirst+finder->GetNdiv()-1;
1654 if (ilast==ifirst) return fSafety;
1655 node = (TGeoNode*)nodes->UncheckedAt(ilast);
1656 node->cd();
1657 safe = node->Safety(point, kFALSE);
1658 if (safe < gTolerance) {
1659 fSafety=0;
1661 return fSafety;
1662 }
1663 if (safe<fSafety) fSafety=safe;
1664 if (fCurrentOverlapping && !inside) SafetyOverlaps();
1665 return fSafety;
1666 }
1667
1668 //---> If no voxels just loop daughters
1669 TGeoVoxelFinder *voxels = vol->GetVoxels();
1670 if (!voxels) {
1671 for (id=0; id<nd; id++) {
1672 node = (TGeoNode*)nodes->UncheckedAt(id);
1673 safe = node->Safety(point, kFALSE);
1674 if (safe < gTolerance) {
1675 fSafety=0;
1677 return fSafety;
1678 }
1679 if (safe<fSafety) fSafety=safe;
1680 }
1681 if (fNmany && !inside) SafetyOverlaps();
1682 return fSafety;
1683 } else {
1684 if (voxels->NeedRebuild()) {
1685 voxels->Voxelize();
1686 vol->FindOverlaps();
1687 }
1688 }
1689
1690 //---> check fast unsafe voxels
1691 Double_t *boxes = voxels->GetBoxes();
1692 for (id=0; id<nd; id++) {
1693 Int_t ist = 6*id;
1694 Double_t dxyz = 0.;
1695 Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
1696 if (dxyz0 > fSafety) continue;
1697 Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
1698 if (dxyz1 > fSafety) continue;
1699 Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
1700 if (dxyz2 > fSafety) continue;
1701 if (dxyz0>0) dxyz+=dxyz0*dxyz0;
1702 if (dxyz1>0) dxyz+=dxyz1*dxyz1;
1703 if (dxyz2>0) dxyz+=dxyz2*dxyz2;
1704 if (dxyz >= fSafety*fSafety) continue;
1705 node = (TGeoNode*)nodes->UncheckedAt(id);
1706 safe = node->Safety(point, kFALSE);
1707 if (safe<gTolerance) {
1708 fSafety=0;
1710 return fSafety;
1711 }
1712 if (safe<fSafety) fSafety = safe;
1713 }
1714 if (fNmany && !inside) SafetyOverlaps();
1715 return fSafety;
1716}
1717
1718////////////////////////////////////////////////////////////////////////////////
1719/// Compute safe distance from the current point within an overlapping node
1720
1722{
1723 Double_t point[3], local[3];
1724 Double_t safe;
1725 Bool_t contains;
1726 TGeoNode *nodeovlp;
1727 TGeoVolume *vol;
1728 Int_t novlp, io;
1729 Int_t *ovlp;
1730 Int_t safelevel = GetSafeLevel();
1731 PushPath(safelevel+1);
1732 while (fCurrentOverlapping) {
1733 ovlp = fCurrentNode->GetOverlaps(novlp);
1734 CdUp();
1735 vol = fCurrentNode->GetVolume();
1737 contains = fCurrentNode->GetVolume()->Contains(point);
1738 safe = fCurrentNode->GetVolume()->GetShape()->Safety(point, contains);
1739 if (safe<fSafety && safe>=0) fSafety=safe;
1740 if (!novlp || !contains) continue;
1741 // we are now in the container, check safety to all candidates
1742 for (io=0; io<novlp; io++) {
1743 nodeovlp = vol->GetNode(ovlp[io]);
1744 nodeovlp->GetMatrix()->MasterToLocal(point,local);
1745 contains = nodeovlp->GetVolume()->Contains(local);
1746 if (contains) {
1747 CdDown(ovlp[io]);
1748 safe = Safety(kTRUE);
1749 CdUp();
1750 } else {
1751 safe = nodeovlp->GetVolume()->GetShape()->Safety(local, kFALSE);
1752 }
1753 if (safe<fSafety && safe>=0) fSafety=safe;
1754 }
1755 }
1756 if (fNmany) {
1757 // We have overlaps up in the branch, check distance to exit
1758 Int_t up = 1;
1759 Int_t imother;
1760 Int_t nmany = fNmany;
1761 Bool_t crtovlp = kFALSE;
1762 Bool_t nextovlp = kFALSE;
1763 TGeoNode *mother, *mup;
1764 TGeoHMatrix *matrix;
1765 while (nmany) {
1766 mother = GetMother(up);
1767 mup = mother;
1768 imother = up+1;
1769 while (mup->IsOffset()) mup = GetMother(imother++);
1770 nextovlp = mup->IsOverlapping();
1771 if (crtovlp) nmany--;
1772 if (crtovlp || nextovlp) {
1773 matrix = GetMotherMatrix(up);
1774 matrix->MasterToLocal(fPoint,local);
1775 safe = mother->GetVolume()->GetShape()->Safety(local,kTRUE);
1776 if (safe<fSafety) fSafety = safe;
1777 crtovlp = nextovlp;
1778 }
1779 up++;
1780 }
1781 }
1782 PopPath();
1783 if (fSafety < gTolerance) {
1784 fSafety = 0.;
1786 }
1787}
1788
1789////////////////////////////////////////////////////////////////////////////////
1790/// Returns the deepest node containing fPoint, which must be set a priori.
1791/// Check if parallel world navigation is enabled
1792
1794{
1797 if (pnode) {
1798 // A node from the parallel world contains the point -> stop the search
1799 // and synchronize with navigation state
1800 pnode->cd();
1802 while (crtindex>=0) {
1803 // Make sure we did not end up in an assembly.
1804 CdDown(crtindex);
1806 }
1807 return fCurrentNode;
1808 }
1809 }
1810 Double_t point[3];
1811 fNextDaughterIndex = -2;
1812 TGeoVolume *vol = 0;
1814 Bool_t inside_current = (fCurrentNode==skipnode)?kTRUE:kFALSE;
1815 if (!downwards) {
1816 // we are looking upwards until inside current node or exit
1818 // We are inside an inactive volume-> go upwards
1819 CdUp();
1821 return SearchNode(kFALSE, skipnode);
1822 }
1823 // Check if the current point is still inside the current volume
1824 vol=fCurrentNode->GetVolume();
1825 if (vol->IsAssembly()) inside_current=kTRUE;
1826 // If the current node is not to be skipped
1827 if (!inside_current) {
1829 inside_current = vol->Contains(point);
1830 }
1831 // Point might be inside an overlapping node
1832 if (fNmany) {
1833 inside_current = GotoSafeLevel();
1834 }
1835 if (!inside_current) {
1836 // If not, go upwards
1838 TGeoNode *skip = fCurrentNode; // skip current node at next search
1839 // check if we can go up
1840 if (!fLevel) {
1841 fIsOutside = kTRUE;
1842 return 0;
1843 }
1844 CdUp();
1845 return SearchNode(kFALSE, skip);
1846 }
1847 }
1848 vol = fCurrentNode->GetVolume();
1850 if (!inside_current && downwards) {
1851 // we are looking downwards
1852 if (fCurrentNode == fForcedNode) inside_current = kTRUE;
1853 else inside_current = vol->Contains(point);
1854 if (!inside_current) {
1856 return 0;
1857 } else {
1858 if (fIsOutside) {
1861 }
1862 if (idebug>4) {
1863 printf("Search node local=(%19.16f, %19.16f, %19.16f) -> %s\n",
1864 point[0],point[1],point[2], fCurrentNode->GetName());
1865 }
1866 }
1867 }
1868 // point inside current (safe) node -> search downwards
1869 TGeoNode *node;
1870 Int_t ncheck = 0;
1871 // if inside an non-overlapping node, reset overlap searches
1872 if (!fCurrentOverlapping) {
1874 }
1875
1876 Int_t crtindex = vol->GetCurrentNodeIndex();
1877 while (crtindex>=0 && downwards) {
1878 // Make sure we did not end up in an assembly.
1879 CdDown(crtindex);
1880 vol = fCurrentNode->GetVolume();
1881 crtindex = vol->GetCurrentNodeIndex();
1882 if (crtindex<0) fGlobalMatrix->MasterToLocal(fPoint, point);
1883 }
1884
1885 Int_t nd = vol->GetNdaughters();
1886 // in case there are no daughters
1887 if (!nd) return fCurrentNode;
1889
1890 TGeoPatternFinder *finder = vol->GetFinder();
1891 // point is inside the current node
1892 // first check if inside a division
1893 if (finder) {
1894 node=finder->FindNode(point);
1895 if (!node && fForcedNode) {
1896 // Point *HAS* to be inside a cell
1897 Double_t dir[3];
1899 finder->FindNode(point,dir);
1900 node = finder->CdNext();
1901 if (!node) return fCurrentNode; // inside divided volume but not in a cell
1902 }
1903 if (node && node!=skipnode) {
1904 // go inside the division cell and search downwards
1906 CdDown(node->GetIndex());
1907 fForcedNode = 0;
1908 return SearchNode(kTRUE, node);
1909 }
1910 // point is not inside the division, but might be in other nodes
1911 // at the same level (NOT SUPPORTED YET)
1912 while (fCurrentNode && fCurrentNode->IsOffset()) CdUp();
1913 return fCurrentNode;
1914 }
1915 // second, look if current volume is voxelized
1916 TGeoVoxelFinder *voxels = vol->GetVoxels();
1917 Int_t *check_list = 0;
1918 Int_t id;
1919 if (voxels) {
1920 // get the list of nodes passing thorough the current voxel
1921 check_list = voxels->GetCheckList(&point[0], ncheck, *fCache->GetInfo());
1922 // if none in voxel, see if this is the last one
1923 if (!check_list) {
1924 if (!fCurrentNode->GetVolume()->IsAssembly()) {
1926 return fCurrentNode;
1927 }
1928 // Point in assembly - go up
1929 node = fCurrentNode;
1930 if (!fLevel) {
1931 fIsOutside = kTRUE;
1933 return 0;
1934 }
1935 CdUp();
1937 return SearchNode(kFALSE,node);
1938 }
1939 // loop all nodes in voxel
1940 for (id=0; id<ncheck; id++) {
1941 node = vol->GetNode(check_list[id]);
1942 if (node==skipnode) continue;
1943 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
1944 if ((id<(ncheck-1)) && node->IsOverlapping()) {
1945 // make the cluster of overlaps
1946 if (ncheck+fOverlapMark > fOverlapSize) {
1947 fOverlapSize = 2*(ncheck+fOverlapMark);
1948 delete [] fOverlapClusters;
1950 }
1951 Int_t *cluster = fOverlapClusters + fOverlapMark;
1952 Int_t nc = GetTouchedCluster(id, &point[0], check_list, ncheck, cluster);
1953 if (nc>1) {
1954 fOverlapMark += nc;
1955 node = FindInCluster(cluster, nc);
1956 fOverlapMark -= nc;
1958 return node;
1959 }
1960 }
1961 CdDown(check_list[id]);
1962 fForcedNode = 0;
1963 node = SearchNode(kTRUE);
1964 if (node) {
1967 return node;
1968 }
1969 CdUp();
1970 }
1971 if (!fCurrentNode->GetVolume()->IsAssembly()) {
1973 return fCurrentNode;
1974 }
1975 node = fCurrentNode;
1976 if (!fLevel) {
1977 fIsOutside = kTRUE;
1979 return 0;
1980 }
1981 CdUp();
1983 return SearchNode(kFALSE,node);
1984 }
1985 // if there are no voxels just loop all daughters
1986 for (id=0; id<nd; id++) {
1987 node=fCurrentNode->GetDaughter(id);
1988 if (node==skipnode) continue;
1989 if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
1990 CdDown(id);
1991 fForcedNode = 0;
1992 node = SearchNode(kTRUE);
1993 if (node) {
1995 return node;
1996 }
1997 CdUp();
1998 }
1999 // point is not inside one of the daughters, so it is in the current vol
2000 if (fCurrentNode->GetVolume()->IsAssembly()) {
2001 node = fCurrentNode;
2002 if (!fLevel) {
2003 fIsOutside = kTRUE;
2004 return 0;
2005 }
2006 CdUp();
2007 return SearchNode(kFALSE,node);
2008 }
2009 return fCurrentNode;
2010}
2011
2012////////////////////////////////////////////////////////////////////////////////
2013/// Find a node inside a cluster of overlapping nodes. Current node must
2014/// be on top of all the nodes in cluster. Always nc>1.
2015
2017{
2018 TGeoNode *clnode = 0;
2019 TGeoNode *priority = fLastNode;
2020 // save current node
2021 TGeoNode *current = fCurrentNode;
2022 TGeoNode *found = 0;
2023 // save path
2024 Int_t ipop = PushPath();
2025 // mark this search
2027 Int_t deepest = fLevel;
2028 Int_t deepest_virtual = fLevel-GetVirtualLevel();
2029 Int_t found_virtual = 0;
2030 Bool_t replace = kFALSE;
2031 Bool_t added = kFALSE;
2032 Int_t i;
2033 for (i=0; i<nc; i++) {
2034 clnode = current->GetDaughter(cluster[i]);
2035 CdDown(cluster[i]);
2036 Bool_t max_priority = (clnode==fNextNode)?kTRUE:kFALSE;
2037 found = SearchNode(kTRUE, clnode);
2038 if (!fSearchOverlaps || max_priority) {
2039 // an only was found during the search -> exiting
2040 // The node given by FindNextBoundary returned -> exiting
2041 PopDummy(ipop);
2042 return found;
2043 }
2044 found_virtual = fLevel-GetVirtualLevel();
2045 if (added) {
2046 // we have put something in stack -> check it
2047 if (found_virtual>deepest_virtual) {
2048 replace = kTRUE;
2049 } else {
2050 if (found_virtual==deepest_virtual) {
2051 if (fLevel>deepest) {
2052 replace = kTRUE;
2053 } else {
2054 if ((fLevel==deepest) && (clnode==priority)) replace=kTRUE;
2055 else replace = kFALSE;
2056 }
2057 } else replace = kFALSE;
2058 }
2059 // if this was the last checked node
2060 if (i==(nc-1)) {
2061 if (replace) {
2062 PopDummy(ipop);
2063 return found;
2064 } else {
2066 PopDummy(ipop);
2067 return fCurrentNode;
2068 }
2069 }
2070 // we still have to go on
2071 if (replace) {
2072 // reset stack
2073 PopDummy();
2074 PushPath();
2075 deepest = fLevel;
2076 deepest_virtual = found_virtual;
2077 }
2078 // restore top of cluster
2080 } else {
2081 // the stack was clean, push new one
2082 PushPath();
2083 added = kTRUE;
2084 deepest = fLevel;
2085 deepest_virtual = found_virtual;
2086 // restore original path
2088 }
2089 }
2090 PopDummy(ipop);
2091 return fCurrentNode;
2092}
2093
2094////////////////////////////////////////////////////////////////////////////////
2095/// Make the cluster of overlapping nodes in a voxel, containing point in reference
2096/// of the mother. Returns number of nodes containing the point. Nodes should not be
2097/// offsets.
2098
2100 Int_t *check_list, Int_t ncheck, Int_t *result)
2101{
2102 // we are in the mother reference system
2103 TGeoNode *current = fCurrentNode->GetDaughter(check_list[start]);
2104 Int_t novlps = 0;
2105 Int_t *ovlps = current->GetOverlaps(novlps);
2106 if (!ovlps) return 0;
2107 Double_t local[3];
2108 // intersect check list with overlap list
2109 Int_t ntotal = 0;
2110 current->MasterToLocal(point, &local[0]);
2111 if (current->GetVolume()->Contains(&local[0])) {
2112 result[ntotal++]=check_list[start];
2113 }
2114
2115 Int_t jst=0, i, j;
2116 while ((jst<novlps) && (ovlps[jst]<=check_list[start])) jst++;
2117 if (jst==novlps) return 0;
2118 for (i=start; i<ncheck; i++) {
2119 for (j=jst; j<novlps; j++) {
2120 if (check_list[i]==ovlps[j]) {
2121 // overlapping node in voxel -> check if touched
2122 current = fCurrentNode->GetDaughter(check_list[i]);
2123 if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
2124 current->MasterToLocal(point, &local[0]);
2125 if (current->GetVolume()->Contains(&local[0])) {
2126 result[ntotal++]=check_list[i];
2127 }
2128 }
2129 }
2130 }
2131 return ntotal;
2132}
2133
2134////////////////////////////////////////////////////////////////////////////////
2135/// Make a rectiliniar step of length fStep from current point (fPoint) on current
2136/// direction (fDirection). If the step is imposed by geometry, is_geom flag
2137/// must be true (default). The cross flag specifies if the boundary should be
2138/// crossed in case of a geometry step (default true). Returns new node after step.
2139/// Set also on boundary condition.
2140
2142{
2143 Double_t epsil = 0;
2144 if (fStep<1E-6) {
2146 if (fStep<0) fStep = 0.;
2147 } else {
2149 }
2150 if (is_geom) epsil=(cross)?1E-6:-1E-6;
2151 TGeoNode *old = fCurrentNode;
2152 Int_t idold = GetNodeId();
2153 if (fIsOutside) old = 0;
2154 fStep += epsil;
2155 for (Int_t i=0; i<3; i++) fPoint[i]+=fStep*fDirection[i];
2156 TGeoNode *current = FindNode();
2157 if (is_geom) {
2158 fIsEntering = (current==old)?kFALSE:kTRUE;
2159 if (!fIsEntering) {
2160 Int_t id = GetNodeId();
2161 fIsEntering = (id==idold)?kFALSE:kTRUE;
2162 }
2166 } else {
2169 }
2170 return current;
2171}
2172
2173////////////////////////////////////////////////////////////////////////////////
2174/// Find level of virtuality of current overlapping node (number of levels
2175/// up having the same tracking media.
2176
2178{
2179 // return if the current node is ONLY
2180 if (!fCurrentOverlapping) return 0;
2181 Int_t new_media = 0;
2182 TGeoMedium *medium = fCurrentNode->GetMedium();
2183 Int_t virtual_level = 1;
2184 TGeoNode *mother = 0;
2185
2186 while ((mother=GetMother(virtual_level))) {
2187 if (!mother->IsOverlapping() && !mother->IsOffset()) {
2188 if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2189 break;
2190 }
2191 if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2192 virtual_level++;
2193 }
2194 return (new_media==0)?virtual_level:(new_media-1);
2195}
2196
2197////////////////////////////////////////////////////////////////////////////////
2198/// Go upwards the tree until a non-overlapping node
2199
2201{
2202 while (fCurrentOverlapping && fLevel) CdUp();
2203 Double_t point[3];
2205 if (!fCurrentNode->GetVolume()->Contains(point)) return kFALSE;
2206 if (fNmany) {
2207 // We still have overlaps on the branch
2208 Int_t up = 1;
2209 Int_t imother;
2210 Int_t nmany = fNmany;
2211 Bool_t ovlp = kFALSE;
2212 Bool_t nextovlp = kFALSE;
2213 TGeoNode *mother, *mup;
2214 TGeoHMatrix *matrix;
2215 while (nmany) {
2216 mother = GetMother(up);
2217 if (!mother) return kTRUE;
2218 mup = mother;
2219 imother = up+1;
2220 while (mup->IsOffset()) mup = GetMother(imother++);
2221 nextovlp = mup->IsOverlapping();
2222 if (ovlp) nmany--;
2223 if (ovlp || nextovlp) {
2224 // check if the point is in the next node up
2225 matrix = GetMotherMatrix(up);
2226 matrix->MasterToLocal(fPoint,point);
2227 if (!mother->GetVolume()->Contains(point)) {
2228 up++;
2229 while (up--) CdUp();
2230 return GotoSafeLevel();
2231 }
2232 }
2233 ovlp = nextovlp;
2234 up++;
2235 }
2236 }
2237 return kTRUE;
2238}
2239
2240////////////////////////////////////////////////////////////////////////////////
2241/// Go upwards the tree until a non-overlapping node
2242
2244{
2245 Bool_t overlapping = fCurrentOverlapping;
2246 if (!overlapping) return fLevel;
2247 Int_t level = fLevel;
2248 TGeoNode *node;
2249 while (overlapping && level) {
2250 level--;
2251 node = GetMother(fLevel-level);
2252 if (!node->IsOffset()) overlapping = node->IsOverlapping();
2253 }
2254 return level;
2255}
2256
2257////////////////////////////////////////////////////////////////////////////////
2258/// Inspects path and all flags for the current state.
2259
2261{
2262 Info("InspectState","Current path is: %s",GetPath());
2263 Int_t level;
2264 TGeoNode *node;
2265 Bool_t is_offset, is_overlapping;
2266 for (level=0; level<fLevel+1; level++) {
2267 node = GetMother(fLevel-level);
2268 if (!node) continue;
2269 is_offset = node->IsOffset();
2270 is_overlapping = node->IsOverlapping();
2271 Info("InspectState","level %i: %s div=%i many=%i",level,node->GetName(),is_offset,is_overlapping);
2272 }
2273 Info("InspectState","on_bound=%i entering=%i", fIsOnBoundary, fIsEntering);
2274}
2275
2276////////////////////////////////////////////////////////////////////////////////
2277/// Checks if point (x,y,z) is still in the current node.
2278/// check if this is an overlapping node
2279
2281{
2282 Double_t oldpt[3];
2283 if (fLastSafety>0) {
2284 Double_t dx = (x-fLastPoint[0]);
2285 Double_t dy = (y-fLastPoint[1]);
2286 Double_t dz = (z-fLastPoint[2]);
2287 Double_t dsq = dx*dx+dy*dy+dz*dz;
2288 if (dsq<fLastSafety*fLastSafety) {
2289 if (change) {
2290 fPoint[0] = x;
2291 fPoint[1] = y;
2292 fPoint[2] = z;
2293 memcpy(fLastPoint, fPoint, 3*sizeof(Double_t));
2294 fLastSafety -= TMath::Sqrt(dsq);
2295 }
2296 return kTRUE;
2297 }
2298 if (change) fLastSafety = 0;
2299 }
2300 if (fCurrentOverlapping) {
2301// TGeoNode *current = fCurrentNode;
2302 Int_t cid = GetCurrentNodeId();
2303 if (!change) PushPoint();
2304 memcpy(oldpt, fPoint, kN3);
2305 SetCurrentPoint(x,y,z);
2306 SearchNode();
2307 memcpy(fPoint, oldpt, kN3);
2308 Bool_t same = (cid==GetCurrentNodeId())?kTRUE:kFALSE;
2309 if (!change) PopPoint();
2310 return same;
2311 }
2312
2313 Double_t point[3];
2314 point[0] = x;
2315 point[1] = y;
2316 point[2] = z;
2317 if (change) memcpy(fPoint, point, kN3);
2319 if (fIsOutside) {
2320 if (vol->GetShape()->Contains(point)) {
2321 if (!change) return kFALSE;
2322 FindNode(x,y,z);
2323 return kFALSE;
2324 }
2325 return kTRUE;
2326 }
2327 Double_t local[3];
2328 // convert to local frame
2329 fGlobalMatrix->MasterToLocal(point,local);
2330 // check if still in current volume.
2331 if (!vol->GetShape()->Contains(local)) {
2332 if (!change) return kFALSE;
2333 CdUp();
2334 FindNode(x,y,z);
2335 return kFALSE;
2336 }
2337
2338 // Check if the point is in a parallel world volume
2341 if (pnode) {
2342 if (!change) return kFALSE;
2343 pnode->cd();
2345 while (crtindex>=0) {
2346 // Make sure we did not end up in an assembly.
2347 CdDown(crtindex);
2349 }
2350 return kFALSE;
2351 }
2352 }
2353 // check if there are daughters
2354 Int_t nd = vol->GetNdaughters();
2355 if (!nd) return kTRUE;
2356
2357 TGeoNode *node;
2358 TGeoPatternFinder *finder = vol->GetFinder();
2359 if (finder) {
2360 node=finder->FindNode(local);
2361 if (node) {
2362 if (!change) return kFALSE;
2363 CdDown(node->GetIndex());
2364 SearchNode(kTRUE,node);
2365 return kFALSE;
2366 }
2367 return kTRUE;
2368 }
2369 // if we are not allowed to do changes, save the current path
2370 TGeoVoxelFinder *voxels = vol->GetVoxels();
2371 Int_t *check_list = 0;
2372 Int_t ncheck = 0;
2373 Double_t local1[3];
2374 if (voxels) {
2375 check_list = voxels->GetCheckList(local, ncheck, *fCache->GetInfo());
2376 if (!check_list) {
2378 return kTRUE;
2379 }
2380 if (!change) PushPath();
2381 for (Int_t id=0; id<ncheck; id++) {
2382// node = vol->GetNode(check_list[id]);
2383 CdDown(check_list[id]);
2384 fGlobalMatrix->MasterToLocal(point,local1);
2385 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2386 if (!change) {
2387 PopPath();
2389 return kFALSE;
2390 }
2393 return kFALSE;
2394 }
2395 CdUp();
2396 }
2397 if (!change) PopPath();
2399 return kTRUE;
2400 }
2401 Int_t id = 0;
2402 if (!change) PushPath();
2403 while (fCurrentNode && fCurrentNode->GetDaughter(id++)) {
2404 CdDown(id-1);
2405 fGlobalMatrix->MasterToLocal(point,local1);
2406 if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2407 if (!change) {
2408 PopPath();
2409 return kFALSE;
2410 }
2412 return kFALSE;
2413 }
2414 CdUp();
2415 if (id == nd) {
2416 if (!change) PopPath();
2417 return kTRUE;
2418 }
2419 }
2420 if (!change) PopPath();
2421 return kTRUE;
2422}
2423
2424////////////////////////////////////////////////////////////////////////////////
2425/// In case a previous safety value was computed, check if the safety region is
2426/// still safe for the current point and proposed step. Return value changed only
2427/// if proposed distance is safe.
2428
2430{
2431 // Last safety not computed.
2432 if (fLastSafety < gTolerance) return kFALSE;
2433 // Proposed step too small
2434 if (proposed < gTolerance) {
2435 newsafety = fLastSafety - proposed;
2436 return kTRUE;
2437 }
2438 // Normal step
2439 Double_t dist = (fPoint[0]-fLastPoint[0])*(fPoint[0]-fLastPoint[0])+
2440 (fPoint[1]-fLastPoint[1])*(fPoint[1]-fLastPoint[1])+
2441 (fPoint[2]-fLastPoint[2])*(fPoint[2]-fLastPoint[2]);
2442 dist = TMath::Sqrt(dist);
2443 Double_t safe = fLastSafety - dist;
2444 if (safe < proposed) return kFALSE;
2445 newsafety = safe;
2446 return kTRUE;
2447}
2448
2449////////////////////////////////////////////////////////////////////////////////
2450/// Check if a new point with given coordinates is the same as the last located one.
2451
2453{
2454 if (TMath::Abs(x-fLastPoint[0]) < 1.E-20) {
2455 if (TMath::Abs(y-fLastPoint[1]) < 1.E-20) {
2456 if (TMath::Abs(z-fLastPoint[2]) < 1.E-20) return kTRUE;
2457 }
2458 }
2459 return kFALSE;
2460}
2461
2462////////////////////////////////////////////////////////////////////////////////
2463/// Backup the current state without affecting the cache stack.
2464
2466{
2468}
2469
2470////////////////////////////////////////////////////////////////////////////////
2471/// Restore a backed-up state without affecting the cache stack.
2472
2474{
2475 if (fBackupState && fCache) {
2480 }
2481}
2482
2483////////////////////////////////////////////////////////////////////////////////
2484/// Return stored current matrix (global matrix of the next touched node).
2485
2487{
2488 if (!fCurrentMatrix) {
2491 }
2492 return fCurrentMatrix;
2493}
2494
2495////////////////////////////////////////////////////////////////////////////////
2496/// Get path to the current node in the form /node0/node1/...
2497
2498const char *TGeoNavigator::GetPath() const
2499{
2500 if (fIsOutside) return kGeoOutsidePath;
2501 return fCache->GetPath();
2502}
2503
2504////////////////////////////////////////////////////////////////////////////////
2505/// Convert coordinates from master volume frame to top.
2506
2507void TGeoNavigator::MasterToTop(const Double_t *master, Double_t *top) const
2508{
2509 fCurrentMatrix->MasterToLocal(master, top);
2510}
2511
2512////////////////////////////////////////////////////////////////////////////////
2513/// Convert coordinates from top volume frame to master.
2514
2515void TGeoNavigator::TopToMaster(const Double_t *top, Double_t *master) const
2516{
2517 fCurrentMatrix->LocalToMaster(top, master);
2518}
2519
2520////////////////////////////////////////////////////////////////////////////////
2521/// Reset the navigator.
2522
2524{
2525 GetHMatrix();
2528 ResetState();
2529 fStep = 0.;
2530 fSafety = 0.;
2531 fLastSafety = 0.;
2532 fLevel = 0;
2533 fNmany = 0;
2534 fNextDaughterIndex = -2;
2541 fLastNode = 0;
2542 fNextNode = 0;
2543 fPath = "";
2544 if (fCache) {
2545 Bool_t dummy=fCache->IsDummy();
2546 Bool_t nodeid = fCache->HasIdArray();
2547 delete fCache;
2548 fCache = nullptr;
2549 delete fBackupState;
2550 fBackupState = nullptr;
2551 BuildCache(dummy,nodeid);
2552 }
2553}
2554
2556
2557////////////////////////////////////////////////////////////////////////////////
2558/// Add a new navigator to the array.
2559
2561{
2562 SetOwner(kTRUE);
2564 nav->BuildCache(kTRUE, kFALSE);
2565 Add(nav);
2567 return nav;
2568}
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
const Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:364
XFontStruct * id
Definition TGX11.cxx:109
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=0)
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
TGeoNode * SearchNode(Bool_t downwards=kFALSE, const TGeoNode *skipnode=0)
Returns the deepest node containing fPoint, which must be set a priori.
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...
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.
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.
Bool_t RestoreState(Int_t &nmany, TGeoCacheState *state, Double_t *point=0)
Pop next state/point from a backed-up state.
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 Bool_t IsOnBoundary(const Double_t *) const
Int_t GetNdiv() const
virtual TGeoNode * FindNode(Double_t *, const Double_t *=0)
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 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=0) const =0
virtual Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=0) 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
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
void Add(TObject *obj)
Definition TObjArray.h:68
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:200
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:963
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:991
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:937
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
Double_t Sqrt(Double_t x)
Definition TMath.h:641
Short_t Min(Short_t a, Short_t b)
Definition TMathBase.h:176
Short_t Abs(Short_t d)
Definition TMathBase.h:120
Definition first.py:1
Statefull info for the current geometry level.
#define snext(osub1, osub2)
Definition triangle.c:1168