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