Logo ROOT   6.14/05
Reference Guide
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
16 allowed for a single geometry.
17 A default navigator is provided for any geometry but one may add several
18 others for parallel navigation:
19 
20 ~~~ {.cpp}
21 TGeoNavigator *navig = new TGeoNavigator(gGeoManager);
22 Int_t inav = gGeoManager->AddNavigator(navig);
23 gGeoManager->SetCurrentNavigator(inav);
24 ~~~
25 
26 .... and then switch back to the default navigator:
27 
28 ~~~ {.cpp}
29 gGeoManager->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 
47 const char *kGeoOutsidePath = " ";
48 const 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),
119  fStartSafe(kTRUE),
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  }
154  fCurrentMatrix = new TGeoHMatrix();
156  fDivMatrix = new TGeoHMatrix();
159  ResetAll();
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Copy constructor.
164 
166  :TObject(gm),
167  fStep(gm.fStep),
168  fSafety(gm.fSafety),
170  fThreadId(0),
171  fLevel(gm.fLevel),
172  fNmany(gm.fNmany),
188  fGeometry(gm.fGeometry),
189  fCache(gm.fCache),
192  fTopNode(gm.fTopNode),
193  fLastNode(gm.fLastNode),
194  fNextNode(gm.fNextNode),
199  fPath(gm.fPath)
200 {
202  for (Int_t i=0; i<3; i++) {
203  fNormal[i] = gm.fNormal[i];
204  fCldir[i] = gm.fCldir[i];
205  fCldirChecked[i] = gm.fCldirChecked[i];
206  fPoint[i] = gm.fPoint[i];
207  fDirection[i] = gm.fDirection[i];
208  fLastPoint[i] = gm.fLastPoint[i];
209  }
210  fDivMatrix = new TGeoHMatrix();
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// assignment operator
216 
218 {
219  if(this!=&gm) {
220  TObject::operator=(gm);
221  fStep = gm.fStep;
222  fSafety = gm.fSafety;
225  fLevel = gm.fLevel;
226  fNmany = gm.fNmany;
233  fStartSafe = gm.fStartSafe;
235  fIsExiting = gm.fIsExiting;
238  fIsOutside = gm.fIsOutside;
242  fGeometry = gm.fGeometry;
243  fCache = gm.fCache;
246  fTopNode = gm.fTopNode;
247  fLastNode = gm.fLastNode;
248  fNextNode = gm.fNextNode;
253  fPath = gm.fPath;
254  for (Int_t i=0; i<3; i++) {
255  fNormal[i] = gm.fNormal[i];
256  fCldir[i] = gm.fCldir[i];
257  fCldirChecked[i] = gm.fCldirChecked[i];
258  fPoint[i] = gm.fPoint[i];
259  fDirection[i] = gm.fDirection[i];
260  fLastPoint[i] = gm.fLastPoint[i];
261  }
262  fDivMatrix = new TGeoHMatrix();
264  }
265  return *this;
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Destructor.
270 
272 {
273  if (fCache) delete fCache;
274  if (fBackupState) delete fBackupState;
275  if (fOverlapClusters) delete [] fOverlapClusters;
276 }
277 
278 ////////////////////////////////////////////////////////////////////////////////
279 /// Builds the cache for physical nodes and global matrices.
280 
281 void TGeoNavigator::BuildCache(Bool_t /*dummy*/, Bool_t nodeid)
282 {
283  static Bool_t first = kTRUE;
285  Int_t nlevel = fGeometry->GetMaxLevel();
286  if (nlevel<=0) nlevel = 100;
287  if (!fCache) {
288  if (nlevel==100) {
289  if (first && verbose>0) Info("BuildCache","--- Maximum geometry depth set to 100");
290  } else {
291  if (first && verbose>0) Info("BuildCache","--- Maximum geometry depth is %i", nlevel);
292  }
293  // build cache
294  fCache = new TGeoNodeCache(fGeometry->GetTopNode(), nodeid, nlevel+1);
296  fBackupState = new TGeoCacheState(nlevel+1);
297  }
298  first = kFALSE;
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// Browse the tree of nodes starting from top node according to pathname.
303 /// Changes the path accordingly. The path is changed to point to the top node
304 /// in case of failure.
305 
306 Bool_t TGeoNavigator::cd(const char *path)
307 {
308  CdTop();
309  if (!path[0]) return kTRUE;
310  TString spath = path;
311  TGeoVolume *vol;
312  Int_t length = spath.Length();
313  Int_t ind1 = spath.Index("/");
314  if (ind1 == length-1) ind1 = -1;
315  Int_t ind2 = 0;
316  Bool_t end = kFALSE;
317  Bool_t first = kTRUE;
318  TString name;
319  TGeoNode *node;
320  while (!end) {
321  ind2 = spath.Index("/", ind1+1);
322  if (ind2<0 || ind2==length-1) {
323  if (ind2<0) ind2 = length;
324  end = kTRUE;
325  }
326  name = spath(ind1+1, ind2-ind1-1);
327  vol = fCurrentNode->GetVolume();
328  if (first) {
329  first = kFALSE;
330  if (name.BeginsWith(vol->GetName())) {
331  ind1 = ind2;
332  continue;
333  }
334  }
335  node = vol->GetNode(name.Data());
336  if (!node) {
337  Error("cd", "Path %s not valid", path);
338  return kFALSE;
339  }
340  CdDown(vol->GetIndex(node));
341  ind1 = ind2;
342  }
343  return kTRUE;
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////////
347 /// Check if a geometry path is valid without changing the state of the navigator.
348 
349 Bool_t TGeoNavigator::CheckPath(const char *path) const
350 {
351  if (!path[0]) return kTRUE;
352  TGeoNode *crtnode = fGeometry->GetTopNode();
353  TString spath = path;
354  TGeoVolume *vol;
355  Int_t length = spath.Length();
356  Int_t ind1 = spath.Index("/");
357  if (ind1 == length-1) ind1 = -1;
358  Int_t ind2 = 0;
359  Bool_t end = kFALSE;
360  Bool_t first = kTRUE;
361  TString name;
362  TGeoNode *node;
363  while (!end) {
364  ind2 = spath.Index("/", ind1+1);
365  if (ind2<0 || ind2==length-1) {
366  if (ind2<0) ind2 = length;
367  end = kTRUE;
368  }
369  name = spath(ind1+1, ind2-ind1-1);
370  vol = crtnode->GetVolume();
371  if (first) {
372  first = kFALSE;
373  if (name.BeginsWith(vol->GetName())) {
374  ind1 = ind2;
375  continue;
376  }
377  }
378  node = vol->GetNode(name.Data());
379  if (!node) return kFALSE;
380  crtnode = node;
381  ind1 = ind2;
382  }
383  return kTRUE;
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Change current path to point to the node having this id.
388 /// Node id has to be in range : 0 to fNNodes-1 (no check for performance reasons)
389 
391 {
392  if (fCache) {
393  fCache->CdNode(nodeid);
395  }
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 /// Make a daughter of current node current. Can be called only with a valid
400 /// daughter index (no check). Updates cache accordingly.
401 
403 {
404  TGeoNode *node = fCurrentNode->GetDaughter(index);
405  Bool_t is_offset = node->IsOffset();
406  if (is_offset)
407  node->cd();
408  else
410  fCache->CdDown(index);
411  fCurrentNode = node;
414  fLevel++;
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// Make a daughter of current node current. Can be called only with a valid
419 /// daughter node (no check). Updates cache accordingly.
420 
422 {
423  Bool_t is_offset = node->IsOffset();
424  if (is_offset)
425  node->cd();
426  else
428  fCache->CdDown(node);
429  fCurrentNode = node;
432  fLevel++;
433 }
434 
435 ////////////////////////////////////////////////////////////////////////////////
436 /// Go one level up in geometry. Updates cache accordingly.
437 /// Determine the overlapping state of current node.
438 
440 {
441  if (!fLevel || !fCache) return;
442  fLevel--;
443  if (!fLevel) {
444  CdTop();
445  return;
446  }
447  fCache->CdUp();
448  if (fCurrentOverlapping) {
450  fNmany--;
451  }
454  if (!fCurrentNode->IsOffset()) {
456  } else {
457  Int_t up = 1;
458  Bool_t offset = kTRUE;
459  TGeoNode *mother = 0;
460  while (offset) {
461  mother = GetMother(up++);
462  offset = mother->IsOffset();
463  }
465  }
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// Make top level node the current node. Updates the cache accordingly.
470 /// Determine the overlapping state of current node.
471 
473 {
474  if (!fCache) return;
475  fLevel = 0;
476  fNmany = 0;
479  fCache->CdTop();
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// Do a cd to the node found next by FindNextBoundary
487 
489 {
490  if (fNextDaughterIndex == -2 || !fCache) return;
491  if (fNextDaughterIndex == -3) {
492  // Next node is a many - restore it
493  DoRestoreState();
494  fNextDaughterIndex = -2;
495  return;
496  }
497  if (fNextDaughterIndex == -1) {
498  CdUp();
499  while (fCurrentNode->GetVolume()->IsAssembly()) CdUp();
501  return;
502  }
503  if (fCurrentNode && fNextDaughterIndex<fCurrentNode->GetNdaughters()) {
505  Int_t nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
506  while (nextindex>=0) {
507  CdDown(nextindex);
508  nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
509  }
510  }
511  fNextDaughterIndex = -2;
512 }
513 
514 ////////////////////////////////////////////////////////////////////////////////
515 /// Fill volume names of current branch into an array.
516 
518 {
519  fCache->GetBranchNames(names);
520 }
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 /// Fill node copy numbers of current branch into an array.
524 
525 void TGeoNavigator::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
526 {
527  fCache->GetBranchNumbers(copyNumbers, volumeNumbers);
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 /// Fill node copy numbers of current branch into an array.
532 
534 {
535  fCache->GetBranchOnlys(isonly);
536 }
537 
538 ////////////////////////////////////////////////////////////////////////////////
539 /// Cross a division cell. Distance to exit contained in fStep, current node
540 /// points to the cell node.
541 
543 {
545  if (!finder) {
546  Fatal("CrossDivisionCell", "Volume has no pattern finder");
547  return 0;
548  }
549  // Mark current node and go up to the level of the divided volume
550  TGeoNode *skip = fCurrentNode;
551  CdUp();
552  Double_t point[3], newpoint[3], dir[3];
553  fGlobalMatrix->MasterToLocal(fPoint, newpoint);
555  // Does step cross a boundary along division axis ?
556  Bool_t onbound = finder->IsOnBoundary(newpoint);
557  if (onbound) {
558  // Work along division axis
559  // Get the starting point
560  point[0] = newpoint[0] - dir[0]*fStep*(1.-gTolerance);
561  point[1] = newpoint[1] - dir[1]*fStep*(1.-gTolerance);
562  point[2] = newpoint[2] - dir[2]*fStep*(1.-gTolerance);
563  // Find which is the next crossed cell.
564  finder->FindNode(point, dir);
565  Int_t inext = finder->GetNext();
566  if (inext<0) {
567  // step fully exits the division along the division axis
568  // Do step exits in a mother cell ?
569  if (fCurrentNode->IsOffset()) {
571  // Do step exit also from mother cell ?
572  if (dist < fStep+2.*gTolerance) {
573  // Step exits mother on its own division axis
574  return CrossDivisionCell();
575  }
576  // We end up here
577  return fCurrentNode;
578  }
579  // Exiting in a non-divided volume
580  while (fCurrentNode->GetVolume()->IsAssembly()) {
581  // Move always to mother for assemblies
582  skip = fCurrentNode;
583  if (!fLevel) break;
584  CdUp();
585  }
586  return CrossBoundaryAndLocate(kFALSE, skip);
587  }
588  // step enters a new cell
589  CdDown(inext+finder->GetDivIndex());
590  skip = fCurrentNode;
591  return CrossBoundaryAndLocate(kTRUE, skip);
592  }
593  // step exits on an axis other than the division axis -> get next slice
594  if (fCurrentNode->IsOffset()) return CrossDivisionCell();
595  return CrossBoundaryAndLocate(kFALSE, skip);
596 }
597 
598 ////////////////////////////////////////////////////////////////////////////////
599 /// Cross next boundary and locate within current node
600 /// The current point must be on the boundary of fCurrentNode.
601 
603 {
604 // Extrapolate current point with estimated error.
606  Double_t trmax = 1.+TMath::Abs(tr[0])+TMath::Abs(tr[1])+TMath::Abs(tr[2]);
607  Double_t extra = 100.*(trmax+fStep)*gTolerance;
608  const Int_t idebug = TGeoManager::GetVerboseLevel();
609  TGeoNode *crtstate[10];
610  Int_t level = fLevel+1;
611  Bool_t samepath = kFALSE;
612  if (!downwards) {
613  for (Int_t i=0; i<fLevel; ++i) {
614  crtstate[i] = GetMother(i);
615  if (i==9) break;
616  }
617  }
618  fPoint[0] += extra*fDirection[0];
619  fPoint[1] += extra*fDirection[1];
620  fPoint[2] += extra*fDirection[2];
621  TGeoNode *current = SearchNode(downwards, skipnode);
622  fForcedNode = 0;
623  fPoint[0] -= extra*fDirection[0];
624  fPoint[1] -= extra*fDirection[1];
625  fPoint[2] -= extra*fDirection[2];
626  if (!current) return 0;
627  if (downwards) {
628  Int_t nextindex = current->GetVolume()->GetNextNodeIndex();
629  while (nextindex>=0) {
630  CdDown(nextindex);
631  current = fCurrentNode;
632  nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
633  }
634  if (idebug>4) {
635  printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
636  }
637  return current;
638  }
639 
640  if (skipnode) {
641  if ((current == skipnode) && (level == fLevel) ) {
642  samepath = kTRUE;
643  level = TMath::Min(level, 10);
644  for (Int_t i=1; i<level; i++) {
645  if (crtstate[i-1] != GetMother(i)) {
646  samepath = kFALSE;
647  break;
648  }
649  }
650  }
651  }
652 
653  if (samepath || current->GetVolume()->IsAssembly()) {
654  if (!fLevel) {
655  fIsOutside = kTRUE;
656  if (idebug>4) {
657  printf("CrossBoundaryAndLocate: Exited geometry\n");
658  }
659  return fGeometry->GetCurrentNode();
660  }
661  CdUp();
662  while (fLevel && fCurrentNode->GetVolume()->IsAssembly()) CdUp();
663  if (!fLevel && fCurrentNode->GetVolume()->IsAssembly()) {
664  fIsOutside = kTRUE;
665  if (idebug>4) {
666  printf("CrossBoundaryAndLocate: Exited geometry\n");
667  }
668  if (idebug>4) {
669  printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
670  }
671  return fCurrentNode;
672  }
673  return fCurrentNode;
674  }
675  if (idebug>4) {
676  printf("CrossBoundaryAndLocate: entered %s\n", GetPath());
677  }
678  return current;
679 }
680 
681 ////////////////////////////////////////////////////////////////////////////////
682 /// Find distance to next boundary and store it in fStep. Returns node to which this
683 /// boundary belongs. If PATH is specified, compute only distance to the node to which
684 /// PATH points. If STEPMAX is specified, compute distance only in case fSafety is smaller
685 /// than this value. STEPMAX represent the step to be made imposed by other reasons than
686 /// geometry (usually physics processes). Therefore in this case this method provides the
687 /// answer to the question : "Is STEPMAX a safe step ?" returning a NULL node and filling
688 /// fStep with a big number.
689 /// In case frombdr=kTRUE, the isotropic safety is set to zero.
690 ///
691 /// Note : safety distance for the current point is computed ONLY in case STEPMAX is
692 /// specified, otherwise users have to call explicitly TGeoManager::Safety() if
693 /// they want this computed for the current point.
694 
695 TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax, const char *path, Bool_t frombdr)
696 {
697  // convert current point and direction to local reference
698  Int_t iact = 3;
700  fNextDaughterIndex = -2;
701  fStep = TGeoShape::Big();
704  fForcedNode = 0;
705  Bool_t computeGlobal = kFALSE;
706  fIsOnBoundary = frombdr;
707  fSafety = 0.;
708  TGeoNode *top_node = fGeometry->GetTopNode();
709  TGeoVolume *top_volume = top_node->GetVolume();
710  // If inside an assembly, go logically up in the hierarchy
711  while (fCurrentNode->GetVolume()->IsAssembly() && fLevel) CdUp();
712  if (stepmax<1E29) {
713  if (stepmax <= 0) {
714  stepmax = - stepmax;
715  computeGlobal = kTRUE;
716  }
717 // if (fLastSafety>0 && IsSamePoint(fPoint[0], fPoint[1], fPoint[2])) fSafety = fLastSafety;
718  fSafety = Safety();
719  // Try to get out easy if proposed step within safe region
720  if (!frombdr && (fSafety>0) && IsSafeStep(stepmax+gTolerance, fSafety)) {
721  fStep = stepmax;
723  return fCurrentNode;
724  }
726  memcpy(fLastPoint, fPoint, kN3);
729  else fIsOnBoundary = kFALSE;
730  fStep = stepmax;
731  if (stepmax+gTolerance<fSafety) {
733  return fCurrentNode;
734  }
735  }
736  if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
738  Double_t safe;
739  Double_t point[3];
740  Double_t dir[3];
741  if (idebug>4) {
742  printf("TGeoManager::FindNextBoundary: point=(%19.16f, %19.16f, %19.16f)\n",
743  fPoint[0],fPoint[1],fPoint[2]);
744  printf(" dir= (%19.16f, %19.16f, %19.16f)\n",
745  fDirection[0], fDirection[1], fDirection[2]);
746  printf(" pstep=%9.6g path=%s\n", stepmax, GetPath());
747  }
748  if (path[0]) {
749  PushPath();
750  if (!cd(path)) {
751  PopPath();
752  return 0;
753  }
754  if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
757  fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
759  if (idebug>4) {
760  printf("=== To path: %s\n", path);
761  printf("=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
762  tvol->GetName(), point[0],point[1],point[2],dir[0],dir[1],dir[2]);
763  }
764  if (tvol->Contains(point)) {
765  if (idebug>4) printf("=== volume %s contains point\n", tvol->GetName());
766  fStep=tvol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
767  } else {
768  fStep=tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, fStep, &safe);
769  if (idebug>4) {
770  printf("=== volume %s does not contain point\n", tvol->GetName());
771  printf("=== distance to path: %g\n", fStep);
772  tvol->InspectShape();
773  if (fStep<1.E20) {
774  Double_t newpt[3];
775  newpt[0] = point[0] + fStep*dir[0];
776  newpt[1] = point[1] + fStep*dir[1];
777  newpt[2] = point[2] + fStep*dir[2];
778  printf("=== Propagated point: (%19.16f, %19.16f, %19.16f)", newpt[0],newpt[1],newpt[2]);
779  }
780  while (fLevel) {
781  CdUp();
782  tvol = fCurrentNode->GetVolume();
783  fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
785  printf("=== local to %s: (%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
786  tvol->GetName(), point[0],point[1],point[2],dir[0],dir[1],dir[2]);
787  if (tvol->Contains(point)) {
788  printf("=== volume %s contains point\n", tvol->GetName());
789  } else {
790  printf("=== volume %s does not contain point\n", tvol->GetName());
791  snext = tvol->GetShape()->DistFromOutside(&point[0], &dir[0], iact, 1.E30, &safe);
792  }
793  }
794  }
795  }
796  PopPath();
797  return fNextNode;
798  }
799  // compute distance to exit point from current node and the distance to its
800  // closest boundary
801  // if point is outside, just check the top node
802  if (fIsOutside) {
803  snext = top_volume->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep, &safe);
804  fNextNode = top_node;
805  if (snext < fStep-gTolerance) {
807  fStep = snext;
808  Int_t indnext = fNextNode->GetVolume()->GetNextNodeIndex();
809  fNextDaughterIndex = indnext;
810  while (indnext>=0) {
811  fNextNode = fNextNode->GetDaughter(indnext);
812  if (computeGlobal) fCurrentMatrix->Multiply(fNextNode->GetMatrix());
813  indnext = fNextNode->GetVolume()->GetNextNodeIndex();
814  }
815  return fNextNode;
816  }
817  return 0;
818  }
819  fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
822  if (idebug>4) {
823  printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
824  point[0],point[1],point[2]);
825  printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
826  dir[0],dir[1],dir[2]);
827  }
828  // find distance to exiting current node
829  snext = vol->GetShape()->DistFromInside(&point[0], &dir[0], iact, fStep, &safe);
830  if (idebug>4) {
831  printf(" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
832  }
833  if (snext < fStep-gTolerance) {
835  fNextDaughterIndex = -1;
837  fStep = snext;
839  if (fStep<1E-6) return fCurrentNode;
840  }
841  fNextNode = (fStep<1E20)?fCurrentNode:0;
842  // Find next daughter boundary for the current volume
843  Int_t idaughter = -1;
844  FindNextDaughterBoundary(point,dir,idaughter,computeGlobal);
845  if (idaughter>=0) fNextDaughterIndex = idaughter;
846  TGeoNode *current = 0;
847  TGeoNode *dnode = 0;
848  TGeoVolume *mother = 0;
849  // if we are in an overlapping node, check also the mother(s)
850  if (fNmany) {
851  Double_t mothpt[3];
852  Double_t vecpt[3];
853  Double_t dpt[3], dvec[3];
854  Int_t novlps;
855  Int_t idovlp = -1;
856  Int_t safelevel = GetSafeLevel();
857  PushPath(safelevel+1);
858  while (fCurrentOverlapping) {
859  Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
860  CdUp();
861  mother = fCurrentNode->GetVolume();
862  fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
864  // check distance to out
865  snext = TGeoShape::Big();
866  if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(&mothpt[0], &vecpt[0], iact, fStep, &safe);
867  if (snext<fStep-gTolerance) {
870  fStep = snext;
871  if (computeGlobal) fCurrentMatrix->CopyFrom(fGlobalMatrix);
873  fNextDaughterIndex = -3;
874  DoBackupState();
875  }
876  // check overlapping nodes
877  for (Int_t i=0; i<novlps; i++) {
878  current = mother->GetNode(ovlps[i]);
879  if (!current->IsOverlapping()) {
880  current->cd();
881  current->MasterToLocal(&mothpt[0], &dpt[0]);
882  current->MasterToLocalVect(&vecpt[0], &dvec[0]);
883  // Current point may be inside the other node - geometry error that we ignore
884  snext = TGeoShape::Big();
885  if (!current->GetVolume()->Contains(dpt))
886  snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
887  if (snext<fStep-gTolerance) {
888  if (computeGlobal) {
890  fCurrentMatrix->Multiply(current->GetMatrix());
891  }
894  fStep = snext;
895  fNextNode = current;
896  fNextDaughterIndex = -3;
897  CdDown(ovlps[i]);
898  DoBackupState();
899  CdUp();
900  }
901  } else {
902  // another many - check if point is in or out
903  current->cd();
904  current->MasterToLocal(&mothpt[0], &dpt[0]);
905  current->MasterToLocalVect(&vecpt[0], &dvec[0]);
906  if (current->GetVolume()->Contains(dpt)) {
907  if (current->GetVolume()->GetNdaughters()) {
908  CdDown(ovlps[i]);
911  dnode = FindNextDaughterBoundary(dpt,dvec,idovlp,computeGlobal);
912  if (dnode) {
913  if (computeGlobal) {
915  fCurrentMatrix->Multiply(dnode->GetMatrix());
916  }
917  fNextNode = dnode;
918  fNextDaughterIndex = -3;
919  CdDown(idovlp);
921  Int_t iup=0;
922  while (indnext>=0) {
923  CdDown(indnext);
924  iup++;
925  indnext = fCurrentNode->GetVolume()->GetNextNodeIndex();
926  }
927  DoBackupState();
928  while (iup>0) {
929  CdUp();
930  iup--;
931  }
932  CdUp();
933  }
934  CdUp();
935  }
936  } else {
937  snext = current->GetVolume()->GetShape()->DistFromOutside(&dpt[0], &dvec[0], iact, fStep, &safe);
938  if (snext<fStep-gTolerance) {
939  if (computeGlobal) {
941  fCurrentMatrix->Multiply(current->GetMatrix());
942  }
945  fStep = snext;
946  fNextNode = current;
947  fNextDaughterIndex = -3;
948  CdDown(ovlps[i]);
949  DoBackupState();
950  CdUp();
951  }
952  }
953  }
954  }
955  }
956  // Now we are in a non-overlapping node
957  if (fNmany) {
958  // We have overlaps up in the branch, check distance to exit
959  Int_t up = 1;
960  Int_t imother;
961  Int_t nmany = fNmany;
962  Bool_t ovlp = kFALSE;
963  Bool_t nextovlp = kFALSE;
964  Bool_t offset = kFALSE;
965  TGeoNode *currentnode = fCurrentNode;
966  TGeoNode *mothernode, *mup;
967  TGeoHMatrix *matrix;
968  while (nmany) {
969  mothernode = GetMother(up);
970  if (!mothernode) {
971  Fatal("FindNextBoundary", "Cannot find mother node");
972  return 0;
973  }
974  mup = mothernode;
975  imother = up+1;
976  offset = kFALSE;
977  while (mup->IsOffset()) {
978  mup = GetMother(imother++);
979  offset = kTRUE;
980  }
981  nextovlp = mup->IsOverlapping();
982  if (offset) {
983  mothernode = mup;
984  if (nextovlp) nmany -= imother-up;
985  up = imother-1;
986  } else {
987  if (ovlp) nmany--;
988  }
989  if (ovlp || nextovlp) {
990  matrix = GetMotherMatrix(up);
991  if (!matrix) {
992  Fatal("FindNextBoundary", "Cannot find mother matrix");
993  return 0;
994  }
995  matrix->MasterToLocal(fPoint,dpt);
996  matrix->MasterToLocalVect(fDirection,dvec);
997  snext = TGeoShape::Big();
998  if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
999  if (snext<fStep-gTolerance) {
1002  fStep = snext;
1003  fNextNode = mothernode;
1004  fNextDaughterIndex = -3;
1005  if (computeGlobal) fCurrentMatrix->CopyFrom(matrix);
1006  while (up--) CdUp();
1007  DoBackupState();
1008  up = 1;
1009  currentnode = fCurrentNode;
1010  ovlp = currentnode->IsOverlapping();
1011  continue;
1012  }
1013  }
1014  currentnode = mothernode;
1015  ovlp = nextovlp;
1016  up++;
1017  }
1018  }
1019  PopPath();
1020  }
1021  // Compute now the distance in case we have a parallel world
1022  Double_t parstep = TGeoShape::Big();
1023  if (fGeometry->IsParallelWorldNav()) {
1024 // printf("path: %s next node %s at %g\n", GetPath(), fNextNode->GetName(), fStep);
1026  if (pnode) {
1027  // A boundary is hit at less than fPStep
1028  fStep = parstep;
1029  fNextNode = pnode->GetNode();
1030  fNextDaughterIndex = -2; // No way to store it for CdNext
1033  Int_t nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1034  while (nextindex>=0) {
1035  fNextNode = fNextNode->GetDaughter(nextindex);
1036  nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1037  }
1038  }
1039  }
1040  return fNextNode;
1041 }
1042 
1043 ////////////////////////////////////////////////////////////////////////////////
1044 /// Computes as fStep the distance to next daughter of the current volume.
1045 /// The point and direction must be converted in the coordinate system of the current volume.
1046 /// The proposed step limit is fStep.
1047 
1049 {
1052  idaughter = -1; // nothing crossed
1053  TGeoNode *nodefound = 0;
1054  // Get number of daughters. If no daughters we are done.
1055 
1056  TGeoVolume *vol = fCurrentNode->GetVolume();
1057  Int_t nd = vol->GetNdaughters();
1058  if (!nd) return 0; // No daughter
1059  if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters()) return 0;
1060  Double_t lpoint[3], ldir[3];
1061  TGeoNode *current = 0;
1062  Int_t i=0;
1063  // if current volume is divided, we are in the non-divided region. We
1064  // check first if we are inside a cell in which case compute distance to next cell
1065  TGeoPatternFinder *finder = vol->GetFinder();
1066  if (finder) {
1067  Int_t ifirst = finder->GetDivIndex();
1068  Int_t ilast = ifirst+finder->GetNdiv()-1;
1069  current = finder->FindNode(point);
1070  if (current) {
1071  // Point inside a cell: find distance to next cell
1072  Int_t index = current->GetIndex();
1073  if ((index-1) >= ifirst) ifirst = index-1;
1074  else ifirst = -1;
1075  if ((index+1) <= ilast) ilast = index+1;
1076  else ilast = -1;
1077  }
1078  if (ifirst>=0) {
1079  current = vol->GetNode(ifirst);
1080  current->cd();
1081  current->MasterToLocal(&point[0], lpoint);
1082  current->MasterToLocalVect(&dir[0], ldir);
1083  snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1084  if (snext<fStep-gTolerance) {
1085  if (compmatrix) {
1087  fCurrentMatrix->Multiply(current->GetMatrix());
1088  }
1091  fStep=snext;
1092  fNextNode = current;
1093  nodefound = current;
1094  idaughter = ifirst;
1095  }
1096  }
1097  if (ilast==ifirst) return nodefound;
1098  if (ilast>=0) {
1099  current = vol->GetNode(ilast);
1100  current->cd();
1101  current->MasterToLocal(&point[0], lpoint);
1102  current->MasterToLocalVect(&dir[0], ldir);
1103  snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1104  if (snext<fStep-gTolerance) {
1105  if (compmatrix) {
1107  fCurrentMatrix->Multiply(current->GetMatrix());
1108  }
1111  fStep=snext;
1112  fNextNode = current;
1113  nodefound = current;
1114  idaughter = ilast;
1115  }
1116  }
1117  return nodefound;
1118  }
1119  // if only few daughters, check all and exit
1120  TGeoVoxelFinder *voxels = vol->GetVoxels();
1121  Int_t indnext;
1122  if (idebug>4) printf(" Checking distance to %d daughters...\n",nd);
1123  if (nd<5 || !voxels) {
1124  for (i=0; i<nd; i++) {
1125  current = vol->GetNode(i);
1126  if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
1127  current->cd();
1128  if (voxels && voxels->IsSafeVoxel(point, i, fStep)) continue;
1129  current->MasterToLocal(point, lpoint);
1130  current->MasterToLocalVect(dir, ldir);
1131  if (current->IsOverlapping() &&
1132  current->GetVolume()->Contains(lpoint) &&
1133  current->GetVolume()->GetShape()->Safety(lpoint, kTRUE) > gTolerance) continue;
1134  snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1135  if (snext<fStep-gTolerance) {
1136  if (idebug>4) {
1137  printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1138  lpoint[0],lpoint[1],lpoint[2]);
1139  printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
1140  ldir[0],ldir[1],ldir[2]);
1141  printf(" -> to: %s shape %s snext=%g\n", current->GetName(),
1142  current->GetVolume()->GetShape()->ClassName(), snext);
1143  }
1144  indnext = current->GetVolume()->GetNextNodeIndex();
1145  if (compmatrix) {
1147  fCurrentMatrix->Multiply(current->GetMatrix());
1148  }
1151  fStep=snext;
1152  fNextNode = current;
1153  nodefound = fNextNode;
1154  idaughter = i;
1155  while (indnext>=0) {
1156  current = current->GetDaughter(indnext);
1157  if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
1158  fNextNode = current;
1159  nodefound = current;
1160  indnext = current->GetVolume()->GetNextNodeIndex();
1161  }
1162  }
1163  }
1164  if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
1165  return nodefound;
1166  }
1167  // if current volume is voxelized, first get current voxel
1168  Int_t ncheck = 0;
1169  Int_t sumchecked = 0;
1170  Int_t *vlist = 0;
1171  TGeoStateInfo &info = *fCache->GetInfo();
1172  voxels->SortCrossedVoxels(point, dir, info);
1173  while ((sumchecked<nd) && (vlist=voxels->GetNextVoxel(point, dir, ncheck, info))) {
1174  for (i=0; i<ncheck; i++) {
1175  current = vol->GetNode(vlist[i]);
1176  if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
1177  current->cd();
1178  current->MasterToLocal(point, lpoint);
1179  current->MasterToLocalVect(dir, ldir);
1180  if (current->IsOverlapping() && current->GetVolume()->Contains(lpoint)) continue;
1181  snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, fStep);
1182  sumchecked++;
1183 // printf("checked %d from %d : snext=%g\n", sumchecked, nd, snext);
1184  if (snext<fStep-gTolerance) {
1185  if (idebug>4) {
1186  printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1187  lpoint[0],lpoint[1],lpoint[2]);
1188  printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
1189  ldir[0],ldir[1],ldir[2]);
1190  printf(" -> to: %s shape %s snext=%g\n", current->GetName(),
1191  current->GetVolume()->GetShape()->ClassName(), snext);
1192  }
1193  indnext = current->GetVolume()->GetNextNodeIndex();
1194  if (compmatrix) {
1196  fCurrentMatrix->Multiply(current->GetMatrix());
1197  }
1200  fStep=snext;
1201  fNextNode = current;
1202  nodefound = fNextNode;
1203  idaughter = vlist[i];
1204  while (indnext>=0) {
1205  current = current->GetDaughter(indnext);
1206  if (compmatrix) fCurrentMatrix->Multiply(current->GetMatrix());
1207  fNextNode = current;
1208  nodefound = current;
1209  indnext = current->GetVolume()->GetNextNodeIndex();
1210  }
1211  }
1212  }
1213  }
1214  fCache->ReleaseInfo();
1215  if (vol->IsAssembly()) ((TGeoVolumeAssembly*)vol)->SetNextNodeIndex(idaughter);
1216  return nodefound;
1217 }
1218 
1219 ////////////////////////////////////////////////////////////////////////////////
1220 /// Compute distance to next boundary within STEPMAX. If no boundary is found,
1221 /// propagate current point along current direction with fStep=STEPMAX. Otherwise
1222 /// propagate with fStep=SNEXT (distance to boundary) and locate/return the next
1223 /// node.
1224 
1226 {
1227  static Int_t icount = 0;
1228  icount++;
1229  Int_t iact = 3;
1231  Int_t nextindex;
1232  Bool_t is_assembly;
1233  fForcedNode = 0;
1235  TGeoNode *skip;
1237  fStep = stepmax;
1239  // If inside an assembly, go logically up in the hierarchy
1240  while (fCurrentNode->GetVolume()->IsAssembly() && fLevel) CdUp();
1241  if (compsafe) {
1242  // Try to get out easy if proposed step within safe region
1244  if (IsSafeStep(stepmax+gTolerance, fSafety)) {
1245  fPoint[0] += stepmax*fDirection[0];
1246  fPoint[1] += stepmax*fDirection[1];
1247  fPoint[2] += stepmax*fDirection[2];
1248  return fCurrentNode;
1249  }
1250  Safety();
1251  fLastSafety = fSafety;
1252  memcpy(fLastPoint, fPoint, kN3);
1253  // If proposed step less than safety, nothing to check
1254  if (fSafety > stepmax+gTolerance) {
1255  fPoint[0] += stepmax*fDirection[0];
1256  fPoint[1] += stepmax*fDirection[1];
1257  fPoint[2] += stepmax*fDirection[2];
1258  return fCurrentNode;
1259  }
1260  }
1261  Double_t extra = (fIsOnBoundary)?gTolerance:0.0;
1263  fPoint[0] += extra*fDirection[0];
1264  fPoint[1] += extra*fDirection[1];
1265  fPoint[2] += extra*fDirection[2];
1267  if (idebug>4) {
1268  printf("TGeoManager::FindNextBAndStep: point=(%19.16f, %19.16f, %19.16f)\n",
1269  fPoint[0],fPoint[1],fPoint[2]);
1270  printf(" dir= (%19.16f, %19.16f, %19.16f)\n",
1271  fDirection[0], fDirection[1], fDirection[2]);
1272  printf(" pstep=%9.6g path=%s\n", stepmax, GetPath());
1273  }
1274 
1275  if (fIsOutside) {
1276  snext = fGeometry->GetTopVolume()->GetShape()->DistFromOutside(fPoint, fDirection, iact, fStep);
1277  if (snext < fStep-gTolerance) {
1278  if (snext<=0) {
1279  snext = 0.0;
1280  fStep = snext;
1281  fPoint[0] -= extra*fDirection[0];
1282  fPoint[1] -= extra*fDirection[1];
1283  fPoint[2] -= extra*fDirection[2];
1284  } else {
1285  fStep = snext+extra;
1286  }
1289  nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1290  while (nextindex>=0) {
1291  CdDown(nextindex);
1293  nextindex = fNextNode->GetVolume()->GetNextNodeIndex();
1294  if (nextindex<0) fCurrentMatrix->CopyFrom(fGlobalMatrix);
1295  }
1296  // Update global point
1297  fPoint[0] += snext*fDirection[0];
1298  fPoint[1] += snext*fDirection[1];
1299  fPoint[2] += snext*fDirection[2];
1300  fIsOnBoundary = kTRUE;
1301  fIsOutside = kFALSE;
1304  }
1305  if (snext<TGeoShape::Big()) {
1306  // New point still outside, but the top node is reachable
1308  fPoint[0] += (fStep-extra)*fDirection[0];
1309  fPoint[1] += (fStep-extra)*fDirection[1];
1310  fPoint[2] += (fStep-extra)*fDirection[2];
1311  return fNextNode;
1312  }
1313  // top node not reachable from current point/direction
1314  fNextNode = 0;
1316  return 0;
1317  }
1318  Double_t point[3],dir[3];
1319  Int_t icrossed = -2;
1320  fGlobalMatrix->MasterToLocal(fPoint, &point[0]);
1321  fGlobalMatrix->MasterToLocalVect(fDirection, &dir[0]);
1322  TGeoVolume *vol = fCurrentNode->GetVolume();
1323  // find distance to exiting current node
1324  if (idebug>4) {
1325  printf(" -> from local=(%19.16f, %19.16f, %19.16f)\n",
1326  point[0],point[1],point[2]);
1327  printf(" ldir =(%19.16f, %19.16f, %19.16f)\n",
1328  dir[0],dir[1],dir[2]);
1329  }
1330  // find distance to exiting current node
1331  snext = vol->GetShape()->DistFromInside(point, dir, iact, fStep);
1332  if (idebug>4) {
1333  printf(" exiting %s shape %s at snext=%g\n", vol->GetName(), vol->GetShape()->ClassName(),snext);
1334  }
1336  if (snext <= gTolerance) {
1337  // Current point on the boundary while track exiting
1338  snext = gTolerance;
1339  fStep = snext;
1340  fIsOnBoundary = kTRUE;
1343  skip = fCurrentNode;
1344  fPoint[0] += fStep*fDirection[0];
1345  fPoint[1] += fStep*fDirection[1];
1346  fPoint[2] += fStep*fDirection[2];
1347  is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1348  if (!fLevel && !is_assembly) {
1349  fIsOutside = kTRUE;
1350  return 0;
1351  }
1352  if (fCurrentNode->IsOffset()) return CrossDivisionCell();
1353  if (fLevel) CdUp();
1354  else skip = 0;
1355  return CrossBoundaryAndLocate(kFALSE, skip);
1356  }
1357 
1358  if (snext < fStep-gTolerance) {
1359  // Currently the minimum step chosen is the exiting one
1360  icrossed = -1;
1361  fStep = snext;
1364  }
1365  // Find next daughter boundary for the current volume
1366  Int_t idaughter = -1;
1367  TGeoNode *crossed = FindNextDaughterBoundary(point,dir, idaughter, kTRUE);
1368  if (crossed) {
1370  icrossed = idaughter;
1372  }
1373  TGeoNode *current = 0;
1374  TGeoNode *dnode = 0;
1375  TGeoVolume *mother = 0;
1376  // if we are in an overlapping node, check also the mother(s)
1377  if (fNmany) {
1378  Double_t mothpt[3];
1379  Double_t vecpt[3];
1380  Double_t dpt[3], dvec[3];
1381  Int_t novlps;
1382  Int_t safelevel = GetSafeLevel();
1383  PushPath(safelevel+1);
1384  while (fCurrentOverlapping) {
1385  Int_t *ovlps = fCurrentNode->GetOverlaps(novlps);
1386  CdUp();
1387  mother = fCurrentNode->GetVolume();
1388  fGlobalMatrix->MasterToLocal(fPoint, &mothpt[0]);
1389  fGlobalMatrix->MasterToLocalVect(fDirection, &vecpt[0]);
1390  // check distance to out
1391  snext = TGeoShape::Big();
1392  if (!mother->IsAssembly()) snext = mother->GetShape()->DistFromInside(mothpt, vecpt, iact, fStep);
1393  if (snext<fStep-gTolerance) {
1394  // exiting mother first (extrusion)
1395  icrossed = -1;
1396  PopDummy();
1397  PushPath(safelevel+1);
1400  fStep = snext;
1402  fNextNode = fCurrentNode;
1403  }
1404  // check overlapping nodes
1405  for (Int_t i=0; i<novlps; i++) {
1406  current = mother->GetNode(ovlps[i]);
1407  if (!current->IsOverlapping()) {
1408  current->cd();
1409  current->MasterToLocal(&mothpt[0], &dpt[0]);
1410  current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1411  // Current point may be inside the other node - geometry error that we ignore
1412  snext = TGeoShape::Big();
1413  if (!current->GetVolume()->Contains(dpt))
1414  snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1415  if (snext<fStep-gTolerance) {
1416  PopDummy();
1417  PushPath(safelevel+1);
1419  fCurrentMatrix->Multiply(current->GetMatrix());
1422  icrossed = ovlps[i];
1423  fStep = snext;
1424  fNextNode = current;
1425  }
1426  } else {
1427  // another many - check if point is in or out
1428  current->cd();
1429  current->MasterToLocal(&mothpt[0], &dpt[0]);
1430  current->MasterToLocalVect(&vecpt[0], &dvec[0]);
1431  if (current->GetVolume()->Contains(dpt)) {
1432  if (current->GetVolume()->GetNdaughters()) {
1433  CdDown(ovlps[i]);
1434  dnode = FindNextDaughterBoundary(dpt,dvec,idaughter,kFALSE);
1435  if (dnode) {
1437  fCurrentMatrix->Multiply(dnode->GetMatrix());
1438  icrossed = idaughter;
1439  PopDummy();
1440  PushPath(safelevel+1);
1443  fNextNode = dnode;
1444  }
1445  CdUp();
1446  }
1447  } else {
1448  snext = current->GetVolume()->GetShape()->DistFromOutside(dpt, dvec, iact, fStep);
1449  if (snext<fStep-gTolerance) {
1451  fCurrentMatrix->Multiply(current->GetMatrix());
1454  fStep = snext;
1455  fNextNode = current;
1456  icrossed = ovlps[i];
1457  PopDummy();
1458  PushPath(safelevel+1);
1459  }
1460  }
1461  }
1462  }
1463  }
1464  // Now we are in a non-overlapping node
1465  if (fNmany) {
1466  // We have overlaps up in the branch, check distance to exit
1467  Int_t up = 1;
1468  Int_t imother;
1469  Int_t nmany = fNmany;
1470  Bool_t ovlp = kFALSE;
1471  Bool_t nextovlp = kFALSE;
1472  Bool_t offset = kFALSE;
1473  TGeoNode *currentnode = fCurrentNode;
1474  TGeoNode *mothernode, *mup;
1475  TGeoHMatrix *matrix;
1476  while (nmany) {
1477  mothernode = GetMother(up);
1478  mup = mothernode;
1479  imother = up+1;
1480  offset = kFALSE;
1481  while (mup->IsOffset()) {
1482  mup = GetMother(imother++);
1483  offset = kTRUE;
1484  }
1485  nextovlp = mup->IsOverlapping();
1486  if (offset) {
1487  mothernode = mup;
1488  if (nextovlp) nmany -= imother-up;
1489  up = imother-1;
1490  } else {
1491  if (ovlp) nmany--;
1492  }
1493  if (ovlp || nextovlp) {
1494  matrix = GetMotherMatrix(up);
1495  matrix->MasterToLocal(fPoint,dpt);
1496  matrix->MasterToLocalVect(fDirection,dvec);
1497  snext = TGeoShape::Big();
1498  if (!mothernode->GetVolume()->IsAssembly()) snext = mothernode->GetVolume()->GetShape()->DistFromInside(dpt,dvec,iact,fStep);
1501  if (snext<fStep-gTolerance) {
1502  fNextNode = mothernode;
1503  fCurrentMatrix->CopyFrom(matrix);
1504  fStep = snext;
1505  while (up--) CdUp();
1506  PopDummy();
1507  PushPath();
1508  icrossed = -1;
1509  up = 1;
1510  currentnode = fCurrentNode;
1511  ovlp = currentnode->IsOverlapping();
1512  continue;
1513  }
1514  }
1515  currentnode = mothernode;
1516  ovlp = nextovlp;
1517  up++;
1518  }
1519  }
1520  PopPath();
1521  }
1522  // Compute now the distance in case we have a parallel world
1523  Double_t parstep = TGeoShape::Big();
1524  TGeoPhysicalNode *pnode = 0;
1525  if (fGeometry->IsParallelWorldNav()) {
1526  pnode = fGeometry->GetParallelWorld()->FindNextBoundary(fPoint, fDirection, parstep, fStep);
1527  if (pnode) {
1528  // A boundary is hit at less than fPStep
1529  fStep = parstep;
1530  fPoint[0] += fStep*fDirection[0];
1531  fPoint[1] += fStep*fDirection[1];
1532  fPoint[2] += fStep*fDirection[2];
1533  fNextNode = pnode->GetNode();
1534 // icrossed = -4; //
1537  cd(pnode->GetName());
1538  nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1539  while (nextindex>=0) {
1540  current = fCurrentNode;
1541  CdDown(nextindex);
1542  nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1543  }
1544  return fCurrentNode;
1545  }
1546  }
1547  fPoint[0] += fStep*fDirection[0];
1548  fPoint[1] += fStep*fDirection[1];
1549  fPoint[2] += fStep*fDirection[2];
1550  fStep += extra;
1551  if (icrossed == -2) {
1552  // Nothing crossed within stepmax -> propagate and return same location
1554  return fCurrentNode;
1555  }
1556  fIsOnBoundary = kTRUE;
1557  if (icrossed == -1) {
1558  // Exiting current node.
1559  skip = fCurrentNode;
1560  is_assembly = fCurrentNode->GetVolume()->IsAssembly();
1561  if (!fLevel && !is_assembly) {
1562  fIsOutside = kTRUE;
1563  return 0;
1564  }
1565  if (fCurrentNode->IsOffset()) return CrossDivisionCell();
1566  if (fLevel) CdUp();
1567  else skip = 0;
1568  return CrossBoundaryAndLocate(kFALSE, skip);
1569  }
1570 
1571  CdDown(icrossed);
1572  nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1573  while (nextindex>=0) {
1574  current = fCurrentNode;
1575  CdDown(nextindex);
1576  nextindex = fCurrentNode->GetVolume()->GetNextNodeIndex();
1577  }
1579  return CrossBoundaryAndLocate(kTRUE, current);
1580 }
1581 
1582 ////////////////////////////////////////////////////////////////////////////////
1583 /// Returns deepest node containing current point.
1584 
1586 {
1587  fSafety = 0;
1589  fIsOutside = kFALSE;
1592  fStartSafe = safe_start;
1594  TGeoNode *last = fCurrentNode;
1595  TGeoNode *found = SearchNode();
1596  if (found != last) {
1598  } else {
1599  if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1600  }
1601  return found;
1602 }
1603 
1604 ////////////////////////////////////////////////////////////////////////////////
1605 /// Returns deepest node containing current point.
1606 
1608 {
1609  fPoint[0] = x;
1610  fPoint[1] = y;
1611  fPoint[2] = z;
1612  fSafety = 0;
1614  fIsOutside = kFALSE;
1617  fStartSafe = kTRUE;
1619  TGeoNode *last = fCurrentNode;
1620  TGeoNode *found = SearchNode();
1621  if (found != last) {
1623  } else {
1624  if (last->IsOverlapping()) fIsSameLocation = kTRUE;
1625  }
1626  return found;
1627 }
1628 
1629 ////////////////////////////////////////////////////////////////////////////////
1630 /// Computes fast normal to next crossed boundary, assuming that the current point
1631 /// is close enough to the boundary. Works only after calling FindNextBoundary.
1632 
1634 {
1635  if (!fNextNode) return 0;
1636  Double_t local[3];
1637  Double_t ldir[3];
1638  Double_t lnorm[3];
1641  fNextNode->GetVolume()->GetShape()->ComputeNormal(local, ldir,lnorm);
1643  return fNormal;
1644 }
1645 
1646 ////////////////////////////////////////////////////////////////////////////////
1647 /// Computes normal vector to the next surface that will be or was already
1648 /// crossed when propagating on a straight line from a given point/direction.
1649 /// Returns the normal vector cosines in the MASTER coordinate system. The dot
1650 /// product of the normal and the current direction is positive defined.
1651 
1653 {
1654  return FindNormalFast();
1655 }
1656 
1657 ////////////////////////////////////////////////////////////////////////////////
1658 /// Initialize current point and current direction vector (normalized)
1659 /// in MARS. Return corresponding node.
1660 
1662 {
1663  SetCurrentPoint(point);
1664  SetCurrentDirection(dir);
1665  return FindNode();
1666 }
1667 
1668 ////////////////////////////////////////////////////////////////////////////////
1669 /// Initialize current point and current direction vector (normalized)
1670 /// in MARS. Return corresponding node.
1671 
1673 {
1674  SetCurrentPoint(x,y,z);
1675  SetCurrentDirection(nx,ny,nz);
1676  return FindNode();
1677 }
1678 
1679 ////////////////////////////////////////////////////////////////////////////////
1680 /// Reset current state flags.
1681 
1683 {
1685  fIsOutside = kFALSE;
1689 }
1690 
1691 ////////////////////////////////////////////////////////////////////////////////
1692 /// Compute safe distance from the current point. This represent the distance
1693 /// from POINT to the closest boundary.
1694 
1696 {
1697  if (fIsOnBoundary) {
1698  fSafety = 0;
1699  return fSafety;
1700  }
1701  Double_t point[3];
1702  Double_t safpar = TGeoShape::Big();
1703  if (!inside) fSafety = TGeoShape::Big();
1704  // Check if parallel navigation is enabled
1705  if (fGeometry->IsParallelWorldNav()) {
1706  safpar = fGeometry->GetParallelWorld()->Safety(fPoint);
1707  }
1708 
1709  if (fIsOutside) {
1711  if (fSafety < gTolerance) {
1712  fSafety = 0;
1713  fIsOnBoundary = kTRUE;
1714  return fSafety;
1715  }
1716  return TMath::Min(fSafety,safpar);
1717  }
1718  //---> convert point to local reference frame of current node
1720 
1721  //---> compute safety to current node
1722  TGeoVolume *vol = fCurrentNode->GetVolume();
1723  if (!inside) {
1724  fSafety = vol->GetShape()->Safety(point, kTRUE);
1725  //---> if we were just entering, return this safety
1726  if (fSafety < gTolerance) {
1727  fSafety = 0;
1728  fIsOnBoundary = kTRUE;
1729  return fSafety;
1730  }
1731  }
1732 
1733  //---> Check against the parallel geometry safety
1734  if (safpar < fSafety) fSafety = safpar;
1735 
1736  //---> if we were just exiting, return this safety
1737  TObjArray *nodes = vol->GetNodes();
1739  if (!nd && !fCurrentOverlapping) return fSafety;
1740  TGeoNode *node;
1741  Double_t safe;
1742  Int_t id;
1743 
1744  // if current volume is divided, we are in the non-divided region. We
1745  // check only the first and the last cell
1746  TGeoPatternFinder *finder = vol->GetFinder();
1747  if (finder) {
1748  Int_t ifirst = finder->GetDivIndex();
1749  node = (TGeoNode*)nodes->UncheckedAt(ifirst);
1750  node->cd();
1751  safe = node->Safety(point, kFALSE);
1752  if (safe < gTolerance) {
1753  fSafety=0;
1754  fIsOnBoundary = kTRUE;
1755  return fSafety;
1756  }
1757  if (safe<fSafety) fSafety=safe;
1758  Int_t ilast = ifirst+finder->GetNdiv()-1;
1759  if (ilast==ifirst) return fSafety;
1760  node = (TGeoNode*)nodes->UncheckedAt(ilast);
1761  node->cd();
1762  safe = node->Safety(point, kFALSE);
1763  if (safe < gTolerance) {
1764  fSafety=0;
1765  fIsOnBoundary = kTRUE;
1766  return fSafety;
1767  }
1768  if (safe<fSafety) fSafety=safe;
1769  if (fCurrentOverlapping && !inside) SafetyOverlaps();
1770  return fSafety;
1771  }
1772 
1773  //---> If no voxels just loop daughters
1774  TGeoVoxelFinder *voxels = vol->GetVoxels();
1775  if (!voxels) {
1776  for (id=0; id<nd; id++) {
1777  node = (TGeoNode*)nodes->UncheckedAt(id);
1778  safe = node->Safety(point, kFALSE);
1779  if (safe < gTolerance) {
1780  fSafety=0;
1781  fIsOnBoundary = kTRUE;
1782  return fSafety;
1783  }
1784  if (safe<fSafety) fSafety=safe;
1785  }
1786  if (fNmany && !inside) SafetyOverlaps();
1787  return fSafety;
1788  } else {
1789  if (voxels->NeedRebuild()) {
1790  voxels->Voxelize();
1791  vol->FindOverlaps();
1792  }
1793  }
1794 
1795  //---> check fast unsafe voxels
1796  Double_t *boxes = voxels->GetBoxes();
1797  for (id=0; id<nd; id++) {
1798  Int_t ist = 6*id;
1799  Double_t dxyz = 0.;
1800  Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
1801  if (dxyz0 > fSafety) continue;
1802  Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
1803  if (dxyz1 > fSafety) continue;
1804  Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
1805  if (dxyz2 > fSafety) continue;
1806  if (dxyz0>0) dxyz+=dxyz0*dxyz0;
1807  if (dxyz1>0) dxyz+=dxyz1*dxyz1;
1808  if (dxyz2>0) dxyz+=dxyz2*dxyz2;
1809  if (dxyz >= fSafety*fSafety) continue;
1810  node = (TGeoNode*)nodes->UncheckedAt(id);
1811  safe = node->Safety(point, kFALSE);
1812  if (safe<gTolerance) {
1813  fSafety=0;
1814  fIsOnBoundary = kTRUE;
1815  return fSafety;
1816  }
1817  if (safe<fSafety) fSafety = safe;
1818  }
1819  if (fNmany && !inside) SafetyOverlaps();
1820  return fSafety;
1821 }
1822 
1823 ////////////////////////////////////////////////////////////////////////////////
1824 /// Compute safe distance from the current point within an overlapping node
1825 
1827 {
1828  Double_t point[3], local[3];
1829  Double_t safe;
1830  Bool_t contains;
1831  TGeoNode *nodeovlp;
1832  TGeoVolume *vol;
1833  Int_t novlp, io;
1834  Int_t *ovlp;
1835  Int_t safelevel = GetSafeLevel();
1836  PushPath(safelevel+1);
1837  while (fCurrentOverlapping) {
1838  ovlp = fCurrentNode->GetOverlaps(novlp);
1839  CdUp();
1840  vol = fCurrentNode->GetVolume();
1841  fGeometry->MasterToLocal(fPoint, point);
1842  contains = fCurrentNode->GetVolume()->Contains(point);
1843  safe = fCurrentNode->GetVolume()->GetShape()->Safety(point, contains);
1844  if (safe<fSafety && safe>=0) fSafety=safe;
1845  if (!novlp || !contains) continue;
1846  // we are now in the container, check safety to all candidates
1847  for (io=0; io<novlp; io++) {
1848  nodeovlp = vol->GetNode(ovlp[io]);
1849  nodeovlp->GetMatrix()->MasterToLocal(point,local);
1850  contains = nodeovlp->GetVolume()->Contains(local);
1851  if (contains) {
1852  CdDown(ovlp[io]);
1853  safe = Safety(kTRUE);
1854  CdUp();
1855  } else {
1856  safe = nodeovlp->GetVolume()->GetShape()->Safety(local, kFALSE);
1857  }
1858  if (safe<fSafety && safe>=0) fSafety=safe;
1859  }
1860  }
1861  if (fNmany) {
1862  // We have overlaps up in the branch, check distance to exit
1863  Int_t up = 1;
1864  Int_t imother;
1865  Int_t nmany = fNmany;
1866  Bool_t crtovlp = kFALSE;
1867  Bool_t nextovlp = kFALSE;
1868  TGeoNode *mother, *mup;
1869  TGeoHMatrix *matrix;
1870  while (nmany) {
1871  mother = GetMother(up);
1872  mup = mother;
1873  imother = up+1;
1874  while (mup->IsOffset()) mup = GetMother(imother++);
1875  nextovlp = mup->IsOverlapping();
1876  if (crtovlp) nmany--;
1877  if (crtovlp || nextovlp) {
1878  matrix = GetMotherMatrix(up);
1879  matrix->MasterToLocal(fPoint,local);
1880  safe = mother->GetVolume()->GetShape()->Safety(local,kTRUE);
1881  if (safe<fSafety) fSafety = safe;
1882  crtovlp = nextovlp;
1883  }
1884  up++;
1885  }
1886  }
1887  PopPath();
1888  if (fSafety < gTolerance) {
1889  fSafety = 0.;
1890  fIsOnBoundary = kTRUE;
1891  }
1892 }
1893 
1894 ////////////////////////////////////////////////////////////////////////////////
1895 /// Returns the deepest node containing fPoint, which must be set a priori.
1896 /// Check if parallel world navigation is enabled
1897 
1899 {
1900  if (fGeometry->IsParallelWorldNav()) {
1902  if (pnode) {
1903  // A node from the parallel world contains the point -> stop the search
1904  // and synchronize with navigation state
1905  pnode->cd();
1907  while (crtindex>=0) {
1908  // Make sure we did not end up in an assembly.
1909  CdDown(crtindex);
1910  crtindex = fCurrentNode->GetVolume()->GetCurrentNodeIndex();
1911  }
1912  return fCurrentNode;
1913  }
1914  }
1915  Double_t point[3];
1916  fNextDaughterIndex = -2;
1917  TGeoVolume *vol = 0;
1919  Bool_t inside_current = (fCurrentNode==skipnode)?kTRUE:kFALSE;
1920  if (!downwards) {
1921  // we are looking upwards until inside current node or exit
1923  // We are inside an inactive volume-> go upwards
1924  CdUp();
1926  return SearchNode(kFALSE, skipnode);
1927  }
1928  // Check if the current point is still inside the current volume
1929  vol=fCurrentNode->GetVolume();
1930  if (vol->IsAssembly()) inside_current=kTRUE;
1931  // If the current node is not to be skipped
1932  if (!inside_current) {
1934  inside_current = vol->Contains(point);
1935  }
1936  // Point might be inside an overlapping node
1937  if (fNmany) {
1938  inside_current = GotoSafeLevel();
1939  }
1940  if (!inside_current) {
1941  // If not, go upwards
1943  TGeoNode *skip = fCurrentNode; // skip current node at next search
1944  // check if we can go up
1945  if (!fLevel) {
1946  fIsOutside = kTRUE;
1947  return 0;
1948  }
1949  CdUp();
1950  return SearchNode(kFALSE, skip);
1951  }
1952  }
1953  vol = fCurrentNode->GetVolume();
1955  if (!inside_current && downwards) {
1956  // we are looking downwards
1957  if (fCurrentNode == fForcedNode) inside_current = kTRUE;
1958  else inside_current = vol->Contains(point);
1959  if (!inside_current) {
1961  return 0;
1962  } else {
1963  if (fIsOutside) {
1964  fIsOutside = kFALSE;
1966  }
1967  if (idebug>4) {
1968  printf("Search node local=(%19.16f, %19.16f, %19.16f) -> %s\n",
1969  point[0],point[1],point[2], fCurrentNode->GetName());
1970  }
1971  }
1972  }
1973  // point inside current (safe) node -> search downwards
1974  TGeoNode *node;
1975  Int_t ncheck = 0;
1976  // if inside an non-overlapping node, reset overlap searches
1977  if (!fCurrentOverlapping) {
1979  }
1980 
1981  Int_t crtindex = vol->GetCurrentNodeIndex();
1982  while (crtindex>=0 && downwards) {
1983  // Make sure we did not end up in an assembly.
1984  CdDown(crtindex);
1985  vol = fCurrentNode->GetVolume();
1986  crtindex = vol->GetCurrentNodeIndex();
1987  if (crtindex<0) fGlobalMatrix->MasterToLocal(fPoint, point);
1988  }
1989 
1990  Int_t nd = vol->GetNdaughters();
1991  // in case there are no daughters
1992  if (!nd) return fCurrentNode;
1993  if (fGeometry->IsActivityEnabled() && !vol->IsActiveDaughters()) return fCurrentNode;
1994 
1995  TGeoPatternFinder *finder = vol->GetFinder();
1996  // point is inside the current node
1997  // first check if inside a division
1998  if (finder) {
1999  node=finder->FindNode(point);
2000  if (!node && fForcedNode) {
2001  // Point *HAS* to be inside a cell
2002  Double_t dir[3];
2004  finder->FindNode(point,dir);
2005  node = finder->CdNext();
2006  if (!node) return fCurrentNode; // inside divided volume but not in a cell
2007  }
2008  if (node && node!=skipnode) {
2009  // go inside the division cell and search downwards
2011  CdDown(node->GetIndex());
2012  fForcedNode = 0;
2013  return SearchNode(kTRUE, node);
2014  }
2015  // point is not inside the division, but might be in other nodes
2016  // at the same level (NOT SUPPORTED YET)
2017  while (fCurrentNode && fCurrentNode->IsOffset()) CdUp();
2018  return fCurrentNode;
2019  }
2020  // second, look if current volume is voxelized
2021  TGeoVoxelFinder *voxels = vol->GetVoxels();
2022  Int_t *check_list = 0;
2023  Int_t id;
2024  if (voxels) {
2025  // get the list of nodes passing thorough the current voxel
2026  check_list = voxels->GetCheckList(&point[0], ncheck, *fCache->GetInfo());
2027  // if none in voxel, see if this is the last one
2028  if (!check_list) {
2029  if (!fCurrentNode->GetVolume()->IsAssembly()) {
2030  fCache->ReleaseInfo();
2031  return fCurrentNode;
2032  }
2033  // Point in assembly - go up
2034  node = fCurrentNode;
2035  if (!fLevel) {
2036  fIsOutside = kTRUE;
2037  fCache->ReleaseInfo();
2038  return 0;
2039  }
2040  CdUp();
2041  fCache->ReleaseInfo();
2042  return SearchNode(kFALSE,node);
2043  }
2044  // loop all nodes in voxel
2045  for (id=0; id<ncheck; id++) {
2046  node = vol->GetNode(check_list[id]);
2047  if (node==skipnode) continue;
2048  if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
2049  if ((id<(ncheck-1)) && node->IsOverlapping()) {
2050  // make the cluster of overlaps
2051  if (ncheck+fOverlapMark > fOverlapSize) {
2052  fOverlapSize = 2*(ncheck+fOverlapMark);
2053  delete [] fOverlapClusters;
2055  }
2056  Int_t *cluster = fOverlapClusters + fOverlapMark;
2057  Int_t nc = GetTouchedCluster(id, &point[0], check_list, ncheck, cluster);
2058  if (nc>1) {
2059  fOverlapMark += nc;
2060  node = FindInCluster(cluster, nc);
2061  fOverlapMark -= nc;
2062  fCache->ReleaseInfo();
2063  return node;
2064  }
2065  }
2066  CdDown(check_list[id]);
2067  fForcedNode = 0;
2068  node = SearchNode(kTRUE);
2069  if (node) {
2071  fCache->ReleaseInfo();
2072  return node;
2073  }
2074  CdUp();
2075  }
2076  if (!fCurrentNode->GetVolume()->IsAssembly()) {
2077  fCache->ReleaseInfo();
2078  return fCurrentNode;
2079  }
2080  node = fCurrentNode;
2081  if (!fLevel) {
2082  fIsOutside = kTRUE;
2083  fCache->ReleaseInfo();
2084  return 0;
2085  }
2086  CdUp();
2087  fCache->ReleaseInfo();
2088  return SearchNode(kFALSE,node);
2089  }
2090  // if there are no voxels just loop all daughters
2091  for (id=0; id<nd; id++) {
2092  node=fCurrentNode->GetDaughter(id);
2093  if (node==skipnode) continue;
2094  if (fGeometry->IsActivityEnabled() && !node->GetVolume()->IsActive()) continue;
2095  CdDown(id);
2096  fForcedNode = 0;
2097  node = SearchNode(kTRUE);
2098  if (node) {
2100  return node;
2101  }
2102  CdUp();
2103  }
2104  // point is not inside one of the daughters, so it is in the current vol
2105  if (fCurrentNode->GetVolume()->IsAssembly()) {
2106  node = fCurrentNode;
2107  if (!fLevel) {
2108  fIsOutside = kTRUE;
2109  return 0;
2110  }
2111  CdUp();
2112  return SearchNode(kFALSE,node);
2113  }
2114  return fCurrentNode;
2115 }
2116 
2117 ////////////////////////////////////////////////////////////////////////////////
2118 /// Find a node inside a cluster of overlapping nodes. Current node must
2119 /// be on top of all the nodes in cluster. Always nc>1.
2120 
2122 {
2123  TGeoNode *clnode = 0;
2124  TGeoNode *priority = fLastNode;
2125  // save current node
2126  TGeoNode *current = fCurrentNode;
2127  TGeoNode *found = 0;
2128  // save path
2129  Int_t ipop = PushPath();
2130  // mark this search
2132  Int_t deepest = fLevel;
2133  Int_t deepest_virtual = fLevel-GetVirtualLevel();
2134  Int_t found_virtual = 0;
2135  Bool_t replace = kFALSE;
2136  Bool_t added = kFALSE;
2137  Int_t i;
2138  for (i=0; i<nc; i++) {
2139  clnode = current->GetDaughter(cluster[i]);
2140  CdDown(cluster[i]);
2141  Bool_t max_priority = (clnode==fNextNode)?kTRUE:kFALSE;
2142  found = SearchNode(kTRUE, clnode);
2143  if (!fSearchOverlaps || max_priority) {
2144  // an only was found during the search -> exiting
2145  // The node given by FindNextBoundary returned -> exiting
2146  PopDummy(ipop);
2147  return found;
2148  }
2149  found_virtual = fLevel-GetVirtualLevel();
2150  if (added) {
2151  // we have put something in stack -> check it
2152  if (found_virtual>deepest_virtual) {
2153  replace = kTRUE;
2154  } else {
2155  if (found_virtual==deepest_virtual) {
2156  if (fLevel>deepest) {
2157  replace = kTRUE;
2158  } else {
2159  if ((fLevel==deepest) && (clnode==priority)) replace=kTRUE;
2160  else replace = kFALSE;
2161  }
2162  } else replace = kFALSE;
2163  }
2164  // if this was the last checked node
2165  if (i==(nc-1)) {
2166  if (replace) {
2167  PopDummy(ipop);
2168  return found;
2169  } else {
2171  PopDummy(ipop);
2172  return fCurrentNode;
2173  }
2174  }
2175  // we still have to go on
2176  if (replace) {
2177  // reset stack
2178  PopDummy();
2179  PushPath();
2180  deepest = fLevel;
2181  deepest_virtual = found_virtual;
2182  }
2183  // restore top of cluster
2184  fCurrentOverlapping = PopPath(ipop);
2185  } else {
2186  // the stack was clean, push new one
2187  PushPath();
2188  added = kTRUE;
2189  deepest = fLevel;
2190  deepest_virtual = found_virtual;
2191  // restore original path
2192  fCurrentOverlapping = PopPath(ipop);
2193  }
2194  }
2195  PopDummy(ipop);
2196  return fCurrentNode;
2197 }
2198 
2199 ////////////////////////////////////////////////////////////////////////////////
2200 /// Make the cluster of overlapping nodes in a voxel, containing point in reference
2201 /// of the mother. Returns number of nodes containing the point. Nodes should not be
2202 /// offsets.
2203 
2205  Int_t *check_list, Int_t ncheck, Int_t *result)
2206 {
2207  // we are in the mother reference system
2208  TGeoNode *current = fCurrentNode->GetDaughter(check_list[start]);
2209  Int_t novlps = 0;
2210  Int_t *ovlps = current->GetOverlaps(novlps);
2211  if (!ovlps) return 0;
2212  Double_t local[3];
2213  // intersect check list with overlap list
2214  Int_t ntotal = 0;
2215  current->MasterToLocal(point, &local[0]);
2216  if (current->GetVolume()->Contains(&local[0])) {
2217  result[ntotal++]=check_list[start];
2218  }
2219 
2220  Int_t jst=0, i, j;
2221  while ((jst<novlps) && (ovlps[jst]<=check_list[start])) jst++;
2222  if (jst==novlps) return 0;
2223  for (i=start; i<ncheck; i++) {
2224  for (j=jst; j<novlps; j++) {
2225  if (check_list[i]==ovlps[j]) {
2226  // overlapping node in voxel -> check if touched
2227  current = fCurrentNode->GetDaughter(check_list[i]);
2228  if (fGeometry->IsActivityEnabled() && !current->GetVolume()->IsActive()) continue;
2229  current->MasterToLocal(point, &local[0]);
2230  if (current->GetVolume()->Contains(&local[0])) {
2231  result[ntotal++]=check_list[i];
2232  }
2233  }
2234  }
2235  }
2236  return ntotal;
2237 }
2238 
2239 ////////////////////////////////////////////////////////////////////////////////
2240 /// Make a rectiliniar step of length fStep from current point (fPoint) on current
2241 /// direction (fDirection). If the step is imposed by geometry, is_geom flag
2242 /// must be true (default). The cross flag specifies if the boundary should be
2243 /// crossed in case of a geometry step (default true). Returns new node after step.
2244 /// Set also on boundary condition.
2245 
2247 {
2248  Double_t epsil = 0;
2249  if (fStep<1E-6) {
2251  if (fStep<0) fStep = 0.;
2252  } else {
2254  }
2255  if (is_geom) epsil=(cross)?1E-6:-1E-6;
2256  TGeoNode *old = fCurrentNode;
2257  Int_t idold = GetNodeId();
2258  if (fIsOutside) old = 0;
2259  fStep += epsil;
2260  for (Int_t i=0; i<3; i++) fPoint[i]+=fStep*fDirection[i];
2261  TGeoNode *current = FindNode();
2262  if (is_geom) {
2263  fIsEntering = (current==old)?kFALSE:kTRUE;
2264  if (!fIsEntering) {
2265  Int_t id = GetNodeId();
2266  fIsEntering = (id==idold)?kFALSE:kTRUE;
2267  }
2270  fIsOnBoundary = kTRUE;
2271  } else {
2274  }
2275  return current;
2276 }
2277 
2278 ////////////////////////////////////////////////////////////////////////////////
2279 /// Find level of virtuality of current overlapping node (number of levels
2280 /// up having the same tracking media.
2281 
2283 {
2284  // return if the current node is ONLY
2285  if (!fCurrentOverlapping) return 0;
2286  Int_t new_media = 0;
2287  TGeoMedium *medium = fCurrentNode->GetMedium();
2288  Int_t virtual_level = 1;
2289  TGeoNode *mother = 0;
2290 
2291  while ((mother=GetMother(virtual_level))) {
2292  if (!mother->IsOverlapping() && !mother->IsOffset()) {
2293  if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2294  break;
2295  }
2296  if (!new_media) new_media=(mother->GetMedium()==medium)?0:virtual_level;
2297  virtual_level++;
2298  }
2299  return (new_media==0)?virtual_level:(new_media-1);
2300 }
2301 
2302 ////////////////////////////////////////////////////////////////////////////////
2303 /// Go upwards the tree until a non-overlapping node
2304 
2306 {
2307  while (fCurrentOverlapping && fLevel) CdUp();
2308  Double_t point[3];
2310  if (!fCurrentNode->GetVolume()->Contains(point)) return kFALSE;
2311  if (fNmany) {
2312  // We still have overlaps on the branch
2313  Int_t up = 1;
2314  Int_t imother;
2315  Int_t nmany = fNmany;
2316  Bool_t ovlp = kFALSE;
2317  Bool_t nextovlp = kFALSE;
2318  TGeoNode *mother, *mup;
2319  TGeoHMatrix *matrix;
2320  while (nmany) {
2321  mother = GetMother(up);
2322  if (!mother) return kTRUE;
2323  mup = mother;
2324  imother = up+1;
2325  while (mup->IsOffset()) mup = GetMother(imother++);
2326  nextovlp = mup->IsOverlapping();
2327  if (ovlp) nmany--;
2328  if (ovlp || nextovlp) {
2329  // check if the point is in the next node up
2330  matrix = GetMotherMatrix(up);
2331  matrix->MasterToLocal(fPoint,point);
2332  if (!mother->GetVolume()->Contains(point)) {
2333  up++;
2334  while (up--) CdUp();
2335  return GotoSafeLevel();
2336  }
2337  }
2338  ovlp = nextovlp;
2339  up++;
2340  }
2341  }
2342  return kTRUE;
2343 }
2344 
2345 ////////////////////////////////////////////////////////////////////////////////
2346 /// Go upwards the tree until a non-overlapping node
2347 
2349 {
2350  Bool_t overlapping = fCurrentOverlapping;
2351  if (!overlapping) return fLevel;
2352  Int_t level = fLevel;
2353  TGeoNode *node;
2354  while (overlapping && level) {
2355  level--;
2356  node = GetMother(fLevel-level);
2357  if (!node->IsOffset()) overlapping = node->IsOverlapping();
2358  }
2359  return level;
2360 }
2361 
2362 ////////////////////////////////////////////////////////////////////////////////
2363 /// Inspects path and all flags for the current state.
2364 
2366 {
2367  Info("InspectState","Current path is: %s",GetPath());
2368  Int_t level;
2369  TGeoNode *node;
2370  Bool_t is_offset, is_overlapping;
2371  for (level=0; level<fLevel+1; level++) {
2372  node = GetMother(fLevel-level);
2373  if (!node) continue;
2374  is_offset = node->IsOffset();
2375  is_overlapping = node->IsOverlapping();
2376  Info("InspectState","level %i: %s div=%i many=%i",level,node->GetName(),is_offset,is_overlapping);
2377  }
2378  Info("InspectState","on_bound=%i entering=%i", fIsOnBoundary, fIsEntering);
2379 }
2380 
2381 ////////////////////////////////////////////////////////////////////////////////
2382 /// Checks if point (x,y,z) is still in the current node.
2383 /// check if this is an overlapping node
2384 
2386 {
2387  Double_t oldpt[3];
2388  if (fLastSafety>0) {
2389  Double_t dx = (x-fLastPoint[0]);
2390  Double_t dy = (y-fLastPoint[1]);
2391  Double_t dz = (z-fLastPoint[2]);
2392  Double_t dsq = dx*dx+dy*dy+dz*dz;
2393  if (dsq<fLastSafety*fLastSafety) {
2394  if (change) {
2395  fPoint[0] = x;
2396  fPoint[1] = y;
2397  fPoint[2] = z;
2398  memcpy(fLastPoint, fPoint, 3*sizeof(Double_t));
2399  fLastSafety -= TMath::Sqrt(dsq);
2400  }
2401  return kTRUE;
2402  }
2403  if (change) fLastSafety = 0;
2404  }
2405  if (fCurrentOverlapping) {
2406 // TGeoNode *current = fCurrentNode;
2407  Int_t cid = GetCurrentNodeId();
2408  if (!change) PushPoint();
2409  memcpy(oldpt, fPoint, kN3);
2410  SetCurrentPoint(x,y,z);
2411  SearchNode();
2412  memcpy(fPoint, oldpt, kN3);
2413  Bool_t same = (cid==GetCurrentNodeId())?kTRUE:kFALSE;
2414  if (!change) PopPoint();
2415  return same;
2416  }
2417 
2418  Double_t point[3];
2419  point[0] = x;
2420  point[1] = y;
2421  point[2] = z;
2422  if (change) memcpy(fPoint, point, kN3);
2423  TGeoVolume *vol = fCurrentNode->GetVolume();
2424  if (fIsOutside) {
2425  if (vol->GetShape()->Contains(point)) {
2426  if (!change) return kFALSE;
2427  FindNode(x,y,z);
2428  return kFALSE;
2429  }
2430  return kTRUE;
2431  }
2432  Double_t local[3];
2433  // convert to local frame
2434  fGlobalMatrix->MasterToLocal(point,local);
2435  // check if still in current volume.
2436  if (!vol->GetShape()->Contains(local)) {
2437  if (!change) return kFALSE;
2438  CdUp();
2439  FindNode(x,y,z);
2440  return kFALSE;
2441  }
2442 
2443  // Check if the point is in a parallel world volume
2444  if (fGeometry->IsParallelWorldNav()) {
2446  if (pnode) {
2447  if (!change) return kFALSE;
2448  pnode->cd();
2450  while (crtindex>=0) {
2451  // Make sure we did not end up in an assembly.
2452  CdDown(crtindex);
2453  crtindex = fCurrentNode->GetVolume()->GetCurrentNodeIndex();
2454  }
2455  return kFALSE;
2456  }
2457  }
2458  // check if there are daughters
2459  Int_t nd = vol->GetNdaughters();
2460  if (!nd) return kTRUE;
2461 
2462  TGeoNode *node;
2463  TGeoPatternFinder *finder = vol->GetFinder();
2464  if (finder) {
2465  node=finder->FindNode(local);
2466  if (node) {
2467  if (!change) return kFALSE;
2468  CdDown(node->GetIndex());
2469  SearchNode(kTRUE,node);
2470  return kFALSE;
2471  }
2472  return kTRUE;
2473  }
2474  // if we are not allowed to do changes, save the current path
2475  TGeoVoxelFinder *voxels = vol->GetVoxels();
2476  Int_t *check_list = 0;
2477  Int_t ncheck = 0;
2478  Double_t local1[3];
2479  if (voxels) {
2480  check_list = voxels->GetCheckList(local, ncheck, *fCache->GetInfo());
2481  if (!check_list) {
2482  fCache->ReleaseInfo();
2483  return kTRUE;
2484  }
2485  if (!change) PushPath();
2486  for (Int_t id=0; id<ncheck; id++) {
2487 // node = vol->GetNode(check_list[id]);
2488  CdDown(check_list[id]);
2489  fGlobalMatrix->MasterToLocal(point,local1);
2490  if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2491  if (!change) {
2492  PopPath();
2493  fCache->ReleaseInfo();
2494  return kFALSE;
2495  }
2496  SearchNode(kTRUE);
2497  fCache->ReleaseInfo();
2498  return kFALSE;
2499  }
2500  CdUp();
2501  }
2502  if (!change) PopPath();
2503  fCache->ReleaseInfo();
2504  return kTRUE;
2505  }
2506  Int_t id = 0;
2507  if (!change) PushPath();
2508  while (fCurrentNode && fCurrentNode->GetDaughter(id++)) {
2509  CdDown(id-1);
2510  fGlobalMatrix->MasterToLocal(point,local1);
2511  if (fCurrentNode->GetVolume()->GetShape()->Contains(local1)) {
2512  if (!change) {
2513  PopPath();
2514  return kFALSE;
2515  }
2516  SearchNode(kTRUE);
2517  return kFALSE;
2518  }
2519  CdUp();
2520  if (id == nd) {
2521  if (!change) PopPath();
2522  return kTRUE;
2523  }
2524  }
2525  if (!change) PopPath();
2526  return kTRUE;
2527 }
2528 
2529 ////////////////////////////////////////////////////////////////////////////////
2530 /// In case a previous safety value was computed, check if the safety region is
2531 /// still safe for the current point and proposed step. Return value changed only
2532 /// if proposed distance is safe.
2533 
2535 {
2536  // Last safety not computed.
2537  if (fLastSafety < gTolerance) return kFALSE;
2538  // Proposed step too small
2539  if (proposed < gTolerance) {
2540  newsafety = fLastSafety - proposed;
2541  return kTRUE;
2542  }
2543  // Normal step
2544  Double_t dist = (fPoint[0]-fLastPoint[0])*(fPoint[0]-fLastPoint[0])+
2545  (fPoint[1]-fLastPoint[1])*(fPoint[1]-fLastPoint[1])+
2546  (fPoint[2]-fLastPoint[2])*(fPoint[2]-fLastPoint[2]);
2547  dist = TMath::Sqrt(dist);
2548  Double_t safe = fLastSafety - dist;
2549  if (safe < proposed) return kFALSE;
2550  newsafety = safe;
2551  return kTRUE;
2552 }
2553 
2554 ////////////////////////////////////////////////////////////////////////////////
2555 /// Check if a new point with given coordinates is the same as the last located one.
2556 
2558 {
2559  if (TMath::Abs(x-fLastPoint[0]) < 1.E-20) {
2560  if (TMath::Abs(y-fLastPoint[1]) < 1.E-20) {
2561  if (TMath::Abs(z-fLastPoint[2]) < 1.E-20) return kTRUE;
2562  }
2563  }
2564  return kFALSE;
2565 }
2566 
2567 ////////////////////////////////////////////////////////////////////////////////
2568 /// Backup the current state without affecting the cache stack.
2569 
2571 {
2573 }
2574 
2575 ////////////////////////////////////////////////////////////////////////////////
2576 /// Restore a backed-up state without affecting the cache stack.
2577 
2579 {
2580  if (fBackupState && fCache) {
2584  fLevel=fCache->GetLevel();
2585  }
2586 }
2587 
2588 ////////////////////////////////////////////////////////////////////////////////
2589 /// Return stored current matrix (global matrix of the next touched node).
2590 
2592 {
2593  if (!fCurrentMatrix) {
2594  fCurrentMatrix = new TGeoHMatrix();
2596  }
2597  return fCurrentMatrix;
2598 }
2599 
2600 ////////////////////////////////////////////////////////////////////////////////
2601 /// Get path to the current node in the form /node0/node1/...
2602 
2603 const char *TGeoNavigator::GetPath() const
2604 {
2605  if (fIsOutside) return kGeoOutsidePath;
2606  return fCache->GetPath();
2607 }
2608 
2609 ////////////////////////////////////////////////////////////////////////////////
2610 /// Convert coordinates from master volume frame to top.
2611 
2612 void TGeoNavigator::MasterToTop(const Double_t *master, Double_t *top) const
2613 {
2614  fCurrentMatrix->MasterToLocal(master, top);
2615 }
2616 
2617 ////////////////////////////////////////////////////////////////////////////////
2618 /// Convert coordinates from top volume frame to master.
2619 
2620 void TGeoNavigator::TopToMaster(const Double_t *top, Double_t *master) const
2621 {
2622  fCurrentMatrix->LocalToMaster(top, master);
2623 }
2624 
2625 ////////////////////////////////////////////////////////////////////////////////
2626 /// Reset the navigator.
2627 
2629 {
2630  GetHMatrix();
2633  ResetState();
2634  fStep = 0.;
2635  fSafety = 0.;
2636  fLastSafety = 0.;
2637  fLevel = 0;
2638  fNmany = 0;
2639  fNextDaughterIndex = -2;
2641  fStartSafe = kFALSE;
2643  fIsNullStep = kFALSE;
2646  fLastNode = 0;
2647  fNextNode = 0;
2648  fPath = "";
2649  if (fCache) {
2651  Bool_t nodeid = fCache->HasIdArray();
2652  delete fCache;
2653  delete fBackupState;
2654  fCache = 0;
2655  BuildCache(dummy,nodeid);
2656  }
2657 }
2658 
2660 
2661 ////////////////////////////////////////////////////////////////////////////////
2662 /// Add a new navigator to the array.
2663 
2665 {
2666  SetOwner(kTRUE);
2667  TGeoNavigator *nav = new TGeoNavigator(fGeoManager);
2668  nav->BuildCache(kTRUE, kFALSE);
2669  Add(nav);
2670  SetCurrentNavigator(GetEntriesFast()-1);
2671  return nav;
2672 }
Int_t fNmany
current geometry level;
Definition: TGeoNavigator.h:57
Statefull info for the current geometry level.
Definition: TGeoStateInfo.h:21
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
void GetBranchNames(Int_t *names) const
Fill volume names of current branch into an array.
Int_t GetMaxLevel() const
Definition: TGeoManager.h:499
TGeoNode * CrossBoundaryAndLocate(Bool_t downwards, TGeoNode *skipnode)
Cross next boundary and locate within current node The current point must be on the boundary of fCurr...
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
Bool_t GotoSafeLevel()
Go upwards the tree until a non-overlapping node.
An array of TObjects.
Definition: TObjArray.h:37
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
TGeoNodeCache * fCache
current geometry
Definition: TGeoNavigator.h:74
The manager class for any TGeo geometry.
Definition: TGeoManager.h:38
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
Definition: TGeoMatrix.cxx:431
#define snext(osub1, osub2)
Definition: triangle.c:1167
Volume assemblies.
Definition: TGeoVolume.h:307
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 IsActive() const
Definition: TGeoVolume.h:146
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)=0
Double_t Safety(Double_t point[3], Double_t safmax=1.E30)
Compute safety for the parallel world.
TGeoNode * InitTrack(const Double_t *point, const Double_t *dir)
Initialize current point and current direction vector (normalized) in MARS.
Bool_t IsOverlapping() const
Definition: TGeoNode.h:102
virtual TGeoNode * FindNode(Double_t *, const Double_t *=0)
TGeoNavigator()
path to current node
TGeoManager * fGeometry
flag that last geometric step was null
Definition: TGeoNavigator.h:73
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 void cd() const
Definition: TGeoNode.h:70
TGeoStateInfo * GetInfo()
Get next state info pointer.
Definition: TGeoCache.cxx:318
Int_t fOverlapMark
current size of fOverlapClusters
Definition: TGeoNavigator.h:60
TGeoNode * GetNode(const char *name) const
get the pointer to a daughter node
virtual const Double_t * GetTranslation() const
Definition: TGeoMatrix.h:467
Double_t fSafety
step to be done from current point and direction
Definition: TGeoNavigator.h:47
virtual void MasterToLocalVect(const Double_t *master, Double_t *local) const
Convert a vector from mother reference to local reference system.
Definition: TGeoNode.cxx:561
void GetBranchOnlys(Int_t *isonly) const
Fill node copy numbers of current branch into an array.
TGeoNode * fCurrentNode
current volume
Definition: TGeoNavigator.h:76
virtual TGeoPatternFinder * GetFinder() const
Definition: TGeoNode.h:87
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition: TGeoVolume.h:48
Int_t GetSafeLevel() const
Go upwards the tree until a non-overlapping node.
static Int_t GetVerboseLevel()
Set verbosity level (static function).
void TopToMaster(const Double_t *top, Double_t *master) const
Convert coordinates from top volume frame to master.
void InspectShape() const
Definition: TGeoVolume.h:196
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
Bool_t fIsOnBoundary
flag that current point is outside geometry
Definition: TGeoNavigator.h:70
Basic string class.
Definition: TString.h:131
Matrix class used for computing global transformations Should NOT be used for node definition...
Definition: TGeoMatrix.h:420
void Multiply(const TGeoMatrix *right)
multiply to the right with an other transformation if right is identity matrix, just return ...
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.
TGeoNode * FindInCluster(Int_t *cluster, Int_t nc)
Find a node inside a cluster of overlapping nodes.
void MasterToLocal(const Double_t *master, Double_t *local) const
Definition: TGeoManager.h:517
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TGeoHMatrix * fDivMatrix
current pointer to cached global matrix
Definition: TGeoNavigator.h:84
Int_t GetNdiv() const
TGeoPhysicalNode * FindNode(Double_t point[3])
Finds physical node containing the point.
Double_t fCldir[3]
cosine of incident angle on current checked surface
Definition: TGeoNavigator.h:50
TGeoNode * GetNode(Int_t level=-1) const
Return node in branch at LEVEL. If not specified, return last leaf.
Double_t fDirection[3]
current point
Definition: TGeoNavigator.h:53
TGeoNode * fLastNode
top physical node
Definition: TGeoNavigator.h:78
Bool_t IsOffset() const
Definition: TGeoNode.h:100
virtual void SortCrossedVoxels(const Double_t *point, const Double_t *dir, TGeoStateInfo &td)
get the list in the next voxel crossed by a ray
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
void GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
Fill copy numbers of current branch nodes.
Definition: TGeoCache.cxx:295
Int_t fNextDaughterIndex
number of overlapping nodes on current branch
Definition: TGeoNavigator.h:58
Bool_t NeedRebuild() const
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")...
TGeoHMatrix * fCurrentMatrix
backup state
Definition: TGeoNavigator.h:82
Double_t fNormal[3]
last computed safety radius
Definition: TGeoNavigator.h:49
TObjArray * GetNodes()
Definition: TGeoVolume.h:170
static Double_t Tolerance()
Definition: TGeoShape.h:91
void InspectState() const
Inspects path and all flags for the current state.
void DoRestoreState()
Restore a backed-up state without affecting the cache stack.
Int_t GetNdaughters() const
Definition: TGeoVolume.h:350
void CdNode(Int_t nodeid)
Change current path to point to the node having this id.
void MasterToTop(const Double_t *master, Double_t *top) const
Convert coordinates from master volume frame to top.
virtual Bool_t Contains(const Double_t *point) const =0
TGeoNavigator & operator=(const TGeoNavigator &)
assignment operator
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
TGeoPatternFinder * GetFinder() const
Definition: TGeoVolume.h:178
Double_t x[n]
Definition: legend1.C:17
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 IsActiveDaughters() const
Definition: TGeoVolume.h:147
Double_t fStep
Definition: TGeoNavigator.h:46
void PopDummy(Int_t ipop=9999)
Bool_t fIsNullStep
flag that a new point is in the same node as previous
Definition: TGeoNavigator.h:72
void CdTop()
Definition: TGeoCache.h:90
const Int_t kN3
Bool_t CheckPath(const char *path) const
Check if a geometry path is valid without changing the state of the navigator.
virtual TGeoMatrix * GetMatrix() const =0
Special pool of reusable nodes.
Definition: TGeoCache.h:53
TObject & operator=(const TObject &rhs)
TObject assignment operator.
Definition: TObject.h:271
XFontStruct * id
Definition: TGX11.cxx:108
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
Definition: TGeoMatrix.cxx:363
void CopyFrom(const TGeoMatrix *other)
Fast copy method.
void ResetState()
Reset current state flags.
TGeoNode * GetCurrentNode() const
Definition: TGeoManager.h:490
void ReleaseInfo()
Release last used state info pointer.
Definition: TGeoCache.cxx:335
Physical nodes are the actual &#39;touchable&#39; objects in the geometry, representing a path of positioned ...
TGeoNode * SearchNode(Bool_t downwards=kFALSE, const TGeoNode *skipnode=0)
Returns the deepest node containing fPoint, which must be set a priori.
void CdTop()
Make top level node the current node.
Base finder class for patterns.
Bool_t IsSameLocation() const
void GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
Fill node copy numbers of current branch into an array.
TGeoMedium * GetMedium() const
Definition: TGeoNode.h:88
TGeoNode * FindNextBoundaryAndStep(Double_t stepmax=TGeoShape::Big(), Bool_t compsafe=kFALSE)
Compute distance to next boundary within STEPMAX.
TGeoNavigator * AddNavigator()
Add a new navigator to the array.
Bool_t PopPath()
void GetBranchNames(Int_t *names) const
Fill names with current branch volume names (4 char - used by GEANT3 interface).
Definition: TGeoCache.cxx:283
Bool_t IsActivityEnabled() const
Definition: TGeoManager.h:409
void BuildCache(Bool_t dummy=kFALSE, Bool_t nodeid=kFALSE)
Builds the cache for physical nodes and global matrices.
Bool_t cd(const char *path="")
Browse the tree of nodes starting from top node according to pathname.
void SetCurrentPoint(const Double_t *point)
Double_t Safety(Bool_t inside=kFALSE)
Compute safe distance from the current point.
TGeoNode * GetDaughter(Int_t ind) const
Definition: TGeoNode.h:82
TGeoHMatrix * fGlobalMatrix
current stored global matrix
Definition: TGeoNavigator.h:83
Int_t GetVirtualLevel()
Find level of virtuality of current overlapping node (number of levels up having the same tracking me...
Double_t fCldirChecked[3]
unit vector to current closest shape
Definition: TGeoNavigator.h:51
Int_t GetIndex(const TGeoNode *node) const
get index number for a given daughter
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const =0
Double_t * GetBoxes() const
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 ...
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
Bool_t fIsOutside
flag that next geometric step will exit current volume
Definition: TGeoNavigator.h:69
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
void CdDown(Int_t index)
Make a daughter of current node current.
Ssiz_t Length() const
Definition: TString.h:405
virtual Bool_t IsOnBoundary(const Double_t *) const
virtual void RegisterYourself()
Register the matrix in the current manager, which will become the owner.
Definition: TGeoMatrix.cxx:526
void SafetyOverlaps()
Compute safe distance from the current point within an overlapping node.
Bool_t fSearchOverlaps
internal array for overlaps
Definition: TGeoNavigator.h:62
Double_t fLastSafety
safety radius from current point
Definition: TGeoNavigator.h:48
TGeoNode * GetTopNode() const
Definition: TGeoManager.h:504
Bool_t fIsStepEntering
flag that current track is about to leave current node
Definition: TGeoNavigator.h:67
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.
virtual ~TGeoNavigator()
Destructor.
static Double_t gTolerance
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
constexpr Double_t E()
Base of natural log: .
Definition: TMath.h:97
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
Definition: TGeoMatrix.cxx:339
Bool_t Contains(const Double_t *point) const
Definition: TGeoVolume.h:112
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:553
const Bool_t kFALSE
Definition: RtypesCore.h:88
Int_t fLevel
thread id for this navigator
Definition: TGeoNavigator.h:56
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
TGeoParallelWorld * GetParallelWorld() const
Definition: TGeoManager.h:555
Int_t PushPath(Int_t startlevel=0)
virtual Int_t GetCurrentNodeIndex() const
Definition: TGeoVolume.h:168
Bool_t PopPoint()
Double_t fPoint[3]
unit vector to current checked shape
Definition: TGeoNavigator.h:52
TGeoNode * GetNode() const
Definition: TGeoCache.h:103
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.
void Add(THist< DIMENSIONS, PRECISION_TO, STAT_TO... > &to, const THist< DIMENSIONS, PRECISION_FROM, STAT_FROM... > &from)
Add two histograms.
Definition: THist.hxx:308
TGeoNode * fNextNode
last searched node
Definition: TGeoNavigator.h:79
TString fPath
current local matrix of the selected division cell
Definition: TGeoNavigator.h:85
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
Bool_t IsDummy() const
Definition: TGeoCache.h:113
#define ClassImp(name)
Definition: Rtypes.h:359
void SetCurrentDirection(const Double_t *dir)
void CdUp()
Go one level up in geometry.
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
Definition: TGeoMatrix.cxx:406
Int_t PushPoint(Int_t startlevel=0)
double Double_t
Definition: RtypesCore.h:55
Bool_t fIsEntering
flag a safe start for point classification
Definition: TGeoNavigator.h:65
TGeoNode * FindNextBoundary(Double_t stepmax=TGeoShape::Big(), const char *path="", Bool_t frombdr=kFALSE)
Find distance to next boundary and store it in fStep.
const char * GetPath()
Returns the current geometry path.
Definition: TGeoCache.cxx:343
TGeoVolume * fCurrentVolume
cache of states
Definition: TGeoNavigator.h:75
Bool_t fIsSameLocation
flag that current point is on some boundary
Definition: TGeoNavigator.h:71
static RooMathCoreReg dummy
Double_t y[n]
Definition: legend1.C:17
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 * GetMother(Int_t up=1) const
Int_t fThreadId
last point for which safety was computed
Definition: TGeoNavigator.h:55
Finder class handling voxels.
static Double_t Big()
Definition: TGeoShape.h:88
Media are used to store properties related to tracking and which are useful only when using geometry ...
Definition: TGeoMedium.h:23
void ResetAll()
Reset the navigator.
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...
TGeoHMatrix * GetHMatrix()
Return stored current matrix (global matrix of the next touched node).
Mother of all ROOT objects.
Definition: TObject.h:37
Bool_t CdDown(Int_t index)
Make daughter INDEX of current node the active state. Compute global matrix.
Definition: TGeoCache.cxx:201
Double_t fLastPoint[3]
current direction
Definition: TGeoNavigator.h:54
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
Bool_t fIsStepExiting
flag that next geometric step will enter new volume
Definition: TGeoNavigator.h:68
Class providing navigation API for TGeo geometries.
Definition: TGeoNavigator.h:33
void CdNext()
Do a cd to the node found next by FindNextBoundary.
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition: TGeoNode.h:39
virtual Int_t GetNextNodeIndex() const
Definition: TGeoVolume.h:169
TGeoHMatrix * GetMotherMatrix(Int_t up=1) const
R__EXTERN TGeoIdentity * gGeoIdentity
Definition: TGeoMatrix.h:478
Bool_t HasIdArray() const
Definition: TGeoCache.h:112
static Int_t ThreadId()
Translates the current thread id to an ordinal number.
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:665
Int_t GetNodeId() const
void CdNode(Int_t nodeid)
Change current path to point to the node having this id.
Definition: TGeoCache.cxx:164
Class storing the state of the cache at a given moment.
Definition: TGeoCache.h:24
Int_t * GetOverlaps(Int_t &novlp) const
Definition: TGeoNode.h:93
Int_t GetNdaughters() const
Definition: TGeoNode.h:90
TGeoNode * FindNode(Bool_t safe_start=kTRUE)
Returns deepest node containing current point.
const char * kGeoOutsidePath
virtual TGeoNode * CdNext()
Make next node (if any) current.
void CdUp()
Make mother of current node the active state.
Definition: TGeoCache.cxx:251
void GetBranchOnlys(Int_t *isonly) const
Fill copy numbers of current branch nodes.
Definition: TGeoCache.cxx:306
Int_t fOverlapSize
next daughter index after FindNextBoundary
Definition: TGeoNavigator.h:59
Definition: first.py:1
Bool_t IsParallelWorldNav() const
Definition: TGeoManager.h:557
Double_t Sqrt(Double_t x)
Definition: TMath.h:690
Int_t GetNext() const
Get index of next division.
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
Bool_t fIsExiting
flag if current step just got into a new node
Definition: TGeoNavigator.h:66
TGeoVolume * GetTopVolume() const
Definition: TGeoManager.h:503
void FindOverlaps() const
loop all nodes marked as overlaps and find overlapping brothers
TGeoNode * fForcedNode
next node that will be crossed
Definition: TGeoNavigator.h:80
Int_t GetCurrentNodeId() const
TGeoShape * GetShape() const
Definition: TGeoVolume.h:191
virtual Int_t GetIndex() const
Definition: TGeoNode.h:86
void DoBackupState()
Backup the current state without affecting the cache stack.
Double_t * FindNormalFast()
Computes fast normal to next crossed boundary, assuming that the current point is close enough to the...
void SetState(Int_t level, Int_t startlevel, Int_t nmany, Bool_t ovlp, Double_t *point=0)
Fill current modeller state.
Definition: TGeoCache.cxx:563
Bool_t fStartSafe
flags the type of the current node
Definition: TGeoNavigator.h:64
const Bool_t kTRUE
Definition: RtypesCore.h:87
TGeoVolume * GetVolume() const
Definition: TGeoNode.h:94
const char * GetPath() const
Get path to the current node in the form /node0/node1/...
char name[80]
Definition: TGX11.cxx:109
Bool_t RestoreState(Int_t &nmany, TGeoCacheState *state, Double_t *point=0)
Pop next state/point from a backed-up state.
Definition: TGeoCache.cxx:392
TGeoNode * CrossDivisionCell()
Cross a division cell.
TGeoHMatrix * GetCurrentMatrix() const
Definition: TGeoCache.h:99
Int_t * fOverlapClusters
current recursive position in fOverlapClusters
Definition: TGeoNavigator.h:61
Int_t GetLevel() const
Definition: TGeoCache.h:108
TGeoNode * fTopNode
current node
Definition: TGeoNavigator.h:77
TGeoCacheState * fBackupState
current point is supposed to be inside this node
Definition: TGeoNavigator.h:81
Bool_t fCurrentOverlapping
flag set when an overlapping cluster is searched
Definition: TGeoNavigator.h:63
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)...
const char * Data() const
Definition: TString.h:364
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.