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{
1483 fUserExtension = nullptr;
1484 if (ext)
1485 fUserExtension = ext->Grab();
1486 if (tmp)
1487 tmp->Release();
1488}
1489
1490////////////////////////////////////////////////////////////////////////////////
1491/// Connect framework defined extension to the volume. The volume "grabs" a copy,
1492/// so the original object can be released by the producer. Release the previously
1493/// connected extension if any.
1494///
1495/// NOTE: This interface is intended for the use by TGeo and the users should
1496/// NOT connect extensions using this method
1497
1499{
1501 fFWExtension = nullptr;
1502 if (ext)
1503 fFWExtension = ext->Grab();
1504 if (tmp)
1505 tmp->Release();
1506}
1507
1508////////////////////////////////////////////////////////////////////////////////
1509/// Get a copy of the user extension pointer. The user must call Release() on
1510/// the copy pointer once this pointer is not needed anymore (equivalent to
1511/// delete() after calling new())
1512
1514{
1515 if (fUserExtension)
1516 return fUserExtension->Grab();
1517 return nullptr;
1518}
1519
1520////////////////////////////////////////////////////////////////////////////////
1521/// Get a copy of the framework extension pointer. The user must call Release() on
1522/// the copy pointer once this pointer is not needed anymore (equivalent to
1523/// delete() after calling new())
1524
1526{
1527 if (fFWExtension)
1528 return fFWExtension->Grab();
1529 return nullptr;
1530}
1531
1532////////////////////////////////////////////////////////////////////////////////
1533/// Save a primitive as a C++ statement(s) on output stream "out".
1534
1535void TGeoVolume::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1536{
1537 Int_t i, icopy;
1538 Int_t nd = GetNdaughters();
1539 TGeoVolume *dvol;
1540 TGeoNode *dnode;
1541 TGeoMatrix *matrix;
1542
1543 // check if we need to save shape/volume
1544 Bool_t mustDraw = kFALSE;
1545 if (fGeoManager->GetGeomPainter()->GetTopVolume() == this)
1546 mustDraw = kTRUE;
1547 if (!option[0]) {
1549 out << " new TGeoManager(\"" << fGeoManager->GetName() << "\", \"" << fGeoManager->GetTitle() << "\");"
1550 << std::endl
1551 << std::endl;
1552 // if (mustDraw) out << " Bool_t mustDraw = kTRUE;" << std::endl;
1553 // else out << " Bool_t mustDraw = kFALSE;" << std::endl;
1554 out << " Double_t dx, dy, dz;" << std::endl;
1555 out << " Double_t dx1, dx2, dy1, dy2;" << std::endl;
1556 out << " Double_t vert[20], par[20];" << std::endl;
1557 out << " Double_t theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2;" << std::endl;
1558 out << " Double_t twist;" << std::endl;
1559 out << " Double_t origin[3];" << std::endl;
1560 out << " Double_t rmin, rmax, rmin1, rmax1, rmin2, rmax2;" << std::endl;
1561 out << " Double_t r, rlo, rhi;" << std::endl;
1562 out << " Double_t a, b;" << std::endl;
1563 out << " Double_t point[3], norm[3];" << std::endl;
1564 out << " Double_t rin, stin, rout, stout;" << std::endl;
1565 out << " Double_t thx, phx, thy, phy, thz, phz;" << std::endl;
1566 out << " Double_t alpha, theta1, theta2, phi1, phi2, dphi;" << std::endl;
1567 out << " Double_t tr[3], rot[9];" << std::endl;
1568 out << " Double_t z, density, radl, absl, w;" << std::endl;
1569 out << " Double_t lx, ly, lz, tx, ty, tz;" << std::endl;
1570 out << " Double_t xvert[50], yvert[50];" << std::endl;
1571 out << " Double_t zsect, x0, y0, scale0;" << std::endl;
1572 out << " Int_t nel, numed, nz, nedges, nvert;" << std::endl;
1573 out << " TGeoBoolNode *pBoolNode = nullptr;" << std::endl << std::endl;
1574 // first save materials/media
1575 out << " // MATERIALS, MIXTURES AND TRACKING MEDIA" << std::endl;
1576 SavePrimitive(out, "m");
1577 // then, save matrices
1578 out << std::endl << " // TRANSFORMATION MATRICES" << std::endl;
1579 SavePrimitive(out, "x");
1580 // save this volume and shape
1581 SavePrimitive(out, "s");
1582 out << std::endl << " // SET TOP VOLUME OF GEOMETRY" << std::endl;
1583 out << " gGeoManager->SetTopVolume(" << GetPointerName() << ");" << std::endl;
1584 // save daughters
1585 out << std::endl << " // SHAPES, VOLUMES AND GEOMETRICAL HIERARCHY" << std::endl;
1586 SavePrimitive(out, "d");
1587 out << std::endl << " // CLOSE GEOMETRY" << std::endl;
1588 out << " gGeoManager->CloseGeometry();" << std::endl;
1589 if (mustDraw) {
1590 if (!IsRaytracing())
1591 out << " gGeoManager->GetTopVolume()->Draw();" << std::endl;
1592 else
1593 out << " gGeoManager->GetTopVolume()->Raytrace();" << std::endl;
1594 }
1595 return;
1596 }
1597 // check if we need to save shape/volume
1598 if (!strcmp(option, "s")) {
1599 // create the shape for this volume
1601 return;
1602 if (!IsAssembly()) {
1604 out << " // Volume: " << GetName() << std::endl;
1605 out << " TGeoVolume *" << GetPointerName() << " = new TGeoVolume(\"" << GetName() << "\","
1606 << fShape->GetPointerName();
1607 if (fMedium)
1608 out << ", " << fMedium->GetPointerName();
1609 out << ");" << std::endl;
1610 } else {
1611 out << " // Assembly: " << GetName() << std::endl;
1612 out << " " << GetPointerName() << " = new TGeoVolumeAssembly(\"" << GetName() << "\""
1613 << ");" << std::endl;
1614 }
1615 SaveLineAttributes(out, GetPointerName(), 1, 1, 1);
1616 if (!IsVisible() && !IsAssembly())
1617 out << " " << GetPointerName() << "->SetVisibility(kFALSE);" << std::endl;
1618 if (!IsVisibleDaughters())
1619 out << " " << GetPointerName() << "->VisibleDaughters(kFALSE);" << std::endl;
1620 if (IsVisContainers())
1621 out << " " << GetPointerName() << "->SetVisContainers(kTRUE);" << std::endl;
1622 if (IsVisLeaves())
1623 out << " " << GetPointerName() << "->SetVisLeaves(kTRUE);" << std::endl;
1625 }
1626 // check if we need to save the media
1627 if (!strcmp(option, "m")) {
1628 if (fMedium)
1630 for (i = 0; i < nd; i++) {
1631 dvol = GetNode(i)->GetVolume();
1632 dvol->SavePrimitive(out, option);
1633 }
1634 return;
1635 }
1636 // check if we need to save the matrices
1637 if (!strcmp(option, "x")) {
1638 if (fFinder) {
1639 dvol = GetNode(0)->GetVolume();
1640 dvol->SavePrimitive(out, option);
1641 return;
1642 }
1643 for (i = 0; i < nd; i++) {
1644 dnode = GetNode(i);
1645 matrix = dnode->GetMatrix();
1646 if (!matrix->IsIdentity())
1647 matrix->SavePrimitive(out, option);
1648 dnode->GetVolume()->SavePrimitive(out, option);
1649 }
1650 return;
1651 }
1652 // check if we need to save volume daughters
1653 if (!strcmp(option, "d")) {
1654 if (!nd)
1655 return;
1657 return;
1659 if (fFinder) {
1660 // volume divided: generate volume->Divide()
1661 dnode = GetNode(0);
1662 dvol = dnode->GetVolume();
1663 out << " TGeoVolume *" << dvol->GetPointerName() << " = ";
1664 out << GetPointerName() << "->Divide(\"" << dvol->GetName() << "\", ";
1666 if (fMedium != dvol->GetMedium())
1667 out << ", " << dvol->GetMedium()->GetId();
1668 out << ");" << std::endl;
1669 dvol->SavePrimitive(out, "d");
1670 return;
1671 }
1672 for (i = 0; i < nd; i++) {
1673 dnode = GetNode(i);
1674 dvol = dnode->GetVolume();
1675 dvol->SavePrimitive(out, "s");
1676 matrix = dnode->GetMatrix();
1677 icopy = dnode->GetNumber();
1678 // generate AddNode()
1679 out << " " << GetPointerName() << "->AddNode";
1680 if (dnode->IsOverlapping())
1681 out << "Overlap";
1682 out << "(" << dvol->GetPointerName() << ", " << icopy;
1683 if (!matrix->IsIdentity())
1684 out << ", " << matrix->GetPointerName();
1685 out << ");" << std::endl;
1686 }
1687 // Recursive loop to daughters
1688 for (i = 0; i < nd; i++) {
1689 dnode = GetNode(i);
1690 dvol = dnode->GetVolume();
1691 dvol->SavePrimitive(out, "d");
1692 }
1693 }
1694}
1695
1696////////////////////////////////////////////////////////////////////////////////
1697/// Reset SavePrimitive bits.
1698
1700{
1703 if (fShape)
1705}
1706
1707////////////////////////////////////////////////////////////////////////////////
1708/// Execute mouse actions on this volume.
1709
1711{
1713 if (!painter)
1714 return;
1715 painter->ExecuteVolumeEvent(this, event, px, py);
1716}
1717
1718////////////////////////////////////////////////////////////////////////////////
1719/// search a daughter inside the list of nodes
1720
1722{
1723 return ((TGeoNode *)fNodes->FindObject(name));
1724}
1725
1726////////////////////////////////////////////////////////////////////////////////
1727/// Get the index of a daughter within check_list by providing the node pointer.
1728
1729Int_t TGeoVolume::GetNodeIndex(const TGeoNode *node, Int_t *check_list, Int_t ncheck) const
1730{
1731 TGeoNode *current = nullptr;
1732 for (Int_t i = 0; i < ncheck; i++) {
1733 current = (TGeoNode *)fNodes->At(check_list[i]);
1734 if (current == node)
1735 return check_list[i];
1736 }
1737 return -1;
1738}
1739
1740////////////////////////////////////////////////////////////////////////////////
1741/// get index number for a given daughter
1742
1744{
1745 TGeoNode *current = nullptr;
1746 Int_t nd = GetNdaughters();
1747 if (!nd)
1748 return -1;
1749 for (Int_t i = 0; i < nd; i++) {
1750 current = (TGeoNode *)fNodes->At(i);
1751 if (current == node)
1752 return i;
1753 }
1754 return -1;
1755}
1756
1757////////////////////////////////////////////////////////////////////////////////
1758/// Get volume info for the browser.
1759
1761{
1762 TGeoVolume *vol = (TGeoVolume *)this;
1764 if (!painter)
1765 return nullptr;
1766 return (char *)painter->GetVolumeInfo(vol, px, py);
1767}
1768
1769////////////////////////////////////////////////////////////////////////////////
1770/// Returns true if cylindrical voxelization is optimal.
1771
1773{
1774 Int_t nd = GetNdaughters();
1775 if (!nd)
1776 return kFALSE;
1777 Int_t id;
1778 Int_t ncyl = 0;
1779 TGeoNode *node;
1780 for (id = 0; id < nd; id++) {
1781 node = (TGeoNode *)fNodes->At(id);
1782 ncyl += node->GetOptimalVoxels();
1783 }
1784 if (ncyl > (nd / 2))
1785 return kTRUE;
1786 return kFALSE;
1787}
1788
1789////////////////////////////////////////////////////////////////////////////////
1790/// Provide a pointer name containing uid.
1791
1793{
1794 static TString name;
1795 name.Form("p%s_%zx", GetName(), (size_t)this);
1796 return name.Data();
1797}
1798
1799////////////////////////////////////////////////////////////////////////////////
1800/// Getter for optimization structure.
1801
1803{
1804 if (fVoxels && !fVoxels->IsInvalid())
1805 return fVoxels;
1806 return nullptr;
1807}
1808
1809////////////////////////////////////////////////////////////////////////////////
1810/// Move perspective view focus to this volume
1811
1813{
1815 if (painter)
1816 painter->GrabFocus();
1817}
1818
1819////////////////////////////////////////////////////////////////////////////////
1820/// Returns true if the volume is an assembly or a scaled assembly.
1821
1823{
1824 return fShape->IsAssembly();
1825}
1826
1827////////////////////////////////////////////////////////////////////////////////
1828/// Clone this volume.
1829/// build a volume with same name, shape and medium
1830
1832{
1833 TGeoVolume *vol = new TGeoVolume(GetName(), fShape, fMedium);
1834 Int_t i;
1835 // copy volume attributes
1836 vol->SetTitle(GetTitle());
1837 vol->SetLineColor(GetLineColor());
1838 vol->SetLineStyle(GetLineStyle());
1839 vol->SetLineWidth(GetLineWidth());
1840 vol->SetFillColor(GetFillColor());
1841 vol->SetFillStyle(GetFillStyle());
1842 // copy other attributes
1843 Int_t nbits = 8 * sizeof(UInt_t);
1844 for (i = 0; i < nbits; i++)
1845 vol->SetAttBit(1 << i, TGeoAtt::TestAttBit(1 << i));
1846 for (i = 14; i < 24; i++)
1847 vol->SetBit(1 << i, TestBit(1 << i));
1848
1849 // copy field
1850 vol->SetField(fField);
1851 // Set bits
1852 for (i = 0; i < nbits; i++)
1853 vol->SetBit(1 << i, TObject::TestBit(1 << i));
1854 vol->SetBit(kVolumeClone);
1855 // copy nodes
1856 // CloneNodesAndConnect(vol);
1857 vol->MakeCopyNodes(this);
1858 // if volume is divided, copy finder
1859 vol->SetFinder(fFinder);
1860 // copy voxels
1861 TGeoVoxelFinder *voxels = nullptr;
1862 if (fVoxels) {
1863 voxels = new TGeoVoxelFinder(vol);
1864 vol->SetVoxelFinder(voxels);
1865 }
1866 // copy option, uid
1867 vol->SetOption(fOption);
1868 vol->SetNumber(fNumber);
1869 vol->SetNtotal(fNtotal);
1870 // copy extensions
1874 return vol;
1875}
1876
1877////////////////////////////////////////////////////////////////////////////////
1878/// Clone the array of nodes.
1879
1881{
1882 if (!fNodes)
1883 return;
1884 TGeoNode *node;
1885 Int_t nd = fNodes->GetEntriesFast();
1886 if (!nd)
1887 return;
1888 // create new list of nodes
1889 TObjArray *list = new TObjArray(nd);
1890 // attach it to new volume
1891 newmother->SetNodes(list);
1892 // ((TObject*)newmother)->SetBit(kVolumeImportNodes);
1893 for (Int_t i = 0; i < nd; i++) {
1894 // create copies of nodes and add them to list
1895 node = GetNode(i)->MakeCopyNode();
1896 if (!node) {
1897 Fatal("CloneNodesAndConnect", "cannot make copy node");
1898 return;
1899 }
1900 node->SetMotherVolume(newmother);
1901 list->Add(node);
1902 }
1903}
1904
1905////////////////////////////////////////////////////////////////////////////////
1906/// make a new list of nodes and copy all nodes of other volume inside
1907
1909{
1910 Int_t nd = other->GetNdaughters();
1911 if (!nd)
1912 return;
1913 if (fNodes) {
1915 fNodes->Delete();
1916 delete fNodes;
1917 }
1918 fNodes = new TObjArray();
1919 for (Int_t i = 0; i < nd; i++)
1920 fNodes->Add(other->GetNode(i));
1922}
1923
1924////////////////////////////////////////////////////////////////////////////////
1925/// make a copy of this volume
1926/// build a volume with same name, shape and medium
1927
1929{
1930 TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
1931 // copy volume attributes
1932 vol->SetVisibility(IsVisible());
1933 vol->SetLineColor(GetLineColor());
1934 vol->SetLineStyle(GetLineStyle());
1935 vol->SetLineWidth(GetLineWidth());
1936 vol->SetFillColor(GetFillColor());
1937 vol->SetFillStyle(GetFillStyle());
1938 // copy field
1939 vol->SetField(fField);
1940 // if divided, copy division object
1941 if (fFinder) {
1942 // Error("MakeCopyVolume", "volume %s divided", GetName());
1943 vol->SetFinder(fFinder);
1944 }
1945 // Copy extensions
1949 // ((TObject*)vol)->SetBit(kVolumeImportNodes);
1950 ((TObject *)vol)->SetBit(kVolumeClone);
1952 return vol;
1953}
1954
1955////////////////////////////////////////////////////////////////////////////////
1956/// Make a copy of this volume which is reflected with respect to XY plane.
1957
1959{
1960 static TMap map(100);
1961 if (!fGeoManager->IsClosed()) {
1962 Error("MakeReflectedVolume", "Geometry must be closed.");
1963 return nullptr;
1964 }
1965 TGeoVolume *vol = (TGeoVolume *)map.GetValue(this);
1966 if (vol) {
1967 if (newname && newname[0])
1968 vol->SetName(newname);
1969 return vol;
1970 }
1971 // printf("Making reflection for volume: %s\n", GetName());
1972 vol = CloneVolume();
1973 if (!vol) {
1974 Fatal("MakeReflectedVolume", "Cannot clone volume %s\n", GetName());
1975 return nullptr;
1976 }
1977 map.Add((TObject *)this, vol);
1978 if (newname && newname[0])
1979 vol->SetName(newname);
1980 delete vol->GetNodes();
1981 vol->SetNodes(nullptr);
1984 // The volume is now properly cloned, but with the same shape.
1985 // Reflect the shape (if any) and connect it.
1986 if (fShape) {
1987 TGeoShape *reflected_shape =
1989 vol->SetShape(reflected_shape);
1990 }
1991 // Reflect the daughters.
1992 Int_t nd = vol->GetNdaughters();
1993 if (!nd)
1994 return vol;
1995 TGeoNodeMatrix *node;
1996 TGeoMatrix *local, *local_cloned;
1997 TGeoVolume *new_vol;
1998 if (!vol->GetFinder()) {
1999 for (Int_t i = 0; i < nd; i++) {
2000 node = (TGeoNodeMatrix *)vol->GetNode(i);
2001 local = node->GetMatrix();
2002 // printf("%s before\n", node->GetName());
2003 // local->Print();
2004 Bool_t reflected = local->IsReflection();
2005 local_cloned = new TGeoCombiTrans(*local);
2006 local_cloned->RegisterYourself();
2007 node->SetMatrix(local_cloned);
2008 if (!reflected) {
2009 // We need to reflect only the translation and propagate to daughters.
2010 // H' = Sz * H * Sz
2011 local_cloned->ReflectZ(kTRUE);
2012 local_cloned->ReflectZ(kFALSE);
2013 // printf("%s after\n", node->GetName());
2014 // node->GetMatrix()->Print();
2015 new_vol = node->GetVolume()->MakeReflectedVolume();
2016 node->SetVolume(new_vol);
2017 continue;
2018 }
2019 // The next daughter is already reflected, so reflect on Z everything and stop
2020 local_cloned->ReflectZ(kTRUE); // rot + tr
2021 // printf("%s already reflected... After:\n", node->GetName());
2022 // node->GetMatrix()->Print();
2023 }
2024 if (vol->GetVoxels())
2025 vol->GetVoxels()->Voxelize();
2026 return vol;
2027 }
2028 // Volume is divided, so we have to reflect the division.
2029 // printf(" ... divided %s\n", fFinder->ClassName());
2030 TGeoPatternFinder *new_finder = fFinder->MakeCopy(kTRUE);
2031 if (!new_finder) {
2032 Fatal("MakeReflectedVolume", "Could not copy finder for volume %s", GetName());
2033 return nullptr;
2034 }
2035 new_finder->SetVolume(vol);
2036 vol->SetFinder(new_finder);
2037 TGeoNodeOffset *nodeoff;
2038 new_vol = nullptr;
2039 for (Int_t i = 0; i < nd; i++) {
2040 nodeoff = (TGeoNodeOffset *)vol->GetNode(i);
2041 nodeoff->SetFinder(new_finder);
2042 new_vol = nodeoff->GetVolume()->MakeReflectedVolume();
2043 nodeoff->SetVolume(new_vol);
2044 }
2045 return vol;
2046}
2047
2048////////////////////////////////////////////////////////////////////////////////
2049/// Set this volume as the TOP one (the whole geometry starts from here)
2050
2052{
2054}
2055
2056////////////////////////////////////////////////////////////////////////////////
2057/// Set the current tracking point.
2058
2060{
2062}
2063
2064////////////////////////////////////////////////////////////////////////////////
2065/// set the shape associated with this volume
2066
2068{
2069 if (!shape) {
2070 Error("SetShape", "No shape");
2071 return;
2072 }
2073 fShape = (TGeoShape *)shape;
2074}
2075
2076////////////////////////////////////////////////////////////////////////////////
2077/// sort nodes by decreasing volume of the bounding box. ONLY nodes comes first,
2078/// then overlapping nodes and finally division nodes.
2079
2081{
2082 if (!Valid()) {
2083 Error("SortNodes", "Bounding box not valid");
2084 return;
2085 }
2086 Int_t nd = GetNdaughters();
2087 // printf("volume : %s, nd=%i\n", GetName(), nd);
2088 if (!nd)
2089 return;
2090 if (fFinder)
2091 return;
2092 // printf("Nodes for %s\n", GetName());
2093 Int_t id = 0;
2094 TGeoNode *node = nullptr;
2095 TObjArray *nodes = new TObjArray(nd);
2096 Int_t inode = 0;
2097 // first put ONLY's
2098 for (id = 0; id < nd; id++) {
2099 node = GetNode(id);
2100 if (node->InheritsFrom(TGeoNodeOffset::Class()) || node->IsOverlapping())
2101 continue;
2102 nodes->Add(node);
2103 // printf("inode %i ONLY\n", inode);
2104 inode++;
2105 }
2106 // second put overlapping nodes
2107 for (id = 0; id < nd; id++) {
2108 node = GetNode(id);
2109 if (node->InheritsFrom(TGeoNodeOffset::Class()) || (!node->IsOverlapping()))
2110 continue;
2111 nodes->Add(node);
2112 // printf("inode %i MANY\n", inode);
2113 inode++;
2114 }
2115 // third put the divided nodes
2116 if (fFinder) {
2117 fFinder->SetDivIndex(inode);
2118 for (id = 0; id < nd; id++) {
2119 node = GetNode(id);
2120 if (!node->InheritsFrom(TGeoNodeOffset::Class()))
2121 continue;
2122 nodes->Add(node);
2123 // printf("inode %i DIV\n", inode);
2124 inode++;
2125 }
2126 }
2127 if (inode != nd)
2128 printf(" volume %s : number of nodes does not match!!!\n", GetName());
2129 delete fNodes;
2130 fNodes = nodes;
2131}
2132
2133////////////////////////////////////////////////////////////////////////////////
2134/// Stream an object of class TGeoVolume.
2135
2137{
2138 if (R__b.IsReading()) {
2139 R__b.ReadClassBuffer(TGeoVolume::Class(), this);
2140 if (fVoxels && fVoxels->IsInvalid())
2141 Voxelize("");
2142 } else {
2143 if (!fVoxels) {
2144 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2145 } else {
2147 TGeoVoxelFinder *voxels = fVoxels;
2148 fVoxels = nullptr;
2149 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2150 fVoxels = voxels;
2151 } else {
2152 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2153 }
2154 }
2155 }
2156}
2157
2158////////////////////////////////////////////////////////////////////////////////
2159/// Set the current options (none implemented)
2160
2162{
2163 fOption = option;
2164}
2165
2166////////////////////////////////////////////////////////////////////////////////
2167/// Set the line color.
2168
2170{
2171 TAttLine::SetLineColor(lcolor);
2172}
2173
2174////////////////////////////////////////////////////////////////////////////////
2175/// Set the line style.
2176
2178{
2179 TAttLine::SetLineStyle(lstyle);
2180}
2181
2182////////////////////////////////////////////////////////////////////////////////
2183/// Set the line width.
2184
2186{
2187 TAttLine::SetLineWidth(lwidth);
2188}
2189
2190////////////////////////////////////////////////////////////////////////////////
2191/// get the pointer to a daughter node
2192
2194{
2195 if (!fNodes)
2196 return nullptr;
2197 TGeoNode *node = (TGeoNode *)fNodes->FindObject(name);
2198 return node;
2199}
2200
2201////////////////////////////////////////////////////////////////////////////////
2202/// get the total size in bytes for this volume
2203
2205{
2206 Int_t count = 28 + 2 + 6 + 4 + 0; // TNamed+TGeoAtt+TAttLine+TAttFill+TAtt3D
2207 count += fName.Capacity() + fTitle.Capacity(); // name+title
2208 count += 7 * sizeof(char *); // fShape + fMedium + fFinder + fField + fNodes + 2 extensions
2209 count += fOption.Capacity(); // fOption
2210 if (fShape)
2211 count += fShape->GetByteCount();
2212 if (fFinder)
2213 count += fFinder->GetByteCount();
2214 if (fNodes) {
2215 count += 32 + 4 * fNodes->GetEntries(); // TObjArray
2216 TIter next(fNodes);
2217 TGeoNode *node;
2218 while ((node = (TGeoNode *)next()))
2219 count += node->GetByteCount();
2220 }
2221 return count;
2222}
2223
2224////////////////////////////////////////////////////////////////////////////////
2225/// loop all nodes marked as overlaps and find overlapping brothers
2226
2228{
2229 if (!Valid()) {
2230 Error("FindOverlaps", "Bounding box not valid");
2231 return;
2232 }
2233 if (!fVoxels)
2234 return;
2235 Int_t nd = GetNdaughters();
2236 if (!nd)
2237 return;
2238 TGeoNode *node = nullptr;
2239 Int_t inode = 0;
2240 for (inode = 0; inode < nd; inode++) {
2241 node = GetNode(inode);
2242 if (!node->IsOverlapping())
2243 continue;
2244 fVoxels->FindOverlaps(inode);
2245 }
2246}
2247
2248////////////////////////////////////////////////////////////////////////////////
2249/// Remove an existing daughter.
2250
2252{
2253 if (!fNodes || !fNodes->GetEntriesFast())
2254 return;
2255 if (!fNodes->Remove(node))
2256 return;
2257 fNodes->Compress();
2258 if (fVoxels)
2260 if (IsAssembly())
2262}
2263
2264////////////////////////////////////////////////////////////////////////////////
2265/// Replace an existing daughter with a new volume having the same name but
2266/// possibly a new shape, position or medium. Not allowed for positioned assemblies.
2267/// For division cells, the new shape/matrix are ignored.
2268
2270{
2271 Int_t ind = GetIndex(nodeorig);
2272 if (ind < 0)
2273 return nullptr;
2274 TGeoVolume *oldvol = nodeorig->GetVolume();
2275 if (oldvol->IsAssembly()) {
2276 Error("ReplaceNode", "Cannot replace node %s since it is an assembly", nodeorig->GetName());
2277 return nullptr;
2278 }
2279 TGeoShape *shape = oldvol->GetShape();
2280 if (newshape && !nodeorig->IsOffset())
2281 shape = newshape;
2282 TGeoMedium *med = oldvol->GetMedium();
2283 if (newmed)
2284 med = newmed;
2285 // Make a new volume
2286 TGeoVolume *vol = new TGeoVolume(oldvol->GetName(), shape, med);
2287 // copy volume attributes
2288 vol->SetVisibility(oldvol->IsVisible());
2289 vol->SetLineColor(oldvol->GetLineColor());
2290 vol->SetLineStyle(oldvol->GetLineStyle());
2291 vol->SetLineWidth(oldvol->GetLineWidth());
2292 vol->SetFillColor(oldvol->GetFillColor());
2293 vol->SetFillStyle(oldvol->GetFillStyle());
2294 // copy field
2295 vol->SetField(oldvol->GetField());
2296 // Make a copy of the node
2297 TGeoNode *newnode = nodeorig->MakeCopyNode();
2298 if (!newnode) {
2299 Fatal("ReplaceNode", "Cannot make copy node for %s", nodeorig->GetName());
2300 return nullptr;
2301 }
2302 // Change the volume for the new node
2303 newnode->SetVolume(vol);
2304 // Replace the matrix
2305 if (newpos && !nodeorig->IsOffset()) {
2306 TGeoNodeMatrix *nodemat = (TGeoNodeMatrix *)newnode;
2307 nodemat->SetMatrix(newpos);
2308 }
2309 // Replace nodeorig with new one
2310 fNodes->RemoveAt(ind);
2311 fNodes->AddAt(newnode, ind);
2312 if (fVoxels)
2314 if (IsAssembly())
2316 return newnode;
2317}
2318
2319////////////////////////////////////////////////////////////////////////////////
2320/// Select this volume as matching an arbitrary criteria. The volume is added to
2321/// a static list and the flag TGeoVolume::kVolumeSelected is set. All flags need
2322/// to be reset at the end by calling the method with CLEAR=true. This will also clear
2323/// the list.
2324
2326{
2327 static TObjArray array(256);
2328 static Int_t len = 0;
2329 Int_t i;
2330 TObject *vol;
2331 if (clear) {
2332 for (i = 0; i < len; i++) {
2333 vol = array.At(i);
2335 }
2336 array.Clear();
2337 len = 0;
2338 return;
2339 }
2341 array.AddAtAndExpand(this, len++);
2342}
2343
2344////////////////////////////////////////////////////////////////////////////////
2345/// set visibility of this volume
2346
2348{
2350 if (fGeoManager->IsClosed())
2353 TSeqCollection *brlist = gROOT->GetListOfBrowsers();
2354 TIter next(brlist);
2355 TBrowser *browser = nullptr;
2356 while ((browser = (TBrowser *)next())) {
2357 browser->CheckObjectItem(this, vis);
2358 browser->Refresh();
2359 }
2360}
2361
2362////////////////////////////////////////////////////////////////////////////////
2363/// Set visibility for containers.
2364
2366{
2368 if (fGeoManager && fGeoManager->IsClosed()) {
2369 if (flag)
2371 else
2373 }
2374}
2375
2376////////////////////////////////////////////////////////////////////////////////
2377/// Set visibility for leaves.
2378
2380{
2382 if (fGeoManager && fGeoManager->IsClosed()) {
2383 if (flag)
2385 else
2387 }
2388}
2389
2390////////////////////////////////////////////////////////////////////////////////
2391/// Set visibility for leaves.
2392
2394{
2395 if (IsAssembly())
2396 return;
2397 TGeoAtt::SetVisOnly(flag);
2398 if (fGeoManager && fGeoManager->IsClosed()) {
2399 if (flag)
2401 else
2403 }
2404}
2405
2406////////////////////////////////////////////////////////////////////////////////
2407/// Check if the shape of this volume is valid.
2408
2410{
2411 return fShape->IsValidBox();
2412}
2413
2414////////////////////////////////////////////////////////////////////////////////
2415/// Find a daughter node having VOL as volume and fill TGeoManager::fHMatrix
2416/// with its global matrix.
2417
2419{
2420 if (vol == this)
2421 return kTRUE;
2422 Int_t nd = GetNdaughters();
2423 if (!nd)
2424 return kFALSE;
2425 TGeoHMatrix *global = fGeoManager->GetHMatrix();
2426 if (!global)
2427 return kFALSE;
2428 TGeoNode *dnode;
2429 TGeoVolume *dvol;
2430 TGeoMatrix *local;
2431 Int_t i;
2432 for (i = 0; i < nd; i++) {
2433 dnode = GetNode(i);
2434 dvol = dnode->GetVolume();
2435 if (dvol == vol) {
2436 local = dnode->GetMatrix();
2437 global->MultiplyLeft(local);
2438 return kTRUE;
2439 }
2440 }
2441 for (i = 0; i < nd; i++) {
2442 dnode = GetNode(i);
2443 dvol = dnode->GetVolume();
2444 if (dvol->FindMatrixOfDaughterVolume(vol))
2445 return kTRUE;
2446 }
2447 return kFALSE;
2448}
2449
2450////////////////////////////////////////////////////////////////////////////////
2451/// set visibility for daughters
2452
2454{
2455 SetVisDaughters(vis);
2456 if (fGeoManager->IsClosed())
2459}
2460
2461////////////////////////////////////////////////////////////////////////////////
2462/// build the voxels for this volume
2463
2465{
2466 if (!Valid()) {
2467 Error("Voxelize", "Bounding box not valid");
2468 return;
2469 }
2470 // do not voxelize divided volumes
2471 if (fFinder)
2472 return;
2473 // or final leaves
2474 Int_t nd = GetNdaughters();
2475 if (!nd)
2476 return;
2477 // If this is an assembly, re-compute bounding box
2478 if (IsAssembly())
2480 // delete old voxelization if any
2481 if (fVoxels) {
2483 delete fVoxels;
2484 fVoxels = nullptr;
2485 }
2486 // Create the voxels structure
2487 fVoxels = new TGeoVoxelFinder(this);
2489 if (fVoxels) {
2490 if (fVoxels->IsInvalid()) {
2491 delete fVoxels;
2492 fVoxels = nullptr;
2493 }
2494 }
2495}
2496
2497////////////////////////////////////////////////////////////////////////////////
2498/// Estimate the weight of a volume (in kg) with SIGMA(M)/M better than PRECISION.
2499/// Option can contain : v - verbose, a - analytical (default)
2500
2502{
2504 if (top != this)
2506 else
2507 top = nullptr;
2508 Double_t weight = fGeoManager->Weight(precision, option);
2509 if (top)
2511 return weight;
2512}
2513
2514////////////////////////////////////////////////////////////////////////////////
2515/// Analytical computation of the weight.
2516
2518{
2519 Double_t capacity = Capacity();
2520 Double_t weight = 0.0;
2521 Int_t i;
2522 Int_t nd = GetNdaughters();
2523 TGeoVolume *daughter;
2524 for (i = 0; i < nd; i++) {
2525 daughter = GetNode(i)->GetVolume();
2526 weight += daughter->WeightA();
2527 capacity -= daughter->Capacity();
2528 }
2529 Double_t density = 0.0;
2530 if (!IsAssembly()) {
2531 if (fMedium)
2532 density = fMedium->GetMaterial()->GetDensity();
2533 if (density < 0.01)
2534 density = 0.0; // do not weight gases
2535 }
2536 weight += 0.001 * capacity * density; //[kg]
2537 return weight;
2538}
2539
2541
2542////////////////////////////////////////////////////////////////////////////////
2543/// dummy constructor
2544
2546{
2547 fVolumes = nullptr;
2548 fDivision = nullptr;
2549 fNumed = 0;
2550 fNdiv = 0;
2551 fAxis = 0;
2552 fStart = 0;
2553 fStep = 0;
2554 fAttSet = kFALSE;
2556}
2557
2558////////////////////////////////////////////////////////////////////////////////
2559/// default constructor
2560
2562{
2563 fVolumes = new TObjArray();
2564 fDivision = nullptr;
2565 fNumed = 0;
2566 fNdiv = 0;
2567 fAxis = 0;
2568 fStart = 0;
2569 fStep = 0;
2570 fAttSet = kFALSE;
2572 SetName(name);
2573 SetMedium(med);
2574 fGeoManager->AddVolume(this);
2575 // printf("--- volume multi %s created\n", name);
2576}
2577
2578////////////////////////////////////////////////////////////////////////////////
2579/// Destructor
2580
2582{
2583 if (fVolumes)
2584 delete fVolumes;
2585}
2586
2587////////////////////////////////////////////////////////////////////////////////
2588/// Add a volume with valid shape to the list of volumes. Copy all existing nodes
2589/// to this volume
2590
2592{
2593 Int_t idx = fVolumes->GetEntriesFast();
2594 fVolumes->AddAtAndExpand(vol, idx);
2595 vol->SetUniqueID(idx + 1);
2596 TGeoVolumeMulti *div;
2597 TGeoVolume *cell;
2598 if (fDivision) {
2600 if (!div) {
2601 Fatal("AddVolume", "Cannot divide volume %s", vol->GetName());
2602 return;
2603 }
2604 for (Int_t i = 0; i < div->GetNvolumes(); i++) {
2605 cell = div->GetVolume(i);
2606 fDivision->AddVolume(cell);
2607 }
2608 }
2609 if (fNodes) {
2610 Int_t nd = fNodes->GetEntriesFast();
2611 for (Int_t id = 0; id < nd; id++) {
2612 TGeoNode *node = (TGeoNode *)fNodes->At(id);
2613 Bool_t many = node->IsOverlapping();
2614 if (many)
2615 vol->AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2616 else
2617 vol->AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2618 }
2619 }
2620 // vol->MakeCopyNodes(this);
2621}
2622
2623////////////////////////////////////////////////////////////////////////////////
2624/// Add a new node to the list of nodes. This is the usual method for adding
2625/// daughters inside the container volume.
2626
2628{
2629 TGeoNode *n = TGeoVolume::AddNode(vol, copy_no, mat, option);
2630 Int_t nvolumes = fVolumes->GetEntriesFast();
2631 TGeoVolume *volume = nullptr;
2632 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2633 volume = GetVolume(ivo);
2634 volume->SetLineColor(GetLineColor());
2635 volume->SetLineStyle(GetLineStyle());
2636 volume->SetLineWidth(GetLineWidth());
2637 volume->SetVisibility(IsVisible());
2638 volume->AddNode(vol, copy_no, mat, option);
2639 }
2640 // printf("--- vmulti %s : node %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2641 return n;
2642}
2643
2644////////////////////////////////////////////////////////////////////////////////
2645/// Add a new node to the list of nodes, This node is possibly overlapping with other
2646/// daughters of the volume or extruding the volume.
2647
2649{
2650 TGeoVolume::AddNodeOverlap(vol, copy_no, mat, option);
2651 Int_t nvolumes = fVolumes->GetEntriesFast();
2652 TGeoVolume *volume = nullptr;
2653 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2654 volume = GetVolume(ivo);
2655 volume->SetLineColor(GetLineColor());
2656 volume->SetLineStyle(GetLineStyle());
2657 volume->SetLineWidth(GetLineWidth());
2658 volume->SetVisibility(IsVisible());
2659 volume->AddNodeOverlap(vol, copy_no, mat, option);
2660 }
2661 // printf("--- vmulti %s : node ovlp %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2662}
2663
2664////////////////////////////////////////////////////////////////////////////////
2665/// Returns the last shape.
2666
2668{
2670 if (!vol)
2671 return nullptr;
2672 return vol->GetShape();
2673}
2674
2675////////////////////////////////////////////////////////////////////////////////
2676/// division of multiple volumes
2677
2678TGeoVolume *TGeoVolumeMulti::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step,
2679 Int_t numed, const char *option)
2680{
2681 if (fDivision) {
2682 Error("Divide", "volume %s already divided", GetName());
2683 return nullptr;
2684 }
2685 Int_t nvolumes = fVolumes->GetEntriesFast();
2686 TGeoMedium *medium = fMedium;
2687 if (numed) {
2688 medium = fGeoManager->GetMedium(numed);
2689 if (!medium) {
2690 Error("Divide", "Invalid medium number %d for division volume %s", numed, divname);
2691 medium = fMedium;
2692 }
2693 }
2694 if (!nvolumes) {
2695 // this is a virtual volume
2696 fDivision = new TGeoVolumeMulti(divname, medium);
2697 fNumed = medium->GetId();
2698 fOption = option;
2699 fAxis = iaxis;
2700 fNdiv = ndiv;
2701 fStart = start;
2702 fStep = step;
2703 // nothing else to do at this stage
2704 return fDivision;
2705 }
2706 TGeoVolume *vol = nullptr;
2707 fDivision = new TGeoVolumeMulti(divname, medium);
2708 if (medium)
2709 fNumed = medium->GetId();
2710 fOption = option;
2711 fAxis = iaxis;
2712 fNdiv = ndiv;
2713 fStart = start;
2714 fStep = step;
2715 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2716 vol = GetVolume(ivo);
2717 vol->SetLineColor(GetLineColor());
2718 vol->SetLineStyle(GetLineStyle());
2719 vol->SetLineWidth(GetLineWidth());
2720 vol->SetVisibility(IsVisible());
2721 fDivision->AddVolume(vol->Divide(divname, iaxis, ndiv, start, step, numed, option));
2722 }
2723 // printf("--- volume multi %s (%i volumes) divided\n", GetName(), nvolumes);
2724 if (numed)
2725 fDivision->SetMedium(medium);
2726 return fDivision;
2727}
2728
2729////////////////////////////////////////////////////////////////////////////////
2730/// Make a copy of this volume
2731/// build a volume with same name, shape and medium
2732
2734{
2735 TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
2736 Int_t i = 0;
2737 // copy volume attributes
2738 vol->SetVisibility(IsVisible());
2739 vol->SetLineColor(GetLineColor());
2740 vol->SetLineStyle(GetLineStyle());
2741 vol->SetLineWidth(GetLineWidth());
2742 vol->SetFillColor(GetFillColor());
2743 vol->SetFillStyle(GetFillStyle());
2744 // copy field
2745 vol->SetField(fField);
2746 // Copy extensions
2749 // if divided, copy division object
2750 // if (fFinder) {
2751 // Error("MakeCopyVolume", "volume %s divided", GetName());
2752 // vol->SetFinder(fFinder);
2753 // }
2754 if (fDivision) {
2755 TGeoVolume *cell;
2756 TGeoVolumeMulti *div =
2758 if (!div) {
2759 Fatal("MakeCopyVolume", "Cannot divide volume %s", vol->GetName());
2760 return nullptr;
2761 }
2762 for (i = 0; i < div->GetNvolumes(); i++) {
2763 cell = div->GetVolume(i);
2764 fDivision->AddVolume(cell);
2765 }
2766 }
2767
2768 if (!fNodes)
2769 return vol;
2770 TGeoNode *node;
2771 Int_t nd = fNodes->GetEntriesFast();
2772 if (!nd)
2773 return vol;
2774 // create new list of nodes
2775 TObjArray *list = new TObjArray();
2776 // attach it to new volume
2777 vol->SetNodes(list);
2778 ((TObject *)vol)->SetBit(kVolumeImportNodes);
2779 for (i = 0; i < nd; i++) {
2780 // create copies of nodes and add them to list
2781 node = GetNode(i)->MakeCopyNode();
2782 if (!node) {
2783 Fatal("MakeCopyNode", "cannot make copy node for daughter %d of %s", i, GetName());
2784 return nullptr;
2785 }
2786 node->SetMotherVolume(vol);
2787 list->Add(node);
2788 }
2789 return vol;
2790}
2791
2792////////////////////////////////////////////////////////////////////////////////
2793/// Set the line color for all components.
2794
2796{
2798 Int_t nvolumes = fVolumes->GetEntriesFast();
2799 TGeoVolume *vol = nullptr;
2800 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2801 vol = GetVolume(ivo);
2802 vol->SetLineColor(lcolor);
2803 }
2804}
2805
2806////////////////////////////////////////////////////////////////////////////////
2807/// Set the line style for all components.
2808
2810{
2812 Int_t nvolumes = fVolumes->GetEntriesFast();
2813 TGeoVolume *vol = nullptr;
2814 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2815 vol = GetVolume(ivo);
2816 vol->SetLineStyle(lstyle);
2817 }
2818}
2819
2820////////////////////////////////////////////////////////////////////////////////
2821/// Set the line width for all components.
2822
2824{
2826 Int_t nvolumes = fVolumes->GetEntriesFast();
2827 TGeoVolume *vol = nullptr;
2828 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2829 vol = GetVolume(ivo);
2830 vol->SetLineWidth(lwidth);
2831 }
2832}
2833
2834////////////////////////////////////////////////////////////////////////////////
2835/// Set medium for a multiple volume.
2836
2838{
2840 Int_t nvolumes = fVolumes->GetEntriesFast();
2841 TGeoVolume *vol = nullptr;
2842 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2843 vol = GetVolume(ivo);
2844 vol->SetMedium(med);
2845 }
2846}
2847
2848////////////////////////////////////////////////////////////////////////////////
2849/// Set visibility for all components.
2850
2852{
2854 Int_t nvolumes = fVolumes->GetEntriesFast();
2855 TGeoVolume *vol = nullptr;
2856 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2857 vol = GetVolume(ivo);
2858 vol->SetVisibility(vis);
2859 }
2860}
2861
2863
2864////////////////////////////////////////////////////////////////////////////////
2865/// Constructor.
2866
2868
2869////////////////////////////////////////////////////////////////////////////////
2870/// Destructor.
2871
2873
2874////////////////////////////////////////////////////////////////////////////////
2875
2877{
2879 return *fThreadData[tid];
2880}
2881
2882////////////////////////////////////////////////////////////////////////////////
2883
2885{
2886 std::lock_guard<std::mutex> guard(fMutex);
2888 std::vector<ThreadData_t *>::iterator i = fThreadData.begin();
2889 while (i != fThreadData.end()) {
2890 delete *i;
2891 ++i;
2892 }
2893 fThreadData.clear();
2894 fThreadSize = 0;
2895}
2896
2897////////////////////////////////////////////////////////////////////////////////
2898
2900{
2901 std::lock_guard<std::mutex> guard(fMutex);
2902 // Create assembly thread data here
2903 fThreadData.resize(nthreads);
2904 fThreadSize = nthreads;
2905 for (Int_t tid = 0; tid < nthreads; tid++) {
2906 if (fThreadData[tid] == nullptr) {
2907 fThreadData[tid] = new ThreadData_t;
2908 }
2909 }
2911}
2912
2913////////////////////////////////////////////////////////////////////////////////
2914
2916{
2917 return fThreadData[TGeoManager::ThreadId()]->fCurrent;
2918}
2919
2920////////////////////////////////////////////////////////////////////////////////
2921
2923{
2924 return fThreadData[TGeoManager::ThreadId()]->fNext;
2925}
2926
2927////////////////////////////////////////////////////////////////////////////////
2928
2930{
2932}
2933
2934////////////////////////////////////////////////////////////////////////////////
2935
2937{
2939}
2940
2941////////////////////////////////////////////////////////////////////////////////
2942/// Default constructor
2943
2945{
2946 fThreadSize = 0;
2948}
2949
2950////////////////////////////////////////////////////////////////////////////////
2951/// Constructor. Just the name has to be provided. Assemblies does not have their own
2952/// shape or medium.
2953
2955{
2956 fName = name;
2957 fName = fName.Strip();
2958 fShape = new TGeoShapeAssembly(this);
2959 if (fGeoManager)
2960 fNumber = fGeoManager->AddVolume(this);
2961 fThreadSize = 0;
2963}
2964
2965////////////////////////////////////////////////////////////////////////////////
2966/// Destructor. The assembly is owner of its "shape".
2967
2969{
2971 if (fShape)
2972 delete fShape;
2973}
2974
2975////////////////////////////////////////////////////////////////////////////////
2976/// Add a component to the assembly.
2977
2979{
2980 TGeoNode *node = TGeoVolume::AddNode(vol, copy_no, mat, option);
2981 // ((TGeoShapeAssembly*)fShape)->RecomputeBoxLast();
2982 ((TGeoShapeAssembly *)fShape)->NeedsBBoxRecompute();
2983 return node;
2984}
2985
2986////////////////////////////////////////////////////////////////////////////////
2987/// Add an overlapping node - not allowed for assemblies.
2988
2990{
2991 Warning("AddNodeOverlap",
2992 "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",
2993 vol->GetName(), GetName());
2994 AddNode(vol, copy_no, mat, option);
2995}
2996
2997////////////////////////////////////////////////////////////////////////////////
2998/// Clone this volume.
2999/// build a volume with same name, shape and medium
3000
3002{
3004 Int_t i;
3005 // copy other attributes
3006 Int_t nbits = 8 * sizeof(UInt_t);
3007 for (i = 0; i < nbits; i++)
3008 vol->SetAttBit(1 << i, TGeoAtt::TestAttBit(1 << i));
3009 for (i = 14; i < 24; i++)
3010 vol->SetBit(1 << i, TestBit(1 << i));
3011
3012 // copy field
3013 vol->SetField(fField);
3014 // Set bits
3015 for (i = 0; i < nbits; i++)
3016 vol->SetBit(1 << i, TObject::TestBit(1 << i));
3017 vol->SetBit(kVolumeClone);
3018 // make copy nodes
3019 vol->MakeCopyNodes(this);
3020 // CloneNodesAndConnect(vol);
3021 ((TGeoShapeAssembly *)vol->GetShape())->NeedsBBoxRecompute();
3022 // copy voxels
3023 TGeoVoxelFinder *voxels = nullptr;
3024 if (fVoxels) {
3025 voxels = new TGeoVoxelFinder(vol);
3026 vol->SetVoxelFinder(voxels);
3027 }
3028 // copy option, uid
3029 vol->SetOption(fOption);
3030 vol->SetNumber(fNumber);
3031 vol->SetNtotal(fNtotal);
3032 vol->SetTitle(GetTitle());
3033 // copy extensions
3036 return vol;
3037}
3038
3039////////////////////////////////////////////////////////////////////////////////
3040/// Division makes no sense for assemblies.
3041
3043{
3044 Error("Divide", "Assemblies cannot be divided");
3045 return nullptr;
3046}
3047
3048////////////////////////////////////////////////////////////////////////////////
3049/// Assign to the assembly a collection of identical volumes positioned according
3050/// a predefined pattern. The option can be spaced out or touching depending on the empty
3051/// space between volumes.
3052
3054{
3055 if (fNodes) {
3056 Error("Divide", "Cannot divide assembly %s since it has nodes", GetName());
3057 return nullptr;
3058 }
3059 if (fFinder) {
3060 Error("Divide", "Assembly %s already divided", GetName());
3061 return nullptr;
3062 }
3063 Int_t ncells = pattern->GetNdiv();
3064 if (!ncells || pattern->GetStep() <= 0) {
3065 Error("Divide", "Pattern finder for dividing assembly %s not initialized. Use SetRange() method.", GetName());
3066 return nullptr;
3067 }
3068 fFinder = pattern;
3069 TString opt(option);
3070 opt.ToLower();
3071 if (opt.Contains("spacedout"))
3073 else
3075 // Position volumes
3076 for (Int_t i = 0; i < ncells; i++) {
3077 fFinder->cd(i);
3078 TGeoNodeOffset *node = new TGeoNodeOffset(cell, i, 0.);
3079 node->SetFinder(fFinder);
3080 fNodes->Add(node);
3081 }
3082 return cell;
3083}
3084
3085////////////////////////////////////////////////////////////////////////////////
3086/// Make a clone of volume VOL but which is an assembly.
3087
3089{
3090 if (volorig->IsAssembly() || volorig->IsVolumeMulti())
3091 return nullptr;
3092 Int_t nd = volorig->GetNdaughters();
3093 if (!nd)
3094 return nullptr;
3095 TGeoVolumeAssembly *vol = new TGeoVolumeAssembly(volorig->GetName());
3096 Int_t i;
3097 // copy other attributes
3098 Int_t nbits = 8 * sizeof(UInt_t);
3099 for (i = 0; i < nbits; i++)
3100 vol->SetAttBit(1 << i, volorig->TestAttBit(1 << i));
3101 for (i = 14; i < 24; i++)
3102 vol->SetBit(1 << i, volorig->TestBit(1 << i));
3103
3104 // copy field
3105 vol->SetField(volorig->GetField());
3106 // Set bits
3107 for (i = 0; i < nbits; i++)
3108 vol->SetBit(1 << i, volorig->TestBit(1 << i));
3109 vol->SetBit(kVolumeClone);
3110 // make copy nodes
3111 vol->MakeCopyNodes(volorig);
3112 // volorig->CloneNodesAndConnect(vol);
3113 vol->GetShape()->ComputeBBox();
3114 // copy voxels
3115 TGeoVoxelFinder *voxels = nullptr;
3116 if (volorig->GetVoxels()) {
3117 voxels = new TGeoVoxelFinder(vol);
3118 vol->SetVoxelFinder(voxels);
3119 }
3120 // copy option, uid
3121 vol->SetOption(volorig->GetOption());
3122 vol->SetNumber(volorig->GetNumber());
3123 vol->SetNtotal(volorig->GetNtotal());
3124 return vol;
3125}
#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:82
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:85
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:84
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:382
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:436
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 an on-disk file, usually with extension .root, that stores objects in a file-system-li...
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:4089
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:829
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:3066
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:307
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:759
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:83
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:199
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:213
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:979
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition TObject.cxx:757
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:886
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:786
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:530
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:993
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1021
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:797
void ResetBit(UInt_t f)
Definition TObject.h:198
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:967
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