Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoParallelWorld.cxx
Go to the documentation of this file.
1 // Author: Andrei Gheata 17/02/04
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 /** \class TGeoParallelWorld
12 \ingroup Geometry_classes
13 Base class for a flat parallel geometry.
14 
15  The parallel geometry can be composed by both normal volumes added
16 using the AddNode interface (not implemented yet) or by physical nodes
17 which will use as position their actual global matrix with respect to the top
18 volume of the main geometry.
19 
20  All these nodes are added as daughters to the "top" volume of
21 the parallel world which acts as a navigation helper in this parallel
22 world. The parallel world has to be closed before calling any navigation
23 method.
24 */
25 
26 #include "TGeoParallelWorld.h"
27 #include "TObjString.h"
28 #include "TGeoManager.h"
29 #include "TGeoVolume.h"
30 #include "TGeoVoxelFinder.h"
31 #include "TGeoMatrix.h"
32 #include "TGeoPhysicalNode.h"
33 #include "TGeoNavigator.h"
34 
35 ClassImp(TGeoParallelWorld);
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Default constructor
39 
40 TGeoParallelWorld::TGeoParallelWorld(const char *name, TGeoManager *mgr)
41  : TNamed(name,""),
42  fGeoManager(mgr),
43  fPaths(new TObjArray(256)),
44  fUseOverlaps(kFALSE),
45  fIsClosed(kFALSE),
46  fVolume(0),
47  fLastState(0),
48  fPhysical(new TObjArray(256))
49 {
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Destructor
54 
55 TGeoParallelWorld::~TGeoParallelWorld()
56 {
57  if (fPhysical) {fPhysical->Delete(); delete fPhysical;}
58  if (fPaths) {fPaths->Delete(); delete fPaths;}
59  delete fVolume;
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 /// Add a node normally to this world. Overlapping nodes not allowed
64 
65 void TGeoParallelWorld::AddNode(const char *path)
66 {
67  if (fIsClosed) Fatal("AddNode", "Cannot add nodes to a closed parallel geometry");
68  if (!fGeoManager->CheckPath(path)) {
69  Error("AddNode", "Path %s not valid.\nCannot add to parallel world!", path);
70  return;
71  }
72  fPaths->Add(new TObjString(path));
73 }
74 
75 ////////////////////////////////////////////////////////////////////////////////
76 /// To use this optimization, the user should declare the full list of volumes
77 /// which may overlap with any of the physical nodes of the parallel world. Better
78 /// be done before misalignment
79 
80 void TGeoParallelWorld::AddOverlap(TGeoVolume *vol, Bool_t activate)
81 {
82  if (activate) fUseOverlaps = kTRUE;
83  vol->SetOverlappingCandidate(kTRUE);
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// To use this optimization, the user should declare the full list of volumes
88 /// which may overlap with any of the physical nodes of the parallel world. Better
89 /// be done before misalignment
90 
91 void TGeoParallelWorld::AddOverlap(const char *volname, Bool_t activate)
92 {
93  if (activate) fUseOverlaps = kTRUE;
94  TIter next(fGeoManager->GetListOfVolumes());
95  TGeoVolume *vol;
96  while ((vol=(TGeoVolume*)next())) {
97  if (!strcmp(vol->GetName(), volname)) vol->SetOverlappingCandidate(kTRUE);
98  }
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Print the overlaps which were detected during real tracking
103 
104 Int_t TGeoParallelWorld::PrintDetectedOverlaps() const
105 {
106  TIter next(fGeoManager->GetListOfVolumes());
107  TGeoVolume *vol;
108  Int_t noverlaps = 0;
109  while ((vol=(TGeoVolume*)next())) {
110  if (vol->IsOverlappingCandidate()) {
111  if (noverlaps==0) Info("PrintDetectedOverlaps", "List of detected volumes overlapping with the PW");
112  noverlaps++;
113  printf("volume: %s at index: %d\n", vol->GetName(), vol->GetNumber());
114  }
115  }
116  return noverlaps;
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Reset overlapflag for all volumes in geometry
121 
122 void TGeoParallelWorld::ResetOverlaps() const
123 {
124  TIter next(fGeoManager->GetListOfVolumes());
125  TGeoVolume *vol;
126  while ((vol=(TGeoVolume*)next())) vol->SetOverlappingCandidate(kFALSE);
127 }
128 
129 ////////////////////////////////////////////////////////////////////////////////
130 /// The main geometry must be closed.
131 
132 Bool_t TGeoParallelWorld::CloseGeometry()
133 {
134  if (fIsClosed) return kTRUE;
135  if (!fGeoManager->IsClosed()) Fatal("CloseGeometry", "Main geometry must be closed first");
136  if (!fPaths || !fPaths->GetEntriesFast()) {
137  Error("CloseGeometry", "List of paths is empty");
138  return kFALSE;
139  }
140  RefreshPhysicalNodes();
141  fIsClosed = kTRUE;
142  Info("CloseGeometry", "Parallel world %s contains %d prioritised objects", GetName(), fPaths->GetEntriesFast());
143  Int_t novlp = 0;
144  TIter next(fGeoManager->GetListOfVolumes());
145  TGeoVolume *vol;
146  while ((vol=(TGeoVolume*)next())) if (vol->IsOverlappingCandidate()) novlp++;
147  Info("CloseGeometry", "Number of declared overlaps: %d", novlp);
148  if (fUseOverlaps) Info("CloseGeometry", "Parallel world will use declared overlaps");
149  else Info("CloseGeometry", "Parallel world will detect overlaps with other volumes");
150  return kTRUE;
151 }
152 
153 ////////////////////////////////////////////////////////////////////////////////
154 /// Refresh the node pointers and re-voxelize. To be called mandatory in case
155 /// re-alignment happened.
156 
157 void TGeoParallelWorld::RefreshPhysicalNodes()
158 {
159  delete fVolume;
160  fVolume = new TGeoVolumeAssembly(GetName());
161  fGeoManager->GetListOfVolumes()->Remove(fVolume);
162  // Loop physical nodes and add them to the navigation helper volume
163  if (fPhysical) {fPhysical->Delete(); delete fPhysical;}
164  fPhysical = new TObjArray(fPaths->GetEntriesFast());
165  TGeoPhysicalNode *pnode;
166  TObjString *objs;
167  TIter next(fPaths);
168  Int_t copy = 0;
169  while ((objs = (TObjString*)next())) {
170  pnode = new TGeoPhysicalNode(objs->GetName());
171  fPhysical->AddAt(pnode, copy);
172  fVolume->AddNode(pnode->GetVolume(), copy++, new TGeoHMatrix(*pnode->GetMatrix()));
173  }
174  // Voxelize the volume
175  fVolume->GetShape()->ComputeBBox();
176  fVolume->Voxelize("ALL");
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// Finds physical node containing the point
181 
182 TGeoPhysicalNode *TGeoParallelWorld::FindNode(Double_t point[3])
183 {
184  if (!fIsClosed) Fatal("FindNode", "Parallel geometry must be closed first");
185  TGeoNavigator *nav = fGeoManager->GetCurrentNavigator();
186  // Fast return if not in an overlapping candidate
187  TGeoVoxelFinder *voxels = fVolume->GetVoxels();
188  Int_t id;
189  Int_t ncheck = 0;
190  Int_t nd = fVolume->GetNdaughters();
191  // get the list of nodes passing thorough the current voxel
192  TGeoNodeCache *cache = nav->GetCache();
193  TGeoStateInfo &info = *cache->GetMakePWInfo(nd);
194  Int_t *check_list = voxels->GetCheckList(point, ncheck, info);
195 // cache->ReleaseInfo(); // no hierarchical use
196  if (!check_list) return 0;
197  // loop all nodes in voxel
198  TGeoNode *node;
199  Double_t local[3];
200  for (id=0; id<ncheck; id++) {
201  node = fVolume->GetNode(check_list[id]);
202  node->MasterToLocal(point, local);
203  if (node->GetVolume()->Contains(local)) {
204  // We found a node containing the point
205  fLastState = (TGeoPhysicalNode*)fPhysical->At(node->GetNumber());
206  return fLastState;
207  }
208  }
209  return 0;
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Same functionality as TGeoNavigator::FindNextDaughterBoundary for the
214 /// parallel world
215 
216 TGeoPhysicalNode *TGeoParallelWorld::FindNextBoundary(Double_t point[3], Double_t dir[3],
217  Double_t &step, Double_t stepmax)
218 {
219  if (!fIsClosed) Fatal("FindNextBoundary", "Parallel geometry must be closed first");
220  TGeoPhysicalNode *pnode = 0;
221  TGeoNavigator *nav = fGeoManager->GetCurrentNavigator();
222  // Fast return if not in an overlapping candidate
223  if (fUseOverlaps && !nav->GetCurrentVolume()->IsOverlappingCandidate()) return 0;
224 // TIter next(fPhysical);
225  // Ignore the request if the current state in the main geometry matches the
226  // last touched physical node in the parallel geometry
227  if (fLastState && fLastState->IsMatchingState(nav)) return 0;
228 // while ((pnode = (TGeoPhysicalNode*)next())) {
229 // if (pnode->IsMatchingState(nav)) return 0;
230 // }
231  Double_t snext = TGeoShape::Big();
232  step = stepmax;
233  TGeoVoxelFinder *voxels = fVolume->GetVoxels();
234  Int_t idaughter = -1; // nothing crossed
235  Int_t nd = fVolume->GetNdaughters();
236  Int_t i;
237  TGeoNode *current;
238  Double_t lpoint[3], ldir[3];
239 // const Double_t tolerance = TGeoShape::Tolerance();
240  if (nd<5) {
241  // loop over daughters
242  for (i=0; i<nd; i++) {
243  current = fVolume->GetNode(i);
244  // validate only within stepmax
245  if (voxels->IsSafeVoxel(point, i, stepmax)) continue;
246  current->MasterToLocal(point, lpoint);
247  current->MasterToLocalVect(dir, ldir);
248  snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, step);
249  if (snext < step) {
250  step = snext;
251  idaughter = i;
252  }
253  }
254  if (idaughter>=0) {
255  pnode = (TGeoPhysicalNode*)fPhysical->At(idaughter);
256  return pnode;
257  }
258  step = TGeoShape::Big();
259  return 0;
260  }
261  // Get current voxel
262  Int_t ncheck = 0;
263  Int_t sumchecked = 0;
264  Int_t *vlist = 0;
265  TGeoNodeCache *cache = nav->GetCache();
266  TGeoStateInfo &info = *cache->GetMakePWInfo(nd);
267 // TGeoStateInfo &info = *cache->GetInfo();
268 // cache->ReleaseInfo(); // no hierarchical use
269  voxels->SortCrossedVoxels(point, dir, info);
270  while ((sumchecked<nd) && (vlist=voxels->GetNextVoxel(point, dir, ncheck, info))) {
271  for (i=0; i<ncheck; i++) {
272  pnode = (TGeoPhysicalNode*)fPhysical->At(vlist[i]);
273  if (pnode->IsMatchingState(nav)) {
274  step = TGeoShape::Big();
275  return 0;
276  }
277  current = fVolume->GetNode(vlist[i]);
278  current->MasterToLocal(point, lpoint);
279  current->MasterToLocalVect(dir, ldir);
280  snext = current->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, step);
281  if (snext < step - 1.E-8) {
282  step = snext;
283  idaughter = vlist[i];
284  }
285  }
286  if (idaughter>=0) {
287  pnode = (TGeoPhysicalNode*)fPhysical->At(idaughter);
288  // mark the overlap
289  if (!fUseOverlaps && !nav->GetCurrentVolume()->IsOverlappingCandidate()) {
290  AddOverlap(nav->GetCurrentVolume(),kFALSE);
291 // printf("object %s overlapping with pn: %s\n", fGeoManager->GetPath(), pnode->GetName());
292  }
293  return pnode;
294  }
295  }
296  step = TGeoShape::Big();
297  return 0;
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Compute safety for the parallel world
302 
303 Double_t TGeoParallelWorld::Safety(Double_t point[3], Double_t safmax)
304 {
305  TGeoNavigator *nav = fGeoManager->GetCurrentNavigator();
306  // Fast return if the state matches the last one recorded
307  if (fLastState && fLastState->IsMatchingState(nav)) return TGeoShape::Big();
308  // Fast return if not in an overlapping candidate
309  if (fUseOverlaps && !nav->GetCurrentVolume()->IsOverlappingCandidate()) return TGeoShape::Big();
310  Double_t local[3];
311  Double_t safe = safmax;
312  Double_t safnext;
313  TGeoPhysicalNode *pnode = 0;
314  const Double_t tolerance = TGeoShape::Tolerance();
315  Int_t nd = fVolume->GetNdaughters();
316  TGeoNode *current;
317  TGeoVoxelFinder *voxels = fVolume->GetVoxels();
318  //---> check fast unsafe voxels
319  Double_t *boxes = voxels->GetBoxes();
320  for (Int_t id=0; id<nd; id++) {
321  Int_t ist = 6*id;
322  Double_t dxyz = 0.;
323  Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
324  if (dxyz0 > safe) continue;
325  Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
326  if (dxyz1 > safe) continue;
327  Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
328  if (dxyz2 > safe) continue;
329  if (dxyz0>0) dxyz+=dxyz0*dxyz0;
330  if (dxyz1>0) dxyz+=dxyz1*dxyz1;
331  if (dxyz2>0) dxyz+=dxyz2*dxyz2;
332  if (dxyz >= safe*safe) continue;
333  pnode = (TGeoPhysicalNode*)fPhysical->At(id);
334  // Return if inside the current node
335  if (pnode->IsMatchingState(nav)) return TGeoShape::Big();
336  current = fVolume->GetNode(id);
337  current->MasterToLocal(point, local);
338  // Safety to current node
339  safnext = current->Safety(local, kFALSE);
340  if (safnext < tolerance) return 0.;
341  if (safnext < safe) safe = safnext;
342  }
343  return safe;
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////////
347 /// Check overlaps within a tolerance value.
348 
349 void TGeoParallelWorld::CheckOverlaps(Double_t ovlp)
350 {
351  fVolume->CheckOverlaps(ovlp);
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Draw the parallel world
356 
357 void TGeoParallelWorld::Draw(Option_t *option)
358 {
359  fVolume->Draw(option);
360 }
361