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");
422 dummyMaterial->SetName("dummy");
423 fgDummyMedium->SetMaterial(dummyMaterial);
424}
425
426////////////////////////////////////////////////////////////////////////////////
427
429{
430 if (fFinder)
432 if (fShape)
434}
435
436////////////////////////////////////////////////////////////////////////////////
437
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 }
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());
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++)
582 capacity += GetNode(i)->GetVolume()->Capacity();
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
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
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 // one-time init per OS thread
684 static thread_local bool navInit = false;
685 if (!navInit) {
686 if (!geom->GetCurrentNavigator())
687 geom->AddNavigator();
688 navInit = true;
689 }
690
691 std::vector<TGeoOverlapResult> local;
692 local.reserve(32);
693
694 for (size_t i = range.first; i < range.second; ++i) {
696 if (checker->ComputeOverlap(candidates[i], r))
697 local.emplace_back(std::move(r));
698 }
699
700 if (!local.empty()) {
701 std::lock_guard<std::mutex> lock(resultsMutex);
702 results.insert(results.end(), std::make_move_iterator(local.begin()), std::make_move_iterator(local.end()));
703 }
704 },
705 chunks);
706#else
707 // serial version
708 Info("CheckOverlaps", "--- checking candidates with on a single thread (IMT not configured)...");
709 timer.Start();
710 for (size_t i = 0; i < candidates.size(); ++i) {
712 if (checker->ComputeOverlap(candidates[i], r))
713 results.emplace_back(std::move(r));
714 }
715#endif
716
717 // -------- Stage 3: materialize overlaps (main thread)
718 for (const auto &r : results)
719 checker->MaterializeOverlap(r);
720
721 geom->SetCheckingOverlaps(kFALSE);
722 geom->SortOverlaps();
723
724 // Rename overlaps as before
725 TObjArray *overlaps = geom->GetListOfOverlaps();
726 const Int_t novlps = overlaps->GetEntriesFast();
727 for (Int_t i = 0; i < novlps; i++)
728 ((TNamed *)overlaps->At(i))->SetName(TString::Format("ov%05d", i));
729
730 timer.Stop();
731 Info("CheckOverlaps", "Number of illegal overlaps/extrusions : %d found in %g [sec]", novlps, timer.RealTime());
732}
733
734////////////////////////////////////////////////////////////////////////////////
735/// Overlap by sampling legacy checking tool. Check for illegal overlaps within a limit OVLP.
736
738{
739 if (!GetNdaughters() || fFinder)
740 return;
744 Info("CheckOverlaps", "[LEGACY] Checking overlaps by sampling %d points for volume %s", npoints, GetName());
745 Info("CheckOverlaps", "=== NOTE: Many overlaps may be missed. Extrusions NOT checked with sampling option ! ===");
746 }
747
748 checker->CheckOverlapsBySampling(this, ovlp, npoints);
749
753 Int_t novlps = overlaps->GetEntriesFast();
754 TNamed *obj;
756 for (Int_t i = 0; i < novlps; i++) {
757 obj = (TNamed *)overlaps->At(i);
758 if (novlps < 1000)
759 name = TString::Format("ov%03d", i);
760 else
761 name = TString::Format("ov%06d", i);
762 obj->SetName(name);
763 }
764 Info("CheckOverlaps", "Number of illegal overlaps/extrusions sampled for volume %s: %d\n", GetName(), novlps);
765 }
766}
767
768////////////////////////////////////////////////////////////////////////////////
769/// Tests for checking the shape navigation algorithms. See TGeoShape::CheckShape()
770
775
776////////////////////////////////////////////////////////////////////////////////
777/// Clean data of the volume.
778
780{
781 ClearNodes();
782 ClearShape();
783}
784
785////////////////////////////////////////////////////////////////////////////////
786/// Clear the shape of this volume from the list held by the current manager.
787
792
793////////////////////////////////////////////////////////////////////////////////
794/// check for negative parameters in shapes.
795
797{
798 if (fShape->IsRunTimeShape()) {
799 Error("CheckShapes", "volume %s has run-time shape", GetName());
800 InspectShape();
801 return;
802 }
803 if (!fNodes)
804 return;
806 TGeoNode *node = nullptr;
808 const TGeoShape *shape = nullptr;
810 for (Int_t i = 0; i < nd; i++) {
811 node = (TGeoNode *)fNodes->At(i);
812 // check if node has name
813 if (!node->GetName()[0])
814 printf("Daughter %i of volume %s - NO NAME!!!\n", i, GetName());
815 old_vol = node->GetVolume();
816 shape = old_vol->GetShape();
817 if (shape->IsRunTimeShape()) {
818 // printf(" Node %s/%s has shape with negative parameters. \n",
819 // GetName(), node->GetName());
820 // old_vol->InspectShape();
821 // make a copy of the node
822 new_node = node->MakeCopyNode();
823 if (!new_node) {
824 Fatal("CheckShapes", "Cannot make copy node for %s", node->GetName());
825 return;
826 }
828 if (!new_shape) {
829 Error("CheckShapes", "cannot resolve runtime shape for volume %s/%s\n", GetName(), old_vol->GetName());
830 continue;
831 }
832 TGeoVolume *new_volume = old_vol->MakeCopyVolume(new_shape);
833 // printf(" new volume %s shape params :\n", new_volume->GetName());
834 // new_volume->InspectShape();
835 new_node->SetVolume(new_volume);
836 // decouple the old node and put the new one instead
837 fNodes->AddAt(new_node, i);
838 // new_volume->CheckShapes();
839 }
840 }
841}
842
843////////////////////////////////////////////////////////////////////////////////
844/// Count total number of subnodes starting from this volume, nlevels down
845/// - option = 0 (default) - count only once per volume
846/// - option = 1 - count every time
847/// - option = 2 - count volumes on visible branches
848/// - option = 3 - return maximum level counted already with option = 0
849
851{
852 static Int_t maxlevel = 0;
853 static Int_t nlev = 0;
854
856 option = 0;
857 Int_t visopt = 0;
858 Int_t nd = GetNdaughters();
859 Bool_t last = (!nlevels || !nd) ? kTRUE : kFALSE;
860 switch (option) {
861 case 0:
862 if (fNtotal)
863 return fNtotal;
864 case 1: fNtotal = 1; break;
865 case 2:
867 if (!IsVisDaughters())
868 last = kTRUE;
869 switch (visopt) {
870 case TVirtualGeoPainter::kGeoVisDefault: fNtotal = (IsVisible()) ? 1 : 0; break;
871 case TVirtualGeoPainter::kGeoVisLeaves: fNtotal = (IsVisible() && last) ? 1 : 0;
872 }
873 if (!IsVisibleDaughters())
874 return fNtotal;
875 break;
876 case 3: return maxlevel;
877 }
878 if (last)
879 return fNtotal;
880 if (gGeoManager->GetTopVolume() == this) {
881 maxlevel = 0;
882 nlev = 0;
883 }
884 if (nlev > maxlevel)
885 maxlevel = nlev;
886 TGeoNode *node;
887 TGeoVolume *vol;
888 nlev++;
889 for (Int_t i = 0; i < nd; i++) {
890 node = GetNode(i);
891 vol = node->GetVolume();
892 fNtotal += vol->CountNodes(nlevels - 1, option);
893 }
894 nlev--;
895 return fNtotal;
896}
897
898////////////////////////////////////////////////////////////////////////////////
899/// Return TRUE if volume and all daughters are invisible.
900
902{
903 if (IsVisible())
904 return kFALSE;
905 Int_t nd = GetNdaughters();
906 for (Int_t i = 0; i < nd; i++)
907 if (GetNode(i)->GetVolume()->IsVisible())
908 return kFALSE;
909 return kTRUE;
910}
911
912////////////////////////////////////////////////////////////////////////////////
913/// Make volume and each of it daughters (in)visible.
914
916{
918 Int_t nd = GetNdaughters();
919 TObjArray *list = new TObjArray(nd + 1);
920 list->Add(this);
921 TGeoVolume *vol;
922 for (Int_t i = 0; i < nd; i++) {
923 vol = GetNode(i)->GetVolume();
924 vol->SetAttVisibility(!flag);
925 list->Add(vol);
926 }
927 TIter next(gROOT->GetListOfBrowsers());
928 TBrowser *browser = nullptr;
929 while ((browser = (TBrowser *)next())) {
930 for (Int_t i = 0; i < nd + 1; i++) {
931 vol = (TGeoVolume *)list->At(i);
932 browser->CheckObjectItem(vol, !flag);
933 }
934 browser->Refresh();
935 }
936 delete list;
938}
939
940////////////////////////////////////////////////////////////////////////////////
941/// Return TRUE if volume contains nodes
942
944{
945 return kTRUE;
946}
947
948////////////////////////////////////////////////////////////////////////////////
949/// check if the visibility and attributes are the default ones
950
952{
953 if (!IsVisible())
954 return kFALSE;
955 if (GetLineColor() != gStyle->GetLineColor())
956 return kFALSE;
957 if (GetLineStyle() != gStyle->GetLineStyle())
958 return kFALSE;
959 if (GetLineWidth() != gStyle->GetLineWidth())
960 return kFALSE;
961 return kTRUE;
962}
963
964////////////////////////////////////////////////////////////////////////////////
965/// True if this is the top volume of the geometry
966
968{
969 if (fGeoManager->GetTopVolume() == this)
970 return kTRUE;
971 return kFALSE;
972}
973
974////////////////////////////////////////////////////////////////////////////////
975/// Check if the painter is currently ray-tracing the content of this volume.
976
981
982////////////////////////////////////////////////////////////////////////////////
983/// Inspect the material for this volume.
984
986{
987 GetMaterial()->Print();
988}
989
990////////////////////////////////////////////////////////////////////////////////
991/// Import a volume from a file.
992
993TGeoVolume *TGeoVolume::Import(const char *filename, const char *name, Option_t * /*option*/)
994{
995 if (!gGeoManager)
996 gGeoManager = new TGeoManager("geometry", "");
997 if (!filename)
998 return nullptr;
999 TGeoVolume *volume = nullptr;
1000 if (strstr(filename, ".gdml")) {
1001 // import from a gdml file
1002 } else {
1003 // import from a root file
1006 if (!f || f->IsZombie()) {
1007 printf("Error: TGeoVolume::Import : Cannot open file %s\n", filename);
1008 return nullptr;
1009 }
1010 if (name && name[0]) {
1011 volume = (TGeoVolume *)f->Get(name);
1012 } else {
1013 TIter next(f->GetListOfKeys());
1014 TKey *key;
1015 while ((key = (TKey *)next())) {
1016 if (strcmp(key->GetClassName(), "TGeoVolume") != 0)
1017 continue;
1018 volume = (TGeoVolume *)key->ReadObj();
1019 break;
1020 }
1021 }
1022 delete f;
1023 }
1024 if (!volume)
1025 return nullptr;
1026 volume->RegisterYourself();
1027 return volume;
1028}
1029
1030////////////////////////////////////////////////////////////////////////////////
1031/// Export this volume to a file.
1032///
1033/// - Case 1: root file or root/xml file
1034/// if filename end with ".root". The key will be named name
1035/// if filename end with ".xml" a root/xml file is produced.
1036///
1037/// - Case 2: C++ script
1038/// if filename end with ".C"
1039///
1040/// - Case 3: gdml file
1041/// if filename end with ".gdml"
1042///
1043/// NOTE that to use this option, the PYTHONPATH must be defined like
1044/// export PYTHONPATH=$ROOTSYS/lib:$ROOTSYS/gdml
1045///
1046
1048{
1050 if (sfile.Contains(".C")) {
1051 // Save volume as a C++ script
1052 Info("Export", "Exporting volume %s as C++ code", GetName());
1053 SaveAs(filename, "");
1054 return 1;
1055 }
1056 if (sfile.Contains(".gdml")) {
1057 // Save geometry as a gdml file
1058 Info("Export", "Exporting %s as gdml code - not implemented yet", GetName());
1059 return 0;
1060 }
1061 if (sfile.Contains(".root") || sfile.Contains(".xml")) {
1062 // Save volume in a root file
1063 Info("Export", "Exporting %s as root file.", GetName());
1064 TString opt(option);
1065 if (!opt.Length())
1066 opt = "recreate";
1067 TFile *f = TFile::Open(filename, opt.Data());
1068 if (!f || f->IsZombie()) {
1069 Error("Export", "Cannot open file");
1070 return 0;
1071 }
1073 if (keyname.IsNull())
1074 keyname = GetName();
1076 delete f;
1077 return nbytes;
1078 }
1079 return 0;
1080}
1081
1082////////////////////////////////////////////////////////////////////////////////
1083/// Actualize matrix of node indexed `<inode>`
1084
1086{
1087 if (fFinder)
1089}
1090
1091////////////////////////////////////////////////////////////////////////////////
1092/// Add a TGeoNode to the list of nodes. This is the usual method for adding
1093/// daughters inside the container volume.
1094
1096{
1098 if (matrix == nullptr)
1100 else
1101 matrix->RegisterYourself();
1102 if (!vol) {
1103 Error("AddNode", "Volume is NULL");
1104 return nullptr;
1105 }
1106 if (!vol->IsValid()) {
1107 Error("AddNode", "Won't add node with invalid shape");
1108 printf("### invalid volume was : %s\n", vol->GetName());
1109 return nullptr;
1110 }
1111 if (!fNodes)
1112 fNodes = new TObjArray();
1113
1114 if (fFinder) {
1115 // volume already divided.
1116 Error("AddNode", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
1117 return nullptr;
1118 }
1119
1120 TGeoNodeMatrix *node = nullptr;
1121 node = new TGeoNodeMatrix(vol, matrix);
1122 node->SetMotherVolume(this);
1123 fNodes->Add(node);
1124 TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
1125 // if (fNodes->FindObject(name))
1126 // Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
1127 node->SetName(name);
1128 node->SetNumber(copy_no);
1129 fRefCount++;
1130 vol->Grab();
1131 return node;
1132}
1133
1134////////////////////////////////////////////////////////////////////////////////
1135/// Add a division node to the list of nodes. The method is called by
1136/// TGeoVolume::Divide() for creating the division nodes.
1137
1139{
1140 if (!vol) {
1141 Error("AddNodeOffset", "invalid volume");
1142 return;
1143 }
1144 if (!vol->IsValid()) {
1145 Error("AddNode", "Won't add node with invalid shape");
1146 printf("### invalid volume was : %s\n", vol->GetName());
1147 return;
1148 }
1149 if (!fNodes)
1150 fNodes = new TObjArray();
1151 TGeoNode *node = new TGeoNodeOffset(vol, copy_no, offset);
1152 node->SetMotherVolume(this);
1153 fNodes->Add(node);
1154 TString name = TString::Format("%s_%d", vol->GetName(), copy_no + 1);
1155 node->SetName(name);
1156 node->SetNumber(copy_no + 1);
1157 vol->Grab();
1158}
1159
1160////////////////////////////////////////////////////////////////////////////////
1161/// Add a TGeoNode to the list of nodes. This is the usual method for adding
1162/// daughters inside the container volume.
1163
1165{
1166 if (!vol) {
1167 Error("AddNodeOverlap", "Volume is NULL");
1168 return;
1169 }
1170 if (!vol->IsValid()) {
1171 Error("AddNodeOverlap", "Won't add node with invalid shape");
1172 printf("### invalid volume was : %s\n", vol->GetName());
1173 return;
1174 }
1175 if (vol->IsAssembly()) {
1176 Warning("AddNodeOverlap",
1177 "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",
1178 vol->GetName(), GetName());
1179 AddNode(vol, copy_no, mat, option);
1180 return;
1181 }
1183 if (matrix == nullptr)
1185 else
1186 matrix->RegisterYourself();
1187 if (!fNodes)
1188 fNodes = new TObjArray();
1189
1190 if (fFinder) {
1191 // volume already divided.
1192 Error("AddNodeOverlap", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
1193 return;
1194 }
1195
1196 TGeoNodeMatrix *node = new TGeoNodeMatrix(vol, matrix);
1197 node->SetMotherVolume(this);
1198 fNodes->Add(node);
1199 TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
1200 if (fNodes->FindObject(name))
1201 Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
1202 node->SetName(name);
1203 node->SetNumber(copy_no);
1204 node->SetOverlapping();
1205 if (vol->GetMedium() == fMedium)
1206 node->SetVirtual();
1207 vol->Grab();
1208}
1209
1210////////////////////////////////////////////////////////////////////////////////
1211/// Division a la G3. The volume will be divided along IAXIS (see shape classes), in NDIV
1212/// slices, from START with given STEP. The division volumes will have medium number NUMED.
1213/// If NUMED=0 they will get the medium number of the divided volume (this). If NDIV<=0,
1214/// all range of IAXIS will be divided and the resulting number of divisions will be centered on
1215/// IAXIS. If STEP<=0, the real STEP will be computed as the full range of IAXIS divided by NDIV.
1216/// Options (case insensitive):
1217/// - N - divide all range in NDIV cells (same effect as STEP<=0) (GSDVN in G3)
1218/// - NX - divide range starting with START in NDIV cells (GSDVN2 in G3)
1219/// - S - divide all range with given STEP. NDIV is computed and divisions will be centered
1220/// in full range (same effect as NDIV<=0) (GSDVS, GSDVT in G3)
1221/// - SX - same as DVS, but from START position. (GSDVS2, GSDVT2 in G3)
1222
1225{
1226 if (fFinder) {
1227 // volume already divided.
1228 Fatal("Divide", "volume %s already divided", GetName());
1229 return nullptr;
1230 }
1231 TString opt(option);
1232 opt.ToLower();
1233 TString stype = fShape->ClassName();
1234 if (!fNodes)
1235 fNodes = new TObjArray();
1236 Double_t xlo, xhi, range;
1237 range = fShape->GetAxisRange(iaxis, xlo, xhi);
1238 // for phi divisions correct the range
1239 if (!strcmp(fShape->GetAxisName(iaxis), "PHI")) {
1240 if ((start - xlo) < -1E-3)
1241 start += 360.;
1243 xlo = start;
1244 xhi = start + range;
1245 }
1246 }
1247 if (range <= 0) {
1248 InspectShape();
1249 Fatal("Divide", "cannot divide volume %s (%s) on %s axis", GetName(), stype.Data(), fShape->GetAxisName(iaxis));
1250 return nullptr;
1251 }
1252 if (ndiv <= 0 || opt.Contains("s")) {
1253 if (step <= 0) {
1254 Fatal("Divide", "invalid division type for volume %s : ndiv=%i, step=%g", GetName(), ndiv, step);
1255 return nullptr;
1256 }
1257 if (opt.Contains("x")) {
1258 if ((xlo - start) > 1E-3 || (xhi - start) < -1E-3) {
1259 Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)", start,
1260 fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1261 return nullptr;
1262 }
1263 xlo = start;
1264 range = xhi - xlo;
1265 }
1266 ndiv = Int_t((range + 0.1 * step) / step);
1267 Double_t ddx = range - ndiv * step;
1268 // always center the division in this case
1269 if (ddx > 1E-3)
1270 Warning("Divide", "division of volume %s on %s axis (ndiv=%d) will be centered in the full range", GetName(),
1271 fShape->GetAxisName(iaxis), ndiv);
1272 start = xlo + 0.5 * ddx;
1273 }
1274 if (step <= 0 || opt.Contains("n")) {
1275 if (opt.Contains("x")) {
1276 if ((xlo - start) > 1E-3 || (xhi - start) < -1E-3) {
1277 Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)", start,
1278 fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1279 return nullptr;
1280 }
1281 xlo = start;
1282 range = xhi - xlo;
1283 }
1284 step = range / ndiv;
1285 start = xlo;
1286 }
1287
1288 Double_t end = start + ndiv * step;
1289 if (((start - xlo) < -1E-3) || ((end - xhi) > 1E-3)) {
1290 Fatal("Divide", "division of volume %s on axis %s exceed range (%g, %g)", GetName(), fShape->GetAxisName(iaxis),
1291 xlo, xhi);
1292 return nullptr;
1293 }
1294 TGeoVolume *voldiv = fShape->Divide(this, divname, iaxis, ndiv, start, step);
1295 if (numed) {
1297 if (!medium) {
1298 Fatal("Divide", "invalid medium number %d for division volume %s", numed, divname);
1299 return voldiv;
1300 }
1301 voldiv->SetMedium(medium);
1302 if (medium->GetMaterial())
1303 medium->GetMaterial()->SetUsed();
1304 }
1305 return voldiv;
1306}
1307
1308////////////////////////////////////////////////////////////////////////////////
1309/// compute the closest distance of approach from point px,py to this volume
1310
1312{
1313 if (gGeoManager != fGeoManager)
1316 Int_t dist = 9999;
1317 if (!painter)
1318 return dist;
1319 dist = painter->DistanceToPrimitiveVol(this, px, py);
1320 return dist;
1321}
1322
1323////////////////////////////////////////////////////////////////////////////////
1324/// draw top volume according to option
1325
1327{
1328 if (gGeoManager != fGeoManager)
1333 if (!IsVisContainers())
1334 SetVisLeaves();
1335 if (option && option[0] > 0) {
1336 painter->DrawVolume(this, option);
1337 } else {
1338 painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption", ""));
1339 }
1340}
1341
1342////////////////////////////////////////////////////////////////////////////////
1343/// draw only this volume
1344
1346{
1347 if (IsAssembly()) {
1348 Info("DrawOnly", "Volume assemblies do not support this option.");
1349 return;
1350 }
1351 if (gGeoManager != fGeoManager)
1353 SetVisOnly();
1356 if (option && option[0] > 0) {
1357 painter->DrawVolume(this, option);
1358 } else {
1359 painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption", ""));
1360 }
1361}
1362
1363////////////////////////////////////////////////////////////////////////////////
1364/// Perform an extensive sampling to find which type of voxelization is
1365/// most efficient.
1366
1368{
1369 printf("Optimizing volume %s ...\n", GetName());
1371 return checker->TestVoxels(this);
1372}
1373
1374////////////////////////////////////////////////////////////////////////////////
1375/// Print volume info
1376
1378{
1379 printf("== Volume: %s type %s positioned %d times\n", GetName(), ClassName(), fRefCount);
1380 InspectShape();
1382}
1383
1384////////////////////////////////////////////////////////////////////////////////
1385/// paint volume
1386
1388{
1390 painter->SetTopVolume(this);
1391 // painter->Paint(option);
1392 if (option && option[0] > 0) {
1393 painter->Paint(option);
1394 } else {
1395 painter->Paint(gEnv->GetValue("Viewer3D.DefaultDrawOption", ""));
1396 }
1397}
1398
1399////////////////////////////////////////////////////////////////////////////////
1400/// Print the voxels for this volume.
1401
1403{
1404 if (fVoxels)
1405 fVoxels->Print();
1406}
1407
1408////////////////////////////////////////////////////////////////////////////////
1409/// Recreate the content of the other volume without pointer copying. Voxels are
1410/// ignored and supposed to be created in a later step via Voxelize.
1411
1413{
1414 Int_t nd = other->GetNdaughters();
1415 if (!nd)
1416 return;
1417 TGeoPatternFinder *finder = other->GetFinder();
1418 if (finder) {
1419 Int_t iaxis = finder->GetDivAxis();
1420 Int_t ndiv = finder->GetNdiv();
1421 Double_t start = finder->GetStart();
1422 Double_t step = finder->GetStep();
1423 Int_t numed = other->GetNode(0)->GetVolume()->GetMedium()->GetId();
1424 TGeoVolume *voldiv = Divide(other->GetNode(0)->GetVolume()->GetName(), iaxis, ndiv, start, step, numed);
1425 voldiv->ReplayCreation(other->GetNode(0)->GetVolume());
1426 return;
1427 }
1428 for (Int_t i = 0; i < nd; i++) {
1429 TGeoNode *node = other->GetNode(i);
1430 if (node->IsOverlapping())
1431 AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1432 else
1433 AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1434 }
1435}
1436
1437////////////////////////////////////////////////////////////////////////////////
1438/// print nodes
1439
1441{
1442 Int_t nd = GetNdaughters();
1443 for (Int_t i = 0; i < nd; i++) {
1444 printf("%s\n", GetNode(i)->GetName());
1445 cd(i);
1446 GetNode(i)->GetMatrix()->Print();
1447 }
1448}
1449////////////////////////////////////////////////////////////////////////////////
1450/// Generate a lego plot fot the top volume, according to option.
1451
1454{
1457 if (old_vol != this)
1459 else
1460 old_vol = nullptr;
1461 TH2F *hist = checker->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);
1462 hist->Draw("lego1sph");
1463 return hist;
1464}
1465
1466////////////////////////////////////////////////////////////////////////////////
1467/// Register the volume and all materials/media/matrices/shapes to the manager.
1468
1470{
1472 return;
1473 // Register volume
1474 fGeoManager->AddVolume(this);
1475 // Register shape
1477 if (fShape->IsComposite()) {
1479 comp->RegisterYourself();
1480 } else {
1482 }
1483 }
1484 // Register medium/material
1489 }
1490 // Register matrices for nodes.
1492 TGeoNode *node;
1493 Int_t nd = GetNdaughters();
1494 Int_t i;
1495 for (i = 0; i < nd; i++) {
1496 node = GetNode(i);
1497 matrix = node->GetMatrix();
1498 if (!matrix->IsRegistered())
1499 matrix->RegisterYourself();
1502 }
1503 }
1504 // Call RegisterYourself recursively
1505 for (i = 0; i < nd; i++)
1507}
1508
1509////////////////////////////////////////////////////////////////////////////////
1510/// Draw random points in the bounding box of this volume.
1511
1513{
1514 if (gGeoManager != fGeoManager)
1517 if (old_vol != this)
1519 else
1520 old_vol = nullptr;
1522 if (old_vol)
1524}
1525
1526////////////////////////////////////////////////////////////////////////////////
1527/// Random raytracing method.
1528
1543
1544////////////////////////////////////////////////////////////////////////////////
1545/// Draw this volume with current settings and perform raytracing in the pad.
1546
1548{
1550 if (gGeoManager != fGeoManager)
1553 Bool_t drawn = (painter->GetDrawnVolume() == this) ? kTRUE : kFALSE;
1554 if (!drawn) {
1555 painter->DrawVolume(this, "");
1557 painter->ModifiedPad();
1558 return;
1559 }
1561 painter->ModifiedPad();
1562}
1563
1564////////////////////////////////////////////////////////////////////////////////
1565/// Save geometry having this as top volume as a C++ macro.
1566
1568{
1569 if (!filename)
1570 return;
1571 std::ofstream out;
1572 out.open(filename, std::ios::out);
1573 if (out.bad()) {
1574 Error("SavePrimitive", "Bad file name: %s", filename);
1575 return;
1576 }
1577 if (fGeoManager->GetTopVolume() != this)
1579
1581 Int_t ind = fname.Index(".");
1582 if (ind > 0)
1583 fname.Remove(ind);
1584 out << "void " << fname << "() {" << std::endl;
1585 out << " gSystem->Load(\"libGeom\");" << std::endl;
1587 out << std::setprecision(prec);
1588 ((TGeoVolume *)this)->SavePrimitive(out, option);
1589 out << "}" << std::endl;
1590}
1591
1592////////////////////////////////////////////////////////////////////////////////
1593/// Connect user-defined extension to the volume. The volume "grabs" a copy, so
1594/// the original object can be released by the producer. Release the previously
1595/// connected extension if any.
1596///
1597/// NOTE: This interface is intended for user extensions and is guaranteed not
1598/// to be used by TGeo
1599
1601{
1603 fUserExtension = nullptr;
1604 if (ext)
1605 fUserExtension = ext->Grab();
1606 if (tmp)
1607 tmp->Release();
1608}
1609
1610////////////////////////////////////////////////////////////////////////////////
1611/// Connect framework defined extension to the volume. The volume "grabs" a copy,
1612/// so the original object can be released by the producer. Release the previously
1613/// connected extension if any.
1614///
1615/// NOTE: This interface is intended for the use by TGeo and the users should
1616/// NOT connect extensions using this method
1617
1619{
1621 fFWExtension = nullptr;
1622 if (ext)
1623 fFWExtension = ext->Grab();
1624 if (tmp)
1625 tmp->Release();
1626}
1627
1628////////////////////////////////////////////////////////////////////////////////
1629/// Get a copy of the user extension pointer. The user must call Release() on
1630/// the copy pointer once this pointer is not needed anymore (equivalent to
1631/// delete() after calling new())
1632
1634{
1635 if (fUserExtension)
1636 return fUserExtension->Grab();
1637 return nullptr;
1638}
1639
1640////////////////////////////////////////////////////////////////////////////////
1641/// Get a copy of the framework extension pointer. The user must call Release() on
1642/// the copy pointer once this pointer is not needed anymore (equivalent to
1643/// delete() after calling new())
1644
1646{
1647 if (fFWExtension)
1648 return fFWExtension->Grab();
1649 return nullptr;
1650}
1651
1652////////////////////////////////////////////////////////////////////////////////
1653/// Save a primitive as a C++ statement(s) on output stream "out".
1654
1655void TGeoVolume::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1656{
1657 Int_t i, icopy;
1658 Int_t nd = GetNdaughters();
1660 TGeoNode *dnode;
1662
1663 // check if we need to save shape/volume
1665 if (fGeoManager->GetGeomPainter()->GetTopVolume() == this)
1666 mustDraw = kTRUE;
1667 if (!option[0]) {
1669 out << " new TGeoManager(\"" << fGeoManager->GetName() << "\", \"" << fGeoManager->GetTitle() << "\");"
1670 << std::endl
1671 << std::endl;
1672 // if (mustDraw) out << " Bool_t mustDraw = kTRUE;" << std::endl;
1673 // else out << " Bool_t mustDraw = kFALSE;" << std::endl;
1674 out << " Double_t dx, dy, dz;" << std::endl;
1675 out << " Double_t dx1, dx2, dy1, dy2;" << std::endl;
1676 out << " Double_t vert[20], par[20];" << std::endl;
1677 out << " Double_t theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2;" << std::endl;
1678 out << " Double_t twist;" << std::endl;
1679 out << " Double_t origin[3];" << std::endl;
1680 out << " Double_t rmin, rmax, rmin1, rmax1, rmin2, rmax2;" << std::endl;
1681 out << " Double_t r, rlo, rhi;" << std::endl;
1682 out << " Double_t a, b;" << std::endl;
1683 out << " Double_t point[3], norm[3];" << std::endl;
1684 out << " Double_t rin, stin, rout, stout;" << std::endl;
1685 out << " Double_t thx, phx, thy, phy, thz, phz;" << std::endl;
1686 out << " Double_t alpha, theta1, theta2, phi1, phi2, dphi;" << std::endl;
1687 out << " Double_t tr[3], rot[9];" << std::endl;
1688 out << " Double_t z, density, radl, absl, w;" << std::endl;
1689 out << " Double_t lx, ly, lz, tx, ty, tz;" << std::endl;
1690 out << " Double_t xvert[50], yvert[50];" << std::endl;
1691 out << " Double_t zsect, x0, y0, scale0;" << std::endl;
1692 out << " Int_t nel, numed, nz, nedges, nvert;" << std::endl;
1693 out << " TGeoBoolNode *pBoolNode = nullptr;" << std::endl << std::endl;
1694 // first save materials/media
1695 out << " // MATERIALS, MIXTURES AND TRACKING MEDIA" << std::endl;
1696 SavePrimitive(out, "m");
1697 // then, save matrices
1698 out << std::endl << " // TRANSFORMATION MATRICES" << std::endl;
1699 SavePrimitive(out, "x");
1700 // save this volume and shape
1701 SavePrimitive(out, "s");
1702 out << std::endl << " // SET TOP VOLUME OF GEOMETRY" << std::endl;
1703 out << " gGeoManager->SetTopVolume(" << GetPointerName() << ");" << std::endl;
1704 // save daughters
1705 out << std::endl << " // SHAPES, VOLUMES AND GEOMETRICAL HIERARCHY" << std::endl;
1706 SavePrimitive(out, "d");
1707 out << std::endl << " // CLOSE GEOMETRY" << std::endl;
1708 out << " gGeoManager->CloseGeometry();" << std::endl;
1709 if (mustDraw) {
1710 if (!IsRaytracing())
1711 out << " gGeoManager->GetTopVolume()->Draw();" << std::endl;
1712 else
1713 out << " gGeoManager->GetTopVolume()->Raytrace();" << std::endl;
1714 }
1715 return;
1716 }
1717 // check if we need to save shape/volume
1718 if (!strcmp(option, "s")) {
1719 // create the shape for this volume
1721 return;
1722 if (!IsAssembly()) {
1724 out << " // Volume: " << GetName() << std::endl;
1725 out << " TGeoVolume *" << GetPointerName() << " = new TGeoVolume(\"" << GetName() << "\","
1726 << fShape->GetPointerName();
1727 if (fMedium)
1728 out << ", " << fMedium->GetPointerName();
1729 out << ");" << std::endl;
1730 } else {
1731 out << " // Assembly: " << GetName() << std::endl;
1732 out << " " << GetPointerName() << " = new TGeoVolumeAssembly(\"" << GetName() << "\""
1733 << ");" << std::endl;
1734 }
1735 SaveLineAttributes(out, GetPointerName(), 1, 1, 1);
1736 if (!IsVisible() && !IsAssembly())
1737 out << " " << GetPointerName() << "->SetVisibility(kFALSE);" << std::endl;
1738 if (!IsVisibleDaughters())
1739 out << " " << GetPointerName() << "->VisibleDaughters(kFALSE);" << std::endl;
1740 if (IsVisContainers())
1741 out << " " << GetPointerName() << "->SetVisContainers(kTRUE);" << std::endl;
1742 if (IsVisLeaves())
1743 out << " " << GetPointerName() << "->SetVisLeaves(kTRUE);" << std::endl;
1745 }
1746 // check if we need to save the media
1747 if (!strcmp(option, "m")) {
1748 if (fMedium)
1750 for (i = 0; i < nd; i++) {
1751 dvol = GetNode(i)->GetVolume();
1752 dvol->SavePrimitive(out, option);
1753 }
1754 return;
1755 }
1756 // check if we need to save the matrices
1757 if (!strcmp(option, "x")) {
1758 if (fFinder) {
1759 dvol = GetNode(0)->GetVolume();
1760 dvol->SavePrimitive(out, option);
1761 return;
1762 }
1763 for (i = 0; i < nd; i++) {
1764 dnode = GetNode(i);
1765 matrix = dnode->GetMatrix();
1766 if (!matrix->IsIdentity())
1767 matrix->SavePrimitive(out, option);
1768 dnode->GetVolume()->SavePrimitive(out, option);
1769 }
1770 return;
1771 }
1772 // check if we need to save volume daughters
1773 if (!strcmp(option, "d")) {
1774 if (!nd)
1775 return;
1777 return;
1779 if (fFinder) {
1780 // volume divided: generate volume->Divide()
1781 dnode = GetNode(0);
1782 dvol = dnode->GetVolume();
1783 out << " TGeoVolume *" << dvol->GetPointerName() << " = ";
1784 out << GetPointerName() << "->Divide(\"" << dvol->GetName() << "\", ";
1786 if (fMedium != dvol->GetMedium())
1787 out << ", " << dvol->GetMedium()->GetId();
1788 out << ");" << std::endl;
1789 dvol->SavePrimitive(out, "d");
1790 return;
1791 }
1792 for (i = 0; i < nd; i++) {
1793 dnode = GetNode(i);
1794 dvol = dnode->GetVolume();
1795 dvol->SavePrimitive(out, "s");
1796 matrix = dnode->GetMatrix();
1797 icopy = dnode->GetNumber();
1798 // generate AddNode()
1799 out << " " << GetPointerName() << "->AddNode";
1800 if (dnode->IsOverlapping())
1801 out << "Overlap";
1802 out << "(" << dvol->GetPointerName() << ", " << icopy;
1803 if (!matrix->IsIdentity())
1804 out << ", " << matrix->GetPointerName();
1805 out << ");" << std::endl;
1806 }
1807 // Recursive loop to daughters
1808 for (i = 0; i < nd; i++) {
1809 dnode = GetNode(i);
1810 dvol = dnode->GetVolume();
1811 dvol->SavePrimitive(out, "d");
1812 }
1813 }
1814}
1815
1816////////////////////////////////////////////////////////////////////////////////
1817/// Reset SavePrimitive bits.
1818
1826
1827////////////////////////////////////////////////////////////////////////////////
1828/// Execute mouse actions on this volume.
1829
1831{
1833 if (!painter)
1834 return;
1835 painter->ExecuteVolumeEvent(this, event, px, py);
1836}
1837
1838////////////////////////////////////////////////////////////////////////////////
1839/// search a daughter inside the list of nodes
1840
1842{
1843 return ((TGeoNode *)fNodes->FindObject(name));
1844}
1845
1846////////////////////////////////////////////////////////////////////////////////
1847/// Get the index of a daughter within check_list by providing the node pointer.
1848
1850{
1851 TGeoNode *current = nullptr;
1852 for (Int_t i = 0; i < ncheck; i++) {
1853 current = (TGeoNode *)fNodes->At(check_list[i]);
1854 if (current == node)
1855 return check_list[i];
1856 }
1857 return -1;
1858}
1859
1860////////////////////////////////////////////////////////////////////////////////
1861/// get index number for a given daughter
1862
1864{
1865 TGeoNode *current = nullptr;
1866 Int_t nd = GetNdaughters();
1867 if (!nd)
1868 return -1;
1869 for (Int_t i = 0; i < nd; i++) {
1870 current = (TGeoNode *)fNodes->At(i);
1871 if (current == node)
1872 return i;
1873 }
1874 return -1;
1875}
1876
1877////////////////////////////////////////////////////////////////////////////////
1878/// Get volume info for the browser.
1879
1881{
1882 TGeoVolume *vol = (TGeoVolume *)this;
1884 if (!painter)
1885 return nullptr;
1886 return (char *)painter->GetVolumeInfo(vol, px, py);
1887}
1888
1889////////////////////////////////////////////////////////////////////////////////
1890/// Returns true if cylindrical voxelization is optimal.
1891
1893{
1894 Int_t nd = GetNdaughters();
1895 if (!nd)
1896 return kFALSE;
1897 Int_t id;
1898 Int_t ncyl = 0;
1899 TGeoNode *node;
1900 for (id = 0; id < nd; id++) {
1901 node = (TGeoNode *)fNodes->At(id);
1902 ncyl += node->GetOptimalVoxels();
1903 }
1904 if (ncyl > (nd / 2))
1905 return kTRUE;
1906 return kFALSE;
1907}
1908
1909////////////////////////////////////////////////////////////////////////////////
1910/// Provide a pointer name containing uid.
1911
1913{
1914 static TString name;
1915 name.Form("p%s_%zx", GetName(), (size_t)this);
1916 return name.Data();
1917}
1918
1919////////////////////////////////////////////////////////////////////////////////
1920/// Getter for optimization structure.
1921
1923{
1924 if (fVoxels && !fVoxels->IsInvalid())
1925 return fVoxels;
1926 return nullptr;
1927}
1928
1929////////////////////////////////////////////////////////////////////////////////
1930/// Move perspective view focus to this volume
1931
1933{
1935 if (painter)
1936 painter->GrabFocus();
1937}
1938
1939////////////////////////////////////////////////////////////////////////////////
1940/// Returns true if the volume is an assembly or a scaled assembly.
1941
1943{
1944 return fShape->IsAssembly();
1945}
1946
1947////////////////////////////////////////////////////////////////////////////////
1948/// Clone this volume.
1949/// build a volume with same name, shape and medium
1950
1952{
1953 TGeoVolume *vol = new TGeoVolume(GetName(), fShape, fMedium);
1954 Int_t i;
1955 // copy volume attributes
1956 vol->SetTitle(GetTitle());
1957 vol->SetLineColor(GetLineColor());
1958 vol->SetLineStyle(GetLineStyle());
1959 vol->SetLineWidth(GetLineWidth());
1960 vol->SetFillColor(GetFillColor());
1961 vol->SetFillStyle(GetFillStyle());
1962 // copy other attributes
1963 Int_t nbits = 8 * sizeof(UInt_t);
1964 for (i = 0; i < nbits; i++)
1965 vol->SetAttBit(1 << i, TGeoAtt::TestAttBit(1 << i));
1966 for (i = 14; i < 24; i++)
1967 vol->SetBit(1 << i, TestBit(1 << i));
1968
1969 // copy field
1970 vol->SetField(fField);
1971 // Set bits
1972 for (i = 0; i < nbits; i++)
1973 vol->SetBit(1 << i, TObject::TestBit(1 << i));
1974 vol->SetBit(kVolumeClone);
1975 // copy nodes
1976 // CloneNodesAndConnect(vol);
1977 vol->MakeCopyNodes(this);
1978 // if volume is divided, copy finder
1979 vol->SetFinder(fFinder);
1980 // copy voxels
1981 TGeoVoxelFinder *voxels = nullptr;
1982 if (fVoxels) {
1983 voxels = new TGeoVoxelFinder(vol);
1984 vol->SetVoxelFinder(voxels);
1985 }
1986 // copy option, uid
1987 vol->SetOption(fOption);
1988 vol->SetNumber(fNumber);
1989 vol->SetNtotal(fNtotal);
1990 // copy extensions
1994 return vol;
1995}
1996
1997////////////////////////////////////////////////////////////////////////////////
1998/// Clone the array of nodes.
1999
2001{
2002 if (!fNodes)
2003 return;
2004 TGeoNode *node;
2005 Int_t nd = fNodes->GetEntriesFast();
2006 if (!nd)
2007 return;
2008 // create new list of nodes
2009 TObjArray *list = new TObjArray(nd);
2010 // attach it to new volume
2011 newmother->SetNodes(list);
2012 // ((TObject*)newmother)->SetBit(kVolumeImportNodes);
2013 for (Int_t i = 0; i < nd; i++) {
2014 // create copies of nodes and add them to list
2015 node = GetNode(i)->MakeCopyNode();
2016 if (!node) {
2017 Fatal("CloneNodesAndConnect", "cannot make copy node");
2018 return;
2019 }
2021 list->Add(node);
2022 }
2023}
2024
2025////////////////////////////////////////////////////////////////////////////////
2026/// make a new list of nodes and copy all nodes of other volume inside
2027
2029{
2030 Int_t nd = other->GetNdaughters();
2031 if (!nd)
2032 return;
2033 if (fNodes) {
2035 fNodes->Delete();
2036 delete fNodes;
2037 }
2038 fNodes = new TObjArray();
2039 for (Int_t i = 0; i < nd; i++)
2040 fNodes->Add(other->GetNode(i));
2042}
2043
2044////////////////////////////////////////////////////////////////////////////////
2045/// make a copy of this volume
2046/// build a volume with same name, shape and medium
2047
2049{
2051 // copy volume attributes
2052 vol->SetVisibility(IsVisible());
2053 vol->SetLineColor(GetLineColor());
2054 vol->SetLineStyle(GetLineStyle());
2055 vol->SetLineWidth(GetLineWidth());
2056 vol->SetFillColor(GetFillColor());
2057 vol->SetFillStyle(GetFillStyle());
2058 // copy field
2059 vol->SetField(fField);
2060 // if divided, copy division object
2061 if (fFinder) {
2062 // Error("MakeCopyVolume", "volume %s divided", GetName());
2063 vol->SetFinder(fFinder);
2064 }
2065 // Copy extensions
2069 // ((TObject*)vol)->SetBit(kVolumeImportNodes);
2070 ((TObject *)vol)->SetBit(kVolumeClone);
2072 return vol;
2073}
2074
2075////////////////////////////////////////////////////////////////////////////////
2076/// Make a copy of this volume which is reflected with respect to XY plane.
2077
2079{
2080 static TMap map(100);
2081 if (!fGeoManager->IsClosed()) {
2082 Error("MakeReflectedVolume", "Geometry must be closed.");
2083 return nullptr;
2084 }
2085 TGeoVolume *vol = (TGeoVolume *)map.GetValue(this);
2086 if (vol) {
2087 if (newname && newname[0])
2088 vol->SetName(newname);
2089 return vol;
2090 }
2091 // printf("Making reflection for volume: %s\n", GetName());
2092 vol = CloneVolume();
2093 if (!vol) {
2094 Fatal("MakeReflectedVolume", "Cannot clone volume %s\n", GetName());
2095 return nullptr;
2096 }
2097 map.Add((TObject *)this, vol);
2098 if (newname && newname[0])
2099 vol->SetName(newname);
2100 delete vol->GetNodes();
2101 vol->SetNodes(nullptr);
2104 // The volume is now properly cloned, but with the same shape.
2105 // Reflect the shape (if any) and connect it.
2106 if (fShape) {
2110 }
2111 // Reflect the daughters.
2112 Int_t nd = vol->GetNdaughters();
2113 if (!nd)
2114 return vol;
2115 TGeoNodeMatrix *node;
2118 if (!vol->GetFinder()) {
2119 for (Int_t i = 0; i < nd; i++) {
2120 node = (TGeoNodeMatrix *)vol->GetNode(i);
2121 local = node->GetMatrix();
2122 // printf("%s before\n", node->GetName());
2123 // local->Print();
2124 Bool_t reflected = local->IsReflection();
2126 local_cloned->RegisterYourself();
2127 node->SetMatrix(local_cloned);
2128 if (!reflected) {
2129 // We need to reflect only the translation and propagate to daughters.
2130 // H' = Sz * H * Sz
2131 local_cloned->ReflectZ(kTRUE);
2132 local_cloned->ReflectZ(kFALSE);
2133 // printf("%s after\n", node->GetName());
2134 // node->GetMatrix()->Print();
2136 node->SetVolume(new_vol);
2137 continue;
2138 }
2139 // The next daughter is already reflected, so reflect on Z everything and stop
2140 local_cloned->ReflectZ(kTRUE); // rot + tr
2141 // printf("%s already reflected... After:\n", node->GetName());
2142 // node->GetMatrix()->Print();
2143 }
2144 if (vol->GetVoxels())
2145 vol->GetVoxels()->Voxelize();
2146 return vol;
2147 }
2148 // Volume is divided, so we have to reflect the division.
2149 // printf(" ... divided %s\n", fFinder->ClassName());
2151 if (!new_finder) {
2152 Fatal("MakeReflectedVolume", "Could not copy finder for volume %s", GetName());
2153 return nullptr;
2154 }
2155 new_finder->SetVolume(vol);
2156 vol->SetFinder(new_finder);
2158 new_vol = nullptr;
2159 for (Int_t i = 0; i < nd; i++) {
2160 nodeoff = (TGeoNodeOffset *)vol->GetNode(i);
2161 nodeoff->SetFinder(new_finder);
2162 new_vol = nodeoff->GetVolume()->MakeReflectedVolume();
2163 nodeoff->SetVolume(new_vol);
2164 }
2165 return vol;
2166}
2167
2168////////////////////////////////////////////////////////////////////////////////
2169/// Set this volume as the TOP one (the whole geometry starts from here)
2170
2175
2176////////////////////////////////////////////////////////////////////////////////
2177/// Set the current tracking point.
2178
2183
2184////////////////////////////////////////////////////////////////////////////////
2185/// set the shape associated with this volume
2186
2188{
2189 if (!shape) {
2190 Error("SetShape", "No shape");
2191 return;
2192 }
2193 fShape = (TGeoShape *)shape;
2194}
2195
2196////////////////////////////////////////////////////////////////////////////////
2197/// sort nodes by decreasing volume of the bounding box. ONLY nodes comes first,
2198/// then overlapping nodes and finally division nodes.
2199
2201{
2202 if (!Valid()) {
2203 Error("SortNodes", "Bounding box not valid");
2204 return;
2205 }
2206 Int_t nd = GetNdaughters();
2207 // printf("volume : %s, nd=%i\n", GetName(), nd);
2208 if (!nd)
2209 return;
2210 if (fFinder)
2211 return;
2212 // printf("Nodes for %s\n", GetName());
2213 Int_t id = 0;
2214 TGeoNode *node = nullptr;
2215 TObjArray *nodes = new TObjArray(nd);
2216 Int_t inode = 0;
2217 // first put ONLY's
2218 for (id = 0; id < nd; id++) {
2219 node = GetNode(id);
2220 if (node->InheritsFrom(TGeoNodeOffset::Class()) || node->IsOverlapping())
2221 continue;
2222 nodes->Add(node);
2223 // printf("inode %i ONLY\n", inode);
2224 inode++;
2225 }
2226 // second put overlapping nodes
2227 for (id = 0; id < nd; id++) {
2228 node = GetNode(id);
2229 if (node->InheritsFrom(TGeoNodeOffset::Class()) || (!node->IsOverlapping()))
2230 continue;
2231 nodes->Add(node);
2232 // printf("inode %i MANY\n", inode);
2233 inode++;
2234 }
2235 // third put the divided nodes
2236 if (fFinder) {
2238 for (id = 0; id < nd; id++) {
2239 node = GetNode(id);
2240 if (!node->InheritsFrom(TGeoNodeOffset::Class()))
2241 continue;
2242 nodes->Add(node);
2243 // printf("inode %i DIV\n", inode);
2244 inode++;
2245 }
2246 }
2247 if (inode != nd)
2248 printf(" volume %s : number of nodes does not match!!!\n", GetName());
2249 delete fNodes;
2250 fNodes = nodes;
2251}
2252
2253////////////////////////////////////////////////////////////////////////////////
2254/// Stream an object of class TGeoVolume.
2255
2257{
2258 if (R__b.IsReading()) {
2259 R__b.ReadClassBuffer(TGeoVolume::Class(), this);
2260 if (fVoxels && fVoxels->IsInvalid())
2261 Voxelize("");
2262 } else {
2263 if (!fVoxels) {
2264 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2265 } else {
2268 fVoxels = nullptr;
2269 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2270 fVoxels = voxels;
2271 } else {
2272 R__b.WriteClassBuffer(TGeoVolume::Class(), this);
2273 }
2274 }
2275 }
2276}
2277
2278////////////////////////////////////////////////////////////////////////////////
2279/// Set the current options (none implemented)
2280
2282{
2283 fOption = option;
2284}
2285
2286////////////////////////////////////////////////////////////////////////////////
2287/// Set the line color.
2288
2293
2294////////////////////////////////////////////////////////////////////////////////
2295/// Set the line style.
2296
2301
2302////////////////////////////////////////////////////////////////////////////////
2303/// Set the line width.
2304
2309
2310////////////////////////////////////////////////////////////////////////////////
2311/// get the pointer to a daughter node
2312
2314{
2315 if (!fNodes)
2316 return nullptr;
2317 TGeoNode *node = (TGeoNode *)fNodes->FindObject(name);
2318 return node;
2319}
2320
2321////////////////////////////////////////////////////////////////////////////////
2322/// get the total size in bytes for this volume
2323
2325{
2326 Int_t count = 28 + 2 + 6 + 4 + 0; // TNamed+TGeoAtt+TAttLine+TAttFill+TAtt3D
2327 count += fName.Capacity() + fTitle.Capacity(); // name+title
2328 count += 7 * sizeof(char *); // fShape + fMedium + fFinder + fField + fNodes + 2 extensions
2329 count += fOption.Capacity(); // fOption
2330 if (fShape)
2331 count += fShape->GetByteCount();
2332 if (fFinder)
2333 count += fFinder->GetByteCount();
2334 if (fNodes) {
2335 count += 32 + 4 * fNodes->GetEntries(); // TObjArray
2336 TIter next(fNodes);
2337 TGeoNode *node;
2338 while ((node = (TGeoNode *)next()))
2339 count += node->GetByteCount();
2340 }
2341 return count;
2342}
2343
2344////////////////////////////////////////////////////////////////////////////////
2345/// loop all nodes marked as overlaps and find overlapping brothers
2346
2348{
2349 if (!Valid()) {
2350 Error("FindOverlaps", "Bounding box not valid");
2351 return;
2352 }
2353 if (!fVoxels)
2354 return;
2355 Int_t nd = GetNdaughters();
2356 if (!nd)
2357 return;
2358 TGeoNode *node = nullptr;
2359 Int_t inode = 0;
2360 for (inode = 0; inode < nd; inode++) {
2361 node = GetNode(inode);
2362 if (!node->IsOverlapping())
2363 continue;
2365 }
2366}
2367
2368////////////////////////////////////////////////////////////////////////////////
2369/// Remove an existing daughter.
2370
2372{
2373 if (!fNodes || !fNodes->GetEntriesFast())
2374 return;
2375 if (!fNodes->Remove(node))
2376 return;
2377 fNodes->Compress();
2378 if (fVoxels)
2380 if (IsAssembly())
2382}
2383
2384////////////////////////////////////////////////////////////////////////////////
2385/// Replace an existing daughter with a new volume having the same name but
2386/// possibly a new shape, position or medium. Not allowed for positioned assemblies.
2387/// For division cells, the new shape/matrix are ignored.
2388
2390{
2392 if (ind < 0)
2393 return nullptr;
2394 TGeoVolume *oldvol = nodeorig->GetVolume();
2395 if (oldvol->IsAssembly()) {
2396 Error("ReplaceNode", "Cannot replace node %s since it is an assembly", nodeorig->GetName());
2397 return nullptr;
2398 }
2399 TGeoShape *shape = oldvol->GetShape();
2400 if (newshape && !nodeorig->IsOffset())
2401 shape = newshape;
2402 TGeoMedium *med = oldvol->GetMedium();
2403 if (newmed)
2404 med = newmed;
2405 // Make a new volume
2406 TGeoVolume *vol = new TGeoVolume(oldvol->GetName(), shape, med);
2407 // copy volume attributes
2408 vol->SetVisibility(oldvol->IsVisible());
2409 vol->SetLineColor(oldvol->GetLineColor());
2410 vol->SetLineStyle(oldvol->GetLineStyle());
2411 vol->SetLineWidth(oldvol->GetLineWidth());
2412 vol->SetFillColor(oldvol->GetFillColor());
2413 vol->SetFillStyle(oldvol->GetFillStyle());
2414 // copy field
2415 vol->SetField(oldvol->GetField());
2416 // Make a copy of the node
2417 TGeoNode *newnode = nodeorig->MakeCopyNode();
2418 if (!newnode) {
2419 Fatal("ReplaceNode", "Cannot make copy node for %s", nodeorig->GetName());
2420 return nullptr;
2421 }
2422 // Change the volume for the new node
2423 newnode->SetVolume(vol);
2424 // Replace the matrix
2425 if (newpos && !nodeorig->IsOffset()) {
2427 nodemat->SetMatrix(newpos);
2428 }
2429 // Replace nodeorig with new one
2432 if (fVoxels)
2434 if (IsAssembly())
2436 return newnode;
2437}
2438
2439////////////////////////////////////////////////////////////////////////////////
2440/// Select this volume as matching an arbitrary criteria. The volume is added to
2441/// a static list and the flag TGeoVolume::kVolumeSelected is set. All flags need
2442/// to be reset at the end by calling the method with CLEAR=true. This will also clear
2443/// the list.
2444
2446{
2447 static TObjArray array(256);
2448 static Int_t len = 0;
2449 Int_t i;
2450 TObject *vol;
2451 if (clear) {
2452 for (i = 0; i < len; i++) {
2453 vol = array.At(i);
2455 }
2456 array.Clear();
2457 len = 0;
2458 return;
2459 }
2461 array.AddAtAndExpand(this, len++);
2462}
2463
2464////////////////////////////////////////////////////////////////////////////////
2465/// set visibility of this volume
2466
2468{
2470 if (fGeoManager->IsClosed())
2473 TSeqCollection *brlist = gROOT->GetListOfBrowsers();
2474 TIter next(brlist);
2475 TBrowser *browser = nullptr;
2476 while ((browser = (TBrowser *)next())) {
2477 browser->CheckObjectItem(this, vis);
2478 browser->Refresh();
2479 }
2480}
2481
2482////////////////////////////////////////////////////////////////////////////////
2483/// Set visibility for containers.
2484
2495
2496////////////////////////////////////////////////////////////////////////////////
2497/// Set visibility for leaves.
2498
2509
2510////////////////////////////////////////////////////////////////////////////////
2511/// Set visibility for leaves.
2512
2525
2526////////////////////////////////////////////////////////////////////////////////
2527/// Check if the shape of this volume is valid.
2528
2530{
2531 return fShape->IsValidBox();
2532}
2533
2534////////////////////////////////////////////////////////////////////////////////
2535/// Find a daughter node having VOL as volume and fill TGeoManager::fHMatrix
2536/// with its global matrix.
2537
2539{
2540 if (vol == this)
2541 return kTRUE;
2542 Int_t nd = GetNdaughters();
2543 if (!nd)
2544 return kFALSE;
2546 if (!global)
2547 return kFALSE;
2548 TGeoNode *dnode;
2551 Int_t i;
2552 for (i = 0; i < nd; i++) {
2553 dnode = GetNode(i);
2554 dvol = dnode->GetVolume();
2555 if (dvol == vol) {
2556 local = dnode->GetMatrix();
2557 global->MultiplyLeft(local);
2558 return kTRUE;
2559 }
2560 }
2561 for (i = 0; i < nd; i++) {
2562 dnode = GetNode(i);
2563 dvol = dnode->GetVolume();
2564 if (dvol->FindMatrixOfDaughterVolume(vol))
2565 return kTRUE;
2566 }
2567 return kFALSE;
2568}
2569
2570////////////////////////////////////////////////////////////////////////////////
2571/// set visibility for daughters
2572
2580
2581////////////////////////////////////////////////////////////////////////////////
2582/// build the voxels for this volume
2583
2585{
2586 if (!Valid()) {
2587 Error("Voxelize", "Bounding box not valid");
2588 return;
2589 }
2590 // do not voxelize divided volumes
2591 if (fFinder)
2592 return;
2593 // or final leaves
2594 Int_t nd = GetNdaughters();
2595 if (!nd)
2596 return;
2597 // If this is an assembly, re-compute bounding box
2598 if (IsAssembly())
2600 // delete old voxelization if any
2601 if (fVoxels) {
2603 delete fVoxels;
2604 fVoxels = nullptr;
2605 }
2606 // Create the voxels structure
2607 fVoxels = new TGeoVoxelFinder(this);
2609 if (fVoxels) {
2610 if (fVoxels->IsInvalid()) {
2611 delete fVoxels;
2612 fVoxels = nullptr;
2613 }
2614 }
2615}
2616
2617////////////////////////////////////////////////////////////////////////////////
2618/// Estimate the weight of a volume (in kg) with SIGMA(M)/M better than PRECISION.
2619/// Option can contain : v - verbose, a - analytical (default)
2620
2622{
2624 if (top != this)
2626 else
2627 top = nullptr;
2628 Double_t weight = fGeoManager->Weight(precision, option);
2629 if (top)
2631 return weight;
2632}
2633
2634////////////////////////////////////////////////////////////////////////////////
2635/// Analytical computation of the weight.
2636
2638{
2639 Double_t capacity = Capacity();
2640 Double_t weight = 0.0;
2641 Int_t i;
2642 Int_t nd = GetNdaughters();
2644 for (i = 0; i < nd; i++) {
2645 daughter = GetNode(i)->GetVolume();
2646 weight += daughter->WeightA();
2647 capacity -= daughter->Capacity();
2648 }
2649 Double_t density = 0.0;
2650 if (!IsAssembly()) {
2651 if (fMedium)
2653 if (density < 0.01)
2654 density = 0.0; // do not weight gases
2655 }
2656 weight += 0.001 * capacity * density; //[kg]
2657 return weight;
2658}
2659
2660////////////////////////////////////////////////////////////////////////////////
2661/// dummy constructor
2662
2664{
2665 fVolumes = nullptr;
2666 fDivision = nullptr;
2667 fNumed = 0;
2668 fNdiv = 0;
2669 fAxis = 0;
2670 fStart = 0;
2671 fStep = 0;
2672 fAttSet = kFALSE;
2674}
2675
2676////////////////////////////////////////////////////////////////////////////////
2677/// default constructor
2678
2680{
2681 fVolumes = new TObjArray();
2682 fDivision = nullptr;
2683 fNumed = 0;
2684 fNdiv = 0;
2685 fAxis = 0;
2686 fStart = 0;
2687 fStep = 0;
2688 fAttSet = kFALSE;
2690 SetName(name);
2691 SetMedium(med);
2692 fGeoManager->AddVolume(this);
2693 // printf("--- volume multi %s created\n", name);
2694}
2695
2696////////////////////////////////////////////////////////////////////////////////
2697/// Destructor
2698
2700{
2701 if (fVolumes)
2702 delete fVolumes;
2703}
2704
2705////////////////////////////////////////////////////////////////////////////////
2706/// Add a volume with valid shape to the list of volumes. Copy all existing nodes
2707/// to this volume
2708
2710{
2711 Int_t idx = fVolumes->GetEntriesFast();
2712 fVolumes->AddAtAndExpand(vol, idx);
2713 vol->SetUniqueID(idx + 1);
2716 if (fDivision) {
2718 if (!div) {
2719 Fatal("AddVolume", "Cannot divide volume %s", vol->GetName());
2720 return;
2721 }
2722 for (Int_t i = 0; i < div->GetNvolumes(); i++) {
2723 cell = div->GetVolume(i);
2725 }
2726 }
2727 if (fNodes) {
2728 Int_t nd = fNodes->GetEntriesFast();
2729 for (Int_t id = 0; id < nd; id++) {
2730 TGeoNode *node = (TGeoNode *)fNodes->At(id);
2731 Bool_t many = node->IsOverlapping();
2732 if (many)
2733 vol->AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2734 else
2735 vol->AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2736 }
2737 }
2738 // vol->MakeCopyNodes(this);
2739}
2740
2741////////////////////////////////////////////////////////////////////////////////
2742/// Add a new node to the list of nodes. This is the usual method for adding
2743/// daughters inside the container volume.
2744
2746{
2749 TGeoVolume *volume = nullptr;
2750 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2751 volume = GetVolume(ivo);
2752 volume->SetLineColor(GetLineColor());
2753 volume->SetLineStyle(GetLineStyle());
2754 volume->SetLineWidth(GetLineWidth());
2755 volume->SetVisibility(IsVisible());
2756 volume->AddNode(vol, copy_no, mat, option);
2757 }
2758 // printf("--- vmulti %s : node %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2759 return n;
2760}
2761
2762////////////////////////////////////////////////////////////////////////////////
2763/// Add a new node to the list of nodes, This node is possibly overlapping with other
2764/// daughters of the volume or extruding the volume.
2765
2767{
2770 TGeoVolume *volume = nullptr;
2771 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2772 volume = GetVolume(ivo);
2773 volume->SetLineColor(GetLineColor());
2774 volume->SetLineStyle(GetLineStyle());
2775 volume->SetLineWidth(GetLineWidth());
2776 volume->SetVisibility(IsVisible());
2777 volume->AddNodeOverlap(vol, copy_no, mat, option);
2778 }
2779 // printf("--- vmulti %s : node ovlp %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
2780}
2781
2782////////////////////////////////////////////////////////////////////////////////
2783/// Returns the last shape.
2784
2786{
2788 if (!vol)
2789 return nullptr;
2790 return vol->GetShape();
2791}
2792
2793////////////////////////////////////////////////////////////////////////////////
2794/// division of multiple volumes
2795
2797 Int_t numed, const char *option)
2798{
2799 if (fDivision) {
2800 Error("Divide", "volume %s already divided", GetName());
2801 return nullptr;
2802 }
2805 if (numed) {
2807 if (!medium) {
2808 Error("Divide", "Invalid medium number %d for division volume %s", numed, divname);
2809 medium = fMedium;
2810 }
2811 }
2812 if (!nvolumes) {
2813 // this is a virtual volume
2815 fNumed = medium->GetId();
2816 fOption = option;
2817 fAxis = iaxis;
2818 fNdiv = ndiv;
2819 fStart = start;
2820 fStep = step;
2821 // nothing else to do at this stage
2822 return fDivision;
2823 }
2824 TGeoVolume *vol = nullptr;
2826 if (medium)
2827 fNumed = medium->GetId();
2828 fOption = option;
2829 fAxis = iaxis;
2830 fNdiv = ndiv;
2831 fStart = start;
2832 fStep = step;
2833 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2834 vol = GetVolume(ivo);
2835 vol->SetLineColor(GetLineColor());
2836 vol->SetLineStyle(GetLineStyle());
2837 vol->SetLineWidth(GetLineWidth());
2838 vol->SetVisibility(IsVisible());
2839 fDivision->AddVolume(vol->Divide(divname, iaxis, ndiv, start, step, numed, option));
2840 }
2841 // printf("--- volume multi %s (%i volumes) divided\n", GetName(), nvolumes);
2842 if (numed)
2844 return fDivision;
2845}
2846
2847////////////////////////////////////////////////////////////////////////////////
2848/// Make a copy of this volume
2849/// build a volume with same name, shape and medium
2850
2852{
2854 Int_t i = 0;
2855 // copy volume attributes
2856 vol->SetVisibility(IsVisible());
2857 vol->SetLineColor(GetLineColor());
2858 vol->SetLineStyle(GetLineStyle());
2859 vol->SetLineWidth(GetLineWidth());
2860 vol->SetFillColor(GetFillColor());
2861 vol->SetFillStyle(GetFillStyle());
2862 // copy field
2863 vol->SetField(fField);
2864 // Copy extensions
2867 // if divided, copy division object
2868 // if (fFinder) {
2869 // Error("MakeCopyVolume", "volume %s divided", GetName());
2870 // vol->SetFinder(fFinder);
2871 // }
2872 if (fDivision) {
2876 if (!div) {
2877 Fatal("MakeCopyVolume", "Cannot divide volume %s", vol->GetName());
2878 return nullptr;
2879 }
2880 for (i = 0; i < div->GetNvolumes(); i++) {
2881 cell = div->GetVolume(i);
2883 }
2884 }
2885
2886 if (!fNodes)
2887 return vol;
2888 TGeoNode *node;
2889 Int_t nd = fNodes->GetEntriesFast();
2890 if (!nd)
2891 return vol;
2892 // create new list of nodes
2893 TObjArray *list = new TObjArray();
2894 // attach it to new volume
2895 vol->SetNodes(list);
2896 ((TObject *)vol)->SetBit(kVolumeImportNodes);
2897 for (i = 0; i < nd; i++) {
2898 // create copies of nodes and add them to list
2899 node = GetNode(i)->MakeCopyNode();
2900 if (!node) {
2901 Fatal("MakeCopyNode", "cannot make copy node for daughter %d of %s", i, GetName());
2902 return nullptr;
2903 }
2904 node->SetMotherVolume(vol);
2905 list->Add(node);
2906 }
2907 return vol;
2908}
2909
2910////////////////////////////////////////////////////////////////////////////////
2911/// Set the line color for all components.
2912
2914{
2917 TGeoVolume *vol = nullptr;
2918 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2919 vol = GetVolume(ivo);
2920 vol->SetLineColor(lcolor);
2921 }
2922}
2923
2924////////////////////////////////////////////////////////////////////////////////
2925/// Set the line style for all components.
2926
2928{
2931 TGeoVolume *vol = nullptr;
2932 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2933 vol = GetVolume(ivo);
2934 vol->SetLineStyle(lstyle);
2935 }
2936}
2937
2938////////////////////////////////////////////////////////////////////////////////
2939/// Set the line width for all components.
2940
2942{
2945 TGeoVolume *vol = nullptr;
2946 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2947 vol = GetVolume(ivo);
2948 vol->SetLineWidth(lwidth);
2949 }
2950}
2951
2952////////////////////////////////////////////////////////////////////////////////
2953/// Set medium for a multiple volume.
2954
2956{
2959 TGeoVolume *vol = nullptr;
2960 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2961 vol = GetVolume(ivo);
2962 vol->SetMedium(med);
2963 }
2964}
2965
2966////////////////////////////////////////////////////////////////////////////////
2967/// Set visibility for all components.
2968
2970{
2973 TGeoVolume *vol = nullptr;
2974 for (Int_t ivo = 0; ivo < nvolumes; ivo++) {
2975 vol = GetVolume(ivo);
2976 vol->SetVisibility(vis);
2977 }
2978}
2979
2980////////////////////////////////////////////////////////////////////////////////
2981/// Constructor.
2982
2984
2985////////////////////////////////////////////////////////////////////////////////
2986/// Destructor.
2987
2989
2990////////////////////////////////////////////////////////////////////////////////
2991
2997
2998////////////////////////////////////////////////////////////////////////////////
2999
3001{
3002 std::lock_guard<std::mutex> guard(fMutex);
3004 std::vector<ThreadData_t *>::iterator i = fThreadData.begin();
3005 while (i != fThreadData.end()) {
3006 delete *i;
3007 ++i;
3008 }
3009 fThreadData.clear();
3010 fThreadSize = 0;
3011}
3012
3013////////////////////////////////////////////////////////////////////////////////
3014
3016{
3017 std::lock_guard<std::mutex> guard(fMutex);
3018 // Create assembly thread data here
3019 fThreadData.resize(nthreads);
3021 for (Int_t tid = 0; tid < nthreads; tid++) {
3022 if (fThreadData[tid] == nullptr) {
3024 }
3025 }
3027}
3028
3029////////////////////////////////////////////////////////////////////////////////
3030
3035
3036////////////////////////////////////////////////////////////////////////////////
3037
3042
3043////////////////////////////////////////////////////////////////////////////////
3044
3049
3050////////////////////////////////////////////////////////////////////////////////
3051
3056
3057////////////////////////////////////////////////////////////////////////////////
3058/// Default constructor
3059
3065
3066////////////////////////////////////////////////////////////////////////////////
3067/// Constructor. Just the name has to be provided. Assemblies does not have their own
3068/// shape or medium.
3069
3071{
3072 fName = name;
3073 fName = fName.Strip();
3074 fShape = new TGeoShapeAssembly(this);
3075 if (fGeoManager)
3076 fNumber = fGeoManager->AddVolume(this);
3077 fThreadSize = 0;
3079}
3080
3081////////////////////////////////////////////////////////////////////////////////
3082/// Destructor. The assembly is owner of its "shape".
3083
3085{
3087 if (fShape)
3088 delete fShape;
3089}
3090
3091////////////////////////////////////////////////////////////////////////////////
3092/// Add a component to the assembly.
3093
3095{
3097 // ((TGeoShapeAssembly*)fShape)->RecomputeBoxLast();
3098 ((TGeoShapeAssembly *)fShape)->NeedsBBoxRecompute();
3099 return node;
3100}
3101
3102////////////////////////////////////////////////////////////////////////////////
3103/// Add an overlapping node - not allowed for assemblies.
3104
3106{
3107 Warning("AddNodeOverlap",
3108 "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",
3109 vol->GetName(), GetName());
3110 AddNode(vol, copy_no, mat, option);
3111}
3112
3113////////////////////////////////////////////////////////////////////////////////
3114/// Clone this volume.
3115/// build a volume with same name, shape and medium
3116
3118{
3120 Int_t i;
3121 // copy other attributes
3122 Int_t nbits = 8 * sizeof(UInt_t);
3123 for (i = 0; i < nbits; i++)
3124 vol->SetAttBit(1 << i, TGeoAtt::TestAttBit(1 << i));
3125 for (i = 14; i < 24; i++)
3126 vol->SetBit(1 << i, TestBit(1 << i));
3127
3128 // copy field
3129 vol->SetField(fField);
3130 // Set bits
3131 for (i = 0; i < nbits; i++)
3132 vol->SetBit(1 << i, TObject::TestBit(1 << i));
3133 vol->SetBit(kVolumeClone);
3134 // make copy nodes
3135 vol->MakeCopyNodes(this);
3136 // CloneNodesAndConnect(vol);
3137 ((TGeoShapeAssembly *)vol->GetShape())->NeedsBBoxRecompute();
3138 // copy voxels
3139 TGeoVoxelFinder *voxels = nullptr;
3140 if (fVoxels) {
3141 voxels = new TGeoVoxelFinder(vol);
3142 vol->SetVoxelFinder(voxels);
3143 }
3144 // copy option, uid
3145 vol->SetOption(fOption);
3146 vol->SetNumber(fNumber);
3147 vol->SetNtotal(fNtotal);
3148 vol->SetTitle(GetTitle());
3149 // copy extensions
3152 return vol;
3153}
3154
3155////////////////////////////////////////////////////////////////////////////////
3156/// Division makes no sense for assemblies.
3157
3159{
3160 Error("Divide", "Assemblies cannot be divided");
3161 return nullptr;
3162}
3163
3164////////////////////////////////////////////////////////////////////////////////
3165/// Assign to the assembly a collection of identical volumes positioned according
3166/// a predefined pattern. The option can be spaced out or touching depending on the empty
3167/// space between volumes.
3168
3170{
3171 if (fNodes) {
3172 Error("Divide", "Cannot divide assembly %s since it has nodes", GetName());
3173 return nullptr;
3174 }
3175 if (fFinder) {
3176 Error("Divide", "Assembly %s already divided", GetName());
3177 return nullptr;
3178 }
3179 Int_t ncells = pattern->GetNdiv();
3180 if (!ncells || pattern->GetStep() <= 0) {
3181 Error("Divide", "Pattern finder for dividing assembly %s not initialized. Use SetRange() method.", GetName());
3182 return nullptr;
3183 }
3184 fFinder = pattern;
3185 TString opt(option);
3186 opt.ToLower();
3187 if (opt.Contains("spacedout"))
3189 else
3191 // Position volumes
3192 for (Int_t i = 0; i < ncells; i++) {
3193 fFinder->cd(i);
3194 TGeoNodeOffset *node = new TGeoNodeOffset(cell, i, 0.);
3195 node->SetFinder(fFinder);
3196 fNodes->Add(node);
3197 }
3198 return cell;
3199}
3200
3201////////////////////////////////////////////////////////////////////////////////
3202/// Make a clone of volume VOL but which is an assembly.
3203
3205{
3206 if (volorig->IsAssembly() || volorig->IsVolumeMulti())
3207 return nullptr;
3208 Int_t nd = volorig->GetNdaughters();
3209 if (!nd)
3210 return nullptr;
3211 TGeoVolumeAssembly *vol = new TGeoVolumeAssembly(volorig->GetName());
3212 Int_t i;
3213 // copy other attributes
3214 Int_t nbits = 8 * sizeof(UInt_t);
3215 for (i = 0; i < nbits; i++)
3216 vol->SetAttBit(1 << i, volorig->TestAttBit(1 << i));
3217 for (i = 14; i < 24; i++)
3218 vol->SetBit(1 << i, volorig->TestBit(1 << i));
3219
3220 // copy field
3221 vol->SetField(volorig->GetField());
3222 // Set bits
3223 for (i = 0; i < nbits; i++)
3224 vol->SetBit(1 << i, volorig->TestBit(1 << i));
3225 vol->SetBit(kVolumeClone);
3226 // make copy nodes
3227 vol->MakeCopyNodes(volorig);
3228 // volorig->CloneNodesAndConnect(vol);
3229 vol->GetShape()->ComputeBBox();
3230 // copy voxels
3231 TGeoVoxelFinder *voxels = nullptr;
3232 if (volorig->GetVoxels()) {
3233 voxels = new TGeoVoxelFinder(vol);
3234 vol->SetVoxelFinder(voxels);
3235 }
3236 // copy option, uid
3237 vol->SetOption(volorig->GetOption());
3238 vol->SetNumber(volorig->GetNumber());
3239 vol->SetNtotal(volorig->GetNtotal());
3240 return vol;
3241}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define s1(x)
Definition RSha256.hxx:91
short Style_t
Style number (short)
Definition RtypesCore.h:96
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Width_t
Line width (short)
Definition RtypesCore.h:98
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
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 void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
R__EXTERN TGeoManager * gGeoManager
R__EXTERN TGeoIdentity * gGeoIdentity
Definition TGeoMatrix.h:538
#define gROOT
Definition TROOT.h:414
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
const_iterator begin() const
const_iterator end() const
This class provides a simple interface to execute the same task multiple times in parallel threads,...
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:31
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:32
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:38
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:40
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:44
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:45
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:42
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:36
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:274
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
Buffer base class used for serializing objects.
Definition TBuffer.h:43
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:503
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
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:3764
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.
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
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
static Int_t ThreadId()
Translates the current thread id to an ordinal number.
Int_t AddShape(const TGeoShape *shape)
Add a shape to the list. Returns index of the shape in list.
void SortOverlaps()
Sort overlaps by decreasing overlap distance. Extrusions comes first.
Base class describing materials.
void SetUsed(Bool_t flag=kTRUE)
void Print(const Option_t *option="") const override
print characteristics of this material
virtual Double_t GetDensity() const
Geometrical transformation package.
Definition TGeoMatrix.h:39
Media are used to store properties related to tracking and which are useful only when using geometry ...
Definition TGeoMedium.h:23
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.
A node containing local transformation.
Definition TGeoNode.h:155
void SetMatrix(const TGeoMatrix *matrix)
Matrix setter.
Definition TGeoNode.cxx:955
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
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
Int_t GetNdiv() const
Double_t GetStep() const
void ClearThreadData() const
virtual Int_t GetByteCount() const
void CreateThreadData(Int_t nthreads)
Create thread data for n threads max.
Class describing scale transformations.
Definition TGeoMatrix.h: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:317
static TGeoVolumeAssembly * MakeAssemblyFromVolume(TGeoVolume *vol)
Make a clone of volume VOL but which is an assembly.
~TGeoVolumeAssembly() override
Destructor. The assembly is owner of its "shape".
Int_t GetNextNodeIndex() const override
void CreateThreadData(Int_t nthreads) override
TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="") override
Add a component to the assembly.
void ClearThreadData() const override
TGeoVolume * CloneVolume() const override
Clone this volume.
void AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option) override
Add an overlapping node - not allowed for assemblies.
std::vector< ThreadData_t * > fThreadData
Definition TGeoVolume.h:332
std::mutex fMutex
Thread vector size.
Definition TGeoVolume.h:334
Int_t fThreadSize
Thread specific data vector.
Definition TGeoVolume.h:333
void SetNextNodeIndex(Int_t index)
Int_t GetCurrentNodeIndex() const override
void SetCurrentNodeIndex(Int_t index)
TGeoVolumeAssembly()
Default constructor.
TGeoVolume * Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed=0, Option_t *option="") override
Division makes no sense for assemblies.
ThreadData_t & GetThreadData() const
Volume families.
Definition TGeoVolume.h:267
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:274
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:287
void SetVisibility(Bool_t vis=kTRUE) override
Set visibility for all components.
~TGeoVolumeMulti() override
Destructor.
TGeoVolumeMulti * fDivision
Definition TGeoVolume.h:270
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.
TObjArray * fVolumes
Definition TGeoVolume.h:269
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:43
Double_t WeightA() const
Analytical computation of the weight.
void AddNodeOffset(TGeoVolume *vol, Int_t copy_no, Double_t offset=0, Option_t *option="")
Add a division node to the list of nodes.
void SetVisContainers(Bool_t flag=kTRUE) override
Set visibility for containers.
virtual void cd(Int_t inode) const
Actualize matrix of node indexed <inode>
virtual void ClearThreadData() const
void SetVisibility(Bool_t vis=kTRUE) override
set visibility of this volume
Bool_t IsVisContainers() const
Definition TGeoVolume.h:158
void SetVoxelFinder(TGeoVoxelFinder *finder)
Definition TGeoVolume.h:244
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:56
void MakeCopyNodes(const TGeoVolume *other)
make a new list of nodes and copy all nodes of other volume inside
void SetUserExtension(TGeoExtension *ext)
Connect user-defined extension to the volume.
TGeoExtension * GrabFWExtension() const
Get a copy of the framework extension pointer.
void SetNumber(Int_t number)
Definition TGeoVolume.h:246
void ClearNodes()
Definition TGeoVolume.h:95
void SetLineWidth(Width_t lwidth) override
Set the line width.
void Raytrace(Bool_t flag=kTRUE)
Draw this volume with current settings and perform raytracing in the pad.
void RandomRays(Int_t nrays=10000, Double_t startx=0, Double_t starty=0, Double_t startz=0, const char *target_vol=nullptr, Bool_t check_norm=kFALSE)
Random raytracing method.
TGeoVolume()
dummy constructor
TGeoMedium * GetMedium() const
Definition TGeoVolume.h:176
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:151
void SortNodes()
sort nodes by decreasing volume of the bounding box.
Bool_t FindMatrixOfDaughterVolume(TGeoVolume *vol) const
Find a daughter node having VOL as volume and fill TGeoManager::fHMatrix with its global matrix.
void Voxelize(Option_t *option)
build the voxels for this volume
Double_t Capacity() const
Computes the capacity of this [cm^3] as the capacity of its shape.
virtual TGeoVolume * MakeCopyVolume(TGeoShape *newshape)
make a copy of this volume build a volume with same name, shape and medium
void ReplayCreation(const TGeoVolume *other)
Recreate the content of the other volume without pointer copying.
Double_t Weight(Double_t precision=0.01, Option_t *option="va")
Estimate the weight of a volume (in kg) with SIGMA(M)/M better than PRECISION.
Int_t fNumber
option - if any
Definition TGeoVolume.h:55
virtual void CreateThreadData(Int_t nthreads)
virtual Int_t GetByteCount() const
get the total size in bytes for this volume
virtual TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="")
Add a TGeoNode to the list of nodes.
Bool_t OptimizeVoxels()
Perform an extensive sampling to find which type of voxelization is most efficient.
void Browse(TBrowser *b) override
How to browse a volume.
void SetCurrentPoint(Double_t x, Double_t y, Double_t z)
Set the current tracking point.
void Paint(Option_t *option="") override
paint volume
void SetVisOnly(Bool_t flag=kTRUE) override
Set visibility for leaves.
TGeoManager * fGeoManager
Definition TGeoVolume.h:51
TH2F * LegoPlot(Int_t ntheta=20, Double_t themin=0., Double_t themax=180., Int_t nphi=60, Double_t phimin=0., Double_t phimax=360., Double_t rmin=0., Double_t rmax=9999999, Option_t *option="")
Generate a lego plot fot the top volume, according to option.
void Draw(Option_t *option="") override
draw top volume according to option
TGeoVoxelFinder * fVoxels
Definition TGeoVolume.h:50
TGeoMaterial * GetMaterial() const
Definition TGeoVolume.h:175
TGeoExtension * GrabUserExtension() const
Get a copy of the user extension pointer.
@ kVolumeSelected
Definition TGeoVolume.h:73
@ kVolumeImportNodes
Definition TGeoVolume.h:76
Int_t CountNodes(Int_t nlevels=1000, Int_t option=0)
Count total number of subnodes starting from this volume, nlevels down.
void GrabFocus()
Move perspective view focus to this volume.
void UnmarkSaved()
Reset SavePrimitive bits.
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute mouse actions on this volume.
virtual TGeoVolume * CloneVolume() const
Clone this volume.
void SetFinder(TGeoPatternFinder *finder)
Definition TGeoVolume.h:245
Int_t GetNdaughters() const
Definition TGeoVolume.h:363
Bool_t IsValid() const
Definition TGeoVolume.h:155
void Grab()
Definition TGeoVolume.h:137
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:170
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:247
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:157
TString fOption
just a hook for now
Definition TGeoVolume.h:54
Int_t GetIndex(const TGeoNode *node) const
get index number for a given daughter
void SetNodes(TObjArray *nodes)
Definition TGeoVolume.h:224
TGeoPatternFinder * GetFinder() const
Definition TGeoVolume.h:178
void PrintVoxels() const
Print the voxels for this volume.
TGeoExtension * fUserExtension
Definition TGeoVolume.h:59
virtual void SetMedium(TGeoMedium *medium)
Definition TGeoVolume.h:243
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
void SetAttVisibility(Bool_t vis)
Definition TGeoVolume.h:234
~TGeoVolume() override
Destructor.
void SetShape(const TGeoShape *shape)
set the shape associated with this volume
static TGeoMedium * DummyMedium()
TObject * fField
pointer to TGeoManager owning this volume
Definition TGeoVolume.h:53
void SetLineColor(Color_t lcolor) override
Set the line color.
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
void CleanAll()
Clean data of the volume.
Bool_t IsTopVolume() const
True if this is the top volume of the geometry.
TGeoMedium * fMedium
Definition TGeoVolume.h:47
TGeoShape * GetShape() const
Definition TGeoVolume.h:191
void InspectMaterial() const
Inspect the material for this volume.
void PrintNodes() const
print nodes
static TGeoMedium * fgDummyMedium
Definition TGeoVolume.h:48
void RegisterYourself(Option_t *option="")
Register the volume and all materials/media/matrices/shapes to the manager.
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:46
void SetField(TObject *field)
Definition TGeoVolume.h:232
static TGeoVolume * Import(const char *filename, const char *name="", Option_t *option="")
Import a volume from a file.
Bool_t IsStyleDefault() const
check if the visibility and attributes are the default ones
Char_t fTransparency
Definition TGeoVolume.h:58
static void CreateDummyMedium()
Create a dummy medium.
TGeoExtension * fFWExtension
Transient user-defined extension to volumes.
Definition TGeoVolume.h:60
void SetAsTopVolume()
Set this volume as the TOP one (the whole geometry starts from here)
Bool_t IsVisLeaves() const
Definition TGeoVolume.h:159
TGeoPatternFinder * fFinder
dummy medium
Definition TGeoVolume.h:49
Int_t Export(const char *filename, const char *name="", Option_t *option="")
Export this volume to a file.
virtual void DrawOnly(Option_t *option="")
draw only this volume
void SetLineStyle(Style_t lstyle) override
Set the line style.
void SetOption(const char *option)
Set the current options (none implemented)
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.
TGeoVolume * MakeReflectedVolume(const char *newname="") const
Make a copy of this volume which is reflected with respect to XY plane.
TObjArray * fNodes
Definition TGeoVolume.h:45
virtual Bool_t IsVisible() const
Definition TGeoVolume.h:156
void SetVisLeaves(Bool_t flag=kTRUE) override
Set visibility for leaves.
void InspectShape() const
Definition TGeoVolume.h:196
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:229
Bool_t IsOverlappingCandidate() const
Definition TGeoVolume.h:149
Int_t fRefCount
Definition TGeoVolume.h:57
void Streamer(TBuffer &) override
Stream an object of class TGeoVolume.
void CheckShape(Int_t testNo, Int_t nsamples=10000, Option_t *option="")
Tests for checking the shape navigation algorithms. See TGeoShape::CheckShape()
Finder class handling voxels.
Bool_t IsInvalid() const
void Print(Option_t *option="") const override
Print the voxels.
void SetNeedRebuild(Bool_t flag=kTRUE)
virtual void Voxelize(Option_t *option="")
Voxelize attached volume according to option If the volume is an assembly, make sure the bbox is comp...
virtual void FindOverlaps(Int_t inode) const
create the list of nodes for which the bboxes overlap with inode's bbox
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3052
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:75
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:760
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:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
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:1074
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition TObject.cxx:852
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:981
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:881
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:543
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1088
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1116
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:892
void ResetBit(UInt_t f)
Definition TObject.h:201
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1062
Sequenceable collection abstract base class.
Stopwatch class.
Definition TStopwatch.h:28
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1170
const char * Data() const
Definition TString.h:384
Ssiz_t Capacity() const
Definition TString.h:372
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:2384
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Abstract class for geometry painters.
virtual TGeoVolume * GetTopVolume() const =0
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:600
UInt_t GetThreadPoolSize()
Returns the size of ROOT's thread pool.
Definition TROOT.cxx:607
ThreadData_t()
index of next node to be entered