Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGeoVolume.cxx
Go to the documentation of this file.
1// @(#)root/geom:$Id$
2// Author: Andrei Gheata 30/05/02
3// Divide(), CheckOverlaps() implemented by Mihaela Gheata
4
5/*************************************************************************
6 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13/** \class TGeoVolume
14\ingroup Shapes_classes
15
16TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes
17
18 Volumes are the basic objects used in building the geometrical hierarchy.
19They represent unpositioned objects but store all information about the
20placement of the other volumes they may contain. Therefore a volume can
21be replicated several times in the geometry. In order to create a volume, one
22has to put together a shape and a medium which are already defined. Volumes
23have to be named by users at creation time. Every different name may represent a
24an unique volume object, but may also represent more general a family (class)
25of volume objects having the same shape type and medium, but possibly
26different shape parameters. It is the user's task to provide different names
27for different volume families in order to avoid ambiguities at tracking time.
28A generic family rather than a single volume is created only in two cases :
29when a generic shape is provided to the volume constructor or when a division
30operation is applied. Each volume in the geometry stores an unique
31ID corresponding to its family. In order to ease-up their creation, the manager
32class is providing an API that allows making a shape and a volume in a single step.
33
34 Volumes are objects that can be visualized, therefore having visibility,
35colour, line and fill attributes that can be defined or modified any time after
36the volume creation. It is advisable however to define these properties just
37after the first creation of a volume namespace, since in case of volume families
38any new member created by the modeler inherits these properties.
39
40 In order to provide navigation features, volumes have to be able to find
41the proper container of any point defined in the local reference frame. This
42can be the volume itself, one of its positioned daughter volumes or none if
43the point is actually outside. On the other hand, volumes have to provide also
44other navigation methods such as finding the distances to its shape boundaries
45or which daughter will be crossed first. The implementation of these features
46is done at shape level, but the local mother-daughters management is handled
47by volumes that builds additional optimisation structures upon geometry closure.
48In order to have navigation features properly working one has to follow the
49general rules for building a valid geometry (see TGeoManager class).
50
51 Now let's make a simple volume representing a copper wire. We suppose that
52a medium is already created (see TGeoMedium class on how to create media).
53We will create a TUBE shape for our wire, having Rmin=0cm, Rmax=0.01cm
54and a half-length dZ=1cm :
55
56~~~ {.cpp}
57 TGeoTube *tube = new TGeoTube("wire_tube", 0, 0.01, 1);
58~~~
59
60One may omit the name for the shape if no retrieving by name is further needed
61during geometry building. The same shape can be shared by different volumes
62having different names and materials. Now let's make the volume for our wire.
63The prototype for volumes constructor looks like :
64
65 TGeoVolume::TGeoVolume(const char *name, TGeoShape *shape, TGeoMedium *med)
66
67Since TGeoTube derives from the base shape class, we can provide it to the volume
68constructor :
69
70~~~ {.cpp}
71 TGeoVolume *wire_co = new TGeoVolume("WIRE_CO", tube, ptrCOPPER);
72~~~
73
74Do not bother to delete neither the media, shapes or volumes that you have
75created since all will be automatically cleaned on exit by the manager class.
76If we would have taken a look inside TGeoManager::MakeTube() method, we would
77have been able to create our wire with a single line :
78
79~~~ {.cpp}
80 TGeoVolume *wire_co = gGeoManager->MakeTube("WIRE_CO", ptrCOPPER, 0, 0.01, 1);
81~~~
82
83The same applies for all primitive shapes, for which there can be found
84corresponding MakeSHAPE() methods. Their usage is much more convenient unless
85a shape has to be shared between more volumes. Let's make now an aluminium wire
86having the same shape, supposing that we have created the copper wire with the
87line above :
88
89~~~ {.cpp}
90 TGeoVolume *wire_al = new TGeoVolume("WIRE_AL", wire_co->GetShape(), ptrAL);
91~~~
92
93Now that we have learned how to create elementary volumes, let's see how we
94can create a geometrical hierarchy.
95
96
97### Positioning volumes
98
99 When creating a volume one does not specify if this will contain or not other
100volumes. Adding daughters to a volume implies creating those and adding them
101one by one to the list of daughters. Since the volume has to know the position
102of all its daughters, we will have to supply at the same time a geometrical
103transformation with respect to its local reference frame for each of them.
104The objects referencing a volume and a transformation are called NODES and
105their creation is fully handled by the modeler. They represent the link
106elements in the hierarchy of volumes. Nodes are unique and distinct geometrical
107objects ONLY from their container point of view. Since volumes can be replicated
108in the geometry, the same node may be found on different branches.
109
110\image html geom_t_example.png width=600px
111
112 An important observation is that volume objects are owned by the TGeoManager
113class. This stores a list of all volumes in the geometry, that is cleaned
114upon destruction.
115
116 Let's consider positioning now our wire in the middle of a gas chamber. We
117need first to define the gas chamber :
118
119~~~ {.cpp}
120 TGeoVolume *chamber = gGeoManager->MakeTube("CHAMBER", ptrGAS, 0, 1, 1);
121~~~
122
123Now we can put the wire inside :
124
125~~~ {.cpp}
126 chamber->AddNode(wire_co, 1);
127~~~
128
129If we inspect now the chamber volume in a browser, we will notice that it has
130one daughter. Of course the gas has some container also, but let's keep it like
131that for the sake of simplicity. The full prototype of AddNode() is :
132
133~~~ {.cpp}
134 TGeoVolume::AddNode(TGeoVolume *daughter, Int_t usernumber,
135 TGeoMatrix *matrix=gGeoIdentity)
136~~~
137
138Since we did not supplied the third argument, the wire will be positioned with
139an identity transformation inside the chamber. One will notice that the inner
140radii of the wire and chamber are both zero - therefore, aren't the two volumes
141overlapping ? The answer is no, the modeler is even relaying on the fact that
142any daughter is fully contained by its mother. On the other hand, neither of
143the nodes positioned inside a volume should overlap with each other. We will
144see that there are allowed some exceptions to those rules.
145
146### Overlapping volumes
147
148 Positioning volumes that does not overlap their neighbours nor extrude
149their container is sometimes quite strong constraint. Some parts of the geometry
150might overlap naturally, e.g. two crossing tubes. The modeller supports such
151cases only if the overlapping nodes are declared by the user. In order to do
152that, one should use TGeoVolume::AddNodeOverlap() instead of TGeoVolume::AddNode().
153 When 2 or more positioned volumes are overlapping, not all of them have to
154be declared so, but at least one. A point inside an overlapping region equally
155belongs to all overlapping nodes, but the way these are defined can enforce
156the modeler to give priorities.
157 The general rule is that the deepest node in the hierarchy containing a point
158have the highest priority. For the same geometry level, non-overlapping is
159prioritised over overlapping. In order to illustrate this, we will consider
160few examples. We will designate non-overlapping nodes as ONLY and the others
161MANY as in GEANT3, where this concept was introduced:
162 1. The part of a MANY node B extruding its container A will never be "seen"
163during navigation, as if B was in fact the result of the intersection of A and B.
164 2. If we have two nodes A (ONLY) and B (MANY) inside the same container, all
165points in the overlapping region of A and B will be designated as belonging to A.
166 3. If A an B in the above case were both MANY, points in the overlapping
167part will be designated to the one defined first. Both nodes must have the
168same medium.
169 4. The slices of a divided MANY will be as well MANY.
170
171One needs to know that navigation inside geometry parts MANY nodes is much
172slower. Any overlapping part can be defined based on composite shapes - this
173is always recommended.
174
175### Replicating volumes
176
177 What can we do if our chamber contains two identical wires instead of one ?
178What if then we would need 1000 chambers in our detector ? Should we create
1792000 wires and 1000 chamber volumes ? No, we will just need to replicate the
180ones that we have already created.
181
182~~~ {.cpp}
183 chamber->AddNode(wire_co, 1, new TGeoTranslation(-0.2,0,0));
184 chamber->AddNode(wire_co, 2, new TGeoTranslation(0.2,0,0));
185~~~
186
187 The 2 nodes that we have created inside chamber will both point to a wire_co
188object, but will be completely distinct : WIRE_CO_1 and WIRE_CO_2. We will
189want now to place symmetrically 1000 chambers on a pad, following a pattern
190of 20 rows and 50 columns. One way to do this will be to replicate our chamber
191by positioning it 1000 times in different positions of the pad. Unfortunately,
192this is far from being the optimal way of doing what we want.
193Imagine that we would like to find out which of the 1000 chambers is containing
194a (x,y,z) point defined in the pad reference. You will never have to do that,
195since the modeller will take care of it for you, but let's guess what it has
196to do. The most simple algorithm will just loop over all daughters, convert
197the point from mother to local reference and check if the current chamber
198contains the point or not. This might be efficient for pads with few chambers,
199but definitely not for 1000. Fortunately the modeler is smarter than that and
200create for each volume some optimization structures called voxels (see Voxelization)
201to minimize the penalty having too many daughters, but if you have 100 pads like
202this in your geometry you will anyway loose a lot in your tracking performance.
203
204 The way out when volumes can be arranged according to simple patterns is the
205usage of divisions. We will describe them in detail later on. Let's think now
206at a different situation : instead of 1000 chambers of the same type, we may
207have several types of chambers. Let's say all chambers are cylindrical and have
208a wire inside, but their dimensions are different. However, we would like all
209to be represented by a single volume family, since they have the same properties.
210*/
211
212/** \class TGeoVolumeMulti
213\ingroup Geometry_classes
214
215Volume families
216
217A volume family is represented by the class TGeoVolumeMulti. It represents
218a class of volumes having the same shape type and each member will be
219identified by the same name and volume ID. Any operation applied to a
220TGeoVolume equally affects all volumes in that family. The creation of a
221family is generally not a user task, but can be forced in particular cases:
222
223~~~ {.cpp}
224 TGeoManager::Volume(const char *vname, const char *shape, Int_t nmed);
225~~~
226
227where VNAME is the family name, NMED is the medium number and SHAPE is the
228shape type that can be:
229
230~~~ {.cpp}
231 box - for TGeoBBox
232 trd1 - for TGeoTrd1
233 trd2 - for TGeoTrd2
234 trap - for TGeoTrap
235 gtra - for TGeoGtra
236 para - for TGeoPara
237 tube, tubs - for TGeoTube, TGeoTubeSeg
238 cone, cons - for TGeoCone, TgeoCons
239 eltu - for TGeoEltu
240 ctub - for TGeoCtub
241 pcon - for TGeoPcon
242 pgon - for TGeoPgon
243~~~
244
245Volumes are then added to a given family upon adding the generic name as node
246inside other volume:
247
248~~~ {.cpp}
249 TGeoVolume *box_family = gGeoManager->Volume("BOXES", "box", nmed);
250 ...
251 gGeoManager->Node("BOXES", Int_t copy_no, "mother_name",
252 Double_t x, Double_t y, Double_t z, Int_t rot_index,
253 Bool_t is_only, Double_t *upar, Int_t npar);
254~~~
255
256here:
257
258~~~ {.cpp}
259 BOXES - name of the family of boxes
260 copy_no - user node number for the created node
261 mother_name - name of the volume to which we want to add the node
262 x,y,z - translation components
263 rot_index - indx of a rotation matrix in the list of matrices
264 upar - array of actual shape parameters
265 npar - number of parameters
266~~~
267
268The parameters order and number are the same as in the corresponding shape
269constructors.
270
271 Another particular case where volume families are used is when we want
272that a volume positioned inside a container to match one ore more container
273limits. Suppose we want to position the same box inside 2 different volumes
274and we want the Z size to match the one of each container:
275
276~~~ {.cpp}
277 TGeoVolume *container1 = gGeoManager->MakeBox("C1", imed, 10,10,30);
278 TGeoVolume *container2 = gGeoManager->MakeBox("C2", imed, 10,10,20);
279 TGeoVolume *pvol = gGeoManager->MakeBox("PVOL", jmed, 3,3,-1);
280 container1->AddNode(pvol, 1);
281 container2->AddNode(pvol, 1);
282~~~
283
284 Note that the third parameter of PVOL is negative, which does not make sense
285as half-length on Z. This is interpreted as: when positioned, create a box
286replacing all invalid parameters with the corresponding dimensions of the
287container. This is also internally handled by the TGeoVolumeMulti class, which
288does not need to be instantiated by users.
289
290### Dividing volumes
291
292 Volumes can be divided according a pattern. The most simple division can
293be done along one axis, that can be: X, Y, Z, Phi, Rxy or Rxyz. Let's take
294the most simple case: we would like to divide a box in N equal slices along X
295coordinate, representing a new volume family. Supposing we already have created
296the initial box, this can be done like:
297
298~~~ {.cpp}
299 TGeoVolume *slicex = box->Divide("SLICEX", 1, N);
300~~~
301
302where SLICE is the name of the new family representing all slices and 1 is the
303slicing axis. The meaning of the axis index is the following: for all volumes
304having shapes like box, trd1, trd2, trap, gtra or para - 1,2,3 means X,Y,Z; for
305tube, tubs, cone, cons - 1 means Rxy, 2 means phi and 3 means Z; for pcon and
306pgon - 2 means phi and 3 means Z; for spheres 1 means R and 2 means phi.
307 In fact, the division operation has the same effect as positioning volumes
308in a given order inside the divided container - the advantage being that the
309navigation in such a structure is much faster. When a volume is divided, a
310volume family corresponding to the slices is created. In case all slices can
311be represented by a single shape, only one volume is added to the family and
312positioned N times inside the divided volume, otherwise, each slice will be
313represented by a distinct volume in the family.
314 Divisions can be also performed in a given range of one axis. For that, one
315have to specify also the starting coordinate value and the step:
316
317~~~ {.cpp}
318 TGeoVolume *slicex = box->Divide("SLICEX", 1, N, start, step);
319~~~
320
321A check is always done on the resulting division range : if not fitting into
322the container limits, an error message is posted. If we will browse the divided
323volume we will notice that it will contain N nodes starting with index 1 upto
324N. The first one has the lower X limit at START position, while the last one
325will have the upper X limit at START+N*STEP. The resulting slices cannot
326be positioned inside an other volume (they are by default positioned inside the
327divided one) but can be further divided and may contain other volumes:
328
329~~~ {.cpp}
330 TGeoVolume *slicey = slicex->Divide("SLICEY", 2, N1);
331 slicey->AddNode(other_vol, index, some_matrix);
332~~~
333
334 When doing that, we have to remember that SLICEY represents a family, therefore
335all members of the family will be divided on Y and the other volume will be
336added as node inside all.
337 In the example above all the resulting slices had the same shape as the
338divided volume (box). This is not always the case. For instance, dividing a
339volume with TUBE shape on PHI axis will create equal slices having TUBESEG
340shape. Other divisions can also create slices having shapes with different
341dimensions, e.g. the division of a TRD1 volume on Z.
342 When positioning volumes inside slices, one can do it using the generic
343volume family (e.g. slicey). This should be done as if the coordinate system
344of the generic slice was the same as the one of the divided volume. The generic
345slice in case of PHI division is centered with respect to X axis. If the
346family contains slices of different sizes, any volume positioned inside should
347fit into the smallest one.
348 Examples for specific divisions according to shape types can be found inside
349shape classes.
350
351~~~ {.cpp}
352 TGeoVolume::Divide(N, Xmin, Xmax, "X");
353~~~
354
355 The GEANT3 option MANY is supported by TGeoVolumeOverlap class. An overlapping
356volume is in fact a virtual container that does not represent a physical object.
357It contains a list of nodes that are not its daughters but that must be checked
358always before the container itself. This list must be defined by users and it
359is checked and resolved in a priority order. Note that the feature is non-standard
360to geometrical modelers and it was introduced just to support conversions of
361GEANT3 geometries, therefore its extensive usage should be avoided.
362*/
363
364/** \class TGeoVolumeAssembly
365\ingroup Geometry_classes
366
367Volume assemblies
368
369Assemblies a volumes that have neither a shape or a material/medium. Assemblies
370behave exactly like normal volumes grouping several daughters together, but
371the daughters can never extrude the assembly since this has no shape. However,
372a bounding box and a voxelization structure are built for assemblies as for
373normal volumes, so that navigation is still optimized. Assemblies are useful
374for grouping hierarchically volumes which are otherwise defined in a flat
375manner, but also to avoid clashes between container shapes.
376To define an assembly one should just input a name, then start adding other
377volumes (or volume assemblies) as content.
378*/
379
380#include <fstream>
381#include <iomanip>
382
383#include "TString.h"
384#include "TBuffer.h"
385#include "TBrowser.h"
386#include "TStyle.h"
387#include "TH2F.h"
388#include "TROOT.h"
389#include "TEnv.h"
390#include "TMap.h"
391#include "TFile.h"
392#include "TKey.h"
393
394#include "TGeoManager.h"
395#include "TGeoNode.h"
396#include "TGeoMatrix.h"
397#include "TVirtualGeoPainter.h"
398#include "TGeoVolume.h"
399#include "TGeoShapeAssembly.h"
400#include "TGeoScaledShape.h"
401#include "TGeoCompositeShape.h"
402#include "TGeoVoxelFinder.h"
403#include "TGeoExtension.h"
404
406
408
409////////////////////////////////////////////////////////////////////////////////
410/// Create a dummy medium
411
413{
414 if (fgDummyMedium)
415 return;
417 fgDummyMedium->SetName("dummy");
418 TGeoMaterial *dummyMaterial = new TGeoMaterial();
419 dummyMaterial->SetName("dummy");
420 fgDummyMedium->SetMaterial(dummyMaterial);
421}
422
423////////////////////////////////////////////////////////////////////////////////
424
426{
427 if (fFinder)
429 if (fShape)
431}
432
433////////////////////////////////////////////////////////////////////////////////
434
436{
437 if (fFinder)
438 fFinder->CreateThreadData(nthreads);
439 if (fShape)
440 fShape->CreateThreadData(nthreads);
441}
442
443////////////////////////////////////////////////////////////////////////////////
444
446{
447 return fgDummyMedium;
448}
449
450////////////////////////////////////////////////////////////////////////////////
451/// dummy constructor
452
454{
455 fNodes = nullptr;
456 fShape = nullptr;
457 fMedium = nullptr;
458 fFinder = nullptr;
459 fVoxels = nullptr;
461 fField = nullptr;
462 fOption = "";
463 fNumber = 0;
464 fNtotal = 0;
465 fRefCount = 0;
466 fUserExtension = nullptr;
467 fFWExtension = nullptr;
468 fTransparency = -1;
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// default constructor
474
475TGeoVolume::TGeoVolume(const char *name, const TGeoShape *shape, const TGeoMedium *med) : TNamed(name, "")
476{
477 fName = fName.Strip();
478 fNodes = nullptr;
479 fShape = (TGeoShape *)shape;
480 if (fShape) {
482 Warning("Ctor", "volume %s has invalid shape", name);
483 }
484 if (!fShape->IsValid()) {
485 Fatal("ctor", "Shape of volume %s invalid. Aborting!", fName.Data());
486 }
487 }
488 fMedium = (TGeoMedium *)med;
489 if (fMedium && fMedium->GetMaterial())
491 fFinder = nullptr;
492 fVoxels = nullptr;
494 fField = nullptr;
495 fOption = "";
496 fNumber = 0;
497 fNtotal = 0;
498 fRefCount = 0;
499 fUserExtension = nullptr;
500 fFWExtension = nullptr;
501 fTransparency = -1;
502 if (fGeoManager)
505}
506
507////////////////////////////////////////////////////////////////////////////////
508/// Destructor
509
511{
512 if (fNodes) {
514 fNodes->Delete();
515 }
516 delete fNodes;
517 }
519 delete fFinder;
520 if (fVoxels)
521 delete fVoxels;
522 if (fUserExtension) {
524 fUserExtension = nullptr;
525 }
526 if (fFWExtension) {
528 fFWExtension = nullptr;
529 }
530}
531
532////////////////////////////////////////////////////////////////////////////////
533/// How to browse a volume
534
536{
537 if (!b)
538 return;
539
540 // if (!GetNdaughters()) b->Add(this, GetName(), IsVisible());
541 TGeoVolume *daughter;
542 TString title;
543 for (Int_t i = 0; i < GetNdaughters(); i++) {
544 daughter = GetNode(i)->GetVolume();
545 if (daughter->GetTitle()[0]) {
546 if (daughter->IsAssembly())
547 title.TString::Format("Assembly with %d daughter(s)", daughter->GetNdaughters());
548 else if (daughter->GetFinder()) {
549 TString s1 = daughter->GetFinder()->ClassName();
550 s1.ReplaceAll("TGeoPattern", "");
551 title.TString::Format("Volume having %s shape divided in %d %s slices", daughter->GetShape()->ClassName(),
552 daughter->GetNdaughters(), s1.Data());
553
554 } else
555 title.TString::Format("Volume with %s shape having %d daughter(s)", daughter->GetShape()->ClassName(),
556 daughter->GetNdaughters());
557 daughter->SetTitle(title.Data());
558 }
559 b->Add(daughter, daughter->GetName(), daughter->IsVisible());
560 // if (IsVisDaughters())
561 // b->AddCheckBox(daughter, daughter->IsVisible());
562 // else
563 // b->AddCheckBox(daughter, kFALSE);
564 }
565}
566
567////////////////////////////////////////////////////////////////////////////////
568/// Computes the capacity of this [cm^3] as the capacity of its shape.
569/// In case of assemblies, the capacity is computed as the sum of daughter's capacities.
570
572{
573 if (!IsAssembly())
574 return fShape->Capacity();
575 Double_t capacity = 0.0;
576 Int_t nd = GetNdaughters();
577 Int_t i;
578 for (i = 0; i < nd; i++)
579 capacity += GetNode(i)->GetVolume()->Capacity();
580 return capacity;
581}
582
583////////////////////////////////////////////////////////////////////////////////
584/// Shoot nrays with random directions from starting point (startx, starty, startz)
585/// in the reference frame of this volume. Track each ray until exiting geometry, then
586/// shoot backwards from exiting point and compare boundary crossing points.
587
588void TGeoVolume::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
589{
590 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
591 if (old_vol != this)
593 else
594 old_vol = nullptr;
597 painter->CheckGeometry(nrays, startx, starty, startz);
598}
599
600////////////////////////////////////////////////////////////////////////////////
601/// Overlap checking tool. Check for illegal overlaps within a limit OVLP.
602/// Use option="s[number]" to force overlap checking by sampling volume with
603/// [number] points.
604///
605/// Ex:
606/// ~~~ {.cpp}
607/// myVol->CheckOverlaps(0.01, "s10000000"); // shoot 10000000 points
608/// myVol->CheckOverlaps(0.01, "s"); // shoot the default value of 1e6 points
609/// ~~~
610
612{
613 if (!GetNdaughters() || fFinder)
614 return;
615 Bool_t sampling = kFALSE;
616 TString opt(option);
617 opt.ToLower();
618 if (opt.Contains("s"))
619 sampling = kTRUE;
621 if (!sampling)
625 // Info("CheckOverlaps", "=== Checking overlaps for volume %s ===\n", GetName());
626 }
627 painter->CheckOverlaps(this, ovlp, option);
628 // if (sampling) return;
632 Int_t novlps = overlaps->GetEntriesFast();
633 TNamed *obj;
635 for (Int_t i = 0; i < novlps; i++) {
636 obj = (TNamed *)overlaps->At(i);
637 if (novlps < 1000)
638 name = TString::Format("ov%03d", i);
639 else
640 name = TString::Format("ov%06d", i);
641 obj->SetName(name);
642 }
643 if (novlps)
644 Info("CheckOverlaps", "Number of illegal overlaps/extrusions for volume %s: %d\n", GetName(), novlps);
645 }
646}
647
648////////////////////////////////////////////////////////////////////////////////
649/// Tests for checking the shape navigation algorithms. See TGeoShape::CheckShape()
650
652{
653 fShape->CheckShape(testNo, nsamples, option);
654}
655
656////////////////////////////////////////////////////////////////////////////////
657/// Clean data of the volume.
658
660{
661 ClearNodes();
662 ClearShape();
663}
664
665////////////////////////////////////////////////////////////////////////////////
666/// Clear the shape of this volume from the list held by the current manager.
667
669{
671}
672
673////////////////////////////////////////////////////////////////////////////////
674/// check for negative parameters in shapes.
675
677{
678 if (fShape->IsRunTimeShape()) {
679 Error("CheckShapes", "volume %s has run-time shape", GetName());
680 InspectShape();
681 return;
682 }
683 if (!fNodes)
684 return;
686 TGeoNode *node = nullptr;
687 TGeoNode *new_node;
688 const TGeoShape *shape = nullptr;
689 TGeoVolume *old_vol;
690 for (Int_t i = 0; i < nd; i++) {
691 node = (TGeoNode *)fNodes->At(i);
692 // check if node has name
693 if (!node->GetName()[0])
694 printf("Daughter %i of volume %s - NO NAME!!!\n", i, GetName());
695 old_vol = node->GetVolume();
696 shape = old_vol->GetShape();
697 if (shape->IsRunTimeShape()) {
698 // printf(" Node %s/%s has shape with negative parameters. \n",
699 // GetName(), node->GetName());
700 // old_vol->InspectShape();
701 // make a copy of the node
702 new_node = node->MakeCopyNode();
703 if (!new_node) {
704 Fatal("CheckShapes", "Cannot make copy node for %s", node->GetName());
705 return;
706 }
707 TGeoShape *new_shape = shape->GetMakeRuntimeShape(fShape, node->GetMatrix());
708 if (!new_shape) {
709 Error("CheckShapes", "cannot resolve runtime shape for volume %s/%s\n", GetName(), old_vol->GetName());
710 continue;
711 }
712 TGeoVolume *new_volume = old_vol->MakeCopyVolume(new_shape);
713 // printf(" new volume %s shape params :\n", new_volume->GetName());
714 // new_volume->InspectShape();
715 new_node->SetVolume(new_volume);
716 // decouple the old node and put the new one instead
717 fNodes->AddAt(new_node, i);
718 // new_volume->CheckShapes();
719 }
720 }
721}
722
723////////////////////////////////////////////////////////////////////////////////
724/// Count total number of subnodes starting from this volume, nlevels down
725/// - option = 0 (default) - count only once per volume
726/// - option = 1 - count every time
727/// - option = 2 - count volumes on visible branches
728/// - option = 3 - return maximum level counted already with option = 0
729
731{
732 static Int_t maxlevel = 0;
733 static Int_t nlev = 0;
734
735 if (option < 0 || option > 3)
736 option = 0;
737 Int_t visopt = 0;
738 Int_t nd = GetNdaughters();
739 Bool_t last = (!nlevels || !nd) ? kTRUE : kFALSE;
740 switch (option) {
741 case 0:
742 if (fNtotal)
743 return fNtotal;
744 case 1: fNtotal = 1; break;
745 case 2:
746 visopt = fGeoManager->GetVisOption();
747 if (!IsVisDaughters())
748 last = kTRUE;
749 switch (visopt) {
750 case TVirtualGeoPainter::kGeoVisDefault: fNtotal = (IsVisible()) ? 1 : 0; break;
751 case TVirtualGeoPainter::kGeoVisLeaves: fNtotal = (IsVisible() && last) ? 1 : 0;
752 }
753 if (!IsVisibleDaughters())
754 return fNtotal;
755 break;
756 case 3: return maxlevel;
757 }
758 if (last)
759 return fNtotal;
760 if (gGeoManager->GetTopVolume() == this) {
761 maxlevel = 0;
762 nlev = 0;
763 }
764 if (nlev > maxlevel)
765 maxlevel = nlev;
766 TGeoNode *node;
767 TGeoVolume *vol;
768 nlev++;
769 for (Int_t i = 0; i < nd; i++) {
770 node = GetNode(i);
771 vol = node->GetVolume();
772 fNtotal += vol->CountNodes(nlevels - 1, option);
773 }
774 nlev--;
775 return fNtotal;
776}
777
778////////////////////////////////////////////////////////////////////////////////
779/// Return TRUE if volume and all daughters are invisible.
780
782{
783 if (IsVisible())
784 return kFALSE;
785 Int_t nd = GetNdaughters();
786 for (Int_t i = 0; i < nd; i++)
787 if (GetNode(i)->GetVolume()->IsVisible())
788 return kFALSE;
789 return kTRUE;
790}
791
792////////////////////////////////////////////////////////////////////////////////
793/// Make volume and each of it daughters (in)visible.
794
796{
797 SetAttVisibility(!flag);
798 Int_t nd = GetNdaughters();
799 TObjArray *list = new TObjArray(nd + 1);
800 list->Add(this);
801 TGeoVolume *vol;
802 for (Int_t i = 0; i < nd; i++) {
803 vol = GetNode(i)->GetVolume();
804 vol->SetAttVisibility(!flag);
805 list->Add(vol);
806 }
807 TIter next(gROOT->GetListOfBrowsers());
808 TBrowser *browser = nullptr;
809 while ((browser = (TBrowser *)next())) {
810 for (Int_t i = 0; i < nd + 1; i++) {
811 vol = (TGeoVolume *)list->At(i);
812 browser->CheckObjectItem(vol, !flag);
813 }
814 browser->Refresh();
815 }
816 delete list;
818}
819
820////////////////////////////////////////////////////////////////////////////////
821/// Return TRUE if volume contains nodes
822
824{
825 return kTRUE;
826}
827
828////////////////////////////////////////////////////////////////////////////////
829/// check if the visibility and attributes are the default ones
830
832{
833 if (!IsVisible())
834 return kFALSE;
835 if (GetLineColor() != gStyle->GetLineColor())
836 return kFALSE;
837 if (GetLineStyle() != gStyle->GetLineStyle())
838 return kFALSE;
839 if (GetLineWidth() != gStyle->GetLineWidth())
840 return kFALSE;
841 return kTRUE;
842}
843
844////////////////////////////////////////////////////////////////////////////////
845/// True if this is the top volume of the geometry
846
848{
849 if (fGeoManager->GetTopVolume() == this)
850 return kTRUE;
851 return kFALSE;
852}
853
854////////////////////////////////////////////////////////////////////////////////
855/// Check if the painter is currently ray-tracing the content of this volume.
856
858{
859 return TGeoAtt::IsVisRaytrace();
860}
861
862////////////////////////////////////////////////////////////////////////////////
863/// Inspect the material for this volume.
864
866{
867 GetMaterial()->Print();
868}
869
870////////////////////////////////////////////////////////////////////////////////
871/// Import a volume from a file.
872
873TGeoVolume *TGeoVolume::Import(const char *filename, const char *name, Option_t * /*option*/)
874{
875 if (!gGeoManager)
876 gGeoManager = new TGeoManager("geometry", "");
877 if (!filename)
878 return nullptr;
879 TGeoVolume *volume = nullptr;
880 if (strstr(filename, ".gdml")) {
881 // import from a gdml file
882 } else {
883 // import from a root file
886 if (!f || f->IsZombie()) {
887 printf("Error: TGeoVolume::Import : Cannot open file %s\n", filename);
888 return nullptr;
889 }
890 if (name && name[0]) {
891 volume = (TGeoVolume *)f->Get(name);
892 } else {
893 TIter next(f->GetListOfKeys());
894 TKey *key;
895 while ((key = (TKey *)next())) {
896 if (strcmp(key->GetClassName(), "TGeoVolume") != 0)
897 continue;
898 volume = (TGeoVolume *)key->ReadObj();
899 break;
900 }
901 }
902 delete f;
903 }
904 if (!volume)
905 return nullptr;
906 volume->RegisterYourself();
907 return volume;
908}
909
910////////////////////////////////////////////////////////////////////////////////
911/// Export this volume to a file.
912///
913/// - Case 1: root file or root/xml file
914/// if filename end with ".root". The key will be named name
915/// if filename end with ".xml" a root/xml file is produced.
916///
917/// - Case 2: C++ script
918/// if filename end with ".C"
919///
920/// - Case 3: gdml file
921/// if filename end with ".gdml"
922///
923/// NOTE that to use this option, the PYTHONPATH must be defined like
924/// export PYTHONPATH=$ROOTSYS/lib:$ROOTSYS/gdml
925///
926
928{
929 TString sfile(filename);
930 if (sfile.Contains(".C")) {
931 // Save volume as a C++ script
932 Info("Export", "Exporting volume %s as C++ code", GetName());
933 SaveAs(filename, "");
934 return 1;
935 }
936 if (sfile.Contains(".gdml")) {
937 // Save geometry as a gdml file
938 Info("Export", "Exporting %s as gdml code - not implemented yet", GetName());
939 return 0;
940 }
941 if (sfile.Contains(".root") || sfile.Contains(".xml")) {
942 // Save volume in a root file
943 Info("Export", "Exporting %s as root file.", GetName());
944 TString opt(option);
945 if (!opt.Length())
946 opt = "recreate";
947 TFile *f = TFile::Open(filename, opt.Data());
948 if (!f || f->IsZombie()) {
949 Error("Export", "Cannot open file");
950 return 0;
951 }
952 TString keyname(name);
953 if (keyname.IsNull())
954 keyname = GetName();
955 Int_t nbytes = Write(keyname);
956 delete f;
957 return nbytes;
958 }
959 return 0;
960}
961
962////////////////////////////////////////////////////////////////////////////////
963/// Actualize matrix of node indexed `<inode>`
964
965void TGeoVolume::cd(Int_t inode) const
966{
967 if (fFinder)
968 fFinder->cd(inode - fFinder->GetDivIndex());
969}
970
971////////////////////////////////////////////////////////////////////////////////
972/// Add a TGeoNode to the list of nodes. This is the usual method for adding
973/// daughters inside the container volume.
974
976{
977 TGeoMatrix *matrix = mat;
978 if (matrix == nullptr)
979 matrix = gGeoIdentity;
980 else
981 matrix->RegisterYourself();
982 if (!vol) {
983 Error("AddNode", "Volume is NULL");
984 return nullptr;
985 }
986 if (!vol->IsValid()) {
987 Error("AddNode", "Won't add node with invalid shape");
988 printf("### invalid volume was : %s\n", vol->GetName());
989 return nullptr;
990 }
991 if (!fNodes)
992 fNodes = new TObjArray();
993
994 if (fFinder) {
995 // volume already divided.
996 Error("AddNode", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
997 return nullptr;
998 }
999
1000 TGeoNodeMatrix *node = nullptr;
1001 node = new TGeoNodeMatrix(vol, matrix);
1002 node->SetMotherVolume(this);
1003 fNodes->Add(node);
1004 TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
1005 // if (fNodes->FindObject(name))
1006 // Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
1007 node->SetName(name);
1008 node->SetNumber(copy_no);
1009 fRefCount++;
1010 vol->Grab();
1011 return node;
1012}
1013
1014////////////////////////////////////////////////////////////////////////////////
1015/// Add a division node to the list of nodes. The method is called by
1016/// TGeoVolume::Divide() for creating the division nodes.
1017
1019{
1020 if (!vol) {
1021 Error("AddNodeOffset", "invalid volume");
1022 return;
1023 }
1024 if (!vol->IsValid()) {
1025 Error("AddNode", "Won't add node with invalid shape");
1026 printf("### invalid volume was : %s\n", vol->GetName());
1027 return;
1028 }
1029 if (!fNodes)
1030 fNodes = new TObjArray();
1031 TGeoNode *node = new TGeoNodeOffset(vol, copy_no, offset);
1032 node->SetMotherVolume(this);
1033 fNodes->Add(node);
1034 TString name = TString::Format("%s_%d", vol->GetName(), copy_no + 1);
1035 node->SetName(name);
1036 node->SetNumber(copy_no + 1);
1037 vol->Grab();
1038}
1039
1040////////////////////////////////////////////////////////////////////////////////
1041/// Add a TGeoNode to the list of nodes. This is the usual method for adding
1042/// daughters inside the container volume.
1043
1045{
1046 if (!vol) {
1047 Error("AddNodeOverlap", "Volume is NULL");
1048 return;
1049 }
1050 if (!vol->IsValid()) {
1051 Error("AddNodeOverlap", "Won't add node with invalid shape");
1052 printf("### invalid volume was : %s\n", vol->GetName());
1053 return;
1054 }
1055 if (vol->IsAssembly()) {
1056 Warning("AddNodeOverlap",
1057 "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",
1058 vol->GetName(), GetName());
1059 AddNode(vol, copy_no, mat, option);
1060 return;
1061 }
1062 TGeoMatrix *matrix = mat;
1063 if (matrix == nullptr)
1064 matrix = gGeoIdentity;
1065 else
1066 matrix->RegisterYourself();
1067 if (!fNodes)
1068 fNodes = new TObjArray();
1069
1070 if (fFinder) {
1071 // volume already divided.
1072 Error("AddNodeOverlap", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
1073 return;
1074 }
1075
1076 TGeoNodeMatrix *node = new TGeoNodeMatrix(vol, matrix);
1077 node->SetMotherVolume(this);
1078 fNodes->Add(node);
1079 TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
1080 if (fNodes->FindObject(name))
1081 Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
1082 node->SetName(name);
1083 node->SetNumber(copy_no);
1084 node->SetOverlapping();
1085 if (vol->GetMedium() == fMedium)
1086 node->SetVirtual();
1087 vol->Grab();
1088}
1089
1090////////////////////////////////////////////////////////////////////////////////
1091/// Division a la G3. The volume will be divided along IAXIS (see shape classes), in NDIV
1092/// slices, from START with given STEP. The division volumes will have medium number NUMED.
1093/// If NUMED=0 they will get the medium number of the divided volume (this). If NDIV<=0,
1094/// all range of IAXIS will be divided and the resulting number of divisions will be centered on
1095/// IAXIS. If STEP<=0, the real STEP will be computed as the full range of IAXIS divided by NDIV.
1096/// Options (case insensitive):
1097/// - N - divide all range in NDIV cells (same effect as STEP<=0) (GSDVN in G3)
1098/// - NX - divide range starting with START in NDIV cells (GSDVN2 in G3)
1099/// - S - divide all range with given STEP. NDIV is computed and divisions will be centered
1100/// in full range (same effect as NDIV<=0) (GSDVS, GSDVT in G3)
1101/// - SX - same as DVS, but from START position. (GSDVS2, GSDVT2 in G3)
1102
1103TGeoVolume *TGeoVolume::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed,
1105{
1106 if (fFinder) {
1107 // volume already divided.
1108 Fatal("Divide", "volume %s already divided", GetName());
1109 return nullptr;
1110 }
1111 TString opt(option);
1112 opt.ToLower();
1113 TString stype = fShape->ClassName();
1114 if (!fNodes)
1115 fNodes = new TObjArray();
1116 Double_t xlo, xhi, range;
1117 range = fShape->GetAxisRange(iaxis, xlo, xhi);
1118 // for phi divisions correct the range
1119 if (!strcmp(fShape->GetAxisName(iaxis), "PHI")) {
1120 if ((start - xlo) < -1E-3)
1121 start += 360.;
1122 if (TGeoShape::IsSameWithinTolerance(range, 360)) {
1123 xlo = start;
1124 xhi = start + range;
1125 }
1126 }
1127 if (range <= 0) {
1128 InspectShape();
1129 Fatal("Divide", "cannot divide volume %s (%s) on %s axis", GetName(), stype.Data(), fShape->GetAxisName(iaxis));
1130 return nullptr;
1131 }
1132 if (ndiv <= 0 || opt.Contains("s")) {
1133 if (step <= 0) {
1134 Fatal("Divide", "invalid division type for volume %s : ndiv=%i, step=%g", GetName(), ndiv, step);
1135 return nullptr;
1136 }
1137 if (opt.Contains("x")) {
1138 if ((xlo - start) > 1E-3 || (xhi - start) < -1E-3) {
1139 Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)", start,
1140 fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1141 return nullptr;
1142 }
1143 xlo = start;
1144 range = xhi - xlo;
1145 }
1146 ndiv = Int_t((range + 0.1 * step) / step);
1147 Double_t ddx = range - ndiv * step;
1148 // always center the division in this case
1149 if (ddx > 1E-3)
1150 Warning("Divide", "division of volume %s on %s axis (ndiv=%d) will be centered in the full range", GetName(),
1151 fShape->GetAxisName(iaxis), ndiv);
1152 start = xlo + 0.5 * ddx;
1153 }
1154 if (step <= 0 || opt.Contains("n")) {
1155 if (opt.Contains("x")) {
1156 if ((xlo - start) > 1E-3 || (xhi - start) < -1E-3) {
1157 Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)", start,
1158 fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1159 return nullptr;
1160 }
1161 xlo = start;
1162 range = xhi - xlo;
1163 }
1164 step = range / ndiv;
1165 start = xlo;
1166 }
1167
1168 Double_t end = start + ndiv * step;
1169 if (((start - xlo) < -1E-3) || ((end - xhi) > 1E-3)) {
1170 Fatal("Divide", "division of volume %s on axis %s exceed range (%g, %g)", GetName(), fShape->GetAxisName(iaxis),
1171 xlo, xhi);
1172 return nullptr;
1173 }
1174 TGeoVolume *voldiv = fShape->Divide(this, divname, iaxis, ndiv, start, step);
1175 if (numed) {
1176 TGeoMedium *medium = fGeoManager->GetMedium(numed);
1177 if (!medium) {
1178 Fatal("Divide", "invalid medium number %d for division volume %s", numed, divname);
1179 return voldiv;
1180 }
1181 voldiv->SetMedium(medium);
1182 if (medium->GetMaterial())
1183 medium->GetMaterial()->SetUsed();
1184 }
1185 return voldiv;
1186}
1187
1188////////////////////////////////////////////////////////////////////////////////
1189/// compute the closest distance of approach from point px,py to this volume
1190
1192{
1193 if (gGeoManager != fGeoManager)
1196 Int_t dist = 9999;
1197 if (!painter)
1198 return dist;
1199 dist = painter->DistanceToPrimitiveVol(this, px, py);
1200 return dist;
1201}
1202
1203////////////////////////////////////////////////////////////////////////////////
1204/// draw top volume according to option
1205
1207{
1208 if (gGeoManager != fGeoManager)
1213 if (!IsVisContainers())
1214 SetVisLeaves();
1215 if (option && option[0] > 0) {
1216 painter->DrawVolume(this, option);
1217 } else {
1218 painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption", ""));
1219 }
1220}
1221
1222////////////////////////////////////////////////////////////////////////////////
1223/// draw only this volume
1224
1226{
1227 if (IsAssembly()) {
1228 Info("DrawOnly", "Volume assemblies do not support this option.");
1229 return;
1230 }
1231 if (gGeoManager != fGeoManager)
1233 SetVisOnly();
1236 if (option && option[0] > 0) {
1237 painter->DrawVolume(this, option);
1238 } else {
1239 painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption", ""));
1240 }
1241}
1242
1243////////////////////////////////////////////////////////////////////////////////
1244/// Perform an extensive sampling to find which type of voxelization is
1245/// most efficient.
1246
1248{
1249 printf("Optimizing volume %s ...\n", GetName());
1251 return painter->TestVoxels(this);
1252}
1253
1254////////////////////////////////////////////////////////////////////////////////
1255/// Print volume info
1256
1258{
1259 printf("== Volume: %s type %s positioned %d times\n", GetName(), ClassName(), fRefCount);
1260 InspectShape();
1262}
1263
1264////////////////////////////////////////////////////////////////////////////////
1265/// paint volume
1266
1268{
1270 painter->SetTopVolume(this);
1271 // painter->Paint(option);
1272 if (option && option[0] > 0) {
1273 painter->Paint(option);
1274 } else {
1275 painter->Paint(gEnv->GetValue("Viewer3D.DefaultDrawOption", ""));
1276 }
1277}
1278
1279////////////////////////////////////////////////////////////////////////////////
1280/// Print the voxels for this volume.
1281
1283{
1284 if (fVoxels)
1285 fVoxels->Print();
1286}
1287
1288////////////////////////////////////////////////////////////////////////////////
1289/// Recreate the content of the other volume without pointer copying. Voxels are
1290/// ignored and supposed to be created in a later step via Voxelize.
1291
1293{
1294 Int_t nd = other->GetNdaughters();
1295 if (!nd)
1296 return;
1297 TGeoPatternFinder *finder = other->GetFinder();
1298 if (finder) {
1299 Int_t iaxis = finder->GetDivAxis();
1300 Int_t ndiv = finder->GetNdiv();
1301 Double_t start = finder->GetStart();
1302 Double_t step = finder->GetStep();
1303 Int_t numed = other->GetNode(0)->GetVolume()->GetMedium()->GetId();
1304 TGeoVolume *voldiv = Divide(other->GetNode(0)->GetVolume()->GetName(), iaxis, ndiv, start, step, numed);
1305 voldiv->ReplayCreation(other->GetNode(0)->GetVolume());
1306 return;
1307 }
1308 for (Int_t i = 0; i < nd; i++) {
1309 TGeoNode *node = other->GetNode(i);
1310 if (node->IsOverlapping())
1311 AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1312 else
1313 AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1314 }
1315}
1316
1317////////////////////////////////////////////////////////////////////////////////
1318/// print nodes
1319
1321{
1322 Int_t nd = GetNdaughters();
1323 for (Int_t i = 0; i < nd; i++) {
1324 printf("%s\n", GetNode(i)->GetName());
1325 cd(i);
1326 GetNode(i)->GetMatrix()->Print();
1327 }
1328}
1329////////////////////////////////////////////////////////////////////////////////
1330/// Generate a lego plot fot the top volume, according to option.
1331
1332TH2F *TGeoVolume::LegoPlot(Int_t ntheta, Double_t themin, Double_t themax, Int_t nphi, Double_t phimin, Double_t phimax,
1333 Double_t rmin, Double_t rmax, Option_t *option)
1334{
1336 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1337 if (old_vol != this)
1339 else
1340 old_vol = nullptr;
1341 TH2F *hist = p->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);
1342 hist->Draw("lego1sph");
1343 return hist;
1344}
1345
1346////////////////////////////////////////////////////////////////////////////////
1347/// Register the volume and all materials/media/matrices/shapes to the manager.
1348
1350{
1352 return;
1353 // Register volume
1354 fGeoManager->AddVolume(this);
1355 // Register shape
1357 if (fShape->IsComposite()) {
1359 comp->RegisterYourself();
1360 } else {
1362 }
1363 }
1364 // Register medium/material
1369 }
1370 // Register matrices for nodes.
1371 TGeoMatrix *matrix;
1372 TGeoNode *node;
1373 Int_t nd = GetNdaughters();
1374 Int_t i;
1375 for (i = 0; i < nd; i++) {
1376 node = GetNode(i);
1377 matrix = node->GetMatrix();
1378 if (!matrix->IsRegistered())
1379 matrix->RegisterYourself();
1380 else if (!fGeoManager->GetListOfMatrices()->FindObject(matrix)) {
1381 fGeoManager->GetListOfMatrices()->Add(matrix);
1382 }
1383 }
1384 // Call RegisterYourself recursively
1385 for (i = 0; i < nd; i++)
1387}
1388
1389////////////////////////////////////////////////////////////////////////////////
1390/// Draw random points in the bounding box of this volume.
1391
1393{
1394 if (gGeoManager != fGeoManager)
1396 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1397 if (old_vol != this)
1399 else
1400 old_vol = nullptr;
1401 fGeoManager->RandomPoints(this, npoints, option);
1402 if (old_vol)
1403 fGeoManager->SetTopVolume(old_vol);
1404}
1405
1406////////////////////////////////////////////////////////////////////////////////
1407/// Random raytracing method.
1408
1409void TGeoVolume::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz, const char *target_vol,
1410 Bool_t check_norm)
1411{
1412 if (gGeoManager != fGeoManager)
1414 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1415 if (old_vol != this)
1417 else
1418 old_vol = nullptr;
1419 fGeoManager->RandomRays(nrays, startx, starty, startz, target_vol, check_norm);
1420 if (old_vol)
1421 fGeoManager->SetTopVolume(old_vol);
1422}
1423
1424////////////////////////////////////////////////////////////////////////////////
1425/// Draw this volume with current settings and perform raytracing in the pad.
1426
1428{
1430 if (gGeoManager != fGeoManager)
1433 Bool_t drawn = (painter->GetDrawnVolume() == this) ? kTRUE : kFALSE;
1434 if (!drawn) {
1435 painter->DrawVolume(this, "");
1437 painter->ModifiedPad();
1438 return;
1439 }
1441 painter->ModifiedPad();
1442}
1443
1444////////////////////////////////////////////////////////////////////////////////
1445/// Save geometry having this as top volume as a C++ macro.
1446
1448{
1449 if (!filename)
1450 return;
1451 std::ofstream out;
1452 out.open(filename, std::ios::out);
1453 if (out.bad()) {
1454 Error("SavePrimitive", "Bad file name: %s", filename);
1455 return;
1456 }
1457 if (fGeoManager->GetTopVolume() != this)
1459
1460 TString fname(filename);
1461 Int_t ind = fname.Index(".");
1462 if (ind > 0)
1463 fname.Remove(ind);
1464 out << "void " << fname << "() {" << std::endl;
1465 out << " gSystem->Load(\"libGeom\");" << std::endl;
1467 out << std::setprecision(prec);
1468 ((TGeoVolume *)this)->SavePrimitive(out, option);
1469 out << "}" << std::endl;
1470}
1471
1472////////////////////////////////////////////////////////////////////////////////
1473/// Connect user-defined extension to the volume. The volume "grabs" a copy, so
1474/// the original object can be released by the producer. Release the previously
1475/// connected extension if any.
1476///
1477/// NOTE: This interface is intended for user extensions and is guaranteed not
1478/// to be used by TGeo
1479
1481{
1482 if (fUserExtension)
1484 fUserExtension = nullptr;
1485 if (ext)
1486 fUserExtension = ext->Grab();
1487}
1488
1489////////////////////////////////////////////////////////////////////////////////
1490/// Connect framework defined extension to the volume. The volume "grabs" a copy,
1491/// so the original object can be released by the producer. Release the previously
1492/// connected extension if any.
1493///
1494/// NOTE: This interface is intended for the use by TGeo and the users should
1495/// NOT connect extensions using this method
1496
1498{
1499 if (fFWExtension)
1501 fFWExtension = nullptr;
1502 if (ext)
1503 fFWExtension = ext->Grab();
1504}
1505
1506////////////////////////////////////////////////////////////////////////////////
1507/// Get a copy of the user extension pointer. The user must call Release() on
1508/// the copy pointer once this pointer is not needed anymore (equivalent to
1509/// delete() after calling new())
1510
1512{
1513 if (fUserExtension)
1514 return fUserExtension->Grab();
1515 return nullptr;
1516}
1517
1518////////////////////////////////////////////////////////////////////////////////
1519/// Get a copy of the framework extension pointer. The user must call Release() on
1520/// the copy pointer once this pointer is not needed anymore (equivalent to
1521/// delete() after calling new())
1522
1524{
1525 if (fFWExtension)
1526 return fFWExtension->Grab();
1527 return nullptr;
1528}
1529
1530////////////////////////////////////////////////////////////////////////////////
1531/// Save a primitive as a C++ statement(s) on output stream "out".
1532
1533void TGeoVolume::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1534{
1535 Int_t i, icopy;
1536 Int_t nd = GetNdaughters();
1537 TGeoVolume *dvol;
1538 TGeoNode *dnode;
1539 TGeoMatrix *matrix;
1540
1541 // check if we need to save shape/volume
1542 Bool_t mustDraw = kFALSE;
1543 if (fGeoManager->GetGeomPainter()->GetTopVolume() == this)
1544 mustDraw = kTRUE;
1545 if (!option[0]) {
1547 out << " new TGeoManager(\"" << fGeoManager->GetName() << "\", \"" << fGeoManager->GetTitle() << "\");"
1548 << std::endl
1549 << std::endl;
1550 // if (mustDraw) out << " Bool_t mustDraw = kTRUE;" << std::endl;
1551 // else out << " Bool_t mustDraw = kFALSE;" << std::endl;
1552 out << " Double_t dx, dy, dz;" << std::endl;
1553 out << " Double_t dx1, dx2, dy1, dy2;" << std::endl;
1554 out << " Double_t vert[20], par[20];" << std::endl;
1555 out << " Double_t theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2;" << std::endl;
1556 out << " Double_t twist;" << std::endl;
1557 out << " Double_t origin[3];" << std::endl;
1558 out << " Double_t rmin, rmax, rmin1, rmax1, rmin2, rmax2;" << std::endl;
1559 out << " Double_t r, rlo, rhi;" << std::endl;
1560 out << " Double_t a, b;" << std::endl;
1561 out << " Double_t point[3], norm[3];" << std::endl;
1562 out << " Double_t rin, stin, rout, stout;" << std::endl;
1563 out << " Double_t thx, phx, thy, phy, thz, phz;" << std::endl;
1564 out << " Double_t alpha, theta1, theta2, phi1, phi2, dphi;" << std::endl;
1565 out << " Double_t tr[3], rot[9];" << std::endl;
1566 out << " Double_t z, density, radl, absl, w;" << std::endl;
1567 out << " Double_t lx, ly, lz, tx, ty, tz;" << std::endl;
1568 out << " Double_t xvert[50], yvert[50];" << std::endl;
1569 out << " Double_t zsect, x0, y0, scale0;" << std::endl;
1570 out << " Int_t nel, numed, nz, nedges, nvert;" << std::endl;
1571 out << " TGeoBoolNode *pBoolNode = nullptr;" << std::endl << std::endl;
1572 // first save materials/media
1573 out << " // MATERIALS, MIXTURES AND TRACKING MEDIA" << std::endl;
1574 SavePrimitive(out, "m");
1575 // then, save matrices
1576 out << std::endl << " // TRANSFORMATION MATRICES" << std::endl;
1577 SavePrimitive(out, "x");
1578 // save this volume and shape
1579 SavePrimitive(out, "s");
1580 out << std::endl << " // SET TOP VOLUME OF GEOMETRY" << std::endl;
1581 out << " gGeoManager->SetTopVolume(" << GetPointerName() << ");" << std::endl;
1582 // save daughters
1583 out << std::endl << " // SHAPES, VOLUMES AND GEOMETRICAL HIERARCHY" << std::endl;
1584 SavePrimitive(out, "d");
1585 out << std::endl << " // CLOSE GEOMETRY" << std::endl;
1586 out << " gGeoManager->CloseGeometry();" << std::endl;
1587 if (mustDraw) {
1588 if (!IsRaytracing())
1589 out << " gGeoManager->GetTopVolume()->Draw();" << std::endl;
1590 else
1591 out << " gGeoManager->GetTopVolume()->Raytrace();" << std::endl;
1592 }
1593 return;
1594 }
1595 // check if we need to save shape/volume
1596 if (!strcmp(option, "s")) {
1597 // create the shape for this volume
1599 return;
1600 if (!IsAssembly()) {
1602 out << " // Volume: " << GetName() << std::endl;
1603 out << " TGeoVolume *" << GetPointerName() << " = new TGeoVolume(\"" << GetName() << "\","
1604 << fShape->GetPointerName();
1605 if (fMedium)
1606 out << ", " << fMedium->GetPointerName();
1607 out << ");" << std::endl;
1608 } else {
1609 out << " // Assembly: " << GetName() << std::endl;
1610 out << " " << GetPointerName() << " = new TGeoVolumeAssembly(\"" << GetName() << "\""
1611 << ");" << std::endl;
1612 }
1613 SaveLineAttributes(out, GetPointerName(), 1, 1, 1);
1614 if (!IsVisible() && !IsAssembly())
1615 out << " " << GetPointerName() << "->SetVisibility(kFALSE);" << std::endl;
1616 if (!IsVisibleDaughters())
1617 out << " " << GetPointerName() << "->VisibleDaughters(kFALSE);" << std::endl;
1618 if (IsVisContainers())
1619 out << " " << GetPointerName() << "->SetVisContainers(kTRUE);" << std::endl;
1620 if (IsVisLeaves())
1621 out << " " << GetPointerName() << "->SetVisLeaves(kTRUE);" << std::endl;
1623 }
1624 // check if we need to save the media
1625 if (!strcmp(option, "m")) {
1626 if (fMedium)
1628 for (i = 0; i < nd; i++) {
1629 dvol = GetNode(i)->GetVolume();
1630 dvol->SavePrimitive(out, option);
1631 }
1632 return;
1633 }
1634 // check if we need to save the matrices
1635 if (!strcmp(option, "x")) {
1636 if (fFinder) {
1637 dvol = GetNode(0)->GetVolume();
1638 dvol->SavePrimitive(out, option);
1639 return;
1640 }
1641 for (i = 0; i < nd; i++) {
1642 dnode = GetNode(i);
1643 matrix = dnode->GetMatrix();
1644 if (!matrix->IsIdentity())
1645 matrix->SavePrimitive(out, option);
1646 dnode->GetVolume()->SavePrimitive(out, option);
1647 }
1648 return;
1649 }
1650 // check if we need to save volume daughters
1651 if (!strcmp(option, "d")) {
1652 if (!nd)
1653 return;
1655 return;
1657 if (fFinder) {
1658 // volume divided: generate volume->Divide()
1659 dnode = GetNode(0);
1660 dvol = dnode->GetVolume();
1661 out << " TGeoVolume *" << dvol->GetPointerName() << " = ";
1662 out << GetPointerName() << "->Divide(\"" << dvol->GetName() << "\", ";
1664 if (fMedium != dvol->GetMedium())
1665 out << ", " << dvol->GetMedium()->GetId();
1666 out << ");" << std::endl;
1667 dvol->SavePrimitive(out, "d");
1668 return;
1669 }
1670 for (i = 0; i < nd; i++) {
1671 dnode = GetNode(i);
1672 dvol = dnode->GetVolume();
1673 dvol->SavePrimitive(out, "s");
1674 matrix = dnode->GetMatrix();
1675 icopy = dnode->GetNumber();
1676 // generate AddNode()
1677 out << " " << GetPointerName() << "->AddNode";
1678 if (dnode->IsOverlapping())
1679 out << "Overlap";
1680 out << "(" << dvol->GetPointerName() << ", " << icopy;
1681 if (!matrix->IsIdentity())
1682 out << ", " << matrix->GetPointerName();
1683 out << ");" << std::endl;
1684 }
1685 // Recursive loop to daughters
1686 for (i = 0; i < nd; i++) {
1687 dnode = GetNode(i);
1688 dvol = dnode->GetVolume();
1689 dvol->SavePrimitive(out, "d");
1690 }
1691 }
1692}
1693
1694////////////////////////////////////////////////////////////////////////////////
1695/// Reset SavePrimitive bits.
1696
1698{
1701 if (fShape)
1703}
1704
1705////////////////////////////////////////////////////////////////////////////////
1706/// Execute mouse actions on this volume.
1707
1709{
1711 if (!painter)
1712 return;
1713 painter->ExecuteVolumeEvent(this, event, px, py);
1714}
1715
1716////////////////////////////////////////////////////////////////////////////////
1717/// search a daughter inside the list of nodes
1718
1720{
1721 return ((TGeoNode *)fNodes->FindObject(name));
1722}
1723
1724////////////////////////////////////////////////////////////////////////////////
1725/// Get the index of a daughter within check_list by providing the node pointer.
1726
1727Int_t TGeoVolume::GetNodeIndex(const TGeoNode *node, Int_t *check_list, Int_t ncheck) const
1728{
1729 TGeoNode *current = nullptr;
1730 for (Int_t i = 0; i < ncheck; i++) {
1731 current = (TGeoNode *)fNodes->At(check_list[i]);
1732 if (current == node)
1733 return check_list[i];
1734 }
1735 return -1;
1736}
1737
1738////////////////////////////////////////////////////////////////////////////////
1739/// get index number for a given daughter
1740
1742{
1743 TGeoNode *current = nullptr;
1744 Int_t nd = GetNdaughters();
1745 if (!nd)
1746 return -1;
1747 for (Int_t i = 0; i < nd; i++) {
1748 current = (TGeoNode *)fNodes->At(i);
1749 if (current == node)
1750 return i;
1751 }
1752 return -1;
1753}
1754
1755////////////////////////////////////////////////////////////////////////////////
1756/// Get volume info for the browser.
1757
1759{
1760 TGeoVolume *vol = (TGeoVolume *)this;
1762 if (!painter)
1763 return nullptr;
1764 return (char *)painter->GetVolumeInfo(vol, px, py);
1765}
1766
1767////////////////////////////////////////////////////////////////////////////////
1768/// Returns true if cylindrical voxelization is optimal.
1769
1771{
1772 Int_t nd = GetNdaughters();
1773 if (!nd)
1774 return kFALSE;
1775 Int_t id;
1776 Int_t ncyl = 0;
1777 TGeoNode *node;
1778 for (id = 0; id < nd; id++) {
1779 node = (TGeoNode *)fNodes->At(id);
1780 ncyl += node->GetOptimalVoxels();
1781 }
1782 if (ncyl > (nd / 2))
1783 return kTRUE;
1784 return kFALSE;
1785}
1786
1787////////////////////////////////////////////////////////////////////////////////
1788/// Provide a pointer name containing uid.
1789
1791{
1792 static TString name;
1793 name.Form("p%s_%zx", GetName(), (size_t)this);
1794 return name.Data();
1795}
1796
1797////////////////////////////////////////////////////////////////////////////////
1798/// Getter for optimization structure.
1799
1801{
1802 if (fVoxels && !fVoxels->IsInvalid())
1803 return fVoxels;
1804 return nullptr;
1805}
1806
1807////////////////////////////////////////////////////////////////////////////////
1808/// Move perspective view focus to this volume
1809
1811{
1813 if (painter)
1814 painter->GrabFocus();
1815}
1816
1817////////////////////////////////////////////////////////////////////////////////
1818/// Returns true if the volume is an assembly or a scaled assembly.
1819
1821{
1822 return fShape->IsAssembly();
1823}
1824
1825////////////////////////////////////////////////////////////////////////////////
1826/// Clone this volume.
1827/// build a volume with same name, shape and medium
1828
1830{
1831 TGeoVolume *vol = new TGeoVolume(GetName(), fShape, fMedium);
1832 Int_t i;
1833 // copy volume attributes
1834 vol->SetTitle(GetTitle());
1835 vol->SetLineColor(GetLineColor());
1836 vol->SetLineStyle(GetLineStyle());
1837 vol->SetLineWidth(GetLineWidth());
1838 vol->SetFillColor(GetFillColor());
1839 vol->SetFillStyle(GetFillStyle());
1840 // copy other attributes
1841 Int_t nbits = 8 * sizeof(UInt_t);
1842 for (i = 0; i < nbits; i++)
1843 vol->SetAttBit(1 << i, TGeoAtt::TestAttBit(1 << i));
1844 for (i = 14; i < 24; i++)
1845 vol->SetBit(1 << i, TestBit(1 << i));
1846
1847 // copy field
1848 vol->SetField(fField);
1849 // Set bits
1850 for (i = 0; i < nbits; i++)
1851 vol->SetBit(1 << i, TObject::TestBit(1 << i));
1852 vol->SetBit(kVolumeClone);
1853 // copy nodes
1854 // CloneNodesAndConnect(vol);
1855 vol->MakeCopyNodes(this);
1856 // if volume is divided, copy finder
1857 vol->SetFinder(fFinder);
1858 // copy voxels
1859 TGeoVoxelFinder *voxels = nullptr;
1860 if (fVoxels) {
1861 voxels = new TGeoVoxelFinder(vol);
1862 vol->SetVoxelFinder(voxels);
1863 }
1864 // copy option, uid
1865 vol->SetOption(fOption);
1866 vol->SetNumber(fNumber);
1867 vol->SetNtotal(fNtotal);
1868 // copy extensions
1872 return vol;
1873}
1874
1875////////////////////////////////////////////////////////////////////////////////
1876/// Clone the array of nodes.
1877
1879{
1880 if (!fNodes)
1881 return;
1882 TGeoNode *node;
1883 Int_t nd = fNodes->GetEntriesFast();
1884 if (!nd)
1885 return;
1886 // create new list of nodes
1887 TObjArray *list = new TObjArray(nd);
1888 // attach it to new volume
1889 newmother->SetNodes(list);
1890 // ((TObject*)newmother)->SetBit(kVolumeImportNodes);
1891 for (Int_t i = 0; i < nd; i++) {
1892 // create copies of nodes and add them to list
1893 node = GetNode(i)->MakeCopyNode();
1894 if (!node) {
1895 Fatal("CloneNodesAndConnect", "cannot make copy node");
1896 return;
1897 }
1898 node->SetMotherVolume(newmother);
1899 list->Add(node);
1900 }
1901}
1902
1903////////////////////////////////////////////////////////////////////////////////
1904/// make a new list of nodes and copy all nodes of other volume inside
1905
1907{
1908 Int_t nd = other->GetNdaughters();
1909 if (!nd)
1910 return;
1911 if (fNodes) {
1913 fNodes->Delete();
1914 delete fNodes;
1915 }
1916 fNodes = new TObjArray();
1917 for (Int_t i = 0; i < nd; i++)
1918 fNodes->Add(other->GetNode(i));
1920}
1921
1922////////////////////////////////////////////////////////////////////////////////
1923/// make a copy of this volume
1924/// build a volume with same name, shape and medium
1925
1927{
1928 TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
1929 // copy volume attributes
1930 vol->SetVisibility(IsVisible());
1931 vol->SetLineColor(GetLineColor());
1932 vol->SetLineStyle(GetLineStyle());
1933 vol->SetLineWidth(GetLineWidth());
1934 vol->SetFillColor(GetFillColor());
1935 vol->SetFillStyle(GetFillStyle());
1936 // copy field
1937 vol->SetField(fField);
1938 // if divided, copy division object
1939 if (fFinder) {
1940 // Error("MakeCopyVolume", "volume %s divided", GetName());
1941 vol->SetFinder(fFinder);
1942 }
1943 // Copy extensions
1947 // ((TObject*)vol)->SetBit(kVolumeImportNodes);
1948 ((TObject *)vol)->SetBit(kVolumeClone);
1950 return vol;
1951}
1952
1953////////////////////////////////////////////////////////////////////////////////
1954/// Make a copy of this volume which is reflected with respect to XY plane.
1955
1957{
1958 static TMap map(100);
1959 if (!fGeoManager->IsClosed()) {
1960 Error("MakeReflectedVolume", "Geometry must be closed.");
1961 return nullptr;
1962 }
1963 TGeoVolume *vol = (TGeoVolume *)map.GetValue(this);
1964 if (vol) {
1965 if (newname && newname[0])
1966 vol->SetName(newname);
1967 return vol;
1968 }
1969 // printf("Making reflection for volume: %s\n", GetName());
1970 vol = CloneVolume();
1971 if (!vol) {
1972 Fatal("MakeReflectedVolume", "Cannot clone volume %s\n", GetName());
1973 return nullptr;
1974 }
1975 map.Add((TObject *)this, vol);
1976 if (newname && newname[0])
1977 vol->SetName(newname);
1978 delete vol->GetNodes();
1979 vol->SetNodes(nullptr);
1982 // The volume is now properly cloned, but with the same shape.
1983 // Reflect the shape (if any) and connect it.
1984 if (fShape) {
1985 TGeoShape *reflected_shape =
1987 vol->SetShape(reflected_shape);
1988 }
1989 // Reflect the daughters.
1990 Int_t nd = vol->GetNdaughters();
1991 if (!nd)
1992 return vol;
1993 TGeoNodeMatrix *node;
1994 TGeoMatrix *local, *local_cloned;
1995 TGeoVolume *new_vol;
1996 if (!vol->GetFinder()) {
1997 for (Int_t i = 0; i < nd; i++) {
1998 node = (TGeoNodeMatrix *)vol->GetNode(i);
1999 local = node->GetMatrix();
2000 // printf("%s before\n", node->GetName());
2001 // local->Print();
2002 Bool_t reflected = local->IsReflection();
2003 local_cloned = new TGeoCombiTrans(*local);
2004 local_cloned->RegisterYourself();
2005 node->SetMatrix(local_cloned);
2006 if (!reflected) {
2007 // We need to reflect only the translation and propagate to daughters.
2008 // H' = Sz * H * Sz
2009 local_cloned->ReflectZ(kTRUE);
2010 local_cloned->ReflectZ(kFALSE);
2011 // printf("%s after\n", node->GetName());
2012 // node->GetMatrix()->Print();
2013 new_vol = node->GetVolume()->MakeReflectedVolume();
2014 node->SetVolume(new_vol);
2015 continue;
2016 }
2017 // The next daughter is already reflected, so reflect on Z everything and stop
2018 local_cloned->ReflectZ(kTRUE); // rot + tr
2019 // printf("%s already reflected... After:\n", node->GetName());
2020 // node->GetMatrix()->Print();
2021 }
2022 if (vol->GetVoxels())
2023 vol->GetVoxels()->Voxelize();
2024 return vol;
2025 }
2026 // Volume is divided, so we have to reflect the division.
2027 // printf(" ... divided %s\n", fFinder->ClassName());
2028 TGeoPatternFinder *new_finder = fFinder->MakeCopy(kTRUE);
2029 if (!new_finder) {
2030 Fatal("MakeReflectedVolume", "Could not copy finder for volume %s", GetName());
2031 return nullptr;
2032 }
2033 new_finder->SetVolume(vol);
2034 vol->SetFinder(new_finder);
2035 TGeoNodeOffset *nodeoff;
2036 new_vol = nullptr;
2037 for (Int_t i = 0; i < nd; i++) {
2038 nodeoff = (TGeoNodeOffset *)vol->GetNode(i);
2039 nodeoff->SetFinder(new_finder);
2040 new_vol = nodeoff->GetVolume()->MakeReflectedVolume();
2041 nodeoff->SetVolume(new_vol);
2042 }
2043 return vol;
2044}
2045
2046////////////////////////////////////////////////////////////////////////////////
2047/// Set this volume as the TOP one (the whole geometry starts from here)
2048
2050{
2052}
2053
2054////////////////////////////////////////////////////////////////////////////////
2055/// Set the current tracking point.
2056
2058{
2060}
2061
2062////////////////////////////////////////////////////////////////////////////////
2063/// set the shape associated with this volume
2064
2066{
2067 if (!shape) {
2068 Error("SetShape", "No shape");
2069 return;
2070 }
2071 fShape = (TGeoShape *)shape;
2072}
2073
2074////////////////////////////////////////////////////////////////////////////////
2075/// sort nodes by decreasing volume of the bounding box. ONLY nodes comes first,
2076/// then overlapping nodes and finally division nodes.
2077
2079{
2080 if (!Valid()) {
2081 Error("SortNodes", "Bounding box not valid");
2082 return;
2083 }
2084 Int_t nd = GetNdaughters();
2085 // printf("volume : %s, nd=%i\n", GetName(), nd);
2086 if (!nd)
2087 return;
2088 if (fFinder)
2089 return;
2090 // printf("Nodes for %s\n", GetName());
2091 Int_t id = 0;
2092 TGeoNode *node = nullptr;
2093 TObjArray *nodes = new TObjArray(nd);
2094 Int_t inode = 0;
2095 // first put ONLY's
2096 for (id = 0; id < nd; id++) {
2097 node = GetNode(id);
2098 if (node->InheritsFrom(TGeoNodeOffset::Class()) || node->IsOverlapping())
2099 continue;
2100 nodes->Add(node);
2101 // printf("inode %i ONLY\n", inode);
2102 inode++;
2103 }
2104 // second put overlapping nodes
2105 for (id = 0; id < nd; id++) {
2106 node = GetNode(id);
2107 if (node->InheritsFrom(TGeoNodeOffset::Class()) || (!node->IsOverlapping()))
2108 continue;
2109 nodes->Add(node);
2110 // printf("inode %i MANY\n", inode);
2111 inode++;
2112 }
2113 // third put the divided nodes
2114 if (fFinder) {
2115 fFinder->SetDivIndex(inode);
2116 for (id = 0; id < nd; id++) {
2117 node = GetNode(id);
2118 if (!node->InheritsFrom(TGeoNodeOffset::Class()))
2119 continue;
2120 nodes->Add(node);
2121 // printf("inode %i DIV\n", inode);
2122 inode++;
2123 }
2124 }
2125 if (inode != nd)
2126 printf(" volume %s : number of nodes does not match!!!\n", GetName());
2127 delete fNodes;
2128 fNodes = nodes;
2129}
2130
2131////////////////////////////////////////////////////////////////////////////////
2132/// Stream an object of class TGeoVolume.
2133
2135{
2136 if (R__b.IsReading()) {
2137 R__b.ReadClassBuffer(TGeoVolume::Class(), this);
2138 if (fVoxels && fVoxels->IsInvalid())
2139 Voxelize("");
2140 } else {
2141 if (!fVoxels) {
2142 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2143 } else {
2145 TGeoVoxelFinder *voxels = fVoxels;
2146 fVoxels = nullptr;
2147 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2148 fVoxels = voxels;
2149 } else {
2150 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2151 }
2152 }
2153 }
2154}
2155
2156////////////////////////////////////////////////////////////////////////////////
2157/// Set the current options (none implemented)
2158
2160{
2161 fOption = option;
2162}
2163
2164////////////////////////////////////////////////////////////////////////////////
2165/// Set the line color.
2166
2168{
2169 TAttLine::SetLineColor(lcolor);
2170}
2171
2172////////////////////////////////////////////////////////////////////////////////
2173/// Set the line style.
2174
2176{
2177 TAttLine::SetLineStyle(lstyle);
2178}
2179
2180////////////////////////////////////////////////////////////////////////////////
2181/// Set the line width.
2182
2184{
2185 TAttLine::SetLineWidth(lwidth);
2186}
2187
2188////////////////////////////////////////////////////////////////////////////////
2189/// get the pointer to a daughter node
2190
2192{
2193 if (!fNodes)
2194 return nullptr;
2195 TGeoNode *node = (TGeoNode *)fNodes->FindObject(name);
2196 return node;
2197}
2198
2199////////////////////////////////////////////////////////////////////////////////
2200/// get the total size in bytes for this volume
2201
2203{
2204 Int_t count = 28 + 2 + 6 + 4 + 0; // TNamed+TGeoAtt+TAttLine+TAttFill+TAtt3D
2205 count += fName.Capacity() + fTitle.Capacity(); // name+title
2206 count += 7 * sizeof(char *); // fShape + fMedium + fFinder + fField + fNodes + 2 extensions
2207 count += fOption.Capacity(); // fOption
2208 if (fShape)
2209 count += fShape->GetByteCount();
2210 if (fFinder)
2211 count += fFinder->GetByteCount();
2212 if (fNodes) {
2213 count += 32 + 4 * fNodes->GetEntries(); // TObjArray
2214 TIter next(fNodes);
2215 TGeoNode *node;
2216 while ((node = (TGeoNode *)next()))
2217 count += node->GetByteCount();
2218 }
2219 return count;
2220}
2221
2222////////////////////////////////////////////////////////////////////////////////
2223/// loop all nodes marked as overlaps and find overlapping brothers
2224
2226{
2227 if (!Valid()) {
2228 Error("FindOverlaps", "Bounding box not valid");
2229 return;
2230 }
2231 if (!fVoxels)
2232 return;
2233 Int_t nd = GetNdaughters();
2234 if (!nd)
2235 return;
2236 TGeoNode *node = nullptr;
2237 Int_t inode = 0;
2238 for (inode = 0; inode < nd; inode++) {
2239 node = GetNode(inode);
2240 if (!node->IsOverlapping())
2241 continue;
2242 fVoxels->FindOverlaps(inode);
2243 }
2244}
2245
2246////////////////////////////////////////////////////////////////////////////////
2247/// Remove an existing daughter.
2248
2250{
2251 if (!fNodes || !fNodes->GetEntriesFast())
2252 return;
2253 if (!fNodes->Remove(node))
2254 return;
2255 fNodes->Compress();
2256 if (fVoxels)
2258 if (IsAssembly())
2260}
2261
2262////////////////////////////////////////////////////////////////////////////////
2263/// Replace an existing daughter with a new volume having the same name but
2264/// possibly a new shape, position or medium. Not allowed for positioned assemblies.
2265/// For division cells, the new shape/matrix are ignored.
2266
2268{
2269 Int_t ind = GetIndex(nodeorig);
2270 if (ind < 0)
2271 return nullptr;
2272 TGeoVolume *oldvol = nodeorig->GetVolume();
2273 if (oldvol->IsAssembly()) {
2274 Error("ReplaceNode", "Cannot replace node %s since it is an assembly", nodeorig->GetName());
2275 return nullptr;
2276 }
2277 TGeoShape *shape = oldvol->GetShape();
2278 if (newshape && !nodeorig->IsOffset())
2279 shape = newshape;
2280 TGeoMedium *med = oldvol->GetMedium();
2281 if (newmed)
2282 med = newmed;
2283 // Make a new volume
2284 TGeoVolume *vol = new TGeoVolume(oldvol->GetName(), shape, med);
2285 // copy volume attributes
2286 vol->SetVisibility(oldvol->IsVisible());
2287 vol->SetLineColor(oldvol->GetLineColor());
2288 vol->SetLineStyle(oldvol->GetLineStyle());
2289 vol->SetLineWidth(oldvol->GetLineWidth());
2290 vol->SetFillColor(oldvol->GetFillColor());
2291 vol->SetFillStyle(oldvol->GetFillStyle());
2292 // copy field
2293 vol->SetField(oldvol->GetField());
2294 // Make a copy of the node
2295 TGeoNode *newnode = nodeorig->MakeCopyNode();
2296 if (!newnode) {
2297 Fatal("ReplaceNode", "Cannot make copy node for %s", nodeorig->GetName());
2298 return nullptr;
2299 }
2300 // Change the volume for the new node
2301 newnode->SetVolume(vol);
2302 // Replace the matrix
2303 if (newpos && !nodeorig->IsOffset()) {
2304 TGeoNodeMatrix *nodemat = (TGeoNodeMatrix *)newnode;
2305 nodemat->SetMatrix(newpos);
2306 }
2307 // Replace nodeorig with new one
2308 fNodes->RemoveAt(ind);
2309 fNodes->AddAt(newnode, ind);
2310 if (fVoxels)
2312 if (IsAssembly())
2314 return newnode;
2315}
2316
2317////////////////////////////////////////////////////////////////////////////////
2318/// Select this volume as matching an arbitrary criteria. The volume is added to
2319/// a static list and the flag TGeoVolume::kVolumeSelected is set. All flags need
2320/// to be reset at the end by calling the method with CLEAR=true. This will also clear
2321/// the list.
2322
2324{
2325 static TObjArray array(256);
2326 static Int_t len = 0;
2327 Int_t i;
2328 TObject *vol;
2329 if (clear) {
2330 for (i = 0; i < len; i++) {
2331 vol = array.At(i);
2333 }
2334 array.Clear();
2335 len = 0;
2336 return;
2337 }
2339 array.AddAtAndExpand(this, len++);
2340}
2341
2342////////////////////////////////////////////////////////////////////////////////
2343/// set visibility of this volume
2344
2346{
2348 if (fGeoManager->IsClosed())
2351 TSeqCollection *brlist = gROOT->GetListOfBrowsers();
2352 TIter next(brlist);
2353 TBrowser *browser = nullptr;
2354 while ((browser = (TBrowser *)next())) {
2355 browser->CheckObjectItem(this, vis);
2356 browser->Refresh();
2357 }
2358}
2359
2360////////////////////////////////////////////////////////////////////////////////
2361/// Set visibility for containers.
2362
2364{
2366 if (fGeoManager && fGeoManager->IsClosed()) {
2367 if (flag)
2369 else
2371 }
2372}
2373
2374////////////////////////////////////////////////////////////////////////////////
2375/// Set visibility for leaves.
2376
2378{
2380 if (fGeoManager && fGeoManager->IsClosed()) {
2381 if (flag)
2383 else
2385 }
2386}
2387
2388////////////////////////////////////////////////////////////////////////////////
2389/// Set visibility for leaves.
2390
2392{
2393 if (IsAssembly())
2394 return;
2395 TGeoAtt::SetVisOnly(flag);
2396 if (fGeoManager && fGeoManager->IsClosed()) {
2397 if (flag)
2399 else
2401 }
2402}
2403
2404////////////////////////////////////////////////////////////////////////////////
2405/// Check if the shape of this volume is valid.
2406
2408{
2409 return fShape->IsValidBox();
2410}
2411
2412////////////////////////////////////////////////////////////////////////////////
2413/// Find a daughter node having VOL as volume and fill TGeoManager::fHMatrix
2414/// with its global matrix.
2415
2417{
2418 if (vol == this)
2419 return kTRUE;
2420 Int_t nd = GetNdaughters();
2421 if (!nd)
2422 return kFALSE;
2423 TGeoHMatrix *global = fGeoManager->GetHMatrix();
2424 if (!global)
2425 return kFALSE;
2426 TGeoNode *dnode;
2427 TGeoVolume *dvol;
2428 TGeoMatrix *local;
2429 Int_t i;
2430 for (i = 0; i < nd; i++) {
2431 dnode = GetNode(i);
2432 dvol = dnode->GetVolume();
2433 if (dvol == vol) {
2434 local = dnode->GetMatrix();
2435 global->MultiplyLeft(local);
2436 return kTRUE;
2437 }
2438 }
2439 for (i = 0; i < nd; i++) {
2440 dnode = GetNode(i);
2441 dvol = dnode->GetVolume();
2442 if (dvol->FindMatrixOfDaughterVolume(vol))
2443 return kTRUE;
2444 }
2445 return kFALSE;
2446}
2447
2448////////////////////////////////////////////////////////////////////////////////
2449/// set visibility for daughters
2450
2452{
2453 SetVisDaughters(vis);
2454 if (fGeoManager->IsClosed())
2457}
2458
2459////////////////////////////////////////////////////////////////////////////////
2460/// build the voxels for this volume
2461
2463{
2464 if (!Valid()) {
2465 Error("Voxelize", "Bounding box not valid");
2466 return;
2467 }
2468 // do not voxelize divided volumes
2469 if (fFinder)
2470 return;
2471 // or final leaves
2472 Int_t nd = GetNdaughters();
2473 if (!nd)
2474 return;
2475 // If this is an assembly, re-compute bounding box
2476 if (IsAssembly())
2478 // delete old voxelization if any
2479 if (fVoxels) {
2481 delete fVoxels;
2482 fVoxels = nullptr;
2483 }
2484 // Create the voxels structure
2485 fVoxels = new TGeoVoxelFinder(this);
2487 if (fVoxels) {
2488 if (fVoxels->IsInvalid()) {
2489 delete fVoxels;
2490 fVoxels = nullptr;
2491 }
2492 }
2493}
2494
2495////////////////////////////////////////////////////////////////////////////////
2496/// Estimate the weight of a volume (in kg) with SIGMA(M)/M better than PRECISION.
2497/// Option can contain : v - verbose, a - analytical (default)
2498
2500{
2502 if (top != this)
2504 else
2505 top = nullptr;
2506 Double_t weight = fGeoManager->Weight(precision, option);
2507 if (top)
2509 return weight;
2510}
2511
2512////////////////////////////////////////////////////////////////////////////////
2513/// Analytical computation of the weight.
2514
2516{
2517 Double_t capacity = Capacity();
2518 Double_t weight = 0.0;
2519 Int_t i;
2520 Int_t nd = GetNdaughters();
2521 TGeoVolume *daughter;
2522 for (i = 0; i < nd; i++) {
2523 daughter = GetNode(i)->GetVolume();
2524 weight += daughter->WeightA();
2525 capacity -= daughter->Capacity();
2526 }
2527 Double_t density = 0.0;
2528 if (!IsAssembly()) {
2529 if (fMedium)
2530 density = fMedium->GetMaterial()->GetDensity();
2531 if (density < 0.01)
2532 density = 0.0; // do not weight gases
2533 }
2534 weight += 0.001 * capacity * density; //[kg]
2535 return weight;
2536}
2537
2539
2540////////////////////////////////////////////////////////////////////////////////
2541/// dummy constructor
2542
2544{
2545 fVolumes = nullptr;
2546 fDivision = nullptr;
2547 fNumed = 0;
2548 fNdiv = 0;
2549 fAxis = 0;
2550 fStart = 0;
2551 fStep = 0;
2552 fAttSet = kFALSE;
2554}
2555
2556////////////////////////////////////////////////////////////////////////////////
2557/// default constructor
2558
2560{
2561 fVolumes = new TObjArray();
2562 fDivision = nullptr;
2563 fNumed = 0;
2564 fNdiv = 0;
2565 fAxis = 0;
2566 fStart = 0;
2567 fStep = 0;
2568 fAttSet = kFALSE;
2570 SetName(name);
2571 SetMedium(med);
2572 fGeoManager->AddVolume(this);
2573 // printf("--- volume multi %s created\n", name);
2574}
2575
2576////////////////////////////////////////////////////////////////////////////////
2577/// Destructor
2578
2580{
2581 if (fVolumes)
2582 delete fVolumes;
2583}
2584
2585////////////////////////////////////////////////////////////////////////////////
2586/// Add a volume with valid shape to the list of volumes. Copy all existing nodes
2587/// to this volume
2588
2590{
2591 Int_t idx = fVolumes->GetEntriesFast();
2592 fVolumes->AddAtAndExpand(vol, idx);
2593 vol->SetUniqueID(idx + 1);
2594 TGeoVolumeMulti *div;
2595 TGeoVolume *cell;
2596 if (fDivision) {
2598 if (!div) {
2599 Fatal("AddVolume", "Cannot divide volume %s", vol->GetName());
2600 return;
2601 }
2602 for (Int_t i = 0; i < div->GetNvolumes(); i++) {
2603 cell = div->GetVolume(i);
2604 fDivision->AddVolume(cell);
2605 }
2606 }
2607 if (fNodes) {
2608 Int_t nd = fNodes->GetEntriesFast();
2609 for (Int_t id = 0; id < nd; id++) {
2610 TGeoNode *node = (TGeoNode *)fNodes->At(id);
2611 Bool_t many = node->IsOverlapping();
2612 if (many)
2613 vol->AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2614 else
2615 vol->AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2616 }
2617 }
2618 // vol->MakeCopyNodes(this);
2619}
2620
2621////////////////////////////////////////////////////////////////////////////////
2622/// Add a new node to the list of nodes. This is the usual method for adding
2623/// daughters inside the container volume.
2624
2626{
2627 TGeoNode *n = TGeoVolume::AddNode(vol, copy_no, mat, option);
2628 Int_t nvolumes = fVolumes->GetEntriesFast();
2629 TGeoVolume *volume = nullptr;
2630 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2631 volume = GetVolume(ivo);
2632 volume->SetLineColor(GetLineColor());
2633 volume->SetLineStyle(GetLineStyle());
2634 volume->SetLineWidth(GetLineWidth());
2635 volume->SetVisibility(IsVisible());
2636 volume->AddNode(vol, copy_no, mat, option);
2637 }
2638 // printf("--- vmulti %s : node %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2639 return n;
2640}
2641
2642////////////////////////////////////////////////////////////////////////////////
2643/// Add a new node to the list of nodes, This node is possibly overlapping with other
2644/// daughters of the volume or extruding the volume.
2645
2647{
2648 TGeoVolume::AddNodeOverlap(vol, copy_no, mat, option);
2649 Int_t nvolumes = fVolumes->GetEntriesFast();
2650 TGeoVolume *volume = nullptr;
2651 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2652 volume = GetVolume(ivo);
2653 volume->SetLineColor(GetLineColor());
2654 volume->SetLineStyle(GetLineStyle());
2655 volume->SetLineWidth(GetLineWidth());
2656 volume->SetVisibility(IsVisible());
2657 volume->AddNodeOverlap(vol, copy_no, mat, option);
2658 }
2659 // printf("--- vmulti %s : node ovlp %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2660}
2661
2662////////////////////////////////////////////////////////////////////////////////
2663/// Returns the last shape.
2664
2666{
2668 if (!vol)
2669 return nullptr;
2670 return vol->GetShape();
2671}
2672
2673////////////////////////////////////////////////////////////////////////////////
2674/// division of multiple volumes
2675
2676TGeoVolume *TGeoVolumeMulti::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step,
2677 Int_t numed, const char *option)
2678{
2679 if (fDivision) {
2680 Error("Divide", "volume %s already divided", GetName());
2681 return nullptr;
2682 }
2683 Int_t nvolumes = fVolumes->GetEntriesFast();
2684 TGeoMedium *medium = fMedium;
2685 if (numed) {
2686 medium = fGeoManager->GetMedium(numed);
2687 if (!medium) {
2688 Error("Divide", "Invalid medium number %d for division volume %s", numed, divname);
2689 medium = fMedium;
2690 }
2691 }
2692 if (!nvolumes) {
2693 // this is a virtual volume
2694 fDivision = new TGeoVolumeMulti(divname, medium);
2695 fNumed = medium->GetId();
2696 fOption = option;
2697 fAxis = iaxis;
2698 fNdiv = ndiv;
2699 fStart = start;
2700 fStep = step;
2701 // nothing else to do at this stage
2702 return fDivision;
2703 }
2704 TGeoVolume *vol = nullptr;
2705 fDivision = new TGeoVolumeMulti(divname, medium);
2706 if (medium)
2707 fNumed = medium->GetId();
2708 fOption = option;
2709 fAxis = iaxis;
2710 fNdiv = ndiv;
2711 fStart = start;
2712 fStep = step;
2713 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2714 vol = GetVolume(ivo);
2715 vol->SetLineColor(GetLineColor());
2716 vol->SetLineStyle(GetLineStyle());
2717 vol->SetLineWidth(GetLineWidth());
2718 vol->SetVisibility(IsVisible());
2719 fDivision->AddVolume(vol->Divide(divname, iaxis, ndiv, start, step, numed, option));
2720 }
2721 // printf("--- volume multi %s (%i volumes) divided\n", GetName(), nvolumes);
2722 if (numed)
2723 fDivision->SetMedium(medium);
2724 return fDivision;
2725}
2726
2727////////////////////////////////////////////////////////////////////////////////
2728/// Make a copy of this volume
2729/// build a volume with same name, shape and medium
2730
2732{
2733 TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
2734 Int_t i = 0;
2735 // copy volume attributes
2736 vol->SetVisibility(IsVisible());
2737 vol->SetLineColor(GetLineColor());
2738 vol->SetLineStyle(GetLineStyle());
2739 vol->SetLineWidth(GetLineWidth());
2740 vol->SetFillColor(GetFillColor());
2741 vol->SetFillStyle(GetFillStyle());
2742 // copy field
2743 vol->SetField(fField);
2744 // Copy extensions
2747 // if divided, copy division object
2748 // if (fFinder) {
2749 // Error("MakeCopyVolume", "volume %s divided", GetName());
2750 // vol->SetFinder(fFinder);
2751 // }
2752 if (fDivision) {
2753 TGeoVolume *cell;
2754 TGeoVolumeMulti *div =
2756 if (!div) {
2757 Fatal("MakeCopyVolume", "Cannot divide volume %s", vol->GetName());
2758 return nullptr;
2759 }
2760 for (i = 0; i < div->GetNvolumes(); i++) {
2761 cell = div->GetVolume(i);
2762 fDivision->AddVolume(cell);
2763 }
2764 }
2765
2766 if (!fNodes)
2767 return vol;
2768 TGeoNode *node;
2769 Int_t nd = fNodes->GetEntriesFast();
2770 if (!nd)
2771 return vol;
2772 // create new list of nodes
2773 TObjArray *list = new TObjArray();
2774 // attach it to new volume
2775 vol->SetNodes(list);
2776 ((TObject *)vol)->SetBit(kVolumeImportNodes);
2777 for (i = 0; i < nd; i++) {
2778 // create copies of nodes and add them to list
2779 node = GetNode(i)->MakeCopyNode();
2780 if (!node) {
2781 Fatal("MakeCopyNode", "cannot make copy node for daughter %d of %s", i, GetName());
2782 return nullptr;
2783 }
2784 node->SetMotherVolume(vol);
2785 list->Add(node);
2786 }
2787 return vol;
2788}
2789
2790////////////////////////////////////////////////////////////////////////////////
2791/// Set the line color for all components.
2792
2794{
2796 Int_t nvolumes = fVolumes->GetEntriesFast();
2797 TGeoVolume *vol = nullptr;
2798 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2799 vol = GetVolume(ivo);
2800 vol->SetLineColor(lcolor);
2801 }
2802}
2803
2804////////////////////////////////////////////////////////////////////////////////
2805/// Set the line style for all components.
2806
2808{
2810 Int_t nvolumes = fVolumes->GetEntriesFast();
2811 TGeoVolume *vol = nullptr;
2812 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2813 vol = GetVolume(ivo);
2814 vol->SetLineStyle(lstyle);
2815 }
2816}
2817
2818////////////////////////////////////////////////////////////////////////////////
2819/// Set the line width for all components.
2820
2822{
2824 Int_t nvolumes = fVolumes->GetEntriesFast();
2825 TGeoVolume *vol = nullptr;
2826 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2827 vol = GetVolume(ivo);
2828 vol->SetLineWidth(lwidth);
2829 }
2830}
2831
2832////////////////////////////////////////////////////////////////////////////////
2833/// Set medium for a multiple volume.
2834
2836{
2838 Int_t nvolumes = fVolumes->GetEntriesFast();
2839 TGeoVolume *vol = nullptr;
2840 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2841 vol = GetVolume(ivo);
2842 vol->SetMedium(med);
2843 }
2844}
2845
2846////////////////////////////////////////////////////////////////////////////////
2847/// Set visibility for all components.
2848
2850{
2852 Int_t nvolumes = fVolumes->GetEntriesFast();
2853 TGeoVolume *vol = nullptr;
2854 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2855 vol = GetVolume(ivo);
2856 vol->SetVisibility(vis);
2857 }
2858}
2859
2861
2862////////////////////////////////////////////////////////////////////////////////
2863/// Constructor.
2864
2866
2867////////////////////////////////////////////////////////////////////////////////
2868/// Destructor.
2869
2871
2872////////////////////////////////////////////////////////////////////////////////
2873
2875{
2877 return *fThreadData[tid];
2878}
2879
2880////////////////////////////////////////////////////////////////////////////////
2881
2883{
2884 std::lock_guard<std::mutex> guard(fMutex);
2886 std::vector<ThreadData_t *>::iterator i = fThreadData.begin();
2887 while (i != fThreadData.end()) {
2888 delete *i;
2889 ++i;
2890 }
2891 fThreadData.clear();
2892 fThreadSize = 0;
2893}
2894
2895////////////////////////////////////////////////////////////////////////////////
2896
2898{
2899 std::lock_guard<std::mutex> guard(fMutex);
2900 // Create assembly thread data here
2901 fThreadData.resize(nthreads);
2902 fThreadSize = nthreads;
2903 for (Int_t tid = 0; tid < nthreads; tid++) {
2904 if (fThreadData[tid] == nullptr) {
2905 fThreadData[tid] = new ThreadData_t;
2906 }
2907 }
2909}
2910
2911////////////////////////////////////////////////////////////////////////////////
2912
2914{
2915 return fThreadData[TGeoManager::ThreadId()]->fCurrent;
2916}
2917
2918////////////////////////////////////////////////////////////////////////////////
2919
2921{
2922 return fThreadData[TGeoManager::ThreadId()]->fNext;
2923}
2924
2925////////////////////////////////////////////////////////////////////////////////
2926
2928{
2930}
2931
2932////////////////////////////////////////////////////////////////////////////////
2933
2935{
2937}
2938
2939////////////////////////////////////////////////////////////////////////////////
2940/// Default constructor
2941
2943{
2944 fThreadSize = 0;
2946}
2947
2948////////////////////////////////////////////////////////////////////////////////
2949/// Constructor. Just the name has to be provided. Assemblies does not have their own
2950/// shape or medium.
2951
2953{
2954 fName = name;
2955 fName = fName.Strip();
2956 fShape = new TGeoShapeAssembly(this);
2957 if (fGeoManager)
2958 fNumber = fGeoManager->AddVolume(this);
2959 fThreadSize = 0;
2961}
2962
2963////////////////////////////////////////////////////////////////////////////////
2964/// Destructor. The assembly is owner of its "shape".
2965
2967{
2969 if (fShape)
2970 delete fShape;
2971}
2972
2973////////////////////////////////////////////////////////////////////////////////
2974/// Add a component to the assembly.
2975
2977{
2978 TGeoNode *node = TGeoVolume::AddNode(vol, copy_no, mat, option);
2979 // ((TGeoShapeAssembly*)fShape)->RecomputeBoxLast();
2980 ((TGeoShapeAssembly *)fShape)->NeedsBBoxRecompute();
2981 return node;
2982}
2983
2984////////////////////////////////////////////////////////////////////////////////
2985/// Add an overlapping node - not allowed for assemblies.
2986
2988{
2989 Warning("AddNodeOverlap",
2990 "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",
2991 vol->GetName(), GetName());
2992 AddNode(vol, copy_no, mat, option);
2993}
2994
2995////////////////////////////////////////////////////////////////////////////////
2996/// Clone this volume.
2997/// build a volume with same name, shape and medium
2998
3000{
3002 Int_t i;
3003 // copy other attributes
3004 Int_t nbits = 8 * sizeof(UInt_t);
3005 for (i = 0; i < nbits; i++)
3006 vol->SetAttBit(1 << i, TGeoAtt::TestAttBit(1 << i));
3007 for (i = 14; i < 24; i++)
3008 vol->SetBit(1 << i, TestBit(1 << i));
3009
3010 // copy field
3011 vol->SetField(fField);
3012 // Set bits
3013 for (i = 0; i < nbits; i++)
3014 vol->SetBit(1 << i, TObject::TestBit(1 << i));
3015 vol->SetBit(kVolumeClone);
3016 // make copy nodes
3017 vol->MakeCopyNodes(this);
3018 // CloneNodesAndConnect(vol);
3019 ((TGeoShapeAssembly *)vol->GetShape())->NeedsBBoxRecompute();
3020 // copy voxels
3021 TGeoVoxelFinder *voxels = nullptr;
3022 if (fVoxels) {
3023 voxels = new TGeoVoxelFinder(vol);
3024 vol->SetVoxelFinder(voxels);
3025 }
3026 // copy option, uid
3027 vol->SetOption(fOption);
3028 vol->SetNumber(fNumber);
3029 vol->SetNtotal(fNtotal);
3030 vol->SetTitle(GetTitle());
3031 return vol;
3032}
3033
3034////////////////////////////////////////////////////////////////////////////////
3035/// Division makes no sense for assemblies.
3036
3038{
3039 Error("Divide", "Assemblies cannot be divided");
3040 return nullptr;
3041}
3042
3043////////////////////////////////////////////////////////////////////////////////
3044/// Assign to the assembly a collection of identical volumes positioned according
3045/// a predefined pattern. The option can be spaced out or touching depending on the empty
3046/// space between volumes.
3047
3049{
3050 if (fNodes) {
3051 Error("Divide", "Cannot divide assembly %s since it has nodes", GetName());
3052 return nullptr;
3053 }
3054 if (fFinder) {
3055 Error("Divide", "Assembly %s already divided", GetName());
3056 return nullptr;
3057 }
3058 Int_t ncells = pattern->GetNdiv();
3059 if (!ncells || pattern->GetStep() <= 0) {
3060 Error("Divide", "Pattern finder for dividing assembly %s not initialized. Use SetRange() method.", GetName());
3061 return nullptr;
3062 }
3063 fFinder = pattern;
3064 TString opt(option);
3065 opt.ToLower();
3066 if (opt.Contains("spacedout"))
3068 else
3070 // Position volumes
3071 for (Int_t i = 0; i < ncells; i++) {
3072 fFinder->cd(i);
3073 TGeoNodeOffset *node = new TGeoNodeOffset(cell, i, 0.);
3074 node->SetFinder(fFinder);
3075 fNodes->Add(node);
3076 }
3077 return cell;
3078}
3079
3080////////////////////////////////////////////////////////////////////////////////
3081/// Make a clone of volume VOL but which is an assembly.
3082
3084{
3085 if (volorig->IsAssembly() || volorig->IsVolumeMulti())
3086 return nullptr;
3087 Int_t nd = volorig->GetNdaughters();
3088 if (!nd)
3089 return nullptr;
3090 TGeoVolumeAssembly *vol = new TGeoVolumeAssembly(volorig->GetName());
3091 Int_t i;
3092 // copy other attributes
3093 Int_t nbits = 8 * sizeof(UInt_t);
3094 for (i = 0; i < nbits; i++)
3095 vol->SetAttBit(1 << i, volorig->TestAttBit(1 << i));
3096 for (i = 14; i < 24; i++)
3097 vol->SetBit(1 << i, volorig->TestBit(1 << i));
3098
3099 // copy field
3100 vol->SetField(volorig->GetField());
3101 // Set bits
3102 for (i = 0; i < nbits; i++)
3103 vol->SetBit(1 << i, volorig->TestBit(1 << i));
3104 vol->SetBit(kVolumeClone);
3105 // make copy nodes
3106 vol->MakeCopyNodes(volorig);
3107 // volorig->CloneNodesAndConnect(vol);
3108 vol->GetShape()->ComputeBBox();
3109 // copy voxels
3110 TGeoVoxelFinder *voxels = nullptr;
3111 if (volorig->GetVoxels()) {
3112 voxels = new TGeoVoxelFinder(vol);
3113 vol->SetVoxelFinder(voxels);
3114 }
3115 // copy option, uid
3116 vol->SetOption(volorig->GetOption());
3117 vol->SetNumber(volorig->GetNumber());
3118 vol->SetNtotal(volorig->GetNtotal());
3119 return vol;
3120}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define s1(x)
Definition RSha256.hxx:91
short Style_t
Definition RtypesCore.h:89
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:92
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:91
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
R__EXTERN TGeoManager * gGeoManager
R__EXTERN TGeoIdentity * gGeoIdentity
Definition TGeoMatrix.h:537
#define gROOT
Definition TROOT.h:406
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:31
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:39
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
virtual void SaveLineAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t widdef=1)
Save line attributes as C++ statement(s) on output stream out.
Definition TAttLine.cxx:275
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
void CheckObjectItem(TObject *obj, Bool_t check=kFALSE)
Change status of checkbox for this item.
Definition TBrowser.cxx:346
void Refresh()
Refresh browser contents.
Definition TBrowser.cxx:419
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
A ROOT file is composed of a header, followed by consecutive data records (TKey instances) with a wel...
Definition TFile.h:53
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4067
Bool_t IsVisRaytrace() const
Definition TGeoAtt.h:82
virtual void SetVisOnly(Bool_t flag=kTRUE)
Set branch type visibility.
Definition TGeoAtt.cxx:94
Bool_t TestAttBit(UInt_t f) const
Definition TGeoAtt.h:64
virtual void SetVisLeaves(Bool_t flag=kTRUE)
Set branch type visibility.
Definition TGeoAtt.cxx:84
@ kSaveNodesAtt
Definition TGeoAtt.h:50
@ kSavePrimitiveAtt
Definition TGeoAtt.h:50
void SetVisDaughters(Bool_t vis=kTRUE)
Set visibility for the daughters.
Definition TGeoAtt.cxx:116
void ResetAttBit(UInt_t f)
Definition TGeoAtt.h:63
void SetVisRaytrace(Bool_t flag=kTRUE)
Definition TGeoAtt.h:66
Bool_t IsVisDaughters() const
Definition TGeoAtt.h:84
virtual void SetVisibility(Bool_t vis=kTRUE)
Set visibility for this object.
Definition TGeoAtt.cxx:104
void SetAttBit(UInt_t f)
Definition TGeoAtt.h:61
void SetVisTouched(Bool_t vis=kTRUE)
Mark visualization attributes as "modified".
Definition TGeoAtt.cxx:138
virtual void SetVisContainers(Bool_t flag=kTRUE)
Set branch type visibility.
Definition TGeoAtt.cxx:76
Class describing rotation + translation.
Definition TGeoMatrix.h:317
Composite shapes are Boolean combinations of two or more shape components.
void RegisterYourself()
Register the shape and all components to TGeoManager class.
ABC for user objects attached to TGeoVolume or TGeoNode.
virtual TGeoExtension * Grab()=0
virtual void Release() const =0
Matrix class used for computing global transformations Should NOT be used for node definition.
Definition TGeoMatrix.h:458
void MultiplyLeft(const TGeoMatrix *left)
multiply to the left with an other transformation if right is identity matrix, just return
The manager class for any TGeo geometry.
Definition TGeoManager.h:44
TObjArray * GetListOfOverlaps()
TList * GetListOfMedia() const
void SetUserPaintVolume(TGeoVolume *vol)
TObjArray * GetListOfVolumes() const
void ClearOverlaps()
Clear the list of overlaps.
TObjArray * GetListOfMatrices() const
Bool_t IsClosed() const
TVirtualGeoPainter * GetGeomPainter()
Make a default painter if none present. Returns pointer to it.
void SetVisOption(Int_t option=0)
set drawing mode :
Int_t AddMaterial(const TGeoMaterial *material)
Add a material to the list. Returns index of the material in list.
TGeoHMatrix * GetHMatrix()
Return stored current matrix (global matrix of the next touched node).
Int_t AddVolume(TGeoVolume *volume)
Add a volume to the list. Returns index of the volume in list.
Bool_t IsStreamingVoxels() const
void SetCurrentPoint(Double_t *point)
Int_t GetVisOption() const
Returns current depth to which geometry is drawn.
void SetTopVolume(TGeoVolume *vol)
Set the top volume and corresponding node as starting point of the geometry.
void ClearShape(const TGeoShape *shape)
Remove a shape from the list of shapes.
TGeoMedium * GetMedium(const char *medium) const
Search for a named tracking medium. All trailing blanks stripped.
Double_t Weight(Double_t precision=0.01, Option_t *option="va")
Estimate weight of volume VOL with a precision SIGMA(W)/W better than PRECISION.
void SetNsegments(Int_t nseg)
Set number of segments for approximating circles in drawing.
static UInt_t GetExportPrecision()
TVirtualGeoPainter * GetPainter() const
Bool_t IsCheckingOverlaps() const
void RandomPoints(const TGeoVolume *vol, Int_t npoints=10000, Option_t *option="")
Draw random points in the bounding box of a volume.
TList * GetListOfMaterials() const
void RandomRays(Int_t nrays=1000, Double_t startx=0, Double_t starty=0, Double_t startz=0, const char *target_vol=nullptr, Bool_t check_norm=kFALSE)
Randomly shoot nrays and plot intersections with surfaces for current top node.
void SetAllIndex()
Assigns uid's for all materials,media and matrices.
TObjArray * GetListOfShapes() const
TGeoVolume * GetTopVolume() const
static Int_t ThreadId()
Translates the current thread id to an ordinal number.
Int_t AddShape(const TGeoShape *shape)
Add a shape to the list. Returns index of the shape in list.
void SortOverlaps()
Sort overlaps by decreasing overlap distance. Extrusions comes first.
Base class describing materials.
void SetUsed(Bool_t flag=kTRUE)
void Print(const Option_t *option="") const override
print characteristics of this material
virtual Double_t GetDensity() const
Geometrical transformation package.
Definition TGeoMatrix.h:38
void Print(Option_t *option="") const override
print the matrix in 4x4 format
virtual void ReflectZ(Bool_t leftside, Bool_t rotonly=kFALSE)
Multiply by a reflection respect to XY.
Bool_t IsReflection() const
Definition TGeoMatrix.h:66
virtual void RegisterYourself()
Register the matrix in the current manager, which will become the owner.
Bool_t IsIdentity() const
Definition TGeoMatrix.h:63
const char * GetPointerName() const
Provide a pointer name containing uid.
Bool_t IsRegistered() const
Definition TGeoMatrix.h:72
Media are used to store properties related to tracking and which are useful only when using geometry ...
Definition TGeoMedium.h:23
Int_t GetId() const
Definition TGeoMedium.h:45
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
TGeoMaterial * GetMaterial() const
Definition TGeoMedium.h:49
const char * GetPointerName() const
Provide a pointer name containing uid.
void SetMaterial(TGeoMaterial *mat)
Definition TGeoMedium.h:52
A node containing local transformation.
Definition TGeoNode.h:154
void SetMatrix(const TGeoMatrix *matrix)
Matrix setter.
Definition TGeoNode.cxx:827
TGeoMatrix * GetMatrix() const override
Definition TGeoNode.h:171
Node containing an offset.
Definition TGeoNode.h:184
void SetFinder(TGeoPatternFinder *finder)
Definition TGeoNode.h:210
static TClass * Class()
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition TGeoNode.h:39
Bool_t IsOverlapping() const
Definition TGeoNode.h:107
TGeoVolume * GetVolume() const
Definition TGeoNode.h:99
void SetVolume(TGeoVolume *volume)
Definition TGeoNode.h:117
Bool_t IsOffset() const
Definition TGeoNode.h:105
virtual Int_t GetByteCount() const
Definition TGeoNode.h:82
void SetOverlapping(Bool_t flag=kTRUE)
Definition TGeoNode.h:120
virtual Int_t GetOptimalVoxels() const
Definition TGeoNode.h:101
virtual TGeoMatrix * GetMatrix() const =0
void SetMotherVolume(TGeoVolume *mother)
Definition TGeoNode.h:125
virtual TGeoNode * MakeCopyNode() const
Definition TGeoNode.h:113
void SetVirtual()
Definition TGeoNode.h:121
Int_t GetNumber() const
Definition TGeoNode.h:93
void SetNumber(Int_t number)
Definition TGeoNode.h:118
Base finder class for patterns.
virtual void cd(Int_t)
void SetSpacedOut(Bool_t flag)
void SetDivIndex(Int_t index)
virtual TGeoPatternFinder * MakeCopy(Bool_t reflect=kFALSE)=0
virtual Int_t GetDivAxis()
Int_t GetNdiv() const
void SetVolume(TGeoVolume *vol)
Double_t GetStep() const
void ClearThreadData() const
Double_t GetStart() const
virtual Int_t GetByteCount() const
void CreateThreadData(Int_t nthreads)
Create thread data for n threads max.
Class describing scale transformations.
Definition TGeoMatrix.h:253
static TGeoShape * MakeScaledShape(const char *name, TGeoShape *shape, TGeoScale *scale)
Create a scaled shape starting from a non-scaled one.
The shape encapsulating an assembly (union) of volumes.
Base abstract class for all shapes.
Definition TGeoShape.h:25
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const =0
virtual void CreateThreadData(Int_t)
Definition TGeoShape.h:67
Bool_t IsValid() const
Definition TGeoShape.h:143
virtual const char * GetAxisName(Int_t iaxis) const =0
virtual TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step)=0
virtual Bool_t IsComposite() const
Definition TGeoShape.h:130
static Bool_t IsSameWithinTolerance(Double_t a, Double_t b)
Check if two numbers differ with less than a tolerance.
Bool_t IsRunTimeShape() const
Definition TGeoShape.h:142
virtual void ClearThreadData() const
Definition TGeoShape.h:66
const char * GetPointerName() const
Provide a pointer name containing uid.
void CheckShape(Int_t testNo, Int_t nsamples=10000, Option_t *option="")
Test for shape navigation methods.
virtual Bool_t IsValidBox() const =0
virtual Int_t GetByteCount() const =0
const char * GetName() const override
Get the shape name.
virtual void ComputeBBox()=0
virtual Double_t Capacity() const =0
@ kGeoSavePrimitive
Definition TGeoShape.h:64
virtual TGeoShape * GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const =0
virtual Bool_t IsAssembly() const
Definition TGeoShape.h:129
Bool_t TestShapeBit(UInt_t f) const
Definition TGeoShape.h:167
Volume assemblies.
Definition TGeoVolume.h:316
static TGeoVolumeAssembly * MakeAssemblyFromVolume(TGeoVolume *vol)
Make a clone of volume VOL but which is an assembly.
~TGeoVolumeAssembly() override
Destructor. The assembly is owner of its "shape".
Int_t GetNextNodeIndex() const override
void CreateThreadData(Int_t nthreads) override
TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="") override
Add a component to the assembly.
void ClearThreadData() const override
TGeoVolume * CloneVolume() const override
Clone this volume.
void AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option) override
Add an overlapping node - not allowed for assemblies.
std::vector< ThreadData_t * > fThreadData
Definition TGeoVolume.h:331
std::mutex fMutex
Thread vector size.
Definition TGeoVolume.h:333
Int_t fThreadSize
Thread specific data vector.
Definition TGeoVolume.h:332
void SetNextNodeIndex(Int_t index)
Int_t GetCurrentNodeIndex() const override
void SetCurrentNodeIndex(Int_t index)
TGeoVolumeAssembly()
Default constructor.
TGeoVolume * Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed=0, Option_t *option="") override
Division makes no sense for assemblies.
ThreadData_t & GetThreadData() const
Volume families.
Definition TGeoVolume.h:266
TGeoVolume * Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed=0, Option_t *option="") override
division of multiple volumes
void SetLineColor(Color_t lcolor) override
Set the line color for all components.
Double_t fStart
Definition TGeoVolume.h:273
void AddVolume(TGeoVolume *vol)
Add a volume with valid shape to the list of volumes.
TGeoVolume * MakeCopyVolume(TGeoShape *newshape) override
Make a copy of this volume build a volume with same name, shape and medium.
void SetMedium(TGeoMedium *medium) override
Set medium for a multiple volume.
TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option="") override
Add a new node to the list of nodes.
TGeoVolume * GetVolume(Int_t id) const
Definition TGeoVolume.h:286
void SetVisibility(Bool_t vis=kTRUE) override
Set visibility for all components.
~TGeoVolumeMulti() override
Destructor.
TGeoVolumeMulti * fDivision
Definition TGeoVolume.h:269
TGeoVolumeMulti()
dummy constructor
void SetLineWidth(Width_t lwidth) override
Set the line width for all components.
TGeoShape * GetLastShape() const
Returns the last shape.
void AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option="") override
Add a new node to the list of nodes, This node is possibly overlapping with other daughters of the vo...
void SetLineStyle(Style_t lstyle) override
Set the line style for all components.
Int_t GetNvolumes() const
Definition TGeoVolume.h:293
TObjArray * fVolumes
Definition TGeoVolume.h:268
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:43
Double_t WeightA() const
Analytical computation of the weight.
void AddNodeOffset(TGeoVolume *vol, Int_t copy_no, Double_t offset=0, Option_t *option="")
Add a division node to the list of nodes.
void SetVisContainers(Bool_t flag=kTRUE) override
Set visibility for containers.
virtual void cd(Int_t inode) const
Actualize matrix of node indexed <inode>
virtual void ClearThreadData() const
void SetVisibility(Bool_t vis=kTRUE) override
set visibility of this volume
Bool_t IsVisContainers() const
Definition TGeoVolume.h:157
void SetVoxelFinder(TGeoVoxelFinder *finder)
Definition TGeoVolume.h:243
void RemoveNode(TGeoNode *node)
Remove an existing daughter.
Int_t GetNodeIndex(const TGeoNode *node, Int_t *check_list, Int_t ncheck) const
Get the index of a daughter within check_list by providing the node pointer.
Bool_t Valid() const
Check if the shape of this volume is valid.
Bool_t IsAllInvisible() const
Return TRUE if volume and all daughters are invisible.
Int_t fNtotal
Definition TGeoVolume.h:56
void MakeCopyNodes(const TGeoVolume *other)
make a new list of nodes and copy all nodes of other volume inside
void SetUserExtension(TGeoExtension *ext)
Connect user-defined extension to the volume.
TGeoExtension * GrabFWExtension() const
Get a copy of the framework extension pointer.
void SetNumber(Int_t number)
Definition TGeoVolume.h:245
void ClearNodes()
Definition TGeoVolume.h:95
void SetLineWidth(Width_t lwidth) override
Set the line width.
void Raytrace(Bool_t flag=kTRUE)
Draw this volume with current settings and perform raytracing in the pad.
void RandomRays(Int_t nrays=10000, Double_t startx=0, Double_t starty=0, Double_t startz=0, const char *target_vol=nullptr, Bool_t check_norm=kFALSE)
Random raytracing method.
TGeoVolume()
dummy constructor
TGeoMedium * GetMedium() const
Definition TGeoVolume.h:175
char * GetObjectInfo(Int_t px, Int_t py) const override
Get volume info for the browser.
void Print(Option_t *option="") const override
Print volume info.
void CloneNodesAndConnect(TGeoVolume *newmother) const
Clone the array of nodes.
void SortNodes()
sort nodes by decreasing volume of the bounding box.
Bool_t FindMatrixOfDaughterVolume(TGeoVolume *vol) const
Find a daughter node having VOL as volume and fill TGeoManager::fHMatrix with its global matrix.
void Voxelize(Option_t *option)
build the voxels for this volume
Double_t Capacity() const
Computes the capacity of this [cm^3] as the capacity of its shape.
virtual TGeoVolume * MakeCopyVolume(TGeoShape *newshape)
make a copy of this volume build a volume with same name, shape and medium
void ReplayCreation(const TGeoVolume *other)
Recreate the content of the other volume without pointer copying.
Double_t Weight(Double_t precision=0.01, Option_t *option="va")
Estimate the weight of a volume (in kg) with SIGMA(M)/M better than PRECISION.
Int_t fNumber
option - if any
Definition TGeoVolume.h:55
virtual void CreateThreadData(Int_t nthreads)
virtual Int_t GetByteCount() const
get the total size in bytes for this volume
virtual TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="")
Add a TGeoNode to the list of nodes.
Bool_t OptimizeVoxels()
Perform an extensive sampling to find which type of voxelization is most efficient.
void Browse(TBrowser *b) override
How to browse a volume.
void SetCurrentPoint(Double_t x, Double_t y, Double_t z)
Set the current tracking point.
void Paint(Option_t *option="") override
paint volume
void SetVisOnly(Bool_t flag=kTRUE) override
Set visibility for leaves.
TGeoManager * fGeoManager
Definition TGeoVolume.h:51
TH2F * LegoPlot(Int_t ntheta=20, Double_t themin=0., Double_t themax=180., Int_t nphi=60, Double_t phimin=0., Double_t phimax=360., Double_t rmin=0., Double_t rmax=9999999, Option_t *option="")
Generate a lego plot fot the top volume, according to option.
void Draw(Option_t *option="") override
draw top volume according to option
TGeoVoxelFinder * fVoxels
Definition TGeoVolume.h:50
TGeoMaterial * GetMaterial() const
Definition TGeoVolume.h:174
virtual Bool_t IsVolumeMulti() const
Definition TGeoVolume.h:110
TGeoExtension * GrabUserExtension() const
Get a copy of the user extension pointer.
@ kVolumeSelected
Definition TGeoVolume.h:73
@ kVolumeImportNodes
Definition TGeoVolume.h:76
Int_t CountNodes(Int_t nlevels=1000, Int_t option=0)
Count total number of subnodes starting from this volume, nlevels down.
void GrabFocus()
Move perspective view focus to this volume.
void UnmarkSaved()
Reset SavePrimitive bits.
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute mouse actions on this volume.
virtual TGeoVolume * CloneVolume() const
Clone this volume.
void SetFinder(TGeoPatternFinder *finder)
Definition TGeoVolume.h:244
Int_t GetNdaughters() const
Definition TGeoVolume.h:362
Bool_t IsValid() const
Definition TGeoVolume.h:154
void Grab()
Definition TGeoVolume.h:136
void CheckGeometry(Int_t nrays=1, Double_t startx=0, Double_t starty=0, Double_t startz=0) const
Shoot nrays with random directions from starting point (startx, starty, startz) in the reference fram...
void SelectVolume(Bool_t clear=kFALSE)
Select this volume as matching an arbitrary criteria.
const char * GetPointerName() const
Provide a pointer name containing uid.
static TClass * Class()
TObjArray * GetNodes()
Definition TGeoVolume.h:169
void ClearShape()
Clear the shape of this volume from the list held by the current manager.
void SetFWExtension(TGeoExtension *ext)
Connect framework defined extension to the volume.
void VisibleDaughters(Bool_t vis=kTRUE)
set visibility for daughters
void FindOverlaps() const
loop all nodes marked as overlaps and find overlapping brothers
virtual void AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="")
Add a TGeoNode to the list of nodes.
TGeoNode * GetNode(const char *name) const
get the pointer to a daughter node
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
compute the closest distance of approach from point px,py to this volume
void RandomPoints(Int_t npoints=1000000, Option_t *option="")
Draw random points in the bounding box of this volume.
void CheckShapes()
check for negative parameters in shapes.
void SetNtotal(Int_t ntotal)
Definition TGeoVolume.h:246
Bool_t GetOptimalVoxels() const
Returns true if cylindrical voxelization is optimal.
TGeoNode * ReplaceNode(TGeoNode *nodeorig, TGeoShape *newshape=nullptr, TGeoMatrix *newpos=nullptr, TGeoMedium *newmed=nullptr)
Replace an existing daughter with a new volume having the same name but possibly a new shape,...
void InvisibleAll(Bool_t flag=kTRUE)
Make volume and each of it daughters (in)visible.
Bool_t IsVisibleDaughters() const
Definition TGeoVolume.h:156
TString fOption
just a hook for now
Definition TGeoVolume.h:54
Int_t GetIndex(const TGeoNode *node) const
get index number for a given daughter
void SetNodes(TObjArray *nodes)
Definition TGeoVolume.h:223
TGeoPatternFinder * GetFinder() const
Definition TGeoVolume.h:177
void PrintVoxels() const
Print the voxels for this volume.
TGeoExtension * fUserExtension
Definition TGeoVolume.h:59
virtual void SetMedium(TGeoMedium *medium)
Definition TGeoVolume.h:242
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
void SetAttVisibility(Bool_t vis)
Definition TGeoVolume.h:233
~TGeoVolume() override
Destructor.
void SetShape(const TGeoShape *shape)
set the shape associated with this volume
static TGeoMedium * DummyMedium()
TObject * fField
pointer to TGeoManager owning this volume
Definition TGeoVolume.h:53
void SetLineColor(Color_t lcolor) override
Set the line color.
Int_t GetNumber() const
Definition TGeoVolume.h:184
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
void CleanAll()
Clean data of the volume.
Bool_t IsTopVolume() const
True if this is the top volume of the geometry.
TGeoMedium * fMedium
Definition TGeoVolume.h:47
TGeoShape * GetShape() const
Definition TGeoVolume.h:190
void InspectMaterial() const
Inspect the material for this volume.
void PrintNodes() const
print nodes
static TGeoMedium * fgDummyMedium
Definition TGeoVolume.h:48
void RegisterYourself(Option_t *option="")
Register the volume and all materials/media/matrices/shapes to the manager.
virtual TGeoVolume * Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed=0, Option_t *option="")
Division a la G3.
Bool_t IsRaytracing() const
Check if the painter is currently ray-tracing the content of this volume.
void SaveAs(const char *filename="", Option_t *option="") const override
Save geometry having this as top volume as a C++ macro.
TGeoShape * fShape
Definition TGeoVolume.h:46
void SetField(TObject *field)
Definition TGeoVolume.h:231
static TGeoVolume * Import(const char *filename, const char *name="", Option_t *option="")
Import a volume from a file.
Bool_t IsStyleDefault() const
check if the visibility and attributes are the default ones
Char_t fTransparency
Definition TGeoVolume.h:58
static void CreateDummyMedium()
Create a dummy medium.
TGeoExtension * fFWExtension
Transient user-defined extension to volumes.
Definition TGeoVolume.h:60
void SetAsTopVolume()
Set this volume as the TOP one (the whole geometry starts from here)
Bool_t IsVisLeaves() const
Definition TGeoVolume.h:158
Option_t * GetOption() const override
Definition TGeoVolume.h:187
TObject * GetField() const
Definition TGeoVolume.h:176
TGeoPatternFinder * fFinder
dummy medium
Definition TGeoVolume.h:49
Int_t Export(const char *filename, const char *name="", Option_t *option="")
Export this volume to a file.
virtual void DrawOnly(Option_t *option="")
draw only this volume
void SetLineStyle(Style_t lstyle) override
Set the line style.
void SetOption(const char *option)
Set the current options (none implemented)
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.
TGeoVolume * MakeReflectedVolume(const char *newname="") const
Make a copy of this volume which is reflected with respect to XY plane.
TObjArray * fNodes
Definition TGeoVolume.h:45
virtual Bool_t IsVisible() const
Definition TGeoVolume.h:155
Int_t GetNtotal() const
Definition TGeoVolume.h:171
void SetVisLeaves(Bool_t flag=kTRUE) override
Set visibility for leaves.
void InspectShape() const
Definition TGeoVolume.h:195
Bool_t IsFolder() const override
Return TRUE if volume contains nodes.
TGeoNode * FindNode(const char *name) const
search a daughter inside the list of nodes
void CheckOverlaps(Double_t ovlp=0.1, Option_t *option="") const
Overlap checking tool.
void SetOverlappingCandidate(Bool_t flag)
Definition TGeoVolume.h:228
Bool_t IsOverlappingCandidate() const
Definition TGeoVolume.h:148
Int_t fRefCount
Definition TGeoVolume.h:57
void Streamer(TBuffer &) override
Stream an object of class TGeoVolume.
void CheckShape(Int_t testNo, Int_t nsamples=10000, Option_t *option="")
Tests for checking the shape navigation algorithms. See TGeoShape::CheckShape()
Finder class handling voxels.
Bool_t IsInvalid() const
void Print(Option_t *option="") const override
Print the voxels.
void SetNeedRebuild(Bool_t flag=kTRUE)
virtual void Voxelize(Option_t *option="")
Voxelize attached volume according to option If the volume is an assembly, make sure the bbox is comp...
virtual void FindOverlaps(Int_t inode) const
create the list of nodes for which the bboxes overlap with inode's bbox
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3062
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:295
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
virtual const char * GetClassName() const
Definition TKey.h:75
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:758
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:81
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition TMap.h:40
void Add(TObject *obj) override
This function may not be used (but we need to provide it since it is a pure virtual in TCollection).
Definition TMap.cxx:54
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition TMap.cxx:236
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
void AddAt(TObject *obj, Int_t idx) override
Add object at position ids.
void Clear(Option_t *option="") override
Remove all objects from the array.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
virtual void Compress()
Remove empty slots from array.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * Remove(TObject *obj) override
Remove object from array.
TObject * RemoveAt(Int_t idx) override
Remove object at index idx.
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:962
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition TObject.cxx:751
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:880
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:976
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1004
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:791
void ResetBit(UInt_t f)
Definition TObject.h:200
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:950
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
const char * Data() const
Definition TString.h:376
Ssiz_t Capacity() const
Definition TString.h:364
Bool_t IsNull() const
Definition TString.h:414
TString & Remove(Ssiz_t pos)
Definition TString.h:685
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Abstract class for geometry painters.
virtual void SetTopVolume(TGeoVolume *vol)=0
virtual void ModifiedPad(Bool_t update=kFALSE) const =0
virtual TGeoVolume * GetTopVolume() const =0
virtual void DrawVolume(TGeoVolume *vol, Option_t *option="")=0
virtual void GrabFocus(Int_t nfr=0, Double_t dlong=0, Double_t dlat=0, Double_t dpsi=0)=0
virtual void CheckOverlaps(const TGeoVolume *vol, Double_t ovlp=0.1, Option_t *option="") const =0
virtual Int_t DistanceToPrimitiveVol(TGeoVolume *vol, Int_t px, Int_t py)=0
void Paint(Option_t *option="") override=0
This method must be overridden if a class wants to paint itself.
virtual Bool_t TestVoxels(TGeoVolume *vol)=0
virtual TGeoVolume * GetDrawnVolume() const =0
virtual const char * GetVolumeInfo(const TGeoVolume *volume, Int_t px, Int_t py) const =0
virtual void ExecuteVolumeEvent(TGeoVolume *volume, Int_t event, Int_t px, Int_t py)=0
virtual void CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const =0
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
ThreadData_t()
index of next node to be entered