Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoNode.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 24/10/01
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 TGeoNode
13 \ingroup Geometry_classes
14 
15  A node represent a volume positioned inside another.They store links to both
16 volumes and to the TGeoMatrix representing the relative positioning. Node are
17 never instantiated directly by users, but created as a result of volume operations.
18 Adding a volume named A with a given user ID inside a volume B will create a node
19 node named A_ID. This will be added to the list of nodes stored by B. Also,
20 when applying a division operation in N slices to a volume A, a list of nodes
21 B_1, B_2, ..., B_N is also created. A node B_i does not represent a unique
22 object in the geometry because its container A might be at its turn positioned
23 as node inside several other volumes. Only when a complete branch of nodes
24 is fully defined up to the top node in the geometry, a given path like:
25 
26  /TOP_1/.../A_3/B_7 will represent an unique object.
27 
28 Its global transformation matrix can be computed as the pile-up of all local
29 transformations in its branch. We will therefore call "logical graph" the
30 hierarchy defined by nodes and volumes. The expansion of the logical graph by
31 all possible paths defines a tree structure where all nodes are unique
32 "touchable" objects. We will call this the "physical tree". Unlike the logical
33 graph, the physical tree can become a huge structure with several milions of nodes
34 in case of complex geometries, therefore it is not always a good idea to keep it
35 transient in memory. Since a the logical and physical structures are correlated, the
36 modeller rather keeps track only of the current branch, updating the current
37 global matrix at each change of the level in geometry. The current physical node
38 is not an object that can be asked for at a given moment, but rather represented
39 by the combination: current node + current global matrix. However, physical nodes
40 have unique ID's that can be retrieved for a given modeler state. These can be
41 fed back to the modeler in order to force a physical node to become current.
42 The advantage of this comes from the fact that all navigation queries check
43 first the current node, therefore knowing the location of a point in the
44 geometry can be saved as a starting state for later use.
45 
46  Nodes can be declared as "overlapping" in case they do overlap with other
47 nodes inside the same container or extrude this container. Non-overlapping
48 nodes can be created with:
49 
50 ~~~ {.cpp}
51  TGeoVolume::AddNode(TGeoVolume *daughter, Int_t copy_No, TGeoMatrix *matr);
52 ~~~
53 
54 The creation of overlapping nodes can be done with a similar prototype:
55 
56 ~~~ {.cpp}
57  TGeoVolume::AddNodeOverlap(same arguments);
58 ~~~
59 
60 When closing the geometry, overlapping nodes perform a check of possible
61 overlaps with their neighbours. These are stored and checked all the time
62 during navigation, therefore navigation is slower when embedding such nodes
63 into geometry.
64 
65  Node have visualization attributes as volume have. When undefined by users,
66 painting a node on a pad will take the corresponding volume attributes.
67 
68 \image html geom_t_node.png
69 */
70 
71 #include "Riostream.h"
72 
73 #include "TBrowser.h"
74 #include "TObjArray.h"
75 #include "TStyle.h"
76 
77 #include "TGeoManager.h"
78 #include "TGeoMatrix.h"
79 #include "TGeoShape.h"
80 #include "TGeoVolume.h"
81 #include "TVirtualGeoPainter.h"
82 #include "TGeoVoxelFinder.h"
83 #include "TGeoNode.h"
84 #include "TMath.h"
85 #include "TStopwatch.h"
86 #include "TGeoExtension.h"
87 
88 // statics and globals
89 
90 ClassImp(TGeoNode);
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 /// Default constructor
94 
95 TGeoNode::TGeoNode()
96 {
97  fVolume = 0;
98  fMother = 0;
99  fNumber = 0;
100  fNovlp = 0;
101  fOverlaps = 0;
102  fUserExtension = 0;
103  fFWExtension = 0;
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// Constructor
108 
109 TGeoNode::TGeoNode(const TGeoVolume *vol)
110 {
111  if (!vol) {
112  Error("ctor", "volume not specified");
113  return;
114  }
115  fVolume = (TGeoVolume*)vol;
116  if (fVolume->IsAdded()) fVolume->SetReplicated();
117  fVolume->SetAdded();
118  fMother = 0;
119  fNumber = 0;
120  fNovlp = 0;
121  fOverlaps = 0;
122  fUserExtension = 0;
123  fFWExtension = 0;
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 /// Destructor
128 
129 TGeoNode::~TGeoNode()
130 {
131  if (fOverlaps) delete [] fOverlaps;
132  if (fUserExtension) {fUserExtension->Release(); fUserExtension=0;}
133  if (fFWExtension) {fFWExtension->Release(); fFWExtension=0;}
134 }
135 
136 ////////////////////////////////////////////////////////////////////////////////
137 /// How-to-browse for a node.
138 
139 void TGeoNode::Browse(TBrowser *b)
140 {
141  if (!b) return;
142  if (!GetNdaughters()) return;
143  TGeoNode *daughter;
144  TString title;
145  for (Int_t i=0; i<GetNdaughters(); i++) {
146  daughter = GetDaughter(i);
147  b->Add(daughter, daughter->GetName(), daughter->IsVisible());
148  }
149 }
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 /// Returns the number of daughters. Nodes pointing to same volume counted
153 /// once if unique_volumes is set.
154 
155 Int_t TGeoNode::CountDaughters(Bool_t unique_volumes)
156 {
157  static Int_t icall = 0;
158  Int_t counter = 0;
159  // Count this node
160  if (unique_volumes) {
161  if (!fVolume->IsSelected()) {
162  counter++;
163  fVolume->SelectVolume(kFALSE);
164  }
165  } else counter++;
166  icall++;
167  Int_t nd = fVolume->GetNdaughters();
168  // Count daughters recursively
169  for (Int_t i=0; i<nd; i++) counter += GetDaughter(i)->CountDaughters(unique_volumes);
170  icall--;
171  // Un-mark volumes
172  if (icall == 0) fVolume->SelectVolume(kTRUE);
173  return counter;
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// Check overlaps bigger than OVLP hierarchically, starting with this node.
178 
179 void TGeoNode::CheckOverlaps(Double_t ovlp, Option_t *option)
180 {
181  Int_t icheck = 0;
182  Int_t ncheck = 0;
183  TStopwatch *timer;
184  Int_t i;
185  Bool_t sampling = kFALSE;
186  TString opt(option);
187  opt.ToLower();
188  if (opt.Contains("s")) sampling = kTRUE;
189 
190  TGeoManager *geom = fVolume->GetGeoManager();
191  ncheck = CountDaughters(kFALSE);
192  timer = new TStopwatch();
193  geom->ClearOverlaps();
194  geom->SetCheckingOverlaps(kTRUE);
195  Info("CheckOverlaps", "Checking overlaps for %s and daughters within %g", fVolume->GetName(),ovlp);
196  if (sampling) {
197  Info("CheckOverlaps", "Checking overlaps by sampling <%s> for %s and daughters", option, fVolume->GetName());
198  Info("CheckOverlaps", "=== NOTE: Extrusions NOT checked with sampling option ! ===");
199  }
200  timer->Start();
201  geom->GetGeomPainter()->OpProgress(fVolume->GetName(),icheck,ncheck,timer,kFALSE);
202  fVolume->CheckOverlaps(ovlp,option);
203  icheck++;
204  TGeoIterator next(fVolume);
205  TGeoNode *node;
206  TString path;
207  TObjArray *overlaps = geom->GetListOfOverlaps();
208  Int_t novlps;
209  TString msg;
210  while ((node=next())) {
211  next.GetPath(path);
212  icheck++;
213  if (!node->GetVolume()->IsSelected()) {
214  msg = TString::Format("found %d overlaps", overlaps->GetEntriesFast());
215  geom->GetGeomPainter()->OpProgress(node->GetVolume()->GetName(),icheck,ncheck,timer,kFALSE, msg);
216  node->GetVolume()->SelectVolume(kFALSE);
217  node->GetVolume()->CheckOverlaps(ovlp,option);
218  }
219  }
220  fVolume->SelectVolume(kTRUE);
221  geom->SetCheckingOverlaps(kFALSE);
222  geom->SortOverlaps();
223  novlps = overlaps->GetEntriesFast();
224  TNamed *obj;
225  for (i=0; i<novlps; i++) {
226  obj = (TNamed*)overlaps->At(i);
227  obj->SetName(TString::Format("ov%05d",i));
228  }
229  geom->GetGeomPainter()->OpProgress("Check overlaps:",icheck,ncheck,timer,kTRUE);
230  Info("CheckOverlaps", "Number of illegal overlaps/extrusions : %d\n", novlps);
231  delete timer;
232 }
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// compute the closest distance of approach from point px,py to this node
236 
237 Int_t TGeoNode::DistancetoPrimitive(Int_t px, Int_t py)
238 {
239  Int_t dist = 9999;
240  if (!fVolume) return dist;
241  if (gGeoManager != fVolume->GetGeoManager()) gGeoManager = fVolume->GetGeoManager();
242  TVirtualGeoPainter *painter = gGeoManager->GetPainter();
243  if (!painter) return dist;
244  dist = painter->DistanceToPrimitiveVol(fVolume, px, py);
245  return dist;
246 }
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 /// Execute mouse actions on this volume.
250 
251 void TGeoNode::ExecuteEvent(Int_t event, Int_t px, Int_t py)
252 {
253  if (!fVolume) return;
254  TVirtualGeoPainter *painter = fVolume->GetGeoManager()->GetPainter();
255  if (!painter) return;
256  painter->ExecuteVolumeEvent(fVolume, event, px, py);
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 /// Get node info for the browser.
261 
262 char *TGeoNode::GetObjectInfo(Int_t px, Int_t py) const
263 {
264  if (!fVolume) return 0;
265  TVirtualGeoPainter *painter = fVolume->GetGeoManager()->GetPainter();
266  if (!painter) return 0;
267  return (char*)painter->GetVolumeInfo(fVolume, px, py);
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// check if this node is drawn. Assumes that this node is current
272 
273 Bool_t TGeoNode::IsOnScreen() const
274 {
275  if (fVolume->TestAttBit(TGeoAtt::kVisOnScreen)) return kTRUE;
276  return kFALSE;
277 }
278 
279 ////////////////////////////////////////////////////////////////////////////////
280 /// Inspect this node.
281 
282 void TGeoNode::InspectNode() const
283 {
284  printf("== Inspecting node %s ", GetName());
285  if (fMother) printf("mother volume %s. ", fMother->GetName());
286  if (IsOverlapping()) printf("(Node is MANY)\n");
287  else printf("\n");
288  if (fOverlaps && fMother) {
289  printf(" possibly overlapping with : ");
290  for (Int_t i=0; i<fNovlp; i++)
291  printf(" %s ", fMother->GetNode(fOverlaps[i])->GetName());
292  printf("\n");
293  }
294  printf("Transformation matrix:\n");
295  TGeoMatrix *matrix = GetMatrix();
296  if (GetMatrix()) matrix->Print();
297  fVolume->Print();
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// check for wrong parameters in shapes
302 
303 void TGeoNode::CheckShapes()
304 {
305  fVolume->CheckShapes();
306  Int_t nd = GetNdaughters();
307  if (!nd) return;
308  for (Int_t i=0; i<nd; i++) fVolume->GetNode(i)->CheckShapes();
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// draw only this node independently of its vis options
313 
314 void TGeoNode::DrawOnly(Option_t *option)
315 {
316  fVolume->DrawOnly(option);
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 /// draw current node according to option
321 
322 void TGeoNode::Draw(Option_t *option)
323 {
324  gGeoManager->FindNode();
325  gGeoManager->CdUp();
326  Double_t point[3];
327  gGeoManager->MasterToLocal(gGeoManager->GetCurrentPoint(), &point[0]);
328  gGeoManager->SetCurrentPoint(&point[0]);
329  gGeoManager->GetCurrentVolume()->Draw(option);
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 /// Method drawing the overlap candidates with this node.
334 
335 void TGeoNode::DrawOverlaps()
336 {
337  if (!fNovlp) {printf("node %s is ONLY\n", GetName()); return;}
338  if (!fOverlaps) {printf("node %s no overlaps\n", GetName()); return;}
339  TGeoNode *node;
340  Int_t i;
341  Int_t nd = fMother->GetNdaughters();
342  for (i=0; i<nd; i++) {
343  node = fMother->GetNode(i);
344  node->GetVolume()->SetVisibility(kFALSE);
345  }
346  fVolume->SetVisibility(kTRUE);
347  for (i=0; i<fNovlp; i++) {
348  node = fMother->GetNode(fOverlaps[i]);
349  node->GetVolume()->SetVisibility(kTRUE);
350  }
351  gGeoManager->SetVisLevel(1);
352  fMother->Draw();
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// Fill array with node id. Recursive on node branch.
357 
358 void TGeoNode::FillIdArray(Int_t &ifree, Int_t &nodeid, Int_t *array) const
359 {
360  Int_t nd = GetNdaughters();
361  if (!nd) return;
362  TGeoNode *daughter;
363  Int_t istart = ifree; // start index for daughters
364  ifree += nd;
365  for (Int_t id=0; id<nd; id++) {
366  daughter = GetDaughter(id);
367  array[istart+id] = ifree;
368  array[ifree++] = ++nodeid;
369  daughter->FillIdArray(ifree, nodeid, array);
370  }
371 }
372 
373 
374 ////////////////////////////////////////////////////////////////////////////////
375 /// Search for a node within the branch of this one.
376 
377 Int_t TGeoNode::FindNode(const TGeoNode *node, Int_t level)
378 {
379  Int_t nd = GetNdaughters();
380  if (!nd) return -1;
381  TIter next(fVolume->GetNodes());
382  TGeoNode *daughter;
383  while ((daughter=(TGeoNode*)next())) {
384  if (daughter==node) {
385  gGeoManager->GetListOfNodes()->AddAt(daughter,level+1);
386  return (level+1);
387  }
388  }
389  next.Reset();
390  Int_t new_level;
391  while ((daughter=(TGeoNode*)next())) {
392  new_level = daughter->FindNode(node, level+1);
393  if (new_level>=0) {
394  gGeoManager->GetListOfNodes()->AddAt(daughter, level+1);
395  return new_level;
396  }
397  }
398  return -1;
399 }
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 /// save attributes for this node
403 
404 void TGeoNode::SaveAttributes(std::ostream &out)
405 {
406  if (IsVisStreamed()) return;
407  SetVisStreamed(kTRUE);
408  char quote='"';
409  Bool_t voldef = kFALSE;
410  if ((fVolume->IsVisTouched()) && (!fVolume->IsVisStreamed())) {
411  fVolume->SetVisStreamed(kTRUE);
412  out << " vol = gGeoManager->GetVolume("<<quote<<fVolume->GetName()<<quote<<");"<<std::endl;
413  voldef = kTRUE;
414  if (!fVolume->IsVisDaughters())
415  out << " vol->SetVisDaughters(kFALSE);"<<std::endl;
416  if (fVolume->IsVisible()) {
417 /*
418  if (fVolume->GetLineColor() != gStyle->GetLineColor())
419  out<<" vol->SetLineColor("<<fVolume->GetLineColor()<<");"<<std::endl;
420  if (fVolume->GetLineStyle() != gStyle->GetLineStyle())
421  out<<" vol->SetLineStyle("<<fVolume->GetLineStyle()<<");"<<std::endl;
422  if (fVolume->GetLineWidth() != gStyle->GetLineWidth())
423  out<<" vol->SetLineWidth("<<fVolume->GetLineWidth()<<");"<<std::endl;
424 */
425  } else {
426  out <<" vol->SetVisibility(kFALSE);"<<std::endl;
427  }
428  }
429  if (!IsVisDaughters()) return;
430  Int_t nd = GetNdaughters();
431  if (!nd) return;
432  TGeoNode *node;
433  for (Int_t i=0; i<nd; i++) {
434  node = GetDaughter(i);
435  if (node->IsVisStreamed()) continue;
436  if (node->IsVisTouched()) {
437  if (!voldef)
438  out << " vol = gGeoManager->GetVolume("<<quote<<fVolume->GetName()<<quote<<");"<<std::endl;
439  out<<" node = vol->GetNode("<<i<<");"<<std::endl;
440  if (!node->IsVisDaughters()) {
441  out<<" node->VisibleDaughters(kFALSE);"<<std::endl;
442  node->SetVisStreamed(kTRUE);
443  continue;
444  }
445  if (!node->IsVisible())
446  out<<" node->SetVisibility(kFALSE);"<<std::endl;
447  }
448  node->SaveAttributes(out);
449  node->SetVisStreamed(kTRUE);
450  }
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////
454 /// Connect user-defined extension to the node. The node "grabs" a copy, so
455 /// the original object can be released by the producer. Release the previously
456 /// connected extension if any.
457 ///
458 /// NOTE: This interface is intended for user extensions and is guaranteed not
459 /// to be used by TGeo
460 
461 void TGeoNode::SetUserExtension(TGeoExtension *ext)
462 {
463  if (fUserExtension) fUserExtension->Release();
464  fUserExtension = 0;
465  if (ext) fUserExtension = ext->Grab();
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 /// Connect framework defined extension to the node. The node "grabs" a copy,
470 /// so the original object can be released by the producer. Release the previously
471 /// connected extension if any.
472 ///
473 /// NOTE: This interface is intended for the use by TGeo and the users should
474 /// NOT connect extensions using this method
475 
476 void TGeoNode::SetFWExtension(TGeoExtension *ext)
477 {
478  if (fFWExtension) fFWExtension->Release();
479  fFWExtension = 0;
480  if (ext) fFWExtension = ext->Grab();
481 }
482 
483 ////////////////////////////////////////////////////////////////////////////////
484 /// Get a copy of the user extension pointer. The user must call Release() on
485 /// the copy pointer once this pointer is not needed anymore (equivalent to
486 /// delete() after calling new())
487 
488 TGeoExtension *TGeoNode::GrabUserExtension() const
489 {
490  if (fUserExtension) return fUserExtension->Grab();
491  return 0;
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 /// Get a copy of the framework extension pointer. The user must call Release() on
496 /// the copy pointer once this pointer is not needed anymore (equivalent to
497 /// delete() after calling new())
498 
499 TGeoExtension *TGeoNode::GrabFWExtension() const
500 {
501  if (fFWExtension) return fFWExtension->Grab();
502  return 0;
503 }
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Check the overlab between the bounding box of the node overlaps with the one
506 /// the brother with index IOTHER.
507 
508 Bool_t TGeoNode::MayOverlap(Int_t iother) const
509 {
510  if (!fOverlaps) return kFALSE;
511  for (Int_t i=0; i<fNovlp; i++) if (fOverlaps[i]==iother) return kTRUE;
512  return kFALSE;
513 }
514 
515 ////////////////////////////////////////////////////////////////////////////////
516 /// Convert the point coordinates from mother reference to local reference system
517 
518 void TGeoNode::MasterToLocal(const Double_t *master, Double_t *local) const
519 {
520  GetMatrix()->MasterToLocal(master, local);
521 }
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Convert a vector from mother reference to local reference system
525 
526 void TGeoNode::MasterToLocalVect(const Double_t *master, Double_t *local) const
527 {
528  GetMatrix()->MasterToLocalVect(master, local);
529 }
530 
531 ////////////////////////////////////////////////////////////////////////////////
532 /// Convert the point coordinates from local reference system to mother reference
533 
534 void TGeoNode::LocalToMaster(const Double_t *local, Double_t *master) const
535 {
536  GetMatrix()->LocalToMaster(local, master);
537 }
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 /// Convert a vector from local reference system to mother reference
541 
542 void TGeoNode::LocalToMasterVect(const Double_t *local, Double_t *master) const
543 {
544  GetMatrix()->LocalToMasterVect(local, master);
545 }
546 
547 ////////////////////////////////////////////////////////////////////////////////
548 /// Print the path (A/B/C/...) to this node on stdout
549 
550 void TGeoNode::ls(Option_t * /*option*/) const
551 {
552 }
553 
554 ////////////////////////////////////////////////////////////////////////////////
555 /// Paint this node and its content according to visualization settings.
556 
557 void TGeoNode::Paint(Option_t *option)
558 {
559  TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
560  if (!painter) return;
561  painter->PaintNode(this, option);
562 }
563 
564 ////////////////////////////////////////////////////////////////////////////////
565 /// print daughters candidates for containing current point
566 
567 void TGeoNode::PrintCandidates() const
568 {
569  Double_t point[3];
570  gGeoManager->MasterToLocal(gGeoManager->GetCurrentPoint(), &point[0]);
571  printf(" Local : %g, %g, %g\n", point[0], point[1], point[2]);
572  if (!fVolume->Contains(&point[0])) {
573  printf("current point not inside this\n");
574  return;
575  }
576  TGeoPatternFinder *finder = fVolume->GetFinder();
577  TGeoNode *node;
578  if (finder) {
579  printf("current node divided\n");
580  node = finder->FindNode(&point[0]);
581  if (!node) {
582  printf("point not inside division element\n");
583  return;
584  }
585  printf("inside division element %s\n", node->GetName());
586  return;
587  }
588  TGeoVoxelFinder *voxels = fVolume->GetVoxels();
589  if (!voxels) {
590  printf("volume not voxelized\n");
591  return;
592  }
593  Int_t ncheck = 0;
594  TGeoNavigator *nav = gGeoManager->GetCurrentNavigator();
595  TGeoStateInfo &info = *nav->GetCache()->GetInfo();
596  Int_t *check_list = voxels->GetCheckList(&point[0], ncheck, info);
597  nav->GetCache()->ReleaseInfo();
598  voxels->PrintVoxelLimits(&point[0]);
599  if (!check_list) {
600  printf("no candidates for current point\n");
601  return;
602  }
603  TString overlap = "ONLY";
604  for (Int_t id=0; id<ncheck; id++) {
605  node = fVolume->GetNode(check_list[id]);
606  if (node->IsOverlapping()) overlap = "MANY";
607  else overlap = "ONLY";
608  printf("%i %s %s\n", check_list[id], node->GetName(), overlap.Data());
609  }
610  PrintOverlaps();
611 }
612 
613 ////////////////////////////////////////////////////////////////////////////////
614 /// print possible overlapping nodes
615 
616 void TGeoNode::PrintOverlaps() const
617 {
618  if (!fOverlaps) {printf("node %s no overlaps\n", GetName()); return;}
619  printf("Overlaps for node %s :\n", GetName());
620  TGeoNode *node;
621  for (Int_t i=0; i<fNovlp; i++) {
622  node = fMother->GetNode(fOverlaps[i]);
623  printf(" %s\n", node->GetName());
624  }
625 }
626 
627 ////////////////////////////////////////////////////////////////////////////////
628 /// computes the closest distance from given point to this shape
629 
630 Double_t TGeoNode::Safety(const Double_t *point, Bool_t in) const
631 {
632  Double_t local[3];
633  GetMatrix()->MasterToLocal(point,local);
634  return fVolume->GetShape()->Safety(local,in);
635 }
636 
637 ////////////////////////////////////////////////////////////////////////////////
638 /// Copy content of lst of overlaps from source array
639 
640 void TGeoNode::CopyOverlaps(Int_t *src, Int_t novlp)
641 {
642  Int_t *ovlps = nullptr;
643  if (src && (novlp > 0)) {
644  ovlps = new Int_t[novlp];
645  memcpy(ovlps, src, novlp*sizeof(Int_t));
646  }
647  SetOverlaps(ovlps, novlp);
648 }
649 
650 ////////////////////////////////////////////////////////////////////////////////
651 /// set the list of overlaps for this node (ovlp must be created with operator new)
652 
653 void TGeoNode::SetOverlaps(Int_t *ovlp, Int_t novlp)
654 {
655  if (fOverlaps) delete [] fOverlaps;
656  fOverlaps = ovlp;
657  fNovlp = novlp;
658 }
659 
660 ////////////////////////////////////////////////////////////////////////////////
661 /// Set visibility of the node (obsolete).
662 
663 void TGeoNode::SetVisibility(Bool_t vis)
664 {
665  if (gGeoManager->IsClosed()) SetVisTouched(kTRUE);
666  TGeoAtt::SetVisibility(vis);
667  if (vis && !fVolume->IsVisible()) fVolume->SetVisibility(vis);
668  gGeoManager->ModifiedPad();
669 }
670 
671 ////////////////////////////////////////////////////////////////////////////////
672 /// Set visibility of the daughters (obsolete).
673 
674 void TGeoNode::VisibleDaughters(Bool_t vis)
675 {
676  if (gGeoManager->IsClosed()) SetVisTouched(kTRUE);
677  SetVisDaughters(vis);
678  gGeoManager->ModifiedPad();
679 }
680 
681 /** \class TGeoNodeMatrix
682 \ingroup Geometry_classes
683 A node containing local transformation.
684 */
685 
686 ClassImp(TGeoNodeMatrix);
687 
688 ////////////////////////////////////////////////////////////////////////////////
689 /// Default constructor
690 
691 TGeoNodeMatrix::TGeoNodeMatrix()
692 {
693  fMatrix = 0;
694 }
695 
696 ////////////////////////////////////////////////////////////////////////////////
697 /// Constructor.
698 
699 TGeoNodeMatrix::TGeoNodeMatrix(const TGeoVolume *vol, const TGeoMatrix *matrix) :
700  TGeoNode(vol)
701 {
702  fMatrix = (TGeoMatrix*)matrix;
703  if (!fMatrix) fMatrix = gGeoIdentity;
704 }
705 
706 ////////////////////////////////////////////////////////////////////////////////
707 /// Destructor
708 
709 TGeoNodeMatrix::~TGeoNodeMatrix()
710 {
711 }
712 
713 ////////////////////////////////////////////////////////////////////////////////
714 /// return the total size in bytes of this node
715 
716 Int_t TGeoNodeMatrix::GetByteCount() const
717 {
718  Int_t count = 40 + 4; // TGeoNode + fMatrix
719 // if (fMatrix) count += fMatrix->GetByteCount();
720  return count;
721 }
722 
723 ////////////////////////////////////////////////////////////////////////////////
724 /// Returns type of optimal voxelization for this node.
725 /// - type = 0 -> cartesian
726 /// - type = 1 -> cylindrical
727 
728 Int_t TGeoNodeMatrix::GetOptimalVoxels() const
729 {
730  Bool_t type = fVolume->GetShape()->IsCylType();
731  if (!type) return 0;
732  if (!fMatrix->IsRotAboutZ()) return 0;
733  const Double_t *transl = fMatrix->GetTranslation();
734  if (TMath::Abs(transl[0])>1E-10) return 0;
735  if (TMath::Abs(transl[1])>1E-10) return 0;
736  return 1;
737 }
738 
739 ////////////////////////////////////////////////////////////////////////////////
740 /// Make a copy of this node.
741 
742 TGeoNode *TGeoNodeMatrix::MakeCopyNode() const
743 {
744  TGeoNodeMatrix *node = new TGeoNodeMatrix(fVolume, fMatrix);
745  node->SetName(GetName());
746  // set the mother
747  node->SetMotherVolume(fMother);
748  // set the copy number
749  node->SetNumber(fNumber);
750  // copy overlaps
751  node->CopyOverlaps(fOverlaps, fNovlp);
752 
753  // copy VC
754  if (IsVirtual()) node->SetVirtual();
755  if (IsOverlapping()) node->SetOverlapping(); // <--- ADDED
756  // Copy extensions
757  node->SetUserExtension(fUserExtension);
758  node->SetFWExtension(fFWExtension);
759  node->SetCloned();
760  return node;
761 }
762 
763 ////////////////////////////////////////////////////////////////////////////////
764 /// Matrix setter.
765 
766 void TGeoNodeMatrix::SetMatrix(const TGeoMatrix *matrix)
767 {
768  fMatrix = (TGeoMatrix*)matrix;
769  if (!fMatrix) fMatrix = gGeoIdentity;
770 }
771 
772 /** \class TGeoNodeOffset
773 \ingroup Geometry_classes
774 Node containing an offset.
775 */
776 
777 ClassImp(TGeoNodeOffset);
778 
779 ////////////////////////////////////////////////////////////////////////////////
780 /// Default constructor
781 
782 TGeoNodeOffset::TGeoNodeOffset()
783 {
784  TObject::SetBit(kGeoNodeOffset);
785  fOffset = 0;
786  fIndex = 0;
787  fFinder = 0;
788 }
789 
790 ////////////////////////////////////////////////////////////////////////////////
791 /// Constructor. Null pointer to matrix means identity transformation
792 
793 TGeoNodeOffset::TGeoNodeOffset(const TGeoVolume *vol, Int_t index, Double_t offset) :
794  TGeoNode(vol)
795 {
796  TObject::SetBit(kGeoNodeOffset);
797  fOffset = offset;
798  fIndex = index;
799  fFinder = 0;
800 }
801 
802 ////////////////////////////////////////////////////////////////////////////////
803 /// Destructor
804 
805 TGeoNodeOffset::~TGeoNodeOffset()
806 {
807 }
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 /// Get the index of this offset.
811 
812 Int_t TGeoNodeOffset::GetIndex() const
813 {
814  return (fIndex+fFinder->GetDivIndex());
815 }
816 
817 ////////////////////////////////////////////////////////////////////////////////
818 /// Make a copy of this node
819 
820 TGeoNode *TGeoNodeOffset::MakeCopyNode() const
821 {
822  TGeoNodeOffset *node = new TGeoNodeOffset(fVolume, GetIndex(), fOffset);
823  node->SetName(GetName());
824  // set the mother
825  node->SetMotherVolume(fMother);
826  // set the copy number
827  node->SetNumber(fNumber);
828  if (IsVirtual()) node->SetVirtual();
829  // set the finder
830  node->SetFinder(GetFinder());
831  // set extensions
832  node->SetUserExtension(fUserExtension);
833  node->SetFWExtension(fFWExtension);
834  return node;
835 }
836 
837 /** \class TGeoIterator
838 \ingroup Geometry_classes
839 A geometry iterator.
840 
841 A geometry iterator that sequentially follows all nodes of the geometrical
842 hierarchy of a volume. The iterator has to be initiated with a top volume
843 pointer:
844 
845 ~~~ {.cpp}
846  TGeoIterator next(myVolume);
847 ~~~
848 
849 One can use the iterator as any other in ROOT:
850 
851 ~~~ {.cpp}
852  TGeoNode *node;
853  while ((node=next())) {
854  ...
855  }
856 ~~~
857 
858 The iterator can perform 2 types of iterations that can be selected via:
859 
860 ~~~ {.cpp}
861  next.SetType(Int_t type);
862 ~~~
863 
864 Here TYPE can be:
865  - 0 (default) - 'first daughter next' behavior
866  - 1 - iteration at the current level only
867 
868 Supposing the tree structure looks like:
869 
870 ~~~ {.cpp}
871 TOP ___ A_1 ___ A1_1 ___ A11_1
872  | | |___ A12_1
873  | |_____A2_1 ___ A21_1
874  | |___ A21_2
875  |___ B_1 ...
876 ~~~
877 
878 The order of iteration for TYPE=0 is: A_1, A1_1, A11_1, A12_1, A2_1, A21_1,
879 A21_2, B_1, ...
880 
881 The order of iteration for TYPE=1 is: A_1, B_1, ...
882 At any moment during iteration, TYPE can be changed. If the last iterated node
883 is for instance A1_1 and the iteration type was 0, one can do:
884 
885 ~~~ {.cpp}
886  next.SetType(1);
887 ~~~
888 
889 The next iterated nodes will be the rest of A daughters: A2,A3,... The iterator
890 will return 0 after finishing all daughters of A.
891 
892 During iteration, the following can be retrieved:
893  - Top volume where iteration started: TGeoIterator::GetTopVolume()
894  - Node at level I in the current branch: TGeoIterator::GetNode(Int_t i)
895  - Iteration type: TGeoIterator::GetType()
896  - Global matrix of the current node with respect to the top volume:
897  TGeoIterator::GetCurrentMatrix()
898 
899 The iterator can be reset by changing (or not) the top volume:
900 
901 ~~~ {.cpp}
902  TGeoIterator::Reset(TGeoVolume *top);
903 ~~~
904 
905 ### Example:
906 
907 We want to find out a volume named "MyVol" in the hierarchy of TOP volume.
908 
909 ~~~ {.cpp}
910  TIter next(TOP);
911  TGeoNode *node;
912  TString name("MyVol");
913  while ((node=next()))
914  if (name == node->GetVolume()->GetName()) return node->GetVolume();
915 ~~~
916 */
917 
918 /** \class TGeoIteratorPlugin
919 \ingroup Geometry_classes
920 */
921 
922 ClassImp(TGeoIteratorPlugin);
923 ClassImp(TGeoIterator);
924 
925 ////////////////////////////////////////////////////////////////////////////////
926 /// Geometry iterator for a branch starting with a TOP node.
927 
928 TGeoIterator::TGeoIterator(TGeoVolume *top)
929 {
930  fTop = top;
931  fLevel = 0;
932  fMustResume = kFALSE;
933  fMustStop = kFALSE;
934  fType = 0;
935  fArray = new Int_t[30];
936  fMatrix = new TGeoHMatrix();
937  fTopName = fTop->GetName();
938  fPlugin = 0;
939  fPluginAutoexec = kFALSE;
940 }
941 
942 ////////////////////////////////////////////////////////////////////////////////
943 /// Copy ctor.
944 
945 TGeoIterator::TGeoIterator(const TGeoIterator &iter)
946 {
947  fTop = iter.GetTopVolume();
948  fLevel = iter.GetLevel();
949  fMustResume = kFALSE;
950  fMustStop = kFALSE;
951  fType = iter.GetType();
952  fArray = new Int_t[30+ 30*Int_t(fLevel/30)];
953  for (Int_t i=0; i<fLevel+1; i++) fArray[i] = iter.GetIndex(i);
954  fMatrix = new TGeoHMatrix(*iter.GetCurrentMatrix());
955  fTopName = fTop->GetName();
956  fPlugin = iter.fPlugin;
957  fPluginAutoexec = iter.fPluginAutoexec;;
958 }
959 
960 ////////////////////////////////////////////////////////////////////////////////
961 /// Destructor.
962 
963 TGeoIterator::~TGeoIterator()
964 {
965  if (fArray) delete [] fArray;
966  delete fMatrix;
967 }
968 
969 ////////////////////////////////////////////////////////////////////////////////
970 /// Assignment.
971 
972 TGeoIterator &TGeoIterator::operator=(const TGeoIterator &iter)
973 {
974  if (&iter == this) return *this;
975  fTop = iter.GetTopVolume();
976  fLevel = iter.GetLevel();
977  fMustResume = kFALSE;
978  fMustStop = kFALSE;
979  fType = iter.GetType();
980  if (fArray) delete [] fArray;
981  fArray = new Int_t[30+ 30*Int_t(fLevel/30)];
982  for (Int_t i=0; i<fLevel+1; i++) fArray[i] = iter.GetIndex(i);
983  if (!fMatrix) fMatrix = new TGeoHMatrix();
984  *fMatrix = *iter.GetCurrentMatrix();
985  fTopName = fTop->GetName();
986  fPlugin = iter.fPlugin;
987  fPluginAutoexec = iter.fPluginAutoexec;;
988  return *this;
989 }
990 
991 ////////////////////////////////////////////////////////////////////////////////
992 /// Returns next node.
993 
994 TGeoNode *TGeoIterator::Next()
995 {
996  if (fMustStop) return 0;
997  TGeoNode *mother = 0;
998  TGeoNode *next = 0;
999  Int_t i;
1000  Int_t nd = fTop->GetNdaughters();
1001  if (!nd) {
1002  fMustStop = kTRUE;
1003  return 0;
1004  }
1005  if (!fLevel) {
1006  fArray[++fLevel] = 0;
1007  next = fTop->GetNode(0);
1008  if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
1009  return next;
1010  }
1011  next = fTop->GetNode(fArray[1]);
1012  // Move to current node
1013  for (i=2; i<fLevel+1; i++) {
1014  mother = next;
1015  next = mother->GetDaughter(fArray[i]);
1016  }
1017  if (fMustResume) {
1018  fMustResume = kFALSE;
1019  if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
1020  return next;
1021  }
1022 
1023  switch (fType) {
1024  case 0: // default next daughter behavior
1025  nd = next->GetNdaughters();
1026  if (nd) {
1027  // First daughter next
1028  fLevel++;
1029  if ((fLevel%30)==0) IncreaseArray();
1030  fArray[fLevel] = 0;
1031  if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
1032  return next->GetDaughter(0);
1033  }
1034  // cd up and pick next
1035  while (next) {
1036  next = GetNode(fLevel-1);
1037  if (!next) {
1038  nd = fTop->GetNdaughters();
1039  if (fArray[fLevel]<nd-1) {
1040  fArray[fLevel]++;
1041  if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
1042  return fTop->GetNode(fArray[fLevel]);
1043  }
1044  fMustStop = kTRUE;
1045  return 0;
1046  } else {
1047  nd = next->GetNdaughters();
1048  if (fArray[fLevel]<nd-1) {
1049  fArray[fLevel]++;
1050  if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
1051  return next->GetDaughter(fArray[fLevel]);
1052  }
1053  }
1054  fLevel--;
1055  }
1056  break;
1057  case 1: // one level search
1058  if (mother) nd = mother->GetNdaughters();
1059  if (fArray[fLevel]<nd-1) {
1060  fArray[fLevel]++;
1061  if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
1062  if (!mother) return fTop->GetNode(fArray[fLevel]);
1063  else return mother->GetDaughter(fArray[fLevel]);
1064  }
1065  }
1066  fMustStop = kTRUE;
1067  return 0;
1068 }
1069 
1070 ////////////////////////////////////////////////////////////////////////////////
1071 /// Returns next node.
1072 
1073 TGeoNode *TGeoIterator::operator()()
1074 {
1075  return Next();
1076 }
1077 
1078 ////////////////////////////////////////////////////////////////////////////////
1079 /// Returns global matrix for current node.
1080 
1081 const TGeoMatrix *TGeoIterator::GetCurrentMatrix() const
1082 {
1083  fMatrix->Clear();
1084  if (!fLevel) return fMatrix;
1085  TGeoNode *node = fTop->GetNode(fArray[1]);
1086  fMatrix->Multiply(node->GetMatrix());
1087  for (Int_t i=2; i<fLevel+1; i++) {
1088  node = node->GetDaughter(fArray[i]);
1089  fMatrix->Multiply(node->GetMatrix());
1090  }
1091  return fMatrix;
1092 }
1093 
1094 ////////////////////////////////////////////////////////////////////////////////
1095 /// Returns current node at a given level.
1096 
1097 TGeoNode *TGeoIterator::GetNode(Int_t level) const
1098 {
1099  if (!level || level>fLevel) return 0;
1100  TGeoNode *node = fTop->GetNode(fArray[1]);
1101  for (Int_t i=2; i<level+1; i++) node = node->GetDaughter(fArray[i]);
1102  return node;
1103 }
1104 
1105 ////////////////////////////////////////////////////////////////////////////////
1106 /// Returns the path for the current node.
1107 
1108 void TGeoIterator::GetPath(TString &path) const
1109 {
1110  path = fTopName;
1111  if (!fLevel) return;
1112  TGeoNode *node = fTop->GetNode(fArray[1]);
1113  path += "/";
1114  path += node->GetName();
1115  for (Int_t i=2; i<fLevel+1; i++) {
1116  node = node->GetDaughter(fArray[i]);
1117  path += "/";
1118  path += node->GetName();
1119  }
1120 }
1121 
1122 ////////////////////////////////////////////////////////////////////////////////
1123 /// Increase by 30 the size of the array.
1124 
1125 void TGeoIterator::IncreaseArray()
1126 {
1127  Int_t *array = new Int_t[fLevel+30];
1128  memcpy(array, fArray, fLevel*sizeof(Int_t));
1129  delete [] fArray;
1130  fArray = array;
1131 }
1132 
1133 ////////////////////////////////////////////////////////////////////////////////
1134 /// Resets the iterator for volume TOP.
1135 
1136 void TGeoIterator::Reset(TGeoVolume *top)
1137 {
1138  if (top) fTop = top;
1139  fLevel = 0;
1140  fMustResume = kFALSE;
1141  fMustStop = kFALSE;
1142 }
1143 
1144 ////////////////////////////////////////////////////////////////////////////////
1145 /// Set the top name for path
1146 
1147 void TGeoIterator::SetTopName(const char *name)
1148 {
1149  fTopName = name;
1150 }
1151 
1152 ////////////////////////////////////////////////////////////////////////////////
1153 /// Stop iterating the current branch. The iteration of the next node will
1154 /// behave as if the branch starting from the current node (included) is not existing.
1155 
1156 void TGeoIterator::Skip()
1157 {
1158  fMustResume = kTRUE;
1159  TGeoNode *next = GetNode(fLevel);
1160  if (!next) return;
1161  Int_t nd;
1162  switch (fType) {
1163  case 0: // default next daughter behavior
1164  // cd up and pick next
1165  while (next) {
1166  next = GetNode(fLevel-1);
1167  nd = (next==0)?fTop->GetNdaughters():next->GetNdaughters();
1168  if (fArray[fLevel]<nd-1) {
1169  ++fArray[fLevel];
1170  return;
1171  }
1172  fLevel--;
1173  if (!fLevel) {
1174  fMustStop = kTRUE;
1175  return;
1176  }
1177  }
1178  break;
1179  case 1: // one level search
1180  next = GetNode(fLevel-1);
1181  nd = (next==0)?fTop->GetNdaughters():next->GetNdaughters();
1182  if (fArray[fLevel]<nd-1) {
1183  ++fArray[fLevel];
1184  return;
1185  }
1186  fMustStop = kTRUE;
1187  break;
1188  }
1189 }
1190 
1191 ////////////////////////////////////////////////////////////////////////////////
1192 /// Set a plugin.
1193 
1194 void TGeoIterator::SetUserPlugin(TGeoIteratorPlugin *plugin)
1195 {
1196  fPlugin = plugin;
1197  if (plugin) plugin->SetIterator(this);
1198 }