35 ClassImp(TGeoParallelWorld);
40 TGeoParallelWorld::TGeoParallelWorld(
const char *name, TGeoManager *mgr)
43 fPaths(new TObjArray(256)),
48 fPhysical(new TObjArray(256))
55 TGeoParallelWorld::~TGeoParallelWorld()
57 if (fPhysical) {fPhysical->Delete();
delete fPhysical;}
58 if (fPaths) {fPaths->Delete();
delete fPaths;}
65 void TGeoParallelWorld::AddNode(
const char *path)
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);
72 fPaths->Add(
new TObjString(path));
80 void TGeoParallelWorld::AddOverlap(TGeoVolume *vol, Bool_t activate)
82 if (activate) fUseOverlaps = kTRUE;
83 vol->SetOverlappingCandidate(kTRUE);
91 void TGeoParallelWorld::AddOverlap(
const char *volname, Bool_t activate)
93 if (activate) fUseOverlaps = kTRUE;
94 TIter next(fGeoManager->GetListOfVolumes());
96 while ((vol=(TGeoVolume*)next())) {
97 if (!strcmp(vol->GetName(), volname)) vol->SetOverlappingCandidate(kTRUE);
104 Int_t TGeoParallelWorld::PrintDetectedOverlaps()
const
106 TIter next(fGeoManager->GetListOfVolumes());
109 while ((vol=(TGeoVolume*)next())) {
110 if (vol->IsOverlappingCandidate()) {
111 if (noverlaps==0) Info(
"PrintDetectedOverlaps",
"List of detected volumes overlapping with the PW");
113 printf(
"volume: %s at index: %d\n", vol->GetName(), vol->GetNumber());
122 void TGeoParallelWorld::ResetOverlaps()
const
124 TIter next(fGeoManager->GetListOfVolumes());
126 while ((vol=(TGeoVolume*)next())) vol->SetOverlappingCandidate(kFALSE);
132 Bool_t TGeoParallelWorld::CloseGeometry()
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");
140 RefreshPhysicalNodes();
142 Info(
"CloseGeometry",
"Parallel world %s contains %d prioritised objects", GetName(), fPaths->GetEntriesFast());
144 TIter next(fGeoManager->GetListOfVolumes());
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");
157 void TGeoParallelWorld::RefreshPhysicalNodes()
160 fVolume =
new TGeoVolumeAssembly(GetName());
161 fGeoManager->GetListOfVolumes()->Remove(fVolume);
163 if (fPhysical) {fPhysical->Delete();
delete fPhysical;}
164 fPhysical =
new TObjArray(fPaths->GetEntriesFast());
165 TGeoPhysicalNode *pnode;
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()));
175 fVolume->GetShape()->ComputeBBox();
176 fVolume->Voxelize(
"ALL");
182 TGeoPhysicalNode *TGeoParallelWorld::FindNode(Double_t point[3])
184 if (!fIsClosed) Fatal(
"FindNode",
"Parallel geometry must be closed first");
185 TGeoNavigator *nav = fGeoManager->GetCurrentNavigator();
187 TGeoVoxelFinder *voxels = fVolume->GetVoxels();
190 Int_t nd = fVolume->GetNdaughters();
192 TGeoNodeCache *cache = nav->GetCache();
193 TGeoStateInfo &info = *cache->GetMakePWInfo(nd);
194 Int_t *check_list = voxels->GetCheckList(point, ncheck, info);
196 if (!check_list)
return 0;
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)) {
205 fLastState = (TGeoPhysicalNode*)fPhysical->At(node->GetNumber());
216 TGeoPhysicalNode *TGeoParallelWorld::FindNextBoundary(Double_t point[3], Double_t dir[3],
217 Double_t &step, Double_t stepmax)
219 if (!fIsClosed) Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
220 TGeoPhysicalNode *pnode = 0;
221 TGeoNavigator *nav = fGeoManager->GetCurrentNavigator();
223 if (fUseOverlaps && !nav->GetCurrentVolume()->IsOverlappingCandidate())
return 0;
227 if (fLastState && fLastState->IsMatchingState(nav))
return 0;
231 Double_t snext = TGeoShape::Big();
233 TGeoVoxelFinder *voxels = fVolume->GetVoxels();
234 Int_t idaughter = -1;
235 Int_t nd = fVolume->GetNdaughters();
238 Double_t lpoint[3], ldir[3];
242 for (i=0; i<nd; i++) {
243 current = fVolume->GetNode(i);
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);
255 pnode = (TGeoPhysicalNode*)fPhysical->At(idaughter);
258 step = TGeoShape::Big();
263 Int_t sumchecked = 0;
265 TGeoNodeCache *cache = nav->GetCache();
266 TGeoStateInfo &info = *cache->GetMakePWInfo(nd);
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();
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) {
283 idaughter = vlist[i];
287 pnode = (TGeoPhysicalNode*)fPhysical->At(idaughter);
289 if (!fUseOverlaps && !nav->GetCurrentVolume()->IsOverlappingCandidate()) {
290 AddOverlap(nav->GetCurrentVolume(),kFALSE);
296 step = TGeoShape::Big();
303 Double_t TGeoParallelWorld::Safety(Double_t point[3], Double_t safmax)
305 TGeoNavigator *nav = fGeoManager->GetCurrentNavigator();
307 if (fLastState && fLastState->IsMatchingState(nav))
return TGeoShape::Big();
309 if (fUseOverlaps && !nav->GetCurrentVolume()->IsOverlappingCandidate())
return TGeoShape::Big();
311 Double_t safe = safmax;
313 TGeoPhysicalNode *pnode = 0;
314 const Double_t tolerance = TGeoShape::Tolerance();
315 Int_t nd = fVolume->GetNdaughters();
317 TGeoVoxelFinder *voxels = fVolume->GetVoxels();
319 Double_t *boxes = voxels->GetBoxes();
320 for (Int_t
id=0;
id<nd;
id++) {
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);
335 if (pnode->IsMatchingState(nav))
return TGeoShape::Big();
336 current = fVolume->GetNode(
id);
337 current->MasterToLocal(point, local);
339 safnext = current->Safety(local, kFALSE);
340 if (safnext < tolerance)
return 0.;
341 if (safnext < safe) safe = safnext;
349 void TGeoParallelWorld::CheckOverlaps(Double_t ovlp)
351 fVolume->CheckOverlaps(ovlp);
357 void TGeoParallelWorld::Draw(Option_t *option)
359 fVolume->Draw(option);