Logo ROOT   6.16/01
Reference Guide
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 Geometry_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
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 "Riostream.h"
381#include "TString.h"
382#include "TBrowser.h"
383#include "TStyle.h"
384#include "TH2F.h"
385#include "TPad.h"
386#include "TROOT.h"
387#include "TClass.h"
388#include "TEnv.h"
389#include "TMap.h"
390#include "TFile.h"
391#include "TKey.h"
392
393#include "TGeoManager.h"
394#include "TGeoNode.h"
395#include "TGeoMatrix.h"
396#include "TVirtualGeoPainter.h"
397#include "TGeoVolume.h"
398#include "TGeoShapeAssembly.h"
399#include "TGeoScaledShape.h"
400#include "TGeoCompositeShape.h"
401#include "TGeoVoxelFinder.h"
402#include "TGeoExtension.h"
403
405
407
408////////////////////////////////////////////////////////////////////////////////
409/// Create a dummy medium
410
412{
413 if (fgDummyMedium) return;
415 fgDummyMedium->SetName("dummy");
416 TGeoMaterial *dummyMaterial = new TGeoMaterial();
417 dummyMaterial->SetName("dummy");
418 fgDummyMedium->SetMaterial(dummyMaterial);
419}
420
421////////////////////////////////////////////////////////////////////////////////
422
424{
427}
428
429////////////////////////////////////////////////////////////////////////////////
430
432{
433 if (fFinder) fFinder->CreateThreadData(nthreads);
434 if (fShape) fShape->CreateThreadData(nthreads);
435}
436
437////////////////////////////////////////////////////////////////////////////////
438
440{
441 return fgDummyMedium;
442}
443
444////////////////////////////////////////////////////////////////////////////////
445/// dummy constructor
446
448{
449 fNodes = 0;
450 fShape = 0;
451 fMedium = 0;
452 fFinder = 0;
453 fVoxels = 0;
455 fField = 0;
456 fOption = "";
457 fNumber = 0;
458 fNtotal = 0;
459 fRefCount = 0;
460 fUserExtension = 0;
461 fFWExtension = 0;
463}
464
465////////////////////////////////////////////////////////////////////////////////
466/// default constructor
467
468TGeoVolume::TGeoVolume(const char *name, const TGeoShape *shape, const TGeoMedium *med)
469 :TNamed(name, "")
470{
471 fName = fName.Strip();
472 fNodes = 0;
473 fShape = (TGeoShape*)shape;
474 if (fShape) {
476 Warning("Ctor", "volume %s has invalid shape", name);
477 }
478 if (!fShape->IsValid()) {
479 Fatal("ctor", "Shape of volume %s invalid. Aborting!", fName.Data());
480 }
481 }
482 fMedium = (TGeoMedium*)med;
484 fFinder = 0;
485 fVoxels = 0;
487 fField = 0;
488 fOption = "";
489 fNumber = 0;
490 fNtotal = 0;
491 fRefCount = 0;
492 fUserExtension = 0;
493 fFWExtension = 0;
496}
497
498////////////////////////////////////////////////////////////////////////////////
499///copy constructor
500
502 TNamed(gv),
503 TGeoAtt(gv),
504 TAttLine(gv),
505 TAttFill(gv),
506 TAtt3D(gv),
507 fNodes(gv.fNodes),
508 fShape(gv.fShape),
509 fMedium(gv.fMedium),
510 fFinder(gv.fFinder),
511 fVoxels(gv.fVoxels),
512 fGeoManager(gv.fGeoManager),
513 fField(gv.fField),
514 fOption(gv.fOption),
515 fNumber(gv.fNumber),
516 fNtotal(gv.fNtotal),
517 fRefCount(0),
518 fUserExtension(gv.fUserExtension->Grab()),
519 fFWExtension(gv.fFWExtension->Grab())
520{
521}
522
523////////////////////////////////////////////////////////////////////////////////
524///assignment operator
525
527{
528 if(this!=&gv) {
534 fNodes=gv.fNodes;
535 fShape=gv.fShape;
536 fMedium=gv.fMedium;
537 fFinder=gv.fFinder;
538 fVoxels=gv.fVoxels;
540 fField=gv.fField;
541 fOption=gv.fOption;
542 fNumber=gv.fNumber;
543 fRefCount = 0;
544 fNtotal=gv.fNtotal;
547 }
548 return *this;
549}
550
551////////////////////////////////////////////////////////////////////////////////
552/// Destructor
553
555{
556 if (fNodes) {
558 fNodes->Delete();
559 }
560 delete fNodes;
561 }
563 if (fVoxels) delete fVoxels;
566}
567
568////////////////////////////////////////////////////////////////////////////////
569/// How to browse a volume
570
572{
573 if (!b) return;
574
575// if (!GetNdaughters()) b->Add(this, GetName(), IsVisible());
576 TGeoVolume *daughter;
577 TString title;
578 for (Int_t i=0; i<GetNdaughters(); i++) {
579 daughter = GetNode(i)->GetVolume();
580 if(daughter->GetTitle()[0]) {
581 if (daughter->IsAssembly()) title.TString::Format("Assembly with %d daughter(s)",
582 daughter->GetNdaughters());
583 else if (daughter->GetFinder()) {
584 TString s1 = daughter->GetFinder()->ClassName();
585 s1.ReplaceAll("TGeoPattern","");
586 title.TString::Format("Volume having %s shape divided in %d %s slices",
587 daughter->GetShape()->ClassName(),daughter->GetNdaughters(), s1.Data());
588
589 } else title.TString::Format("Volume with %s shape having %d daughter(s)",
590 daughter->GetShape()->ClassName(),daughter->GetNdaughters());
591 daughter->SetTitle(title.Data());
592 }
593 b->Add(daughter, daughter->GetName(), daughter->IsVisible());
594// if (IsVisDaughters())
595// b->AddCheckBox(daughter, daughter->IsVisible());
596// else
597// b->AddCheckBox(daughter, kFALSE);
598 }
599}
600
601////////////////////////////////////////////////////////////////////////////////
602/// Computes the capacity of this [cm^3] as the capacity of its shape.
603/// In case of assemblies, the capacity is computed as the sum of daughter's capacities.
604
606{
607 if (!IsAssembly()) return fShape->Capacity();
608 Double_t capacity = 0.0;
609 Int_t nd = GetNdaughters();
610 Int_t i;
611 for (i=0; i<nd; i++) capacity += GetNode(i)->GetVolume()->Capacity();
612 return capacity;
613}
614
615////////////////////////////////////////////////////////////////////////////////
616/// Shoot nrays with random directions from starting point (startx, starty, startz)
617/// in the reference frame of this volume. Track each ray until exiting geometry, then
618/// shoot backwards from exiting point and compare boundary crossing points.
619
620void TGeoVolume::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
621{
622 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
623 if (old_vol!=this) fGeoManager->SetTopVolume((TGeoVolume*)this);
624 else old_vol=0;
627 painter->CheckGeometry(nrays, startx, starty, startz);
628}
629
630////////////////////////////////////////////////////////////////////////////////
631/// Overlap checking tool. Check for illegal overlaps within a limit OVLP.
632/// Use option="s[number]" to force overlap checking by sampling volume with
633/// [number] points.
634///
635/// Ex:
636/// ~~~ {.cpp}
637/// myVol->CheckOverlaps(0.01, "s10000000"); // shoot 10000000 points
638/// myVol->CheckOverlaps(0.01, "s"); // shoot the default value of 1e6 points
639/// ~~~
640
642{
643 if (!GetNdaughters() || fFinder) return;
644 Bool_t sampling = kFALSE;
645 TString opt(option);
646 opt.ToLower();
647 if (opt.Contains("s")) sampling = kTRUE;
649 if (!sampling) fGeoManager->SetNsegments(80);
652// Info("CheckOverlaps", "=== Checking overlaps for volume %s ===\n", GetName());
653 }
654 painter->CheckOverlaps(this, ovlp, option);
655// if (sampling) return;
659 Int_t novlps = overlaps->GetEntriesFast();
660 TNamed *obj;
662 for (Int_t i=0; i<novlps; i++) {
663 obj = (TNamed*)overlaps->At(i);
664 if (novlps<1000) name = TString::Format("ov%03d", i);
665 else name = TString::Format("ov%06d", i);
666 obj->SetName(name);
667 }
668 if (novlps) Info("CheckOverlaps", "Number of illegal overlaps/extrusions for volume %s: %d\n", GetName(), novlps);
669 }
670}
671
672////////////////////////////////////////////////////////////////////////////////
673/// Tests for checking the shape navigation algorithms. See TGeoShape::CheckShape()
674
675void TGeoVolume::CheckShape(Int_t testNo, Int_t nsamples, Option_t *option)
676{
677 fShape->CheckShape(testNo,nsamples,option);
678}
679
680////////////////////////////////////////////////////////////////////////////////
681/// Clean data of the volume.
682
684{
685 ClearNodes();
686 ClearShape();
687}
688
689////////////////////////////////////////////////////////////////////////////////
690/// Clear the shape of this volume from the list held by the current manager.
691
693{
695}
696
697////////////////////////////////////////////////////////////////////////////////
698/// check for negative parameters in shapes.
699
701{
702 if (fShape->IsRunTimeShape()) {
703 Error("CheckShapes", "volume %s has run-time shape", GetName());
704 InspectShape();
705 return;
706 }
707 if (!fNodes) return;
709 TGeoNode *node = 0;
710 TGeoNode *new_node;
711 const TGeoShape *shape = 0;
712 TGeoVolume *old_vol;
713 for (Int_t i=0; i<nd; i++) {
714 node=(TGeoNode*)fNodes->At(i);
715 // check if node has name
716 if (!node->GetName()[0]) printf("Daughter %i of volume %s - NO NAME!!!\n",
717 i, GetName());
718 old_vol = node->GetVolume();
719 shape = old_vol->GetShape();
720 if (shape->IsRunTimeShape()) {
721// printf(" Node %s/%s has shape with negative parameters. \n",
722// GetName(), node->GetName());
723// old_vol->InspectShape();
724 // make a copy of the node
725 new_node = node->MakeCopyNode();
726 if (!new_node) {
727 Fatal("CheckShapes", "Cannot make copy node for %s", node->GetName());
728 return;
729 }
730 TGeoShape *new_shape = shape->GetMakeRuntimeShape(fShape, node->GetMatrix());
731 if (!new_shape) {
732 Error("CheckShapes","cannot resolve runtime shape for volume %s/%s\n",
733 GetName(),old_vol->GetName());
734 continue;
735 }
736 TGeoVolume *new_volume = old_vol->MakeCopyVolume(new_shape);
737// printf(" new volume %s shape params :\n", new_volume->GetName());
738// new_volume->InspectShape();
739 new_node->SetVolume(new_volume);
740 // decouple the old node and put the new one instead
741 fNodes->AddAt(new_node, i);
742// new_volume->CheckShapes();
743 }
744 }
745}
746
747////////////////////////////////////////////////////////////////////////////////
748/// Count total number of subnodes starting from this volume, nlevels down
749/// - option = 0 (default) - count only once per volume
750/// - option = 1 - count every time
751/// - option = 2 - count volumes on visible branches
752/// - option = 3 - return maximum level counted already with option = 0
753
755{
756 static Int_t maxlevel = 0;
757 static Int_t nlev = 0;
758
759 if (option<0 || option>3) option = 0;
760 Int_t visopt = 0;
761 Int_t nd = GetNdaughters();
762 Bool_t last = (!nlevels || !nd)?kTRUE:kFALSE;
763 switch (option) {
764 case 0:
765 if (fNtotal) return fNtotal;
766 case 1:
767 fNtotal = 1;
768 break;
769 case 2:
770 visopt = fGeoManager->GetVisOption();
771 if (!IsVisDaughters()) last = kTRUE;
772 switch (visopt) {
774 fNtotal = (IsVisible())?1:0;
775 break;
777 fNtotal = (IsVisible() && last)?1:0;
778 }
779 if (!IsVisibleDaughters()) return fNtotal;
780 break;
781 case 3:
782 return maxlevel;
783 }
784 if (last) return fNtotal;
785 if (gGeoManager->GetTopVolume() == this) {
786 maxlevel=0;
787 nlev = 0;
788 }
789 if (nlev>maxlevel) maxlevel = nlev;
790 TGeoNode *node;
791 TGeoVolume *vol;
792 nlev++;
793 for (Int_t i=0; i<nd; i++) {
794 node = GetNode(i);
795 vol = node->GetVolume();
796 fNtotal += vol->CountNodes(nlevels-1, option);
797 }
798 nlev--;
799 return fNtotal;
800}
801
802////////////////////////////////////////////////////////////////////////////////
803/// Return TRUE if volume and all daughters are invisible.
804
806{
807 if (IsVisible()) return kFALSE;
808 Int_t nd = GetNdaughters();
809 for (Int_t i=0; i<nd; i++) if (GetNode(i)->GetVolume()->IsVisible()) return kFALSE;
810 return kTRUE;
811}
812
813////////////////////////////////////////////////////////////////////////////////
814/// Make volume and each of it daughters (in)visible.
815
817{
818 SetAttVisibility(!flag);
819 Int_t nd = GetNdaughters();
820 TObjArray *list = new TObjArray(nd+1);
821 list->Add(this);
822 TGeoVolume *vol;
823 for (Int_t i=0; i<nd; i++) {
824 vol = GetNode(i)->GetVolume();
825 vol->SetAttVisibility(!flag);
826 list->Add(vol);
827 }
828 TIter next(gROOT->GetListOfBrowsers());
829 TBrowser *browser = 0;
830 while ((browser=(TBrowser*)next())) {
831 for (Int_t i=0; i<nd+1; i++) {
832 vol = (TGeoVolume*)list->At(i);
833 browser->CheckObjectItem(vol, !flag);
834 }
835 browser->Refresh();
836 }
837 delete list;
839}
840
841////////////////////////////////////////////////////////////////////////////////
842/// Return TRUE if volume contains nodes
843
845{
846 return kTRUE;
847}
848
849////////////////////////////////////////////////////////////////////////////////
850/// check if the visibility and attributes are the default ones
851
853{
854 if (!IsVisible()) return kFALSE;
855 if (GetLineColor() != gStyle->GetLineColor()) return kFALSE;
856 if (GetLineStyle() != gStyle->GetLineStyle()) return kFALSE;
857 if (GetLineWidth() != gStyle->GetLineWidth()) return kFALSE;
858 return kTRUE;
859}
860
861////////////////////////////////////////////////////////////////////////////////
862/// True if this is the top volume of the geometry
863
865{
866 if (fGeoManager->GetTopVolume() == this) return kTRUE;
867 return kFALSE;
868}
869
870////////////////////////////////////////////////////////////////////////////////
871/// Check if the painter is currently ray-tracing the content of this volume.
872
874{
875 return TGeoAtt::IsVisRaytrace();
876}
877
878////////////////////////////////////////////////////////////////////////////////
879/// Inspect the material for this volume.
880
882{
883 GetMaterial()->Print();
884}
885
886////////////////////////////////////////////////////////////////////////////////
887/// Import a volume from a file.
888
889TGeoVolume *TGeoVolume::Import(const char *filename, const char *name, Option_t * /*option*/)
890{
891 if (!gGeoManager) gGeoManager = new TGeoManager("geometry","");
892 if (!filename) return 0;
893 TGeoVolume *volume = 0;
894 if (strstr(filename,".gdml")) {
895 // import from a gdml file
896 } else {
897 // import from a root file
899 TFile *f = TFile::Open(filename);
900 if (!f || f->IsZombie()) {
901 printf("Error: TGeoVolume::Import : Cannot open file %s\n", filename);
902 return 0;
903 }
904 if (name && name[0]) {
905 volume = (TGeoVolume*)f->Get(name);
906 } else {
907 TIter next(f->GetListOfKeys());
908 TKey *key;
909 while ((key = (TKey*)next())) {
910 if (strcmp(key->GetClassName(),"TGeoVolume") != 0) continue;
911 volume = (TGeoVolume*)key->ReadObj();
912 break;
913 }
914 }
915 delete f;
916 }
917 if (!volume) return NULL;
918 volume->RegisterYourself();
919 return volume;
920}
921
922////////////////////////////////////////////////////////////////////////////////
923/// Export this volume to a file.
924///
925/// - Case 1: root file or root/xml file
926/// if filename end with ".root". The key will be named name
927/// if filename end with ".xml" a root/xml file is produced.
928///
929/// - Case 2: C++ script
930/// if filename end with ".C"
931///
932/// - Case 3: gdml file
933/// if filename end with ".gdml"
934///
935/// NOTE that to use this option, the PYTHONPATH must be defined like
936/// export PYTHONPATH=$ROOTSYS/lib:$ROOTSYS/gdml
937///
938
939Int_t TGeoVolume::Export(const char *filename, const char *name, Option_t *option)
940{
941 TString sfile(filename);
942 if (sfile.Contains(".C")) {
943 //Save volume as a C++ script
944 Info("Export","Exporting volume %s as C++ code", GetName());
945 SaveAs(filename, "");
946 return 1;
947 }
948 if (sfile.Contains(".gdml")) {
949 //Save geometry as a gdml file
950 Info("Export","Exporting %s as gdml code - not implemented yet", GetName());
951 return 0;
952 }
953 if (sfile.Contains(".root") || sfile.Contains(".xml")) {
954 //Save volume in a root file
955 Info("Export","Exporting %s as root file.", GetName());
956 TString opt(option);
957 if (!opt.Length()) opt = "recreate";
958 TFile *f = TFile::Open(filename,opt.Data());
959 if (!f || f->IsZombie()) {
960 Error("Export","Cannot open file");
961 return 0;
962 }
963 TString keyname(name);
964 if (keyname.IsNull()) keyname = GetName();
965 Int_t nbytes = Write(keyname);
966 delete f;
967 return nbytes;
968 }
969 return 0;
970}
971
972////////////////////////////////////////////////////////////////////////////////
973/// Actualize matrix of node indexed <inode>
974
975void TGeoVolume::cd(Int_t inode) const
976{
977 if (fFinder) fFinder->cd(inode-fFinder->GetDivIndex());
978}
979
980////////////////////////////////////////////////////////////////////////////////
981/// Add a TGeoNode to the list of nodes. This is the usual method for adding
982/// daughters inside the container volume.
983
984void TGeoVolume::AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t * /*option*/)
985{
986 TGeoMatrix *matrix = mat;
987 if (matrix==0) matrix = gGeoIdentity;
988 else matrix->RegisterYourself();
989 if (!vol) {
990 Error("AddNode", "Volume is NULL");
991 return;
992 }
993 if (!vol->IsValid()) {
994 Error("AddNode", "Won't add node with invalid shape");
995 printf("### invalid volume was : %s\n", vol->GetName());
996 return;
997 }
998 if (!fNodes) fNodes = new TObjArray();
999
1000 if (fFinder) {
1001 // volume already divided.
1002 Error("AddNode", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
1003 return;
1004 }
1005
1006 TGeoNodeMatrix *node = 0;
1007 node = new TGeoNodeMatrix(vol, matrix);
1008 node->SetMotherVolume(this);
1009 fNodes->Add(node);
1010 TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
1011// if (fNodes->FindObject(name))
1012// Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
1013 node->SetName(name);
1014 node->SetNumber(copy_no);
1015 fRefCount++;
1016 vol->Grab();
1017}
1018
1019////////////////////////////////////////////////////////////////////////////////
1020/// Add a division node to the list of nodes. The method is called by
1021/// TGeoVolume::Divide() for creating the division nodes.
1022
1023void TGeoVolume::AddNodeOffset(TGeoVolume *vol, Int_t copy_no, Double_t offset, Option_t * /*option*/)
1024{
1025 if (!vol) {
1026 Error("AddNodeOffset", "invalid volume");
1027 return;
1028 }
1029 if (!vol->IsValid()) {
1030 Error("AddNode", "Won't add node with invalid shape");
1031 printf("### invalid volume was : %s\n", vol->GetName());
1032 return;
1033 }
1034 if (!fNodes) fNodes = new TObjArray();
1035 TGeoNode *node = new TGeoNodeOffset(vol, copy_no, offset);
1036 node->SetMotherVolume(this);
1037 fNodes->Add(node);
1038 TString name = TString::Format("%s_%d", vol->GetName(), copy_no+1);
1039 node->SetName(name);
1040 node->SetNumber(copy_no+1);
1041 vol->Grab();
1042}
1043
1044////////////////////////////////////////////////////////////////////////////////
1045/// Add a TGeoNode to the list of nodes. This is the usual method for adding
1046/// daughters inside the container volume.
1047
1049{
1050 if (!vol) {
1051 Error("AddNodeOverlap", "Volume is NULL");
1052 return;
1053 }
1054 if (!vol->IsValid()) {
1055 Error("AddNodeOverlap", "Won't add node with invalid shape");
1056 printf("### invalid volume was : %s\n", vol->GetName());
1057 return;
1058 }
1059 if (vol->IsAssembly()) {
1060 Warning("AddNodeOverlap", "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
1061 AddNode(vol, copy_no, mat, option);
1062 return;
1063 }
1064 TGeoMatrix *matrix = mat;
1065 if (matrix==0) matrix = gGeoIdentity;
1066 else matrix->RegisterYourself();
1067 if (!fNodes) fNodes = new TObjArray();
1068
1069 if (fFinder) {
1070 // volume already divided.
1071 Error("AddNodeOverlap", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
1072 return;
1073 }
1074
1075 TGeoNodeMatrix *node = new TGeoNodeMatrix(vol, matrix);
1076 node->SetMotherVolume(this);
1077 fNodes->Add(node);
1078 TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
1079 if (fNodes->FindObject(name))
1080 Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
1081 node->SetName(name);
1082 node->SetNumber(copy_no);
1083 node->SetOverlapping();
1084 if (vol->GetMedium() == fMedium)
1085 node->SetVirtual();
1086 vol->Grab();
1087}
1088
1089////////////////////////////////////////////////////////////////////////////////
1090/// Division a la G3. The volume will be divided along IAXIS (see shape classes), in NDIV
1091/// slices, from START with given STEP. The division volumes will have medium number NUMED.
1092/// If NUMED=0 they will get the medium number of the divided volume (this). If NDIV<=0,
1093/// all range of IAXIS will be divided and the resulting number of divisions will be centered on
1094/// IAXIS. If STEP<=0, the real STEP will be computed as the full range of IAXIS divided by NDIV.
1095/// Options (case insensitive):
1096/// - N - divide all range in NDIV cells (same effect as STEP<=0) (GSDVN in G3)
1097/// - NX - divide range starting with START in NDIV cells (GSDVN2 in G3)
1098/// - S - divide all range with given STEP. NDIV is computed and divisions will be centered
1099/// in full range (same effect as NDIV<=0) (GSDVS, GSDVT in G3)
1100/// - SX - same as DVS, but from START position. (GSDVS2, GSDVT2 in G3)
1101
1102TGeoVolume *TGeoVolume::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, Option_t *option)
1103{
1104 if (fFinder) {
1105 // volume already divided.
1106 Fatal("Divide","volume %s already divided", GetName());
1107 return 0;
1108 }
1109 TString opt(option);
1110 opt.ToLower();
1111 TString stype = fShape->ClassName();
1112 if (!fNodes) fNodes = new TObjArray();
1113 Double_t xlo, xhi, range;
1114 range = fShape->GetAxisRange(iaxis, xlo, xhi);
1115 // for phi divisions correct the range
1116 if (!strcmp(fShape->GetAxisName(iaxis), "PHI")) {
1117 if ((start-xlo)<-1E-3) start+=360.;
1118 if (TGeoShape::IsSameWithinTolerance(range,360)) {
1119 xlo = start;
1120 xhi = start+range;
1121 }
1122 }
1123 if (range <=0) {
1124 InspectShape();
1125 Fatal("Divide", "cannot divide volume %s (%s) on %s axis", GetName(), stype.Data(), fShape->GetAxisName(iaxis));
1126 return 0;
1127 }
1128 if (ndiv<=0 || opt.Contains("s")) {
1129 if (step<=0) {
1130 Fatal("Divide", "invalid division type for volume %s : ndiv=%i, step=%g", GetName(), ndiv, step);
1131 return 0;
1132 }
1133 if (opt.Contains("x")) {
1134 if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
1135 Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
1136 start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1137 return 0;
1138 }
1139 xlo = start;
1140 range = xhi-xlo;
1141 }
1142 ndiv = Int_t((range+0.1*step)/step);
1143 Double_t ddx = range - ndiv*step;
1144 // always center the division in this case
1145 if (ddx>1E-3) Warning("Divide", "division of volume %s on %s axis (ndiv=%d) will be centered in the full range",
1146 GetName(), fShape->GetAxisName(iaxis), ndiv);
1147 start = xlo + 0.5*ddx;
1148 }
1149 if (step<=0 || opt.Contains("n")) {
1150 if (opt.Contains("x")) {
1151 if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
1152 Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
1153 start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1154 return 0;
1155 }
1156 xlo = start;
1157 range = xhi-xlo;
1158 }
1159 step = range/ndiv;
1160 start = xlo;
1161 }
1162
1163 Double_t end = start+ndiv*step;
1164 if (((start-xlo)<-1E-3) || ((end-xhi)>1E-3)) {
1165 Fatal("Divide", "division of volume %s on axis %s exceed range (%g, %g)",
1166 GetName(), fShape->GetAxisName(iaxis), xlo, xhi);
1167 return 0;
1168 }
1169 TGeoVolume *voldiv = fShape->Divide(this, divname, iaxis, ndiv, start, step);
1170 if (numed) {
1171 TGeoMedium *medium = fGeoManager->GetMedium(numed);
1172 if (!medium) {
1173 Fatal("Divide", "invalid medium number %d for division volume %s", numed, divname);
1174 return voldiv;
1175 }
1176 voldiv->SetMedium(medium);
1177 if (medium->GetMaterial()) medium->GetMaterial()->SetUsed();
1178 }
1179 return voldiv;
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// compute the closest distance of approach from point px,py to this volume
1184
1186{
1189 Int_t dist = 9999;
1190 if (!painter) return dist;
1191 dist = painter->DistanceToPrimitiveVol(this, px, py);
1192 return dist;
1193}
1194
1195////////////////////////////////////////////////////////////////////////////////
1196/// draw top volume according to option
1197
1199{
1204 if (!IsVisContainers()) SetVisLeaves();
1205 if (option && option[0] > 0) {
1206 painter->DrawVolume(this, option);
1207 } else {
1208 painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
1209 }
1210}
1211
1212////////////////////////////////////////////////////////////////////////////////
1213/// draw only this volume
1214
1216{
1217 if (IsAssembly()) {
1218 Info("DrawOnly", "Volume assemblies do not support this option.");
1219 return;
1220 }
1222 SetVisOnly();
1225 if (option && option[0] > 0) {
1226 painter->DrawVolume(this, option);
1227 } else {
1228 painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
1229 }
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// Perform an extensive sampling to find which type of voxelization is
1234/// most efficient.
1235
1237{
1238 printf("Optimizing volume %s ...\n", GetName());
1240 return painter->TestVoxels(this);
1241}
1242
1243////////////////////////////////////////////////////////////////////////////////
1244/// Print volume info
1245
1247{
1248 printf("== Volume: %s type %s positioned %d times\n", GetName(), ClassName(), fRefCount);
1249 InspectShape();
1251}
1252
1253////////////////////////////////////////////////////////////////////////////////
1254/// paint volume
1255
1257{
1259 painter->SetTopVolume(this);
1260// painter->Paint(option);
1261 if (option && option[0] > 0) {
1262 painter->Paint(option);
1263 } else {
1264 painter->Paint(gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
1265 }
1266}
1267
1268////////////////////////////////////////////////////////////////////////////////
1269/// Print the voxels for this volume.
1270
1272{
1273 if (fVoxels) fVoxels->Print();
1274}
1275
1276////////////////////////////////////////////////////////////////////////////////
1277/// Recreate the content of the other volume without pointer copying. Voxels are
1278/// ignored and supposed to be created in a later step via Voxelize.
1279
1281{
1282 Int_t nd = other->GetNdaughters();
1283 if (!nd) return;
1284 TGeoPatternFinder *finder = other->GetFinder();
1285 if (finder) {
1286 Int_t iaxis = finder->GetDivAxis();
1287 Int_t ndiv = finder->GetNdiv();
1288 Double_t start = finder->GetStart();
1289 Double_t step = finder->GetStep();
1290 Int_t numed = other->GetNode(0)->GetVolume()->GetMedium()->GetId();
1291 TGeoVolume *voldiv = Divide(other->GetNode(0)->GetVolume()->GetName(), iaxis, ndiv, start, step, numed);
1292 voldiv->ReplayCreation(other->GetNode(0)->GetVolume());
1293 return;
1294 }
1295 for (Int_t i=0; i<nd; i++) {
1296 TGeoNode *node = other->GetNode(i);
1297 if (node->IsOverlapping()) AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1298 else AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1299 }
1300}
1301
1302////////////////////////////////////////////////////////////////////////////////
1303/// print nodes
1304
1306{
1307 Int_t nd = GetNdaughters();
1308 for (Int_t i=0; i<nd; i++) {
1309 printf("%s\n", GetNode(i)->GetName());
1310 cd(i);
1311 GetNode(i)->GetMatrix()->Print();
1312 }
1313}
1314////////////////////////////////////////////////////////////////////////////////
1315/// Generate a lego plot fot the top volume, according to option.
1316
1318 Int_t nphi, Double_t phimin, Double_t phimax,
1319 Double_t rmin, Double_t rmax, Option_t *option)
1320{
1322 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1323 if (old_vol!=this) fGeoManager->SetTopVolume(this);
1324 else old_vol=0;
1325 TH2F *hist = p->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);
1326 hist->Draw("lego1sph");
1327 return hist;
1328}
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// Register the volume and all materials/media/matrices/shapes to the manager.
1332
1334{
1335 if (fGeoManager->GetListOfVolumes()->FindObject(this)) return;
1336 // Register volume
1337 fGeoManager->AddVolume(this);
1338 // Register shape
1340 if (fShape->IsComposite()) {
1342 comp->RegisterYourself();
1343 } else {
1345 }
1346 }
1347 // Register medium/material
1352 }
1353 // Register matrices for nodes.
1354 TGeoMatrix *matrix;
1355 TGeoNode *node;
1356 Int_t nd = GetNdaughters();
1357 Int_t i;
1358 for (i=0; i<nd; i++) {
1359 node = GetNode(i);
1360 matrix = node->GetMatrix();
1361 if (!matrix->IsRegistered()) matrix->RegisterYourself();
1362 else if (!fGeoManager->GetListOfMatrices()->FindObject(matrix)) {
1363 fGeoManager->GetListOfMatrices()->Add(matrix);
1364 }
1365 }
1366 // Call RegisterYourself recursively
1367 for (i=0; i<nd; i++) GetNode(i)->GetVolume()->RegisterYourself(option);
1368}
1369
1370////////////////////////////////////////////////////////////////////////////////
1371/// Draw random points in the bounding box of this volume.
1372
1374{
1376 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1377 if (old_vol!=this) fGeoManager->SetTopVolume(this);
1378 else old_vol=0;
1379 fGeoManager->RandomPoints(this, npoints, option);
1380 if (old_vol) fGeoManager->SetTopVolume(old_vol);
1381}
1382
1383////////////////////////////////////////////////////////////////////////////////
1384/// Random raytracing method.
1385
1386void TGeoVolume::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz, const char *target_vol, Bool_t check_norm)
1387{
1389 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1390 if (old_vol!=this) fGeoManager->SetTopVolume(this);
1391 else old_vol=0;
1392 fGeoManager->RandomRays(nrays, startx, starty, startz, target_vol, check_norm);
1393 if (old_vol) fGeoManager->SetTopVolume(old_vol);
1394}
1395
1396////////////////////////////////////////////////////////////////////////////////
1397/// Draw this volume with current settings and perform raytracing in the pad.
1398
1400{
1404 Bool_t drawn = (painter->GetDrawnVolume()==this)?kTRUE:kFALSE;
1405 if (!drawn) {
1406 painter->DrawVolume(this, "");
1408 painter->ModifiedPad();
1409 return;
1410 }
1412 painter->ModifiedPad();
1413}
1414
1415////////////////////////////////////////////////////////////////////////////////
1416/// Save geometry having this as top volume as a C++ macro.
1417
1418void TGeoVolume::SaveAs(const char *filename, Option_t *option) const
1419{
1420 if (!filename) return;
1421 std::ofstream out;
1422 out.open(filename, std::ios::out);
1423 if (out.bad()) {
1424 Error("SavePrimitive", "Bad file name: %s", filename);
1425 return;
1426 }
1428
1429 TString fname(filename);
1430 Int_t ind = fname.Index(".");
1431 if (ind>0) fname.Remove(ind);
1432 out << "void "<<fname<<"() {" << std::endl;
1433 out << " gSystem->Load(\"libGeom\");" << std::endl;
1435 out << std::setprecision(prec);
1436 ((TGeoVolume*)this)->SavePrimitive(out,option);
1437 out << "}" << std::endl;
1438}
1439
1440////////////////////////////////////////////////////////////////////////////////
1441/// Connect user-defined extension to the volume. The volume "grabs" a copy, so
1442/// the original object can be released by the producer. Release the previously
1443/// connected extension if any.
1444///
1445/// NOTE: This interface is intended for user extensions and is guaranteed not
1446/// to be used by TGeo
1447
1449{
1451 fUserExtension = 0;
1452 if (ext) fUserExtension = ext->Grab();
1453}
1454
1455////////////////////////////////////////////////////////////////////////////////
1456/// Connect framework defined extension to the volume. The volume "grabs" a copy,
1457/// so the original object can be released by the producer. Release the previously
1458/// connected extension if any.
1459///
1460/// NOTE: This interface is intended for the use by TGeo and the users should
1461/// NOT connect extensions using this method
1462
1464{
1466 fFWExtension = 0;
1467 if (ext) fFWExtension = ext->Grab();
1468}
1469
1470////////////////////////////////////////////////////////////////////////////////
1471/// Get a copy of the user extension pointer. The user must call Release() on
1472/// the copy pointer once this pointer is not needed anymore (equivalent to
1473/// delete() after calling new())
1474
1476{
1477 if (fUserExtension) return fUserExtension->Grab();
1478 return 0;
1479}
1480
1481////////////////////////////////////////////////////////////////////////////////
1482/// Get a copy of the framework extension pointer. The user must call Release() on
1483/// the copy pointer once this pointer is not needed anymore (equivalent to
1484/// delete() after calling new())
1485
1487{
1488 if (fFWExtension) return fFWExtension->Grab();
1489 return 0;
1490}
1491
1492////////////////////////////////////////////////////////////////////////////////
1493/// Save a primitive as a C++ statement(s) on output stream "out".
1494
1495void TGeoVolume::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1496{
1497 Int_t i,icopy;
1498 Int_t nd = GetNdaughters();
1499 TGeoVolume *dvol;
1500 TGeoNode *dnode;
1501 TGeoMatrix *matrix;
1502
1503 // check if we need to save shape/volume
1504 Bool_t mustDraw = kFALSE;
1505 if (fGeoManager->GetGeomPainter()->GetTopVolume()==this) mustDraw = kTRUE;
1506 if (!option[0]) {
1508 out << " new TGeoManager(\"" << fGeoManager->GetName() << "\", \"" << fGeoManager->GetTitle() << "\");" << std::endl << std::endl;
1509// if (mustDraw) out << " Bool_t mustDraw = kTRUE;" << std::endl;
1510// else out << " Bool_t mustDraw = kFALSE;" << std::endl;
1511 out << " Double_t dx,dy,dz;" << std::endl;
1512 out << " Double_t dx1, dx2, dy1, dy2;" << std::endl;
1513 out << " Double_t vert[20], par[20];" << std::endl;
1514 out << " Double_t theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2;" << std::endl;
1515 out << " Double_t twist;" << std::endl;
1516 out << " Double_t origin[3];" << std::endl;
1517 out << " Double_t rmin, rmax, rmin1, rmax1, rmin2, rmax2;" << std::endl;
1518 out << " Double_t r, rlo, rhi;" << std::endl;
1519 out << " Double_t phi1, phi2;" << std::endl;
1520 out << " Double_t a,b;" << std::endl;
1521 out << " Double_t point[3], norm[3];" << std::endl;
1522 out << " Double_t rin, stin, rout, stout;" << std::endl;
1523 out << " Double_t thx, phx, thy, phy, thz, phz;" << std::endl;
1524 out << " Double_t alpha, theta1, theta2, phi1, phi2, dphi;" << std::endl;
1525 out << " Double_t tr[3], rot[9];" << std::endl;
1526 out << " Double_t z, density, radl, absl, w;" << std::endl;
1527 out << " Double_t lx,ly,lz,tx,ty,tz;" << std::endl;
1528 out << " Double_t xvert[50], yvert[50];" << std::endl;
1529 out << " Double_t zsect,x0,y0,scale0;" << std::endl;
1530 out << " Int_t nel, numed, nz, nedges, nvert;" << std::endl;
1531 out << " TGeoBoolNode *pBoolNode = 0;" << std::endl << std::endl;
1532 // first save materials/media
1533 out << " // MATERIALS, MIXTURES AND TRACKING MEDIA" << std::endl;
1534 SavePrimitive(out, "m");
1535 // then, save matrices
1536 out << std::endl << " // TRANSFORMATION MATRICES" << std::endl;
1537 SavePrimitive(out, "x");
1538 // save this volume and shape
1539 SavePrimitive(out, "s");
1540 out << std::endl << " // SET TOP VOLUME OF GEOMETRY" << std::endl;
1541 out << " gGeoManager->SetTopVolume(" << GetPointerName() << ");" << std::endl;
1542 // save daughters
1543 out << std::endl << " // SHAPES, VOLUMES AND GEOMETRICAL HIERARCHY" << std::endl;
1544 SavePrimitive(out, "d");
1545 out << std::endl << " // CLOSE GEOMETRY" << std::endl;
1546 out << " gGeoManager->CloseGeometry();" << std::endl;
1547 if (mustDraw) {
1548 if (!IsRaytracing()) out << " gGeoManager->GetTopVolume()->Draw();" << std::endl;
1549 else out << " gGeoManager->GetTopVolume()->Raytrace();" << std::endl;
1550 }
1551 return;
1552 }
1553 // check if we need to save shape/volume
1554 if (!strcmp(option, "s")) {
1555 // create the shape for this volume
1557 if (!IsAssembly()) {
1558 fShape->SavePrimitive(out,option);
1559 out << " // Volume: " << GetName() << std::endl;
1560 if (fMedium) out << " " << GetPointerName() << " = new TGeoVolume(\"" << GetName() << "\"," << fShape->GetPointerName() << ", "<< fMedium->GetPointerName() << ");" << std::endl;
1561 else out << " " << GetPointerName() << " = new TGeoVolume(\"" << GetName() << "\"," << fShape->GetPointerName() << ");" << std::endl;
1562
1563 } else {
1564 out << " // Assembly: " << GetName() << std::endl;
1565 out << " " << GetPointerName() << " = new TGeoVolumeAssembly(\"" << GetName() << "\"" << ");" << std::endl;
1566 }
1567 if (fLineColor != 1) out << " " << GetPointerName() << "->SetLineColor(" << fLineColor << ");" << std::endl;
1568 if (fLineWidth != 1) out << " " << GetPointerName() << "->SetLineWidth(" << fLineWidth << ");" << std::endl;
1569 if (fLineStyle != 1) out << " " << GetPointerName() << "->SetLineStyle(" << fLineStyle << ");" << std::endl;
1570 if (!IsVisible() && !IsAssembly()) out << " " << GetPointerName() << "->SetVisibility(kFALSE);" << std::endl;
1571 if (!IsVisibleDaughters()) out << " " << GetPointerName() << "->VisibleDaughters(kFALSE);" << std::endl;
1572 if (IsVisContainers()) out << " " << GetPointerName() << "->SetVisContainers(kTRUE);" << std::endl;
1573 if (IsVisLeaves()) out << " " << GetPointerName() << "->SetVisLeaves(kTRUE);" << std::endl;
1575 }
1576 // check if we need to save the media
1577 if (!strcmp(option, "m")) {
1578 if (fMedium) fMedium->SavePrimitive(out,option);
1579 for (i=0; i<nd; i++) {
1580 dvol = GetNode(i)->GetVolume();
1581 dvol->SavePrimitive(out,option);
1582 }
1583 return;
1584 }
1585 // check if we need to save the matrices
1586 if (!strcmp(option, "x")) {
1587 if (fFinder) {
1588 dvol = GetNode(0)->GetVolume();
1589 dvol->SavePrimitive(out,option);
1590 return;
1591 }
1592 for (i=0; i<nd; i++) {
1593 dnode = GetNode(i);
1594 matrix = dnode->GetMatrix();
1595 if (!matrix->IsIdentity()) matrix->SavePrimitive(out,option);
1596 dnode->GetVolume()->SavePrimitive(out,option);
1597 }
1598 return;
1599 }
1600 // check if we need to save volume daughters
1601 if (!strcmp(option, "d")) {
1602 if (!nd) return;
1605 if (fFinder) {
1606 // volume divided: generate volume->Divide()
1607 dnode = GetNode(0);
1608 dvol = dnode->GetVolume();
1609 out << " TGeoVolume *" << dvol->GetPointerName() << " = ";
1610 out << GetPointerName() << "->Divide(\"" << dvol->GetName() << "\", ";
1611 fFinder->SavePrimitive(out,option);
1612 if (fMedium != dvol->GetMedium()) {
1613 out << ", " << dvol->GetMedium()->GetId();
1614 }
1615 out << ");" << std::endl;
1616 dvol->SavePrimitive(out,"d");
1617 return;
1618 }
1619 for (i=0; i<nd; i++) {
1620 dnode = GetNode(i);
1621 dvol = dnode->GetVolume();
1622 dvol->SavePrimitive(out,"s");
1623 matrix = dnode->GetMatrix();
1624 icopy = dnode->GetNumber();
1625 // generate AddNode()
1626 out << " " << GetPointerName() << "->AddNode";
1627 if (dnode->IsOverlapping()) out << "Overlap";
1628 out << "(" << dvol->GetPointerName() << ", " << icopy;
1629 if (!matrix->IsIdentity()) out << ", " << matrix->GetPointerName();
1630 out << ");" << std::endl;
1631 }
1632 // Recursive loop to daughters
1633 for (i=0; i<nd; i++) {
1634 dnode = GetNode(i);
1635 dvol = dnode->GetVolume();
1636 dvol->SavePrimitive(out,"d");
1637 }
1638 }
1639}
1640
1641////////////////////////////////////////////////////////////////////////////////
1642/// Reset SavePrimitive bits.
1643
1645{
1649}
1650
1651////////////////////////////////////////////////////////////////////////////////
1652/// Execute mouse actions on this volume.
1653
1655{
1657 if (!painter) return;
1658 painter->ExecuteVolumeEvent(this, event, px, py);
1659}
1660
1661////////////////////////////////////////////////////////////////////////////////
1662/// search a daughter inside the list of nodes
1663
1665{
1666 return ((TGeoNode*)fNodes->FindObject(name));
1667}
1668
1669////////////////////////////////////////////////////////////////////////////////
1670/// Get the index of a daughter within check_list by providing the node pointer.
1671
1672Int_t TGeoVolume::GetNodeIndex(const TGeoNode *node, Int_t *check_list, Int_t ncheck) const
1673{
1674 TGeoNode *current = 0;
1675 for (Int_t i=0; i<ncheck; i++) {
1676 current = (TGeoNode*)fNodes->At(check_list[i]);
1677 if (current==node) return check_list[i];
1678 }
1679 return -1;
1680}
1681
1682////////////////////////////////////////////////////////////////////////////////
1683/// get index number for a given daughter
1684
1686{
1687 TGeoNode *current = 0;
1688 Int_t nd = GetNdaughters();
1689 if (!nd) return -1;
1690 for (Int_t i=0; i<nd; i++) {
1691 current = (TGeoNode*)fNodes->At(i);
1692 if (current==node) return i;
1693 }
1694 return -1;
1695}
1696
1697////////////////////////////////////////////////////////////////////////////////
1698/// Get volume info for the browser.
1699
1701{
1702 TGeoVolume *vol = (TGeoVolume*)this;
1704 if (!painter) return 0;
1705 return (char*)painter->GetVolumeInfo(vol, px, py);
1706}
1707
1708////////////////////////////////////////////////////////////////////////////////
1709/// Returns true if cylindrical voxelization is optimal.
1710
1712{
1713 Int_t nd = GetNdaughters();
1714 if (!nd) return kFALSE;
1715 Int_t id;
1716 Int_t ncyl = 0;
1717 TGeoNode *node;
1718 for (id=0; id<nd; id++) {
1719 node = (TGeoNode*)fNodes->At(id);
1720 ncyl += node->GetOptimalVoxels();
1721 }
1722 if (ncyl>(nd/2)) return kTRUE;
1723 return kFALSE;
1724}
1725
1726////////////////////////////////////////////////////////////////////////////////
1727/// Provide a pointer name containing uid.
1728
1730{
1731 static TString name;
1732 name = TString::Format("p%s_%lx", GetName(), (ULong_t)this);
1733 return (char*)name.Data();
1734}
1735
1736////////////////////////////////////////////////////////////////////////////////
1737/// Getter for optimization structure.
1738
1740{
1741 if (fVoxels && !fVoxels->IsInvalid()) return fVoxels;
1742 return NULL;
1743}
1744
1745////////////////////////////////////////////////////////////////////////////////
1746/// Move perspective view focus to this volume
1747
1749{
1751 if (painter) painter->GrabFocus();
1752}
1753
1754////////////////////////////////////////////////////////////////////////////////
1755/// Returns true if the volume is an assembly or a scaled assembly.
1756
1758{
1759 return fShape->IsAssembly();
1760}
1761
1762////////////////////////////////////////////////////////////////////////////////
1763/// Clone this volume.
1764/// build a volume with same name, shape and medium
1765
1767{
1768 TGeoVolume *vol = new TGeoVolume(GetName(), fShape, fMedium);
1769 Int_t i;
1770 // copy volume attributes
1771 vol->SetLineColor(GetLineColor());
1772 vol->SetLineStyle(GetLineStyle());
1773 vol->SetLineWidth(GetLineWidth());
1774 vol->SetFillColor(GetFillColor());
1775 vol->SetFillStyle(GetFillStyle());
1776 // copy other attributes
1777 Int_t nbits = 8*sizeof(UInt_t);
1778 for (i=0; i<nbits; i++)
1779 vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
1780 for (i=14; i<24; i++)
1781 vol->SetBit(1<<i, TestBit(1<<i));
1782
1783 // copy field
1784 vol->SetField(fField);
1785 // Set bits
1786 for (i=0; i<nbits; i++)
1787 vol->SetBit(1<<i, TObject::TestBit(1<<i));
1788 vol->SetBit(kVolumeClone);
1789 // copy nodes
1790// CloneNodesAndConnect(vol);
1791 vol->MakeCopyNodes(this);
1792 // if volume is divided, copy finder
1793 vol->SetFinder(fFinder);
1794 // copy voxels
1795 TGeoVoxelFinder *voxels = 0;
1796 if (fVoxels) {
1797 voxels = new TGeoVoxelFinder(vol);
1798 vol->SetVoxelFinder(voxels);
1799 }
1800 // copy option, uid
1801 vol->SetOption(fOption);
1802 vol->SetNumber(fNumber);
1803 vol->SetNtotal(fNtotal);
1804 // copy extensions
1808 return vol;
1809}
1810
1811////////////////////////////////////////////////////////////////////////////////
1812/// Clone the array of nodes.
1813
1815{
1816 if (!fNodes) return;
1817 TGeoNode *node;
1818 Int_t nd = fNodes->GetEntriesFast();
1819 if (!nd) return;
1820 // create new list of nodes
1821 TObjArray *list = new TObjArray(nd);
1822 // attach it to new volume
1823 newmother->SetNodes(list);
1824// ((TObject*)newmother)->SetBit(kVolumeImportNodes);
1825 for (Int_t i=0; i<nd; i++) {
1826 //create copies of nodes and add them to list
1827 node = GetNode(i)->MakeCopyNode();
1828 if (!node) {
1829 Fatal("CloneNodesAndConnect", "cannot make copy node");
1830 return;
1831 }
1832 node->SetMotherVolume(newmother);
1833 list->Add(node);
1834 }
1835}
1836
1837////////////////////////////////////////////////////////////////////////////////
1838/// make a new list of nodes and copy all nodes of other volume inside
1839
1841{
1842 Int_t nd = other->GetNdaughters();
1843 if (!nd) return;
1844 if (fNodes) {
1846 delete fNodes;
1847 }
1848 fNodes = new TObjArray();
1849 for (Int_t i=0; i<nd; i++) fNodes->Add(other->GetNode(i));
1851}
1852
1853////////////////////////////////////////////////////////////////////////////////
1854/// make a copy of this volume
1855/// build a volume with same name, shape and medium
1856
1858{
1859 TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
1860 // copy volume attributes
1861 vol->SetVisibility(IsVisible());
1862 vol->SetLineColor(GetLineColor());
1863 vol->SetLineStyle(GetLineStyle());
1864 vol->SetLineWidth(GetLineWidth());
1865 vol->SetFillColor(GetFillColor());
1866 vol->SetFillStyle(GetFillStyle());
1867 // copy field
1868 vol->SetField(fField);
1869 // if divided, copy division object
1870 if (fFinder) {
1871// Error("MakeCopyVolume", "volume %s divided", GetName());
1872 vol->SetFinder(fFinder);
1873 }
1874 // Copy extensions
1878// ((TObject*)vol)->SetBit(kVolumeImportNodes);
1879 ((TObject*)vol)->SetBit(kVolumeClone);
1881 return vol;
1882}
1883
1884////////////////////////////////////////////////////////////////////////////////
1885/// Make a copy of this volume which is reflected with respect to XY plane.
1886
1888{
1889 static TMap map(100);
1890 if (!fGeoManager->IsClosed()) {
1891 Error("MakeReflectedVolume", "Geometry must be closed.");
1892 return NULL;
1893 }
1894 TGeoVolume *vol = (TGeoVolume*)map.GetValue(this);
1895 if (vol) {
1896 if (newname && newname[0]) vol->SetName(newname);
1897 return vol;
1898 }
1899// printf("Making reflection for volume: %s\n", GetName());
1900 vol = CloneVolume();
1901 if (!vol) {
1902 Fatal("MakeReflectedVolume", "Cannot clone volume %s\n", GetName());
1903 return 0;
1904 }
1905 map.Add((TObject*)this, vol);
1906 if (newname && newname[0]) vol->SetName(newname);
1907 delete vol->GetNodes();
1908 vol->SetNodes(NULL);
1911 // The volume is now properly cloned, but with the same shape.
1912 // Reflect the shape (if any) and connect it.
1913 if (fShape) {
1914 TGeoShape *reflected_shape =
1916 vol->SetShape(reflected_shape);
1917 }
1918 // Reflect the daughters.
1919 Int_t nd = vol->GetNdaughters();
1920 if (!nd) return vol;
1921 TGeoNodeMatrix *node;
1922 TGeoMatrix *local, *local_cloned;
1923 TGeoVolume *new_vol;
1924 if (!vol->GetFinder()) {
1925 for (Int_t i=0; i<nd; i++) {
1926 node = (TGeoNodeMatrix*)vol->GetNode(i);
1927 local = node->GetMatrix();
1928// printf("%s before\n", node->GetName());
1929// local->Print();
1930 Bool_t reflected = local->IsReflection();
1931 local_cloned = new TGeoCombiTrans(*local);
1932 local_cloned->RegisterYourself();
1933 node->SetMatrix(local_cloned);
1934 if (!reflected) {
1935 // We need to reflect only the translation and propagate to daughters.
1936 // H' = Sz * H * Sz
1937 local_cloned->ReflectZ(kTRUE);
1938 local_cloned->ReflectZ(kFALSE);
1939// printf("%s after\n", node->GetName());
1940// node->GetMatrix()->Print();
1941 new_vol = node->GetVolume()->MakeReflectedVolume();
1942 node->SetVolume(new_vol);
1943 continue;
1944 }
1945 // The next daughter is already reflected, so reflect on Z everything and stop
1946 local_cloned->ReflectZ(kTRUE); // rot + tr
1947// printf("%s already reflected... After:\n", node->GetName());
1948// node->GetMatrix()->Print();
1949 }
1950 if (vol->GetVoxels()) vol->GetVoxels()->Voxelize();
1951 return vol;
1952 }
1953 // Volume is divided, so we have to reflect the division.
1954// printf(" ... divided %s\n", fFinder->ClassName());
1955 TGeoPatternFinder *new_finder = fFinder->MakeCopy(kTRUE);
1956 if (!new_finder) {
1957 Fatal("MakeReflectedVolume", "Could not copy finder for volume %s", GetName());
1958 return 0;
1959 }
1960 new_finder->SetVolume(vol);
1961 vol->SetFinder(new_finder);
1962 TGeoNodeOffset *nodeoff;
1963 new_vol = 0;
1964 for (Int_t i=0; i<nd; i++) {
1965 nodeoff = (TGeoNodeOffset*)vol->GetNode(i);
1966 nodeoff->SetFinder(new_finder);
1967 new_vol = nodeoff->GetVolume()->MakeReflectedVolume();
1968 nodeoff->SetVolume(new_vol);
1969 }
1970 return vol;
1971}
1972
1973////////////////////////////////////////////////////////////////////////////////
1974/// Set this volume as the TOP one (the whole geometry starts from here)
1975
1977{
1979}
1980
1981////////////////////////////////////////////////////////////////////////////////
1982/// Set the current tracking point.
1983
1985{
1987}
1988
1989////////////////////////////////////////////////////////////////////////////////
1990/// set the shape associated with this volume
1991
1993{
1994 if (!shape) {
1995 Error("SetShape", "No shape");
1996 return;
1997 }
1998 fShape = (TGeoShape*)shape;
1999}
2000
2001////////////////////////////////////////////////////////////////////////////////
2002/// sort nodes by decreasing volume of the bounding box. ONLY nodes comes first,
2003/// then overlapping nodes and finally division nodes.
2004
2006{
2007 if (!Valid()) {
2008 Error("SortNodes", "Bounding box not valid");
2009 return;
2010 }
2011 Int_t nd = GetNdaughters();
2012// printf("volume : %s, nd=%i\n", GetName(), nd);
2013 if (!nd) return;
2014 if (fFinder) return;
2015// printf("Nodes for %s\n", GetName());
2016 Int_t id = 0;
2017 TGeoNode *node = 0;
2018 TObjArray *nodes = new TObjArray(nd);
2019 Int_t inode = 0;
2020 // first put ONLY's
2021 for (id=0; id<nd; id++) {
2022 node = GetNode(id);
2023 if (node->InheritsFrom(TGeoNodeOffset::Class()) || node->IsOverlapping()) continue;
2024 nodes->Add(node);
2025// printf("inode %i ONLY\n", inode);
2026 inode++;
2027 }
2028 // second put overlapping nodes
2029 for (id=0; id<nd; id++) {
2030 node = GetNode(id);
2031 if (node->InheritsFrom(TGeoNodeOffset::Class()) || (!node->IsOverlapping())) continue;
2032 nodes->Add(node);
2033// printf("inode %i MANY\n", inode);
2034 inode++;
2035 }
2036 // third put the divided nodes
2037 if (fFinder) {
2038 fFinder->SetDivIndex(inode);
2039 for (id=0; id<nd; id++) {
2040 node = GetNode(id);
2041 if (!node->InheritsFrom(TGeoNodeOffset::Class())) continue;
2042 nodes->Add(node);
2043// printf("inode %i DIV\n", inode);
2044 inode++;
2045 }
2046 }
2047 if (inode != nd) printf(" volume %s : number of nodes does not match!!!\n", GetName());
2048 delete fNodes;
2049 fNodes = nodes;
2050}
2051
2052////////////////////////////////////////////////////////////////////////////////
2053/// Stream an object of class TGeoVolume.
2054
2055void TGeoVolume::Streamer(TBuffer &R__b)
2056{
2057 if (R__b.IsReading()) {
2058 R__b.ReadClassBuffer(TGeoVolume::Class(), this);
2059 if (fVoxels && fVoxels->IsInvalid()) Voxelize("");
2060 } else {
2061 if (!fVoxels) {
2062 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2063 } else {
2065 TGeoVoxelFinder *voxels = fVoxels;
2066 fVoxels = 0;
2067 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2068 fVoxels = voxels;
2069 } else {
2070 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2071 }
2072 }
2073 }
2074}
2075
2076////////////////////////////////////////////////////////////////////////////////
2077/// Set the current options (none implemented)
2078
2079void TGeoVolume::SetOption(const char *option)
2080{
2081 fOption = option;
2082}
2083
2084////////////////////////////////////////////////////////////////////////////////
2085/// Set the line color.
2086
2088{
2089 TAttLine::SetLineColor(lcolor);
2090}
2091
2092////////////////////////////////////////////////////////////////////////////////
2093/// Set the line style.
2094
2096{
2097 TAttLine::SetLineStyle(lstyle);
2098}
2099
2100////////////////////////////////////////////////////////////////////////////////
2101/// Set the line width.
2102
2104{
2105 TAttLine::SetLineWidth(lwidth);
2106}
2107
2108////////////////////////////////////////////////////////////////////////////////
2109/// get the pointer to a daughter node
2110
2112{
2113 if (!fNodes) return 0;
2114 TGeoNode *node = (TGeoNode *)fNodes->FindObject(name);
2115 return node;
2116}
2117
2118////////////////////////////////////////////////////////////////////////////////
2119/// get the total size in bytes for this volume
2120
2122{
2123 Int_t count = 28+2+6+4+0; // TNamed+TGeoAtt+TAttLine+TAttFill+TAtt3D
2124 count += fName.Capacity() + fTitle.Capacity(); // name+title
2125 count += 7*sizeof(char*); // fShape + fMedium + fFinder + fField + fNodes + 2 extensions
2126 count += fOption.Capacity(); // fOption
2127 if (fShape) count += fShape->GetByteCount();
2128 if (fFinder) count += fFinder->GetByteCount();
2129 if (fNodes) {
2130 count += 32 + 4*fNodes->GetEntries(); // TObjArray
2131 TIter next(fNodes);
2132 TGeoNode *node;
2133 while ((node=(TGeoNode*)next())) count += node->GetByteCount();
2134 }
2135 return count;
2136}
2137
2138////////////////////////////////////////////////////////////////////////////////
2139/// loop all nodes marked as overlaps and find overlapping brothers
2140
2142{
2143 if (!Valid()) {
2144 Error("FindOverlaps","Bounding box not valid");
2145 return;
2146 }
2147 if (!fVoxels) return;
2148 Int_t nd = GetNdaughters();
2149 if (!nd) return;
2150 TGeoNode *node=0;
2151 Int_t inode = 0;
2152 for (inode=0; inode<nd; inode++) {
2153 node = GetNode(inode);
2154 if (!node->IsOverlapping()) continue;
2155 fVoxels->FindOverlaps(inode);
2156 }
2157}
2158
2159////////////////////////////////////////////////////////////////////////////////
2160/// Remove an existing daughter.
2161
2163{
2164 if (!fNodes || !fNodes->GetEntriesFast()) return;
2165 if (!fNodes->Remove(node)) return;
2166 fNodes->Compress();
2168 if (IsAssembly()) fShape->ComputeBBox();
2169}
2170
2171////////////////////////////////////////////////////////////////////////////////
2172/// Replace an existing daughter with a new volume having the same name but
2173/// possibly a new shape, position or medium. Not allowed for positioned assemblies.
2174/// For division cells, the new shape/matrix are ignored.
2175
2177{
2178 Int_t ind = GetIndex(nodeorig);
2179 if (ind < 0) return NULL;
2180 TGeoVolume *oldvol = nodeorig->GetVolume();
2181 if (oldvol->IsAssembly()) {
2182 Error("ReplaceNode", "Cannot replace node %s since it is an assembly", nodeorig->GetName());
2183 return NULL;
2184 }
2185 TGeoShape *shape = oldvol->GetShape();
2186 if (newshape && !nodeorig->IsOffset()) shape = newshape;
2187 TGeoMedium *med = oldvol->GetMedium();
2188 if (newmed) med = newmed;
2189 // Make a new volume
2190 TGeoVolume *vol = new TGeoVolume(oldvol->GetName(), shape, med);
2191 // copy volume attributes
2192 vol->SetVisibility(oldvol->IsVisible());
2193 vol->SetLineColor(oldvol->GetLineColor());
2194 vol->SetLineStyle(oldvol->GetLineStyle());
2195 vol->SetLineWidth(oldvol->GetLineWidth());
2196 vol->SetFillColor(oldvol->GetFillColor());
2197 vol->SetFillStyle(oldvol->GetFillStyle());
2198 // copy field
2199 vol->SetField(oldvol->GetField());
2200 // Make a copy of the node
2201 TGeoNode *newnode = nodeorig->MakeCopyNode();
2202 if (!newnode) {
2203 Fatal("ReplaceNode", "Cannot make copy node for %s", nodeorig->GetName());
2204 return 0;
2205 }
2206 // Change the volume for the new node
2207 newnode->SetVolume(vol);
2208 // Replace the matrix
2209 if (newpos && !nodeorig->IsOffset()) {
2210 TGeoNodeMatrix *nodemat = (TGeoNodeMatrix*)newnode;
2211 nodemat->SetMatrix(newpos);
2212 }
2213 // Replace nodeorig with new one
2214 fNodes->RemoveAt(ind);
2215 fNodes->AddAt(newnode, ind);
2217 if (IsAssembly()) fShape->ComputeBBox();
2218 return newnode;
2219}
2220
2221////////////////////////////////////////////////////////////////////////////////
2222/// Select this volume as matching an arbitrary criteria. The volume is added to
2223/// a static list and the flag TGeoVolume::kVolumeSelected is set. All flags need
2224/// to be reset at the end by calling the method with CLEAR=true. This will also clear
2225/// the list.
2226
2228{
2229 static TObjArray array(256);
2230 static Int_t len = 0;
2231 Int_t i;
2232 TObject *vol;
2233 if (clear) {
2234 for (i=0; i<len; i++) {
2235 vol = array.At(i);
2237 }
2238 array.Clear();
2239 len = 0;
2240 return;
2241 }
2243 array.AddAtAndExpand(this, len++);
2244}
2245
2246////////////////////////////////////////////////////////////////////////////////
2247/// set visibility of this volume
2248
2250{
2254 TSeqCollection *brlist = gROOT->GetListOfBrowsers();
2255 TIter next(brlist);
2256 TBrowser *browser = 0;
2257 while ((browser=(TBrowser*)next())) {
2258 browser->CheckObjectItem(this, vis);
2259 browser->Refresh();
2260 }
2261}
2262
2263////////////////////////////////////////////////////////////////////////////////
2264/// Set visibility for containers.
2265
2267{
2269 if (fGeoManager && fGeoManager->IsClosed()) {
2272 }
2273}
2274
2275////////////////////////////////////////////////////////////////////////////////
2276/// Set visibility for leaves.
2277
2279{
2281 if (fGeoManager && fGeoManager->IsClosed()) {
2284 }
2285}
2286
2287////////////////////////////////////////////////////////////////////////////////
2288/// Set visibility for leaves.
2289
2291{
2292 if (IsAssembly()) return;
2293 TGeoAtt::SetVisOnly(flag);
2294 if (fGeoManager && fGeoManager->IsClosed()) {
2297 }
2298}
2299
2300////////////////////////////////////////////////////////////////////////////////
2301/// Check if the shape of this volume is valid.
2302
2304{
2305 return fShape->IsValidBox();
2306}
2307
2308////////////////////////////////////////////////////////////////////////////////
2309/// Find a daughter node having VOL as volume and fill TGeoManager::fHMatrix
2310/// with its global matrix.
2311
2313{
2314 if (vol == this) return kTRUE;
2315 Int_t nd = GetNdaughters();
2316 if (!nd) return kFALSE;
2317 TGeoHMatrix *global = fGeoManager->GetHMatrix();
2318 if (!global) return kFALSE;
2319 TGeoNode *dnode;
2320 TGeoVolume *dvol;
2321 TGeoMatrix *local;
2322 Int_t i;
2323 for (i=0; i<nd; i++) {
2324 dnode = GetNode(i);
2325 dvol = dnode->GetVolume();
2326 if (dvol == vol) {
2327 local = dnode->GetMatrix();
2328 global->MultiplyLeft(local);
2329 return kTRUE;
2330 }
2331 }
2332 for (i=0; i<nd; i++) {
2333 dnode = GetNode(i);
2334 dvol = dnode->GetVolume();
2335 if (dvol->FindMatrixOfDaughterVolume(vol)) return kTRUE;
2336 }
2337 return kFALSE;
2338}
2339
2340////////////////////////////////////////////////////////////////////////////////
2341/// set visibility for daughters
2342
2344{
2345 SetVisDaughters(vis);
2348}
2349
2350////////////////////////////////////////////////////////////////////////////////
2351/// build the voxels for this volume
2352
2354{
2355 if (!Valid()) {
2356 Error("Voxelize", "Bounding box not valid");
2357 return;
2358 }
2359 // do not voxelize divided volumes
2360 if (fFinder) return;
2361 // or final leaves
2362 Int_t nd = GetNdaughters();
2363 if (!nd) return;
2364 // If this is an assembly, re-compute bounding box
2365 if (IsAssembly()) fShape->ComputeBBox();
2366 // delete old voxelization if any
2367 if (fVoxels) {
2369 fVoxels = 0;
2370 }
2371 // Create the voxels structure
2372 fVoxels = new TGeoVoxelFinder(this);
2373 fVoxels->Voxelize(option);
2374 if (fVoxels) {
2375 if (fVoxels->IsInvalid()) {
2376 delete fVoxels;
2377 fVoxels = 0;
2378 }
2379 }
2380}
2381
2382////////////////////////////////////////////////////////////////////////////////
2383/// Estimate the weight of a volume (in kg) with SIGMA(M)/M better than PRECISION.
2384/// Option can contain : v - verbose, a - analytical (default)
2385
2387{
2389 if (top != this) fGeoManager->SetTopVolume(this);
2390 else top = 0;
2391 Double_t weight = fGeoManager->Weight(precision, option);
2392 if (top) fGeoManager->SetTopVolume(top);
2393 return weight;
2394}
2395
2396////////////////////////////////////////////////////////////////////////////////
2397/// Analytical computation of the weight.
2398
2400{
2401 Double_t capacity = Capacity();
2402 Double_t weight = 0.0;
2403 Int_t i;
2404 Int_t nd = GetNdaughters();
2405 TGeoVolume *daughter;
2406 for (i=0; i<nd; i++) {
2407 daughter = GetNode(i)->GetVolume();
2408 weight += daughter->WeightA();
2409 capacity -= daughter->Capacity();
2410 }
2411 Double_t density = 0.0;
2412 if (!IsAssembly()) {
2413 if (fMedium) density = fMedium->GetMaterial()->GetDensity();
2414 if (density<0.01) density = 0.0; // do not weight gases
2415 }
2416 weight += 0.001*capacity * density; //[kg]
2417 return weight;
2418}
2419
2421
2422
2423////////////////////////////////////////////////////////////////////////////////
2424/// dummy constructor
2425
2427{
2428 fVolumes = 0;
2429 fDivision = 0;
2430 fNumed = 0;
2431 fNdiv = 0;
2432 fAxis = 0;
2433 fStart = 0;
2434 fStep = 0;
2435 fAttSet = kFALSE;
2437}
2438
2439////////////////////////////////////////////////////////////////////////////////
2440/// default constructor
2441
2443{
2444 fVolumes = new TObjArray();
2445 fDivision = 0;
2446 fNumed = 0;
2447 fNdiv = 0;
2448 fAxis = 0;
2449 fStart = 0;
2450 fStep = 0;
2451 fAttSet = kFALSE;
2453 SetName(name);
2454 SetMedium(med);
2455 fGeoManager->AddVolume(this);
2456// printf("--- volume multi %s created\n", name);
2457}
2458
2459////////////////////////////////////////////////////////////////////////////////
2460///copy constructor
2461
2463 TGeoVolume(vm),
2464 fVolumes(vm.fVolumes),
2465 fDivision(vm.fDivision),
2466 fNumed(vm.fNumed),
2467 fNdiv(vm.fNdiv),
2468 fAxis(vm.fAxis),
2469 fStart(vm.fStart),
2470 fStep(vm.fStep),
2471 fAttSet(vm.fAttSet)
2472{
2473}
2474
2475////////////////////////////////////////////////////////////////////////////////
2476///assignment operator
2477
2479{
2480 if(this!=&vm) {
2482 fVolumes=vm.fVolumes;
2484 fNumed=vm.fNumed;
2485 fNdiv=vm.fNdiv;
2486 fAxis=vm.fAxis;
2487 fStart=vm.fStart;
2488 fStep=vm.fStep;
2489 fAttSet=vm.fAttSet;
2490 }
2491 return *this;
2492}
2493
2494////////////////////////////////////////////////////////////////////////////////
2495/// Destructor
2496
2498{
2499 if (fVolumes) delete fVolumes;
2500}
2501
2502////////////////////////////////////////////////////////////////////////////////
2503/// Add a volume with valid shape to the list of volumes. Copy all existing nodes
2504/// to this volume
2505
2507{
2508 Int_t idx = fVolumes->GetEntriesFast();
2509 fVolumes->AddAtAndExpand(vol,idx);
2510 vol->SetUniqueID(idx+1);
2511 TGeoVolumeMulti *div;
2512 TGeoVolume *cell;
2513 if (fDivision) {
2515 if (!div) {
2516 Fatal("AddVolume", "Cannot divide volume %s", vol->GetName());
2517 return;
2518 }
2519 for (Int_t i=0; i<div->GetNvolumes(); i++) {
2520 cell = div->GetVolume(i);
2521 fDivision->AddVolume(cell);
2522 }
2523 }
2524 if (fNodes) {
2525 Int_t nd = fNodes->GetEntriesFast();
2526 for (Int_t id=0; id<nd; id++) {
2527 TGeoNode *node = (TGeoNode*)fNodes->At(id);
2528 Bool_t many = node->IsOverlapping();
2529 if (many) vol->AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2530 else vol->AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2531 }
2532 }
2533// vol->MakeCopyNodes(this);
2534}
2535
2536
2537////////////////////////////////////////////////////////////////////////////////
2538/// Add a new node to the list of nodes. This is the usual method for adding
2539/// daughters inside the container volume.
2540
2542{
2543 TGeoVolume::AddNode(vol, copy_no, mat, option);
2544 Int_t nvolumes = fVolumes->GetEntriesFast();
2545 TGeoVolume *volume = 0;
2546 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2547 volume = GetVolume(ivo);
2548 volume->SetLineColor(GetLineColor());
2549 volume->SetLineStyle(GetLineStyle());
2550 volume->SetLineWidth(GetLineWidth());
2551 volume->SetVisibility(IsVisible());
2552 volume->AddNode(vol, copy_no, mat, option);
2553 }
2554// printf("--- vmulti %s : node %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2555}
2556
2557////////////////////////////////////////////////////////////////////////////////
2558/// Add a new node to the list of nodes, This node is possibly overlapping with other
2559/// daughters of the volume or extruding the volume.
2560
2562{
2563 TGeoVolume::AddNodeOverlap(vol, copy_no, mat, option);
2564 Int_t nvolumes = fVolumes->GetEntriesFast();
2565 TGeoVolume *volume = 0;
2566 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2567 volume = GetVolume(ivo);
2568 volume->SetLineColor(GetLineColor());
2569 volume->SetLineStyle(GetLineStyle());
2570 volume->SetLineWidth(GetLineWidth());
2571 volume->SetVisibility(IsVisible());
2572 volume->AddNodeOverlap(vol, copy_no, mat, option);
2573 }
2574// printf("--- vmulti %s : node ovlp %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2575}
2576
2577////////////////////////////////////////////////////////////////////////////////
2578/// Returns the last shape.
2579
2581{
2583 if (!vol) return 0;
2584 return vol->GetShape();
2585}
2586
2587////////////////////////////////////////////////////////////////////////////////
2588/// division of multiple volumes
2589
2590TGeoVolume *TGeoVolumeMulti::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, const char *option)
2591{
2592 if (fDivision) {
2593 Error("Divide", "volume %s already divided", GetName());
2594 return 0;
2595 }
2596 Int_t nvolumes = fVolumes->GetEntriesFast();
2597 TGeoMedium *medium = fMedium;
2598 if (numed) {
2599 medium = fGeoManager->GetMedium(numed);
2600 if (!medium) {
2601 Error("Divide", "Invalid medium number %d for division volume %s", numed, divname);
2602 medium = fMedium;
2603 }
2604 }
2605 if (!nvolumes) {
2606 // this is a virtual volume
2607 fDivision = new TGeoVolumeMulti(divname, medium);
2608 fNumed = medium->GetId();
2609 fOption = option;
2610 fAxis = iaxis;
2611 fNdiv = ndiv;
2612 fStart = start;
2613 fStep = step;
2614 // nothing else to do at this stage
2615 return fDivision;
2616 }
2617 TGeoVolume *vol = 0;
2618 fDivision = new TGeoVolumeMulti(divname, medium);
2619 if (medium) fNumed = medium->GetId();
2620 fOption = option;
2621 fAxis = iaxis;
2622 fNdiv = ndiv;
2623 fStart = start;
2624 fStep = step;
2625 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2626 vol = GetVolume(ivo);
2627 vol->SetLineColor(GetLineColor());
2628 vol->SetLineStyle(GetLineStyle());
2629 vol->SetLineWidth(GetLineWidth());
2630 vol->SetVisibility(IsVisible());
2631 fDivision->AddVolume(vol->Divide(divname,iaxis,ndiv,start,step, numed, option));
2632 }
2633// printf("--- volume multi %s (%i volumes) divided\n", GetName(), nvolumes);
2634 if (numed) fDivision->SetMedium(medium);
2635 return fDivision;
2636}
2637
2638////////////////////////////////////////////////////////////////////////////////
2639/// Make a copy of this volume
2640/// build a volume with same name, shape and medium
2641
2643{
2644 TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
2645 Int_t i=0;
2646 // copy volume attributes
2647 vol->SetVisibility(IsVisible());
2648 vol->SetLineColor(GetLineColor());
2649 vol->SetLineStyle(GetLineStyle());
2650 vol->SetLineWidth(GetLineWidth());
2651 vol->SetFillColor(GetFillColor());
2652 vol->SetFillStyle(GetFillStyle());
2653 // copy field
2654 vol->SetField(fField);
2655 // Copy extensions
2658 // if divided, copy division object
2659// if (fFinder) {
2660// Error("MakeCopyVolume", "volume %s divided", GetName());
2661// vol->SetFinder(fFinder);
2662// }
2663 if (fDivision) {
2664 TGeoVolume *cell;
2666 if (!div) {
2667 Fatal("MakeCopyVolume", "Cannot divide volume %s", vol->GetName());
2668 return 0;
2669 }
2670 for (i=0; i<div->GetNvolumes(); i++) {
2671 cell = div->GetVolume(i);
2672 fDivision->AddVolume(cell);
2673 }
2674 }
2675
2676 if (!fNodes) return vol;
2677 TGeoNode *node;
2678 Int_t nd = fNodes->GetEntriesFast();
2679 if (!nd) return vol;
2680 // create new list of nodes
2681 TObjArray *list = new TObjArray();
2682 // attach it to new volume
2683 vol->SetNodes(list);
2684 ((TObject*)vol)->SetBit(kVolumeImportNodes);
2685 for (i=0; i<nd; i++) {
2686 //create copies of nodes and add them to list
2687 node = GetNode(i)->MakeCopyNode();
2688 if (!node) {
2689 Fatal("MakeCopyNode", "cannot make copy node for daughter %d of %s", i, GetName());
2690 return 0;
2691 }
2692 node->SetMotherVolume(vol);
2693 list->Add(node);
2694 }
2695 return vol;
2696}
2697
2698////////////////////////////////////////////////////////////////////////////////
2699/// Set the line color for all components.
2700
2702{
2704 Int_t nvolumes = fVolumes->GetEntriesFast();
2705 TGeoVolume *vol = 0;
2706 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2707 vol = GetVolume(ivo);
2708 vol->SetLineColor(lcolor);
2709 }
2710}
2711
2712////////////////////////////////////////////////////////////////////////////////
2713/// Set the line style for all components.
2714
2716{
2718 Int_t nvolumes = fVolumes->GetEntriesFast();
2719 TGeoVolume *vol = 0;
2720 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2721 vol = GetVolume(ivo);
2722 vol->SetLineStyle(lstyle);
2723 }
2724}
2725
2726////////////////////////////////////////////////////////////////////////////////
2727/// Set the line width for all components.
2728
2730{
2732 Int_t nvolumes = fVolumes->GetEntriesFast();
2733 TGeoVolume *vol = 0;
2734 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2735 vol = GetVolume(ivo);
2736 vol->SetLineWidth(lwidth);
2737 }
2738}
2739
2740////////////////////////////////////////////////////////////////////////////////
2741/// Set medium for a multiple volume.
2742
2744{
2746 Int_t nvolumes = fVolumes->GetEntriesFast();
2747 TGeoVolume *vol = 0;
2748 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2749 vol = GetVolume(ivo);
2750 vol->SetMedium(med);
2751 }
2752}
2753
2754
2755////////////////////////////////////////////////////////////////////////////////
2756/// Set visibility for all components.
2757
2759{
2761 Int_t nvolumes = fVolumes->GetEntriesFast();
2762 TGeoVolume *vol = 0;
2763 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2764 vol = GetVolume(ivo);
2765 vol->SetVisibility(vis);
2766 }
2767}
2768
2770
2771////////////////////////////////////////////////////////////////////////////////
2772/// Constructor.
2773
2775 fCurrent(-1), fNext(-1)
2776{
2777}
2778
2779////////////////////////////////////////////////////////////////////////////////
2780/// Destructor.
2781
2783{
2784}
2785
2786////////////////////////////////////////////////////////////////////////////////
2787
2789{
2791 return *fThreadData[tid];
2792}
2793
2794////////////////////////////////////////////////////////////////////////////////
2795
2797{
2798 std::lock_guard<std::mutex> guard(fMutex);
2800 std::vector<ThreadData_t*>::iterator i = fThreadData.begin();
2801 while (i != fThreadData.end())
2802 {
2803 delete *i;
2804 ++i;
2805 }
2806 fThreadData.clear();
2807 fThreadSize = 0;
2808}
2809
2810////////////////////////////////////////////////////////////////////////////////
2811
2813{
2814 std::lock_guard<std::mutex> guard(fMutex);
2815 // Create assembly thread data here
2816 fThreadData.resize(nthreads);
2817 fThreadSize = nthreads;
2818 for (Int_t tid=0; tid<nthreads; tid++) {
2819 if (fThreadData[tid] == 0) {
2820 fThreadData[tid] = new ThreadData_t;
2821 }
2822 }
2824}
2825
2826////////////////////////////////////////////////////////////////////////////////
2827
2829{
2830 return fThreadData[TGeoManager::ThreadId()]->fCurrent;
2831}
2832
2833////////////////////////////////////////////////////////////////////////////////
2834
2836{
2837 return fThreadData[TGeoManager::ThreadId()]->fNext;
2838}
2839
2840////////////////////////////////////////////////////////////////////////////////
2841
2843{
2844 fThreadData[TGeoManager::ThreadId()]->fCurrent = index;
2845}
2846
2847////////////////////////////////////////////////////////////////////////////////
2848
2850{
2851 fThreadData[TGeoManager::ThreadId()]->fNext = index;
2852}
2853
2854////////////////////////////////////////////////////////////////////////////////
2855/// Default constructor
2856
2858 :TGeoVolume()
2859{
2860 fThreadSize = 0;
2862}
2863
2864////////////////////////////////////////////////////////////////////////////////
2865/// Constructor. Just the name has to be provided. Assemblies does not have their own
2866/// shape or medium.
2867
2869 :TGeoVolume()
2870{
2871 fName = name;
2872 fName = fName.Strip();
2873 fShape = new TGeoShapeAssembly(this);
2875 fThreadSize = 0;
2877}
2878
2879////////////////////////////////////////////////////////////////////////////////
2880/// Destructor. The assembly is owner of its "shape".
2881
2883{
2885 if (fShape) delete fShape;
2886}
2887
2888////////////////////////////////////////////////////////////////////////////////
2889/// Add a component to the assembly.
2890
2892{
2893 TGeoVolume::AddNode(vol,copy_no,mat,option);
2894// ((TGeoShapeAssembly*)fShape)->RecomputeBoxLast();
2895 ((TGeoShapeAssembly*)fShape)->NeedsBBoxRecompute();
2896}
2897
2898////////////////////////////////////////////////////////////////////////////////
2899/// Add an overlapping node - not allowed for assemblies.
2900
2902{
2903 Warning("AddNodeOverlap", "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
2904 AddNode(vol, copy_no, mat, option);
2905}
2906
2907////////////////////////////////////////////////////////////////////////////////
2908/// Clone this volume.
2909/// build a volume with same name, shape and medium
2910
2912{
2914 Int_t i;
2915 // copy other attributes
2916 Int_t nbits = 8*sizeof(UInt_t);
2917 for (i=0; i<nbits; i++)
2918 vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
2919 for (i=14; i<24; i++)
2920 vol->SetBit(1<<i, TestBit(1<<i));
2921
2922 // copy field
2923 vol->SetField(fField);
2924 // Set bits
2925 for (i=0; i<nbits; i++)
2926 vol->SetBit(1<<i, TObject::TestBit(1<<i));
2927 vol->SetBit(kVolumeClone);
2928 // make copy nodes
2929 vol->MakeCopyNodes(this);
2930// CloneNodesAndConnect(vol);
2931 ((TGeoShapeAssembly*)vol->GetShape())->NeedsBBoxRecompute();
2932 // copy voxels
2933 TGeoVoxelFinder *voxels = 0;
2934 if (fVoxels) {
2935 voxels = new TGeoVoxelFinder(vol);
2936 vol->SetVoxelFinder(voxels);
2937 }
2938 // copy option, uid
2939 vol->SetOption(fOption);
2940 vol->SetNumber(fNumber);
2941 vol->SetNtotal(fNtotal);
2942 return vol;
2943}
2944
2945////////////////////////////////////////////////////////////////////////////////
2946/// Division makes no sense for assemblies.
2947
2949{
2950 Error("Divide","Assemblies cannot be divided");
2951 return 0;
2952}
2953
2954////////////////////////////////////////////////////////////////////////////////
2955/// Assign to the assembly a collection of identical volumes positioned according
2956/// a predefined pattern. The option can be spaced out or touching depending on the empty
2957/// space between volumes.
2958
2960{
2961 if (fNodes) {
2962 Error("Divide", "Cannot divide assembly %s since it has nodes", GetName());
2963 return NULL;
2964 }
2965 if (fFinder) {
2966 Error("Divide", "Assembly %s already divided", GetName());
2967 return NULL;
2968 }
2969 Int_t ncells = pattern->GetNdiv();
2970 if (!ncells || pattern->GetStep()<=0) {
2971 Error("Divide", "Pattern finder for dividing assembly %s not initialized. Use SetRange() method.", GetName());
2972 return NULL;
2973 }
2974 fFinder = pattern;
2975 TString opt(option);
2976 opt.ToLower();
2977 if (opt.Contains("spacedout")) fFinder->SetSpacedOut(kTRUE);
2979 // Position volumes
2980 for (Int_t i=0; i<ncells; i++) {
2981 fFinder->cd(i);
2982 TGeoNodeOffset *node = new TGeoNodeOffset(cell, i, 0.);
2983 node->SetFinder(fFinder);
2984 fNodes->Add(node);
2985 }
2986 return cell;
2987}
2988
2989////////////////////////////////////////////////////////////////////////////////
2990/// Make a clone of volume VOL but which is an assembly.
2991
2993{
2994 if (volorig->IsAssembly() || volorig->IsVolumeMulti()) return 0;
2995 Int_t nd = volorig->GetNdaughters();
2996 if (!nd) return 0;
2997 TGeoVolumeAssembly *vol = new TGeoVolumeAssembly(volorig->GetName());
2998 Int_t i;
2999 // copy other attributes
3000 Int_t nbits = 8*sizeof(UInt_t);
3001 for (i=0; i<nbits; i++)
3002 vol->SetAttBit(1<<i, volorig->TestAttBit(1<<i));
3003 for (i=14; i<24; i++)
3004 vol->SetBit(1<<i, volorig->TestBit(1<<i));
3005
3006 // copy field
3007 vol->SetField(volorig->GetField());
3008 // Set bits
3009 for (i=0; i<nbits; i++)
3010 vol->SetBit(1<<i, volorig->TestBit(1<<i));
3011 vol->SetBit(kVolumeClone);
3012 // make copy nodes
3013 vol->MakeCopyNodes(volorig);
3014// volorig->CloneNodesAndConnect(vol);
3015 vol->GetShape()->ComputeBBox();
3016 // copy voxels
3017 TGeoVoxelFinder *voxels = 0;
3018 if (volorig->GetVoxels()) {
3019 voxels = new TGeoVoxelFinder(vol);
3020 vol->SetVoxelFinder(voxels);
3021 }
3022 // copy option, uid
3023 vol->SetOption(volorig->GetOption());
3024 vol->SetNumber(volorig->GetNumber());
3025 vol->SetNtotal(volorig->GetNtotal());
3026 return vol;
3027}
void Class()
Definition: Class.C:29
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define s1(x)
Definition: RSha256.hxx:91
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
short Width_t
Definition: RtypesCore.h:78
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
short Color_t
Definition: RtypesCore.h:79
short Style_t
Definition: RtypesCore.h:76
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
R__EXTERN TGeoManager * gGeoManager
Definition: TGeoManager.h:572
R__EXTERN TGeoIdentity * gGeoIdentity
Definition: TGeoMatrix.h:478
Binding & operator=(OUT(*fun)(void))
#define gROOT
Definition: TROOT.h:410
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
Use this attribute class when an object should have 3D capabilities.
Definition: TAtt3D.h:19
Fill Area Attributes class.
Definition: TAttFill.h:19
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
Line Attributes class.
Definition: TAttLine.h:18
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
Width_t fLineWidth
Line width.
Definition: TAttLine.h:23
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
Style_t fLineStyle
Line style.
Definition: TAttLine.h:22
Color_t fLineColor
Line color.
Definition: TAttLine.h:21
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:304
void Refresh()
Refresh browser contents.
Definition: TBrowser.cxx:377
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
Bool_t IsReading() const
Definition: TBuffer.h:83
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
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 a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3975
Visualization and tracking attributes for volumes and nodes.
Definition: TGeoAtt.h:18
Bool_t IsVisRaytrace() const
Definition: TGeoAtt.h:87
virtual void SetVisOnly(Bool_t flag=kTRUE)
Set branch type visibility.
Definition: TGeoAtt.cxx:95
Bool_t TestAttBit(UInt_t f) const
Definition: TGeoAtt.h:68
virtual void SetVisLeaves(Bool_t flag=kTRUE)
Set branch type visibility.
Definition: TGeoAtt.cxx:85
@ kSaveNodesAtt
Definition: TGeoAtt.h:53
@ kSavePrimitiveAtt
Definition: TGeoAtt.h:52
void SetVisDaughters(Bool_t vis=kTRUE)
Set visibility for the daughters.
Definition: TGeoAtt.cxx:114
void ResetAttBit(UInt_t f)
Definition: TGeoAtt.h:67
void SetVisRaytrace(Bool_t flag=kTRUE)
Definition: TGeoAtt.h:70
Bool_t IsVisDaughters() const
Definition: TGeoAtt.h:89
virtual void SetVisibility(Bool_t vis=kTRUE)
Set visibility for this object.
Definition: TGeoAtt.cxx:105
void SetAttBit(UInt_t f)
Definition: TGeoAtt.h:65
void SetVisTouched(Bool_t vis=kTRUE)
Mark visualization attributes as "modified".
Definition: TGeoAtt.cxx:131
virtual void SetVisContainers(Bool_t flag=kTRUE)
Set branch type visibility.
Definition: TGeoAtt.cxx:77
Class describing rotation + translation.
Definition: TGeoMatrix.h:292
Class handling Boolean composition of shapes.
void RegisterYourself()
Register the shape and all components to TGeoManager class.
ABC for user objects attached to TGeoVolume or TGeoNode.
Definition: TGeoExtension.h:20
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:421
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:39
TObjArray * GetListOfOverlaps()
Definition: TGeoManager.h:474
TList * GetListOfMedia() const
Definition: TGeoManager.h:477
void SetUserPaintVolume(TGeoVolume *vol)
Definition: TGeoManager.h:223
TObjArray * GetListOfVolumes() const
Definition: TGeoManager.h:478
void ClearOverlaps()
Clear the list of overlaps.
TObjArray * GetListOfMatrices() const
Definition: TGeoManager.h:475
Bool_t IsClosed() const
Definition: TGeoManager.h:290
void RandomRays(Int_t nrays=1000, Double_t startx=0, Double_t starty=0, Double_t startz=0, const char *target_vol=0, Bool_t check_norm=kFALSE)
Randomly shoot nrays and plot intersections with surfaces for current top node.
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
Definition: TGeoManager.h:468
void SetCurrentPoint(Double_t *point)
Definition: TGeoManager.h:516
Int_t GetVisOption() const
Returns current depth to which geometry is drawn.
static UInt_t GetExportPrecision()
Definition: TGeoManager.h:464
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.
TVirtualGeoPainter * GetPainter() const
Definition: TGeoManager.h:198
Bool_t IsCheckingOverlaps() const
Definition: TGeoManager.h:396
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
Definition: TGeoManager.h:476
void SetAllIndex()
Assigns uid's for all materials,media and matrices.
TObjArray * GetListOfShapes() const
Definition: TGeoManager.h:480
TGeoVolume * GetTopVolume() const
Definition: TGeoManager.h:513
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.
Definition: TGeoMaterial.h:31
virtual void Print(const Option_t *option="") const
print characteristics of this material
void SetUsed(Bool_t flag=kTRUE)
Definition: TGeoMaterial.h:117
virtual Double_t GetDensity() const
Definition: TGeoMaterial.h:87
Geometrical transformation package.
Definition: TGeoMatrix.h:41
virtual void ReflectZ(Bool_t leftside, Bool_t rotonly=kFALSE)
Multiply by a reflection respect to XY.
Definition: TGeoMatrix.cxx:519
Bool_t IsReflection() const
Definition: TGeoMatrix.h:69
virtual void RegisterYourself()
Register the matrix in the current manager, which will become the owner.
Definition: TGeoMatrix.cxx:526
void Print(Option_t *option="") const
print the matrix in 4x4 format
Definition: TGeoMatrix.cxx:486
Bool_t IsIdentity() const
Definition: TGeoMatrix.h:66
Bool_t IsRegistered() const
Definition: TGeoMatrix.h:77
char * GetPointerName() const
Provide a pointer name containing uid.
Definition: TGeoMatrix.cxx:294
Media are used to store properties related to tracking and which are useful only when using geometry ...
Definition: TGeoMedium.h:24
Int_t GetId() const
Definition: TGeoMedium.h:48
TGeoMaterial * GetMaterial() const
Definition: TGeoMedium.h:52
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TGeoMedium.cxx:137
void SetMaterial(TGeoMaterial *mat)
Definition: TGeoMedium.h:55
char * GetPointerName() const
Provide a pointer name containing uid.
Definition: TGeoMedium.cxx:127
A node containing local transformation.
Definition: TGeoNode.h:150
void SetMatrix(const TGeoMatrix *matrix)
Matrix setter.
Definition: TGeoNode.cxx:816
virtual TGeoMatrix * GetMatrix() const
Definition: TGeoNode.h:168
Node containing an offset.
Definition: TGeoNode.h:182
void SetFinder(TGeoPatternFinder *finder)
Definition: TGeoNode.h:205
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition: TGeoNode.h:41
Bool_t IsOverlapping() const
Definition: TGeoNode.h:102
TGeoVolume * GetVolume() const
Definition: TGeoNode.h:94
void SetVolume(TGeoVolume *volume)
Definition: TGeoNode.h:112
Bool_t IsOffset() const
Definition: TGeoNode.h:100
virtual Int_t GetByteCount() const
Definition: TGeoNode.h:81
void SetOverlapping(Bool_t flag=kTRUE)
Definition: TGeoNode.h:115
virtual Int_t GetOptimalVoxels() const
Definition: TGeoNode.h:96
virtual TGeoMatrix * GetMatrix() const =0
void SetMotherVolume(TGeoVolume *mother)
Definition: TGeoNode.h:120
virtual TGeoNode * MakeCopyNode() const
Definition: TGeoNode.h:108
void SetVirtual()
Definition: TGeoNode.h:116
Int_t GetNumber() const
Definition: TGeoNode.h:92
void SetNumber(Int_t number)
Definition: TGeoNode.h:113
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:245
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:26
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const =0
virtual void CreateThreadData(Int_t)
Definition: TGeoShape.h:68
Bool_t IsValid() const
Definition: TGeoShape.h:140
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.
Definition: TGeoShape.cxx:326
Bool_t IsRunTimeShape() const
Definition: TGeoShape.h:139
virtual void ClearThreadData() const
Definition: TGeoShape.h:67
const char * GetPointerName() const
Provide a pointer name containing uid.
Definition: TGeoShape.cxx:699
void CheckShape(Int_t testNo, Int_t nsamples=10000, Option_t *option="")
Test for shape navigation methods.
Definition: TGeoShape.cxx:209
virtual Bool_t IsValidBox() const =0
virtual Int_t GetByteCount() const =0
virtual void ComputeBBox()=0
virtual Double_t Capacity() const =0
@ kGeoSavePrimitive
Definition: TGeoShape.h:65
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:163
Volume assemblies.
Definition: TGeoVolume.h:308
static TGeoVolumeAssembly * MakeAssemblyFromVolume(TGeoVolume *vol)
Make a clone of volume VOL but which is an assembly.
virtual Int_t GetCurrentNodeIndex() const
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 makes no sense for assemblies.
virtual void ClearThreadData() const
virtual Int_t GetNextNodeIndex() const
virtual void AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
Add an overlapping node - not allowed for assemblies.
std::vector< ThreadData_t * > fThreadData
Definition: TGeoVolume.h:324
virtual ~TGeoVolumeAssembly()
Destructor. The assembly is owner of its "shape".
std::mutex fMutex
Thread vector size.
Definition: TGeoVolume.h:326
virtual void AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=0, Option_t *option="")
Add a component to the assembly.
Int_t fThreadSize
Thread specific data vector.
Definition: TGeoVolume.h:325
void SetNextNodeIndex(Int_t index)
virtual TGeoVolume * CloneVolume() const
Clone this volume.
void SetCurrentNodeIndex(Int_t index)
TGeoVolumeAssembly()
Mutex for concurrent operations.
virtual void CreateThreadData(Int_t nthreads)
ThreadData_t & GetThreadData() const
Volume families.
Definition: TGeoVolume.h:257
virtual void SetVisibility(Bool_t vis=kTRUE)
Set visibility for all components.
virtual TGeoVolume * MakeCopyVolume(TGeoShape *newshape)
Make a copy of this volume build a volume with same name, shape and medium.
Double_t fStart
Definition: TGeoVolume.h:264
void AddVolume(TGeoVolume *vol)
Add a volume with valid shape to the list of volumes.
virtual void SetLineStyle(Style_t lstyle)
Set the line style for all components.
virtual void AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option="")
Add a new node to the list of nodes, This node is possibly overlapping with other daughters of the vo...
TGeoVolume * GetVolume(Int_t id) const
Definition: TGeoVolume.h:278
virtual ~TGeoVolumeMulti()
Destructor.
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 of multiple volumes
Double_t fStep
Definition: TGeoVolume.h:265
virtual void SetLineColor(Color_t lcolor)
Set the line color for all components.
TGeoVolumeMulti * fDivision
Definition: TGeoVolume.h:260
TGeoVolumeMulti & operator=(const TGeoVolumeMulti &)
assignment operator
TGeoVolumeMulti()
dummy constructor
virtual void AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option="")
Add a new node to the list of nodes.
TGeoShape * GetLastShape() const
Returns the last shape.
Int_t GetNvolumes() const
Definition: TGeoVolume.h:283
virtual void SetMedium(TGeoMedium *medium)
Set medium for a multiple volume.
TObjArray * fVolumes
Definition: TGeoVolume.h:259
virtual void SetLineWidth(Width_t lwidth)
Set the line width for all components.
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition: TGeoVolume.h:53
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.
virtual void cd(Int_t inode) const
Actualize matrix of node indexed <inode>
Definition: TGeoVolume.cxx:975
virtual void ClearThreadData() const
Definition: TGeoVolume.cxx:423
virtual ~TGeoVolume()
Destructor.
Definition: TGeoVolume.cxx:554
virtual void Print(Option_t *option="") const
Print volume info.
Bool_t IsVisContainers() const
Definition: TGeoVolume.h:158
void SetVoxelFinder(TGeoVoxelFinder *finder)
Definition: TGeoVolume.h:233
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.
void RandomRays(Int_t nrays=10000, Double_t startx=0, Double_t starty=0, Double_t startz=0, const char *target_vol=0, Bool_t check_norm=kFALSE)
Random raytracing method.
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.
Definition: TGeoVolume.cxx:805
Int_t fNtotal
Definition: TGeoVolume.h:66
void MakeCopyNodes(const TGeoVolume *other)
make a new list of nodes and copy all nodes of other volume inside
TGeoNode * ReplaceNode(TGeoNode *nodeorig, TGeoShape *newshape=0, TGeoMatrix *newpos=0, TGeoMedium *newmed=0)
Replace an existing daughter with a new volume having the same name but possibly a new shape,...
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:235
void ClearNodes()
Definition: TGeoVolume.h:103
void Raytrace(Bool_t flag=kTRUE)
Draw this volume with current settings and perform raytracing in the pad.
TGeoVolume()
dummy constructor
Definition: TGeoVolume.cxx:447
TGeoMedium * GetMedium() const
Definition: TGeoVolume.h:176
virtual Bool_t IsFolder() const
Return TRUE if volume contains nodes.
Definition: TGeoVolume.cxx:844
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
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
compute the closest distance of approach from point px,py to this volume
Double_t Capacity() const
Computes the capacity of this [cm^3] as the capacity of its shape.
Definition: TGeoVolume.cxx:605
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:65
virtual void CreateThreadData(Int_t nthreads)
Definition: TGeoVolume.cxx:431
virtual Int_t GetByteCount() const
get the total size in bytes for this volume
Bool_t OptimizeVoxels()
Perform an extensive sampling to find which type of voxelization is most efficient.
void SetCurrentPoint(Double_t x, Double_t y, Double_t z)
Set the current tracking point.
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute mouse actions on this volume.
virtual void SetVisLeaves(Bool_t flag=kTRUE)
Set visibility for leaves.
void Browse(TBrowser *b)
How to browse a volume.
Definition: TGeoVolume.cxx:571
TGeoManager * fGeoManager
Definition: TGeoVolume.h:61
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.
TGeoVoxelFinder * fVoxels
Definition: TGeoVolume.h:60
TGeoMaterial * GetMaterial() const
Definition: TGeoVolume.h:175
virtual Bool_t IsVolumeMulti() const
Definition: TGeoVolume.h:118
TGeoExtension * GrabUserExtension() const
Get a copy of the user extension pointer.
@ kVolumeClone
Definition: TGeoVolume.h:88
@ kVolumeSelected
Definition: TGeoVolume.h:81
@ kVolumeMulti
Definition: TGeoVolume.h:85
@ kVolumeImportNodes
Definition: TGeoVolume.h:84
Int_t CountNodes(Int_t nlevels=1000, Int_t option=0)
Count total number of subnodes starting from this volume, nlevels down.
Definition: TGeoVolume.cxx:754
void GrabFocus()
Move perspective view focus to this volume.
void UnmarkSaved()
Reset SavePrimitive bits.
virtual TGeoVolume * CloneVolume() const
Clone this volume.
void SetFinder(TGeoPatternFinder *finder)
Definition: TGeoVolume.h:234
Int_t GetNdaughters() const
Definition: TGeoVolume.h:350
Bool_t IsValid() const
Definition: TGeoVolume.h:155
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
void Grab()
Definition: TGeoVolume.h:142
char * GetPointerName() const
Provide a pointer name containing uid.
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...
Definition: TGeoVolume.cxx:620
void SelectVolume(Bool_t clear=kFALSE)
Select this volume as matching an arbitrary criteria.
TObjArray * GetNodes()
Definition: TGeoVolume.h:170
virtual char * GetObjectInfo(Int_t px, Int_t py) const
Get volume info for the browser.
Option_t * GetOption() const
Definition: TGeoVolume.h:188
void ClearShape()
Clear the shape of this volume from the list held by the current manager.
Definition: TGeoVolume.cxx:692
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
TGeoNode * GetNode(const char *name) const
get the pointer to a daughter node
virtual void SetVisibility(Bool_t vis=kTRUE)
set visibility of 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.
Definition: TGeoVolume.cxx:700
void SetNtotal(Int_t ntotal)
Definition: TGeoVolume.h:236
virtual void Paint(Option_t *option="")
paint volume
Bool_t GetOptimalVoxels() const
Returns true if cylindrical voxelization is optimal.
void InvisibleAll(Bool_t flag=kTRUE)
Make volume and each of it daughters (in)visible.
Definition: TGeoVolume.cxx:816
Bool_t IsVisibleDaughters() const
Definition: TGeoVolume.h:157
TString fOption
just a hook for now
Definition: TGeoVolume.h:64
void SaveAs(const char *filename, Option_t *option="") const
Save geometry having this as top volume as a C++ macro.
Int_t GetIndex(const TGeoNode *node) const
get index number for a given daughter
void SetNodes(TObjArray *nodes)
Definition: TGeoVolume.h:217
TGeoPatternFinder * GetFinder() const
Definition: TGeoVolume.h:178
void PrintVoxels() const
Print the voxels for this volume.
TGeoExtension * fUserExtension
Definition: TGeoVolume.h:68
virtual void SetMedium(TGeoMedium *medium)
Definition: TGeoVolume.h:232
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
void SetAttVisibility(Bool_t vis)
Definition: TGeoVolume.h:223
TGeoVolume & operator=(const TGeoVolume &)
assignment operator
Definition: TGeoVolume.cxx:526
void SetShape(const TGeoShape *shape)
set the shape associated with this volume
static TGeoMedium * DummyMedium()
Definition: TGeoVolume.cxx:439
TObject * fField
pointer to TGeoManager owning this volume
Definition: TGeoVolume.h:63
Int_t GetNumber() const
Definition: TGeoVolume.h:185
void CleanAll()
Clean data of the volume.
Definition: TGeoVolume.cxx:683
Bool_t IsTopVolume() const
True if this is the top volume of the geometry.
Definition: TGeoVolume.cxx:864
TGeoMedium * fMedium
Definition: TGeoVolume.h:57
TGeoShape * GetShape() const
Definition: TGeoVolume.h:191
void InspectMaterial() const
Inspect the material for this volume.
Definition: TGeoVolume.cxx:881
void PrintNodes() const
print nodes
static TGeoMedium * fgDummyMedium
Definition: TGeoVolume.h:58
void RegisterYourself(Option_t *option="")
Register the volume and all materials/media/matrices/shapes to the manager.
virtual void AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=0, Option_t *option="")
Add a TGeoNode to the list of nodes.
virtual void Draw(Option_t *option="")
draw top volume according to option
virtual void SetVisOnly(Bool_t flag=kTRUE)
Set visibility for leaves.
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.
Definition: TGeoVolume.cxx:873
TGeoShape * fShape
Definition: TGeoVolume.h:56
void SetField(TObject *field)
Definition: TGeoVolume.h:221
static TGeoVolume * Import(const char *filename, const char *name="", Option_t *option="")
Import a volume from a file.
Definition: TGeoVolume.cxx:889
Bool_t IsStyleDefault() const
check if the visibility and attributes are the default ones
Definition: TGeoVolume.cxx:852
static void CreateDummyMedium()
Create a dummy medium.
Definition: TGeoVolume.cxx:411
TGeoExtension * fFWExtension
Transient user-defined extension to volumes.
Definition: TGeoVolume.h:69
void SetAsTopVolume()
Set this volume as the TOP one (the whole geometry starts from here)
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Bool_t IsVisLeaves() const
Definition: TGeoVolume.h:159
virtual void SetVisContainers(Bool_t flag=kTRUE)
Set visibility for containers.
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
TObject * GetField() const
Definition: TGeoVolume.h:177
TGeoPatternFinder * fFinder
dummy medium
Definition: TGeoVolume.h:59
Int_t Export(const char *filename, const char *name="", Option_t *option="")
Export this volume to a file.
Definition: TGeoVolume.cxx:939
virtual void DrawOnly(Option_t *option="")
draw only this volume
virtual void SetLineColor(Color_t lcolor)
Set the line color.
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.
virtual void AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=0, Option_t *option="")
Add a TGeoNode to the list of nodes.
Definition: TGeoVolume.cxx:984
TObjArray * fNodes
Definition: TGeoVolume.h:55
virtual Bool_t IsVisible() const
Definition: TGeoVolume.h:156
Int_t GetNtotal() const
Definition: TGeoVolume.h:172
void InspectShape() const
Definition: TGeoVolume.h:196
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.
Definition: TGeoVolume.cxx:641
void SetOverlappingCandidate(Bool_t flag)
Definition: TGeoVolume.h:218
Bool_t IsOverlappingCandidate() const
Definition: TGeoVolume.h:149
Int_t fRefCount
Definition: TGeoVolume.h:67
void CheckShape(Int_t testNo, Int_t nsamples=10000, Option_t *option="")
Tests for checking the shape navigation algorithms. See TGeoShape::CheckShape()
Definition: TGeoVolume.cxx:675
Finder class handling voxels.
Bool_t IsInvalid() const
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
virtual void Print(Option_t *option="") const
Print the voxels.
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:2974
2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:250
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual const char * GetClassName() const
Definition: TKey.h:71
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition: TKey.cxx:722
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:40
void Add(TObject *obj)
This function may not be used (but we need to provide it since it is a pure virtual in TCollection).
Definition: TMap.cxx:53
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition: TMap.cxx:235
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
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
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TNamed & operator=(const TNamed &rhs)
TNamed assignment operator.
Definition: TNamed.cxx:51
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
void Add(TObject *obj)
Definition: TObjArray.h:73
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:333
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:414
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:703
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:253
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:678
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:785
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TObject.cxx:664
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
void ResetBit(UInt_t f)
Definition: TObject.h:171
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Sequenceable collection abstract base class.
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1100
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
const char * Data() const
Definition: TString.h:364
Ssiz_t Capacity() const
Definition: TString.h:352
Bool_t IsNull() const
Definition: TString.h:402
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
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:2286
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
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 TH2F * LegoPlot(Int_t ntheta=60, Double_t themin=0., Double_t themax=180., Int_t nphi=90, Double_t phimin=0., Double_t phimax=360., Double_t rmin=0., Double_t rmax=9999999, Option_t *option="")=0
virtual void CheckOverlaps(const TGeoVolume *vol, Double_t ovlp=0.1, Option_t *option="") const =0
virtual void Paint(Option_t *option="")=0
This method must be overridden if a class wants to paint itself.
virtual Int_t DistanceToPrimitiveVol(TGeoVolume *vol, Int_t px, Int_t py)=0
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
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
constexpr Double_t E()
Base of natural log:
Definition: TMath.h:97
ThreadData_t()
index of next node to be entered