Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGeoManager.cxx
Go to the documentation of this file.
1// @(#)root/geom:$Id$
2// Author: Andrei Gheata 25/10/01
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TGeoManager
13\ingroup Geometry_classes
14
15The manager class for any TGeo geometry. Provides user
16interface for geometry creation, navigation, state querying,
17visualization, IO, geometry checking and other utilities.
18
19## General architecture
20
21 The ROOT geometry package is a tool designed for building, browsing,
22tracking and visualizing a detector geometry. The code is independent from
23other external MC for simulation, therefore it does not contain any
24constraints related to physics. However, the package defines a number of
25hooks for tracking, such as media, materials, magnetic field or track state flags,
26in order to allow interfacing to tracking MC's. The final goal is to be
27able to use the same geometry for several purposes, such as tracking,
28reconstruction or visualization, taking advantage of the ROOT features
29related to bookkeeping, I/O, histogramming, browsing and GUI's.
30
31 The geometrical modeler is the most important component of the package and
32it provides answers to the basic questions like "Where am I ?" or "How far
33from the next boundary ?", but also to more complex ones like "How far from
34the closest surface ?" or "Which is the next crossing along a helix ?".
35
36 The architecture of the modeler is a combination between a GEANT-like
37containment scheme and a normal CSG binary tree at the level of shapes. An
38important common feature of all detector geometry descriptions is the
39mother-daughter concept. This is the most natural approach when tracking
40is concerned and imposes a set of constraints to the way geometry is defined.
41Constructive solid geometry composition is used only in order to create more
42complex shapes from an existing set of primitives through boolean operations.
43This feature is not implemented yet but in future full definition of boolean
44expressions will be supported.
45
46 Practically every geometry defined in GEANT style can be mapped by the modeler.
47The basic components used for building the logical hierarchy of the geometry
48are called "volumes" and "nodes". Volumes (sometimes called "solids") are fully
49defined geometrical objects having a given shape and medium and possibly
50containing a list of nodes. Nodes represent just positioned instances of volumes
51inside a container volume and they are not directly defined by user. They are
52automatically created as a result of adding one volume inside other or dividing
53a volume. The geometrical transformation hold by nodes is always defined with
54respect to their mother (relative positioning). Reflection matrices are allowed.
55All volumes have to be fully aware of their containees when the geometry is
56closed. They will build additional structures (voxels) in order to fasten-up
57the search algorithms. Finally, nodes can be regarded as bidirectional links
58between containers and containees objects.
59
60 The structure defined in this way is a graph structure since volumes are
61replicable (same volume can become daughter node of several other volumes),
62every volume becoming a branch in this graph. Any volume in the logical graph
63can become the actual top volume at run time (see TGeoManager::SetTopVolume()).
64All functionalities of the modeler will behave in this case as if only the
65corresponding branch starting from this volume is the registered geometry.
66
67\image html geom_graf.jpg
68
69 A given volume can be positioned several times in the geometry. A volume
70can be divided according default or user-defined patterns, creating automatically
71the list of division nodes inside. The elementary volumes created during the
72dividing process follow the same scheme as usual volumes, therefore it is possible
73to position further geometrical structures inside or to divide them further more
74(see TGeoVolume::Divide()).
75
76 The primitive shapes supported by the package are basically the GEANT3
77shapes (see class TGeoShape), arbitrary wedges with eight vertices on two parallel
78planes. All basic primitives inherits from class TGeoBBox since the bounding box
79of a solid is essential for the tracking algorithms. They also implement the
80virtual methods defined in the virtual class TGeoShape (point and segment
81classification). User-defined primitives can be directly plugged into the modeler
82provided that they override these methods. Composite shapes will be soon supported
83by the modeler. In order to build a TGeoCompositeShape, one will have to define
84first the primitive components. The object that handle boolean
85operations among components is called TGeoBoolCombinator and it has to be
86constructed providing a string boolean expression between the components names.
87
88
89## Example for building a simple geometry
90
91Begin_Macro(source)
92../../../tutorials/geom/rootgeom.C
93End_Macro
94
95## TGeoManager - the manager class for the geometry package.
96
97 TGeoManager class is embedding all the API needed for building and tracking
98a geometry. It defines a global pointer (gGeoManager) in order to be fully
99accessible from external code. The mechanism of handling multiple geometries
100at the same time will be soon implemented.
101
102 TGeoManager is the owner of all geometry objects defined in a session,
103therefore users must not try to control their deletion. It contains lists of
104media, materials, transformations, shapes and volumes. Logical nodes (positioned
105volumes) are created and destroyed by the TGeoVolume class. Physical
106nodes and their global transformations are subjected to a caching mechanism
107due to the sometimes very large memory requirements of logical graph expansion.
108The caching mechanism is triggered by the total number of physical instances
109of volumes and the cache manager is a client of TGeoManager. The manager class
110also controls the painter client. This is linked with ROOT graphical libraries
111loaded on demand in order to control visualization actions.
112
113## Rules for building a valid geometry
114
115 A given geometry can be built in various ways, but there are mandatory steps
116that have to be followed in order to be validated by the modeler. There are
117general rules : volumes needs media and shapes in order to be created,
118both container and containee volumes must be created before linking them together,
119and the relative transformation matrix must be provided. All branches must
120have an upper link point otherwise they will not be considered as part of the
121geometry. Visibility or tracking properties of volumes can be provided both
122at build time or after geometry is closed, but global visualization settings
123(see TGeoPainter class) should not be provided at build time, otherwise the
124drawing package will be loaded. There is also a list of specific rules :
125positioned daughters should not extrude their mother or intersect with sisters
126unless this is specified (see TGeoVolume::AddNodeOverlap()), the top volume
127(containing all geometry tree) must be specified before closing the geometry
128and must not be positioned - it represents the global reference frame. After
129building the full geometry tree, the geometry must be closed
130(see TGeoManager::CloseGeometry()). Voxelization can be redone per volume after
131this process.
132
133
134 Below is the general scheme of the manager class.
135
136\image html geom_mgr.jpg
137
138## An interactive session
139
140 Provided that a geometry was successfully built and closed (for instance the
141previous example $ROOTSYS/tutorials/geom/rootgeom.C ), the manager class will register
142itself to ROOT and the logical/physical structures will become immediately browsable.
143The ROOT browser will display starting from the geometry folder : the list of
144transformations and media, the top volume and the top logical node. These last
145two can be fully expanded, any intermediate volume/node in the browser being subject
146of direct access context menu operations (right mouse button click). All user
147utilities of classes TGeoManager, TGeoVolume and TGeoNode can be called via the
148context menu.
149
150\image html geom_browser.jpg
151
152### Drawing the geometry
153
154 Any logical volume can be drawn via TGeoVolume::Draw() member function.
155This can be directly accessed from the context menu of the volume object
156directly from the browser.
157 There are several drawing options that can be set with
158TGeoManager::SetVisOption(Int_t opt) method :
159
160#### opt=0
161 only the content of the volume is drawn, N levels down (default N=3).
162 This is the default behavior. The number of levels to be drawn can be changed
163 via TGeoManager::SetVisLevel(Int_t level) method.
164
165\image html geom_frame0.jpg
166
167#### opt=1
168 the final leaves (e.g. daughters with no containment) of the branch
169 starting from volume are drawn down to the current number of levels.
170 WARNING : This mode is memory consuming
171 depending of the size of geometry, so drawing from top level within this mode
172 should be handled with care for expensive geometries. In future there will be
173 a limitation on the maximum number of nodes to be visualized.
174
175\image html geom_frame1.jpg
176
177#### opt=2
178 only the clicked volume is visualized. This is automatically set by
179 TGeoVolume::DrawOnly() method
180
181#### opt=3 - only a given path is visualized. This is automatically set by
182 TGeoVolume::DrawPath(const char *path) method
183
184 The current view can be exploded in cartesian, cylindrical or spherical
185coordinates :
186 TGeoManager::SetExplodedView(Int_t opt). Options may be :
187- 0 - default (no bombing)
188- 1 - cartesian coordinates. The bomb factor on each axis can be set with
189 TGeoManager::SetBombX(Double_t bomb) and corresponding Y and Z.
190- 2 - bomb in cylindrical coordinates. Only the bomb factors on Z and R
191 are considered
192 \image html geom_frameexp.jpg
193
194- 3 - bomb in radial spherical coordinate : TGeoManager::SetBombR()
195
196Volumes themselves support different visualization settings :
197 - TGeoVolume::SetVisibility() : set volume visibility.
198 - TGeoVolume::VisibleDaughters() : set daughters visibility.
199All these actions automatically updates the current view if any.
200
201### Checking the geometry
202
203 Several checking methods are accessible from the volume context menu. They
204generally apply only to the visible parts of the drawn geometry in order to
205ease geometry checking, and their implementation is in the TGeoChecker class
206from the painting package.
207
208#### Checking a given point.
209 Can be called from TGeoManager::CheckPoint(Double_t x, Double_t y, Double_t z).
210This method is drawing the daughters of the volume containing the point one
211level down, printing the path to the deepest physical node holding this point.
212It also computes the closest distance to any boundary. The point will be drawn
213in red.
214
215\image html geom_checkpoint.jpg
216
217#### Shooting random points.
218 Can be called from TGeoVolume::RandomPoints() (context menu function) and
219it will draw this volume with current visualization settings. Random points
220are generated in the bounding box of the top drawn volume. The points are
221classified and drawn with the color of their deepest container. Only points
222in visible nodes will be drawn.
223
224\image html geom_random1.jpg
225
226
227#### Raytracing.
228 Can be called from TGeoVolume::RandomRays() (context menu of volumes) and
229will shoot rays from a given point in the local reference frame with random
230directions. The intersections with displayed nodes will appear as segments
231having the color of the touched node. Drawn geometry will be then made invisible
232in order to enhance rays.
233
234\image html geom_random2.jpg
235*/
236
237#include <cstdlib>
238#include <iostream>
239#include <fstream>
240
241#include "TROOT.h"
242#include "TGeoManager.h"
243#include "TStyle.h"
244#include "TVirtualPad.h"
245#include "TBrowser.h"
246#include "TFile.h"
247#include "TKey.h"
248#include "THashList.h"
249#include "TClass.h"
250#include "ThreadLocalStorage.h"
251#include "TBufferText.h"
252
253#include "TGeoVoxelFinder.h"
254#include "TGeoElement.h"
255#include "TGeoMaterial.h"
256#include "TGeoMedium.h"
257#include "TGeoMatrix.h"
258#include "TGeoNode.h"
259#include "TGeoPhysicalNode.h"
260#include "TGeoPara.h"
261#include "TGeoParaboloid.h"
262#include "TGeoTube.h"
263#include "TGeoEltu.h"
264#include "TGeoHype.h"
265#include "TGeoCone.h"
266#include "TGeoSphere.h"
267#include "TGeoArb8.h"
268#include "TGeoPgon.h"
269#include "TGeoTrd1.h"
270#include "TGeoTrd2.h"
271#include "TGeoTorus.h"
272#include "TGeoXtru.h"
273#include "TGeoCompositeShape.h"
274#include "TGeoBoolNode.h"
275#include "TGeoBuilder.h"
276#include "TVirtualGeoPainter.h"
277#include "TPluginManager.h"
278#include "TVirtualGeoTrack.h"
279#include "TQObject.h"
280#include "TMath.h"
281#include "TEnv.h"
282#include "TGeoParallelWorld.h"
283#include "TGeoRegion.h"
284#include "TGDMLMatrix.h"
285#include "TGeoOpticalSurface.h"
286
287// statics and globals
288
290
292
293std::mutex TGeoManager::fgMutex;
305
306////////////////////////////////////////////////////////////////////////////////
307/// Default constructor.
308
310{
311 if (!fgThreadId)
315 fTmin = 0.;
316 fTmax = 999.;
317 fPhiCut = kFALSE;
318 fPhimin = 0;
319 fPhimax = 360;
324 fClosed = kFALSE;
326 fBits = 0;
328 fMaterials = 0;
329 fHashPNE = 0;
330 fArrayPNE = 0;
331 fMatrices = 0;
332 fNodes = 0;
333 fOverlaps = 0;
334 fRegions = 0;
335 fNNodes = 0;
336 fMaxVisNodes = 10000;
337 fVolumes = 0;
338 fPhysicalNodes = 0;
339 fShapes = 0;
340 fGVolumes = 0;
341 fGShapes = 0;
342 fTracks = 0;
343 fMedia = 0;
344 fNtracks = 0;
345 fNpdg = 0;
346 fPdgNames = 0;
347 fGDMLMatrices = 0;
349 fSkinSurfaces = 0;
350 fBorderSurfaces = 0;
351 memset(fPdgId, 0, 1024 * sizeof(Int_t));
352 // TObjArray *fNavigators; //! list of navigators
353 fCurrentTrack = 0;
354 fCurrentVolume = 0;
355 fTopVolume = 0;
356 fTopNode = 0;
357 fMasterVolume = 0;
358 fPainter = 0;
361 fVisDensity = 0.;
362 fVisLevel = 3;
363 fVisOption = 1;
364 fExplodedView = 0;
365 fNsegments = 20;
366 fNLevel = 0;
367 fUniqueVolumes = 0;
368 fClippingShape = 0;
371 fGLMatrix = 0;
372 fPaintVolume = 0;
374 fElementTable = 0;
375 fHashVolumes = 0;
376 fHashGVolumes = 0;
377 fSizePNEId = 0;
378 fNPNEId = 0;
379 fKeyPNEId = 0;
380 fValuePNEId = 0;
382 fRaytraceMode = 0;
383 fMaxThreads = 0;
385 fParallelWorld = 0;
387 } else {
388 Init();
390 gGeoIdentity = new TGeoIdentity("Identity");
392 }
393}
394
395////////////////////////////////////////////////////////////////////////////////
396/// Constructor.
397
398TGeoManager::TGeoManager(const char *name, const char *title) : TNamed(name, title)
399{
400 if (!gROOT->GetListOfGeometries()->FindObject(this))
401 gROOT->GetListOfGeometries()->Add(this);
402 if (!gROOT->GetListOfBrowsables()->FindObject(this))
403 gROOT->GetListOfBrowsables()->Add(this);
404 Init();
405 gGeoIdentity = new TGeoIdentity("Identity");
407 if (fgVerboseLevel > 0)
408 Info("TGeoManager", "Geometry %s, %s created", GetName(), GetTitle());
409}
410
411////////////////////////////////////////////////////////////////////////////////
412/// Initialize manager class.
413
415{
416 if (gGeoManager) {
417 Warning("Init", "Deleting previous geometry: %s/%s", gGeoManager->GetName(), gGeoManager->GetTitle());
418 delete gGeoManager;
419 if (fgLock)
420 Fatal("Init", "New geometry created while the old one locked !!!");
421 }
422
423 gGeoManager = this;
424 if (!fgThreadId)
427 fTmin = 0.;
428 fTmax = 999.;
429 fPhiCut = kFALSE;
430 fPhimin = 0;
431 fPhimax = 360;
436 fClosed = kFALSE;
438 fBits = new UChar_t[50000]; // max 25000 nodes per volume
440 fHashPNE = new THashList(256, 3);
441 fArrayPNE = 0;
442 fMaterials = new THashList(200, 3);
443 fMatrices = new TObjArray(256);
444 fNodes = new TObjArray(30);
445 fOverlaps = new TObjArray(256);
446 fRegions = new TObjArray(256);
447 fNNodes = 0;
448 fMaxVisNodes = 10000;
449 fVolumes = new TObjArray(256);
450 fPhysicalNodes = new TObjArray(256);
451 fShapes = new TObjArray(256);
452 fGVolumes = new TObjArray(256);
453 fGShapes = new TObjArray(256);
454 fTracks = new TObjArray(256);
455 fMedia = new THashList(200, 3);
456 fNtracks = 0;
457 fNpdg = 0;
458 fPdgNames = 0;
459 fGDMLMatrices = new TObjArray();
461 fSkinSurfaces = new TObjArray();
463 memset(fPdgId, 0, 1024 * sizeof(Int_t));
464 fCurrentTrack = 0;
465 fCurrentVolume = 0;
466 fTopVolume = 0;
467 fTopNode = 0;
468 fMasterVolume = 0;
469 fPainter = 0;
472 fVisDensity = 0.;
473 fVisLevel = 3;
474 fVisOption = 1;
475 fExplodedView = 0;
476 fNsegments = 20;
477 fNLevel = 0;
478 fUniqueVolumes = new TObjArray(256);
479 fClippingShape = 0;
482 fGLMatrix = new TGeoHMatrix();
483 fPaintVolume = 0;
485 fElementTable = 0;
486 fHashVolumes = 0;
487 fHashGVolumes = 0;
488 fSizePNEId = 0;
489 fNPNEId = 0;
490 fKeyPNEId = 0;
491 fValuePNEId = 0;
493 fRaytraceMode = 0;
494 fMaxThreads = 0;
496 fParallelWorld = 0;
498}
499
500////////////////////////////////////////////////////////////////////////////////
501/// Destructor
502
504{
505 if (gGeoManager != this)
506 gGeoManager = this;
508
509 if (gROOT->GetListOfFiles()) { // in case this function is called from TROOT destructor
510 gROOT->GetListOfGeometries()->Remove(this);
511 gROOT->GetListOfBrowsables()->Remove(this);
512 }
513 // TSeqCollection *brlist = gROOT->GetListOfBrowsers();
514 // TIter next(brlist);
515 // TBrowser *browser = 0;
516 // while ((browser=(TBrowser*)next())) browser->RecursiveRemove(this);
519 delete TGeoBuilder::Instance(this);
520 if (fBits)
521 delete[] fBits;
524 if (fOverlaps) {
525 fOverlaps->Delete();
527 }
528 if (fRegions) {
529 fRegions->Delete();
531 }
532 if (fMaterials) {
535 }
537 if (fMedia) {
538 fMedia->Delete();
540 }
541 if (fHashVolumes) {
542 fHashVolumes->Clear("nodelete");
544 }
545 if (fHashGVolumes) {
546 fHashGVolumes->Clear("nodelete");
548 }
549 if (fHashPNE) {
550 fHashPNE->Delete();
552 }
553 if (fArrayPNE) {
554 delete fArrayPNE;
555 }
556 if (fVolumes) {
557 fVolumes->Delete();
559 }
560 if (fShapes) {
561 fShapes->Delete();
563 }
564 if (fPhysicalNodes) {
567 }
568 if (fMatrices) {
569 fMatrices->Delete();
571 }
572 if (fTracks) {
573 fTracks->Delete();
575 }
577 if (fPdgNames) {
578 fPdgNames->Delete();
580 }
581 if (fGDMLMatrices) {
584 }
585 if (fOpticalSurfaces) {
588 }
589 if (fSkinSurfaces) {
592 }
593 if (fBorderSurfaces) {
596 }
598 CleanGarbage();
601 if (fSizePNEId) {
602 delete[] fKeyPNEId;
603 delete[] fValuePNEId;
604 }
605 delete fParallelWorld;
607 gGeoIdentity = 0;
608 gGeoManager = 0;
609}
610
611////////////////////////////////////////////////////////////////////////////////
612/// Add a material to the list. Returns index of the material in list.
613
615{
616 return TGeoBuilder::Instance(this)->AddMaterial((TGeoMaterial *)material);
617}
618
619////////////////////////////////////////////////////////////////////////////////
620/// Add an illegal overlap/extrusion to the list.
621
623{
625 fOverlaps->Add((TObject *)ovlp);
626 return size;
627}
628
629////////////////////////////////////////////////////////////////////////////////
630/// Add a new region of volumes.
632{
634 fRegions->Add(region);
635 return size;
636}
637
638////////////////////////////////////////////////////////////////////////////////
639/// Add a user-defined property. Returns true if added, false if existing.
640
642{
643 auto pos = fProperties.insert(ConstPropMap_t::value_type(property, value));
644 if (!pos.second) {
645 Warning("AddProperty", "Property \"%s\" already exists with value %g", property, (pos.first)->second);
646 return false;
647 }
648 return true;
649}
650
651////////////////////////////////////////////////////////////////////////////////
652/// Get a user-defined property
653
655{
656 auto pos = fProperties.find(property);
657 if (pos == fProperties.end()) {
658 if (error)
659 *error = kTRUE;
660 return 0.;
661 }
662 if (error)
663 *error = kFALSE;
664 return pos->second;
665}
666
667////////////////////////////////////////////////////////////////////////////////
668/// Get a user-defined property from a given index
669
671{
672 // This is a quite inefficient way to access map elements, but needed for the GDML writer to
673 if (i >= fProperties.size()) {
674 if (error)
675 *error = kTRUE;
676 return 0.;
677 }
678 size_t pos = 0;
679 auto it = fProperties.begin();
680 while (pos < i) {
681 ++it;
682 ++pos;
683 }
684 if (error)
685 *error = kFALSE;
686 name = (*it).first;
687 return (*it).second;
688}
689
690////////////////////////////////////////////////////////////////////////////////
691/// Add a matrix to the list. Returns index of the matrix in list.
692
694{
695 return TGeoBuilder::Instance(this)->AddTransformation((TGeoMatrix *)matrix);
696}
697
698////////////////////////////////////////////////////////////////////////////////
699/// Add a shape to the list. Returns index of the shape in list.
700
702{
703 return TGeoBuilder::Instance(this)->AddShape((TGeoShape *)shape);
704}
705
706////////////////////////////////////////////////////////////////////////////////
707/// Add a track to the list of tracks. Use this for primaries only. For secondaries,
708/// add them to the parent track. The method create objects that are registered
709/// to the analysis manager but have to be cleaned-up by the user via ClearTracks().
710
712{
714 fTracks->AddAtAndExpand(GetGeomPainter()->AddTrack(id, pdgcode, particle), fNtracks++);
715 return index;
716}
717
718////////////////////////////////////////////////////////////////////////////////
719/// Add a track to the list of tracks
720
722{
725 return index;
726}
727
728////////////////////////////////////////////////////////////////////////////////
729/// Makes a primary track but do not attach it to the list of tracks. The track
730/// can be attached as daughter to another one with TVirtualGeoTrack::AddTrack
731
733{
734 TVirtualGeoTrack *track = GetGeomPainter()->AddTrack(id, pdgcode, particle);
735 return track;
736}
737
738////////////////////////////////////////////////////////////////////////////////
739/// Add a volume to the list. Returns index of the volume in list.
740
742{
743 if (!volume) {
744 Error("AddVolume", "invalid volume");
745 return -1;
746 }
748 if (!uid)
749 uid++;
750 if (!fCurrentVolume) {
751 fCurrentVolume = volume;
752 fUniqueVolumes->AddAtAndExpand(volume, uid);
753 } else {
754 if (!strcmp(volume->GetName(), fCurrentVolume->GetName())) {
755 uid = fCurrentVolume->GetNumber();
756 } else {
757 fCurrentVolume = volume;
758 Int_t olduid = GetUID(volume->GetName());
759 if (olduid < 0) {
760 fUniqueVolumes->AddAtAndExpand(volume, uid);
761 } else {
762 uid = olduid;
763 }
764 }
765 }
766 volume->SetNumber(uid);
767 if (!fHashVolumes) {
768 fHashVolumes = new THashList(256);
769 fHashGVolumes = new THashList(256);
770 }
771 TObjArray *list = fVolumes;
772 if (!volume->GetShape() || volume->IsRunTime() || volume->IsVolumeMulti()) {
773 list = fGVolumes;
774 fHashGVolumes->Add(volume);
775 } else {
776 fHashVolumes->Add(volume);
777 }
778 Int_t index = list->GetEntriesFast();
779 list->AddAtAndExpand(volume, index);
780 return uid;
781}
782
783////////////////////////////////////////////////////////////////////////////////
784/// Add a navigator in the list of navigators. If it is the first one make it
785/// current navigator.
786
788{
789 if (fMultiThread) {
791 fgMutex.lock();
792 }
793 std::thread::id threadId = std::this_thread::get_id();
794 NavigatorsMap_t::const_iterator it = fNavigators.find(threadId);
795 TGeoNavigatorArray *array = 0;
796 if (it != fNavigators.end())
797 array = it->second;
798 else {
799 array = new TGeoNavigatorArray(this);
800 fNavigators.insert(NavigatorsMap_t::value_type(threadId, array));
801 }
802 TGeoNavigator *nav = array->AddNavigator();
803 if (fClosed)
804 nav->GetCache()->BuildInfoBranch();
805 if (fMultiThread)
806 fgMutex.unlock();
807 return nav;
808}
809
810////////////////////////////////////////////////////////////////////////////////
811/// Returns current navigator for the calling thread.
812
814{
815 TTHREAD_TLS(TGeoNavigator *) tnav = 0;
816 if (!fMultiThread)
817 return fCurrentNavigator;
818 TGeoNavigator *nav = tnav; // TTHREAD_TLS_GET(TGeoNavigator*,tnav);
819 if (nav)
820 return nav;
821 std::thread::id threadId = std::this_thread::get_id();
822 NavigatorsMap_t::const_iterator it = fNavigators.find(threadId);
823 if (it == fNavigators.end())
824 return 0;
825 TGeoNavigatorArray *array = it->second;
826 nav = array->GetCurrentNavigator();
827 tnav = nav; // TTHREAD_TLS_SET(TGeoNavigator*,tnav,nav);
828 return nav;
829}
830
831////////////////////////////////////////////////////////////////////////////////
832/// Get list of navigators for the calling thread.
833
835{
836 std::thread::id threadId = std::this_thread::get_id();
837 NavigatorsMap_t::const_iterator it = fNavigators.find(threadId);
838 if (it == fNavigators.end())
839 return 0;
840 TGeoNavigatorArray *array = it->second;
841 return array;
842}
843
844////////////////////////////////////////////////////////////////////////////////
845/// Switch to another existing navigator for the calling thread.
846
848{
849 std::thread::id threadId = std::this_thread::get_id();
850 NavigatorsMap_t::const_iterator it = fNavigators.find(threadId);
851 if (it == fNavigators.end()) {
852 Error("SetCurrentNavigator", "No navigator defined for this thread\n");
853 std::cout << " thread id: " << threadId << std::endl;
854 return kFALSE;
855 }
856 TGeoNavigatorArray *array = it->second;
858 if (!nav) {
859 Error("SetCurrentNavigator", "Navigator %d not existing for this thread\n", index);
860 std::cout << " thread id: " << threadId << std::endl;
861 return kFALSE;
862 }
863 if (!fMultiThread)
864 fCurrentNavigator = nav;
865 return kTRUE;
866}
867
868////////////////////////////////////////////////////////////////////////////////
869/// Set the lock for navigators.
870
872{
873 fgLockNavigators = flag;
874}
875
876////////////////////////////////////////////////////////////////////////////////
877/// Clear all navigators.
878
880{
881 if (fMultiThread)
882 fgMutex.lock();
883 TGeoNavigatorArray *arr = 0;
884 for (NavigatorsMap_t::iterator it = fNavigators.begin(); it != fNavigators.end(); ++it) {
885 arr = (*it).second;
886 if (arr)
887 delete arr;
888 }
889 fNavigators.clear();
890 if (fMultiThread)
891 fgMutex.unlock();
892}
893
894////////////////////////////////////////////////////////////////////////////////
895/// Clear a single navigator.
896
898{
899 if (fMultiThread)
900 fgMutex.lock();
901 for (NavigatorsMap_t::iterator it = fNavigators.begin(); it != fNavigators.end(); ++it) {
902 TGeoNavigatorArray *arr = (*it).second;
903 if (arr) {
904 if ((TGeoNavigator *)arr->Remove((TObject *)nav)) {
905 delete nav;
906 if (!arr->GetEntries())
907 fNavigators.erase(it);
908 if (fMultiThread)
909 fgMutex.unlock();
910 return;
911 }
912 }
913 }
914 Error("Remove navigator", "Navigator %p not found", nav);
915 if (fMultiThread)
916 fgMutex.unlock();
917}
918
919////////////////////////////////////////////////////////////////////////////////
920/// Set maximum number of threads for navigation.
921
923{
924 if (!fClosed) {
925 Error("SetMaxThreads", "Cannot set maximum number of threads before closing the geometry");
926 return;
927 }
928 if (!fMultiThread) {
930 std::thread::id threadId = std::this_thread::get_id();
931 NavigatorsMap_t::const_iterator it = fNavigators.find(threadId);
932 if (it != fNavigators.end()) {
933 TGeoNavigatorArray *array = it->second;
934 fNavigators.erase(it);
935 fNavigators.insert(NavigatorsMap_t::value_type(threadId, array));
936 }
937 }
938 if (fMaxThreads) {
941 }
942 fMaxThreads = nthreads + 1;
943 if (fMaxThreads > 0) {
946 }
947}
948
949////////////////////////////////////////////////////////////////////////////////
950
952{
953 if (!fMaxThreads)
954 return;
955 fgMutex.lock();
956 TIter next(fVolumes);
957 TGeoVolume *vol;
958 while ((vol = (TGeoVolume *)next()))
959 vol->ClearThreadData();
960 fgMutex.unlock();
961}
962
963////////////////////////////////////////////////////////////////////////////////
964/// Create thread private data for all geometry objects.
965
967{
968 if (!fMaxThreads)
969 return;
970 fgMutex.lock();
971 TIter next(fVolumes);
972 TGeoVolume *vol;
973 while ((vol = (TGeoVolume *)next()))
975 fgMutex.unlock();
976}
977
978////////////////////////////////////////////////////////////////////////////////
979/// Clear the current map of threads. This will be filled again by the calling
980/// threads via ThreadId calls.
981
983{
985 return;
986 fgMutex.lock();
987 if (!fgThreadId->empty())
988 fgThreadId->clear();
989 fgNumThreads = 0;
990 fgMutex.unlock();
991}
992
993////////////////////////////////////////////////////////////////////////////////
994/// Translates the current thread id to an ordinal number. This can be used to
995/// manage data which is specific for a given thread.
996
998{
999 TTHREAD_TLS(Int_t) tid = -1;
1000 Int_t ttid = tid; // TTHREAD_TLS_GET(Int_t,tid);
1001 if (ttid > -1)
1002 return ttid;
1004 return 0;
1005 std::thread::id threadId = std::this_thread::get_id();
1006 TGeoManager::ThreadsMapIt_t it = fgThreadId->find(threadId);
1007 if (it != fgThreadId->end())
1008 return it->second;
1009 // Map needs to be updated.
1010 fgMutex.lock();
1011 (*fgThreadId)[threadId] = fgNumThreads;
1012 tid = fgNumThreads; // TTHREAD_TLS_SET(Int_t,tid,fgNumThreads);
1013 ttid = fgNumThreads++;
1014 fgMutex.unlock();
1015 return ttid;
1016}
1017
1018////////////////////////////////////////////////////////////////////////////////
1019/// Describe how to browse this object.
1020
1022{
1023 if (!b)
1024 return;
1025 if (fMaterials)
1026 b->Add(fMaterials, "Materials");
1027 if (fMedia)
1028 b->Add(fMedia, "Media");
1029 if (fMatrices)
1030 b->Add(fMatrices, "Local transformations");
1031 if (fOverlaps)
1032 b->Add(fOverlaps, "Illegal overlaps");
1033 if (fTracks)
1034 b->Add(fTracks, "Tracks");
1035 if (fMasterVolume)
1036 b->Add(fMasterVolume, "Master Volume", fMasterVolume->IsVisible());
1037 if (fTopVolume)
1038 b->Add(fTopVolume, "Top Volume", fTopVolume->IsVisible());
1039 if (fTopNode)
1040 b->Add(fTopNode);
1041 TString browserImp(gEnv->GetValue("Browser.Name", "TRootBrowserLite"));
1042 TQObject::Connect(browserImp.Data(), "Checked(TObject*,Bool_t)", "TGeoManager", this,
1043 "SetVisibility(TObject*,Bool_t)");
1044}
1045
1046////////////////////////////////////////////////////////////////////////////////
1047/// Append a pad for this geometry.
1048
1050{
1051 AppendPad("");
1053}
1054
1055////////////////////////////////////////////////////////////////////////////////
1056/// Set visibility for a volume.
1057
1059{
1060 if (obj->IsA() == TGeoVolume::Class()) {
1061 TGeoVolume *vol = (TGeoVolume *)obj;
1062 vol->SetVisibility(vis);
1063 } else {
1064 if (obj->InheritsFrom(TGeoNode::Class())) {
1065 TGeoNode *node = (TGeoNode *)obj;
1066 node->SetVisibility(vis);
1067 } else
1068 return;
1069 }
1071}
1072
1073////////////////////////////////////////////////////////////////////////////////
1074/// Get the new 'bombed' translation vector according current exploded view mode.
1075
1077{
1078 if (fPainter)
1079 fPainter->BombTranslation(tr, bombtr);
1080 return;
1081}
1082
1083////////////////////////////////////////////////////////////////////////////////
1084/// Get the new 'unbombed' translation vector according current exploded view mode.
1085
1087{
1088 if (fPainter)
1089 fPainter->UnbombTranslation(tr, bombtr);
1090 return;
1091}
1092
1093////////////////////////////////////////////////////////////////////////////////
1094/// Backup the current state without affecting the cache stack.
1095
1097{
1099}
1100
1101////////////////////////////////////////////////////////////////////////////////
1102/// Restore a backed-up state without affecting the cache stack.
1103
1105{
1107}
1108
1109////////////////////////////////////////////////////////////////////////////////
1110/// Register a matrix to the list of matrices. It will be cleaned-up at the
1111/// destruction TGeoManager.
1112
1114{
1115 return TGeoBuilder::Instance(this)->RegisterMatrix((TGeoMatrix *)matrix);
1116}
1117
1118////////////////////////////////////////////////////////////////////////////////
1119/// Replaces all occurrences of VORIG with VNEW in the geometry tree. The volume VORIG
1120/// is not replaced from the list of volumes, but all node referencing it will reference
1121/// VNEW instead. Returns number of occurrences changed.
1122
1124{
1125 Int_t nref = 0;
1126 if (!vorig || !vnew)
1127 return nref;
1128 TGeoMedium *morig = vorig->GetMedium();
1129 Bool_t checkmed = kFALSE;
1130 if (morig)
1131 checkmed = kTRUE;
1132 TGeoMedium *mnew = vnew->GetMedium();
1133 // Try to limit the damage produced by incorrect usage.
1134 if (!mnew && !vnew->IsAssembly()) {
1135 Error("ReplaceVolume", "Replacement volume %s has no medium and it is not an assembly", vnew->GetName());
1136 return nref;
1137 }
1138 if (mnew && checkmed) {
1139 if (mnew->GetId() != morig->GetId())
1140 Warning("ReplaceVolume", "Replacement volume %s has different medium than original volume %s", vnew->GetName(),
1141 vorig->GetName());
1142 checkmed = kFALSE;
1143 }
1144
1145 // Medium checking now performed only if replacement is an assembly and old volume a real one.
1146 // Check result is dependent on positioning.
1147 Int_t nvol = fVolumes->GetEntriesFast();
1148 Int_t i, j, nd;
1149 Int_t ierr = 0;
1150 TGeoVolume *vol;
1151 TGeoNode *node;
1152 TGeoVoxelFinder *voxels;
1153 for (i = 0; i < nvol; i++) {
1154 vol = (TGeoVolume *)fVolumes->At(i);
1155 if (!vol)
1156 continue;
1157 if (vol == vorig || vol == vnew)
1158 continue;
1159 nd = vol->GetNdaughters();
1160 for (j = 0; j < nd; j++) {
1161 node = vol->GetNode(j);
1162 if (node->GetVolume() == vorig) {
1163 if (checkmed) {
1164 mnew = node->GetMotherVolume()->GetMedium();
1165 if (mnew && mnew->GetId() != morig->GetId())
1166 ierr++;
1167 }
1168 nref++;
1169 if (node->IsOverlapping()) {
1170 node->SetOverlapping(kFALSE);
1171 Info("ReplaceVolume", "%s replaced with assembly and declared NON-OVERLAPPING!", node->GetName());
1172 }
1173 node->SetVolume(vnew);
1174 voxels = node->GetMotherVolume()->GetVoxels();
1175 if (voxels)
1176 voxels->SetNeedRebuild();
1177 } else {
1178 if (node->GetMotherVolume() == vorig) {
1179 nref++;
1180 node->SetMotherVolume(vnew);
1181 if (node->IsOverlapping()) {
1182 node->SetOverlapping(kFALSE);
1183 Info("ReplaceVolume", "%s inside substitute assembly %s declared NON-OVERLAPPING!", node->GetName(),
1184 vnew->GetName());
1185 }
1186 }
1187 }
1188 }
1189 }
1190 if (ierr)
1191 Warning("ReplaceVolume",
1192 "Volumes should not be replaced with assemblies if they are positioned in containers having a different "
1193 "medium ID.\n %i occurrences for assembly replacing volume %s",
1194 ierr, vorig->GetName());
1195 return nref;
1196}
1197
1198////////////////////////////////////////////////////////////////////////////////
1199/// Transform all volumes named VNAME to assemblies. The volumes must be virtual.
1200
1202{
1203 TGeoVolume *toTransform = FindVolumeFast(vname);
1204 if (!toTransform) {
1205 Warning("TransformVolumeToAssembly", "Volume %s not found", vname);
1206 return 0;
1207 }
1208 Int_t index = fVolumes->IndexOf(toTransform);
1209 Int_t count = 0;
1210 Int_t indmax = fVolumes->GetEntries();
1211 Bool_t replace = kTRUE;
1212 TGeoVolume *transformed;
1213 while (index < indmax) {
1214 if (replace) {
1215 replace = kFALSE;
1216 transformed = TGeoVolumeAssembly::MakeAssemblyFromVolume(toTransform);
1217 if (transformed) {
1218 ReplaceVolume(toTransform, transformed);
1219 count++;
1220 } else {
1221 if (toTransform->IsAssembly())
1222 Warning("TransformVolumeToAssembly", "Volume %s already assembly", toTransform->GetName());
1223 if (!toTransform->GetNdaughters())
1224 Warning("TransformVolumeToAssembly", "Volume %s has no daughters, cannot transform",
1225 toTransform->GetName());
1226 if (toTransform->IsVolumeMulti())
1227 Warning("TransformVolumeToAssembly", "Volume %s divided, cannot transform", toTransform->GetName());
1228 }
1229 }
1230 index++;
1231 if (index >= indmax)
1232 return count;
1233 toTransform = (TGeoVolume *)fVolumes->At(index);
1234 if (!strcmp(toTransform->GetName(), vname))
1235 replace = kTRUE;
1236 }
1237 return count;
1238}
1239
1240////////////////////////////////////////////////////////////////////////////////
1241/// Create a new volume by dividing an existing one (GEANT3 like)
1242///
1243/// Divides MOTHER into NDIV divisions called NAME
1244/// along axis IAXIS starting at coordinate value START
1245/// and having size STEP. The created volumes will have tracking
1246/// media ID=NUMED (if NUMED=0 -> same media as MOTHER)
1247/// The behavior of the division operation can be triggered using OPTION :
1248///
1249/// OPTION (case insensitive) :
1250/// - N - divide all range in NDIV cells (same effect as STEP<=0) (GSDVN in G3)
1251/// - NX - divide range starting with START in NDIV cells (GSDVN2 in G3)
1252/// - S - divide all range with given STEP. NDIV is computed and divisions will be centered
1253/// in full range (same effect as NDIV<=0) (GSDVS, GSDVT in G3)
1254/// - SX - same as DVS, but from START position. (GSDVS2, GSDVT2 in G3)
1255
1256TGeoVolume *TGeoManager::Division(const char *name, const char *mother, Int_t iaxis, Int_t ndiv, Double_t start,
1257 Double_t step, Int_t numed, Option_t *option)
1258{
1259 return TGeoBuilder::Instance(this)->Division(name, mother, iaxis, ndiv, start, step, numed, option);
1260}
1261
1262////////////////////////////////////////////////////////////////////////////////
1263/// Create rotation matrix named 'mat<index>'.
1264///
1265/// - index rotation matrix number
1266/// - theta1 polar angle for axis X
1267/// - phi1 azimuthal angle for axis X
1268/// - theta2 polar angle for axis Y
1269/// - phi2 azimuthal angle for axis Y
1270/// - theta3 polar angle for axis Z
1271/// - phi3 azimuthal angle for axis Z
1272///
1273
1275 Double_t phi3)
1276{
1277 TGeoBuilder::Instance(this)->Matrix(index, theta1, phi1, theta2, phi2, theta3, phi3);
1278}
1279
1280////////////////////////////////////////////////////////////////////////////////
1281/// Create material with given A, Z and density, having an unique id.
1282
1284 Double_t intlen)
1285{
1286 return TGeoBuilder::Instance(this)->Material(name, a, z, dens, uid, radlen, intlen);
1287}
1288
1289////////////////////////////////////////////////////////////////////////////////
1290/// Create mixture OR COMPOUND IMAT as composed by THE BASIC nelem
1291/// materials defined by arrays A,Z and WMAT, having an unique id.
1292
1294TGeoManager::Mixture(const char *name, Float_t *a, Float_t *z, Double_t dens, Int_t nelem, Float_t *wmat, Int_t uid)
1295{
1296 return TGeoBuilder::Instance(this)->Mixture(name, a, z, dens, nelem, wmat, uid);
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Create mixture OR COMPOUND IMAT as composed by THE BASIC nelem
1301/// materials defined by arrays A,Z and WMAT, having an unique id.
1302
1304TGeoManager::Mixture(const char *name, Double_t *a, Double_t *z, Double_t dens, Int_t nelem, Double_t *wmat, Int_t uid)
1305{
1306 return TGeoBuilder::Instance(this)->Mixture(name, a, z, dens, nelem, wmat, uid);
1307}
1308
1309////////////////////////////////////////////////////////////////////////////////
1310/// Create tracking medium
1311///
1312/// - numed tracking medium number assigned
1313/// - name tracking medium name
1314/// - nmat material number
1315/// - isvol sensitive volume flag
1316/// - ifield magnetic field
1317/// - fieldm max. field value (kilogauss)
1318/// - tmaxfd max. angle due to field (deg/step)
1319/// - stemax max. step allowed
1320/// - deemax max. fraction of energy lost in a step
1321/// - epsil tracking precision (cm)
1322/// - stmin min. step due to continuous processes (cm)
1323///
1324/// - ifield = 0 if no magnetic field; ifield = -1 if user decision in guswim;
1325/// - ifield = 1 if tracking performed with g3rkuta; ifield = 2 if tracking
1326/// performed with g3helix; ifield = 3 if tracking performed with g3helx3.
1327///
1328
1329TGeoMedium *TGeoManager::Medium(const char *name, Int_t numed, Int_t nmat, Int_t isvol, Int_t ifield, Double_t fieldm,
1330 Double_t tmaxfd, Double_t stemax, Double_t deemax, Double_t epsil, Double_t stmin)
1331{
1332 return TGeoBuilder::Instance(this)->Medium(name, numed, nmat, isvol, ifield, fieldm, tmaxfd, stemax, deemax, epsil,
1333 stmin);
1334}
1335
1336////////////////////////////////////////////////////////////////////////////////
1337/// Create a node called `<name_nr>` pointing to the volume called `<name>`
1338/// as daughter of the volume called `<mother>` (gspos). The relative matrix is
1339/// made of : a translation (x,y,z) and a rotation matrix named `<matIROT>`.
1340/// In case npar>0, create the volume to be positioned in mother, according
1341/// its actual parameters (gsposp).
1342/// - NAME Volume name
1343/// - NUMBER Copy number of the volume
1344/// - MOTHER Mother volume name
1345/// - X X coord. of the volume in mother ref. sys.
1346/// - Y Y coord. of the volume in mother ref. sys.
1347/// - Z Z coord. of the volume in mother ref. sys.
1348/// - IROT Rotation matrix number w.r.t. mother ref. sys.
1349/// - ISONLY ONLY/MANY flag
1350
1351void TGeoManager::Node(const char *name, Int_t nr, const char *mother, Double_t x, Double_t y, Double_t z, Int_t irot,
1352 Bool_t isOnly, Float_t *upar, Int_t npar)
1353{
1354 TGeoBuilder::Instance(this)->Node(name, nr, mother, x, y, z, irot, isOnly, upar, npar);
1355}
1356
1357////////////////////////////////////////////////////////////////////////////////
1358/// Create a node called `<name_nr>` pointing to the volume called `<name>`
1359/// as daughter of the volume called `<mother>` (gspos). The relative matrix is
1360/// made of : a translation (x,y,z) and a rotation matrix named `<matIROT>`.
1361/// In case npar>0, create the volume to be positioned in mother, according
1362/// its actual parameters (gsposp).
1363/// - NAME Volume name
1364/// - NUMBER Copy number of the volume
1365/// - MOTHER Mother volume name
1366/// - X X coord. of the volume in mother ref. sys.
1367/// - Y Y coord. of the volume in mother ref. sys.
1368/// - Z Z coord. of the volume in mother ref. sys.
1369/// - IROT Rotation matrix number w.r.t. mother ref. sys.
1370/// - ISONLY ONLY/MANY flag
1371
1372void TGeoManager::Node(const char *name, Int_t nr, const char *mother, Double_t x, Double_t y, Double_t z, Int_t irot,
1373 Bool_t isOnly, Double_t *upar, Int_t npar)
1374{
1375 TGeoBuilder::Instance(this)->Node(name, nr, mother, x, y, z, irot, isOnly, upar, npar);
1376}
1377
1378////////////////////////////////////////////////////////////////////////////////
1379/// Create a volume in GEANT3 style.
1380/// - NAME Volume name
1381/// - SHAPE Volume type
1382/// - NMED Tracking medium number
1383/// - NPAR Number of shape parameters
1384/// - UPAR Vector containing shape parameters
1385
1386TGeoVolume *TGeoManager::Volume(const char *name, const char *shape, Int_t nmed, Float_t *upar, Int_t npar)
1387{
1388 return TGeoBuilder::Instance(this)->Volume(name, shape, nmed, upar, npar);
1389}
1390
1391////////////////////////////////////////////////////////////////////////////////
1392/// Create a volume in GEANT3 style.
1393/// - NAME Volume name
1394/// - SHAPE Volume type
1395/// - NMED Tracking medium number
1396/// - NPAR Number of shape parameters
1397/// - UPAR Vector containing shape parameters
1398
1399TGeoVolume *TGeoManager::Volume(const char *name, const char *shape, Int_t nmed, Double_t *upar, Int_t npar)
1400{
1401 return TGeoBuilder::Instance(this)->Volume(name, shape, nmed, upar, npar);
1402}
1403
1404////////////////////////////////////////////////////////////////////////////////
1405/// Assigns uid's for all materials,media and matrices.
1406
1408{
1409 Int_t index = 1;
1410 TIter next(fMaterials);
1411 TGeoMaterial *mater;
1412 while ((mater = (TGeoMaterial *)next())) {
1413 mater->SetUniqueID(index++);
1415 }
1416 index = 1;
1417 TIter next1(fMedia);
1418 TGeoMedium *med;
1419 while ((med = (TGeoMedium *)next1())) {
1420 med->SetUniqueID(index++);
1422 }
1423 index = 1;
1424 TIter next2(fShapes);
1425 TGeoShape *shape;
1426 while ((shape = (TGeoShape *)next2())) {
1427 shape->SetUniqueID(index++);
1428 if (shape->IsComposite())
1429 ((TGeoCompositeShape *)shape)->GetBoolNode()->RegisterMatrices();
1430 }
1431
1432 TIter next3(fMatrices);
1433 TGeoMatrix *matrix;
1434 while ((matrix = (TGeoMatrix *)next3())) {
1435 matrix->RegisterYourself();
1436 }
1437 TIter next4(fMatrices);
1438 index = 1;
1439 while ((matrix = (TGeoMatrix *)next4())) {
1440 matrix->SetUniqueID(index++);
1442 }
1443 TIter next5(fVolumes);
1444 TGeoVolume *vol;
1445 while ((vol = (TGeoVolume *)next5()))
1446 vol->UnmarkSaved();
1447}
1448
1449////////////////////////////////////////////////////////////////////////////////
1450/// Reset all attributes to default ones. Default attributes for visualization
1451/// are those defined before closing the geometry.
1452
1454{
1455 if (gPad)
1456 delete gPad;
1457 gPad = 0;
1458 SetVisOption(0);
1459 SetVisLevel(3);
1460 SetExplodedView(0);
1462 if (!gStyle)
1463 return;
1464 TIter next(fVolumes);
1465 TGeoVolume *vol = 0;
1466 while ((vol = (TGeoVolume *)next())) {
1467 if (!vol->IsVisTouched())
1468 continue;
1469 vol->SetVisTouched(kFALSE);
1470 }
1471}
1472////////////////////////////////////////////////////////////////////////////////
1473/// Closing geometry implies checking the geometry validity, fixing shapes
1474/// with negative parameters (run-time shapes)building the cache manager,
1475/// voxelizing all volumes, counting the total number of physical nodes and
1476/// registering the manager class to the browser.
1477
1479{
1480 if (fClosed) {
1481 Warning("CloseGeometry", "geometry already closed");
1482 return;
1483 }
1484 if (!fMasterVolume) {
1485 Error("CloseGeometry", "you MUST call SetTopVolume() first !");
1486 return;
1487 }
1488 if (!gROOT->GetListOfGeometries()->FindObject(this))
1489 gROOT->GetListOfGeometries()->Add(this);
1490 if (!gROOT->GetListOfBrowsables()->FindObject(this))
1491 gROOT->GetListOfBrowsables()->Add(this);
1492 // TSeqCollection *brlist = gROOT->GetListOfBrowsers();
1493 // TIter next(brlist);
1494 // TBrowser *browser = 0;
1495 // while ((browser=(TBrowser*)next())) browser->Refresh();
1496 TString opt(option);
1497 opt.ToLower();
1498 // Bool_t dummy = opt.Contains("d");
1499 Bool_t nodeid = opt.Contains("i");
1500 // Create a geometry navigator if not present
1501 TGeoNavigator *nav = 0;
1502 Int_t nnavigators = 0;
1503 // Check if the geometry is streamed from file
1504 if (fIsGeomReading) {
1505 if (fgVerboseLevel > 0)
1506 Info("CloseGeometry", "Geometry loaded from file...");
1508 if (!fElementTable)
1510 if (!fTopNode) {
1511 if (!fMasterVolume) {
1512 Error("CloseGeometry", "Master volume not streamed");
1513 return;
1514 }
1516 if (fStreamVoxels && fgVerboseLevel > 0)
1517 Info("CloseGeometry", "Voxelization retrieved from file");
1518 }
1519 // Create a geometry navigator if not present
1520 if (!GetCurrentNavigator())
1522 nnavigators = GetListOfNavigators()->GetEntriesFast();
1523 if (!opt.Contains("nv")) {
1524 Voxelize("ALL");
1525 }
1526 CountLevels();
1527 for (Int_t i = 0; i < nnavigators; i++) {
1528 nav = (TGeoNavigator *)GetListOfNavigators()->At(i);
1529 nav->GetCache()->BuildInfoBranch();
1530 if (nodeid)
1531 nav->GetCache()->BuildIdArray();
1532 }
1533 if (!fHashVolumes) {
1534 Int_t nvol = fVolumes->GetEntriesFast();
1535 Int_t ngvol = fGVolumes->GetEntriesFast();
1536 fHashVolumes = new THashList(nvol + 1);
1537 fHashGVolumes = new THashList(ngvol + 1);
1538 Int_t i;
1539 for (i = 0; i < ngvol; i++)
1541 for (i = 0; i < nvol; i++)
1543 }
1544 fClosed = kTRUE;
1545 if (fParallelWorld) {
1546 if (fgVerboseLevel > 0)
1547 Info("CloseGeometry", "Recreating parallel world %s ...", fParallelWorld->GetName());
1549 }
1550
1551 if (fgVerboseLevel > 0)
1552 Info("CloseGeometry", "%i nodes/ %i volume UID's in %s", fNNodes, fUniqueVolumes->GetEntriesFast() - 1,
1553 GetTitle());
1554 if (fgVerboseLevel > 0)
1555 Info("CloseGeometry", "----------------modeler ready----------------");
1556 return;
1557 }
1558
1559 // Create a geometry navigator if not present
1560 if (!GetCurrentNavigator())
1562 nnavigators = GetListOfNavigators()->GetEntriesFast();
1564 CheckGeometry();
1565 if (fgVerboseLevel > 0)
1566 Info("CloseGeometry", "Counting nodes...");
1567 fNNodes = CountNodes();
1568 fNLevel = fMasterVolume->CountNodes(1, 3) + 1;
1569 if (fNLevel < 30)
1570 fNLevel = 100;
1571
1572 // BuildIdArray();
1573 // avoid voxelization if requested to speed up geometry startup
1574 if (!opt.Contains("nv")) {
1575 Voxelize("ALL");
1576 } else {
1577 TGeoVolume *vol;
1578 TIter next(fVolumes);
1579 while ((vol = (TGeoVolume *)next())) {
1580 vol->SortNodes();
1581 }
1582 }
1583 if (fgVerboseLevel > 0)
1584 Info("CloseGeometry", "Building cache...");
1585 CountLevels();
1586 for (Int_t i = 0; i < nnavigators; i++) {
1587 nav = (TGeoNavigator *)GetListOfNavigators()->At(i);
1588 nav->GetCache()->BuildInfoBranch();
1589 if (nodeid)
1590 nav->GetCache()->BuildIdArray();
1591 }
1592 fClosed = kTRUE;
1593 if (fgVerboseLevel > 0) {
1594 Info("CloseGeometry", "%i nodes/ %i volume UID's in %s", fNNodes, fUniqueVolumes->GetEntriesFast() - 1,
1595 GetTitle());
1596 Info("CloseGeometry", "----------------modeler ready----------------");
1597 }
1598}
1599
1600////////////////////////////////////////////////////////////////////////////////
1601/// Clear the list of overlaps.
1602
1604{
1605 if (fOverlaps) {
1606 fOverlaps->Delete();
1607 delete fOverlaps;
1608 }
1609 fOverlaps = new TObjArray();
1610}
1611
1612////////////////////////////////////////////////////////////////////////////////
1613/// Remove a shape from the list of shapes.
1614
1616{
1617 if (fShapes->FindObject(shape))
1618 fShapes->Remove((TGeoShape *)shape);
1619 delete shape;
1620}
1621
1622////////////////////////////////////////////////////////////////////////////////
1623/// Clean temporary volumes and shapes from garbage collection.
1624
1626{
1627 if (!fGVolumes && !fGShapes)
1628 return;
1629 Int_t i, nentries;
1630 if (fGVolumes) {
1632 TGeoVolume *vol = 0;
1633 for (i = 0; i < nentries; i++) {
1634 vol = (TGeoVolume *)fGVolumes->At(i);
1635 if (vol)
1636 vol->SetFinder(0);
1637 }
1638 fGVolumes->Delete();
1639 delete fGVolumes;
1640 fGVolumes = 0;
1641 }
1642 if (fGShapes) {
1643 fGShapes->Delete();
1644 delete fGShapes;
1645 fGShapes = 0;
1646 }
1647}
1648
1649////////////////////////////////////////////////////////////////////////////////
1650/// Change current path to point to the node having this id.
1651/// Node id has to be in range : 0 to fNNodes-1 (no check for performance reasons)
1652
1654{
1655 GetCurrentNavigator()->CdNode(nodeid);
1656}
1657
1658////////////////////////////////////////////////////////////////////////////////
1659/// Get the unique ID of the current node.
1660
1662{
1664}
1665
1666////////////////////////////////////////////////////////////////////////////////
1667/// Make top level node the current node. Updates the cache accordingly.
1668/// Determine the overlapping state of current node.
1669
1671{
1673}
1674
1675////////////////////////////////////////////////////////////////////////////////
1676/// Go one level up in geometry. Updates cache accordingly.
1677/// Determine the overlapping state of current node.
1678
1680{
1682}
1683
1684////////////////////////////////////////////////////////////////////////////////
1685/// Make a daughter of current node current. Can be called only with a valid
1686/// daughter index (no check). Updates cache accordingly.
1687
1689{
1691}
1692
1693////////////////////////////////////////////////////////////////////////////////
1694/// Do a cd to the node found next by FindNextBoundary
1695
1697{
1699}
1700
1701////////////////////////////////////////////////////////////////////////////////
1702/// Browse the tree of nodes starting from fTopNode according to pathname.
1703/// Changes the path accordingly.
1704
1705Bool_t TGeoManager::cd(const char *path)
1706{
1707 return GetCurrentNavigator()->cd(path);
1708}
1709
1710////////////////////////////////////////////////////////////////////////////////
1711/// Check if a geometry path is valid without changing the state of the current navigator.
1712
1713Bool_t TGeoManager::CheckPath(const char *path) const
1714{
1715 return GetCurrentNavigator()->CheckPath(path);
1716}
1717
1718////////////////////////////////////////////////////////////////////////////////
1719/// Convert all reflections in geometry to normal rotations + reflected shapes.
1720
1722{
1723 if (!fTopNode)
1724 return;
1725 if (fgVerboseLevel > 0)
1726 Info("ConvertReflections", "Converting reflections in: %s - %s ...", GetName(), GetTitle());
1728 TGeoNode *node;
1729 TGeoNodeMatrix *nodematrix;
1730 TGeoMatrix *matrix, *mclone;
1731 TGeoVolume *reflected;
1732 while ((node = next())) {
1733 matrix = node->GetMatrix();
1734 if (matrix->IsReflection()) {
1735 // printf("%s before\n", node->GetName());
1736 // matrix->Print();
1737 mclone = new TGeoCombiTrans(*matrix);
1738 mclone->RegisterYourself();
1739 // Reflect just the rotation component
1740 mclone->ReflectZ(kFALSE, kTRUE);
1741 nodematrix = (TGeoNodeMatrix *)node;
1742 nodematrix->SetMatrix(mclone);
1743 // printf("%s after\n", node->GetName());
1744 // node->GetMatrix()->Print();
1745 reflected = node->GetVolume()->MakeReflectedVolume();
1746 node->SetVolume(reflected);
1747 }
1748 }
1749 if (fgVerboseLevel > 0)
1750 Info("ConvertReflections", "Done");
1751}
1752
1753////////////////////////////////////////////////////////////////////////////////
1754/// Count maximum number of nodes per volume, maximum depth and maximum
1755/// number of xtru vertices.
1756
1758{
1759 if (!fTopNode) {
1760 Error("CountLevels", "Top node not defined.");
1761 return;
1762 }
1764 Bool_t fixrefs = fIsGeomReading && (fMasterVolume->GetRefCount() == 1);
1765 if (fMasterVolume->GetRefCount() > 1)
1767 if (fgVerboseLevel > 1 && fixrefs)
1768 Info("CountLevels", "Fixing volume reference counts");
1769 TGeoNode *node;
1770 Int_t maxlevel = 1;
1771 Int_t maxnodes = fTopVolume->GetNdaughters();
1772 Int_t maxvertices = 1;
1773 while ((node = next())) {
1774 if (fixrefs) {
1775 node->GetVolume()->Grab();
1776 for (Int_t ibit = 10; ibit < 14; ibit++) {
1777 node->SetBit(BIT(ibit + 4), node->TestBit(BIT(ibit)));
1778 // node->ResetBit(BIT(ibit)); // cannot overwrite old crap for reproducibility
1779 }
1780 }
1781 if (node->GetNdaughters() > maxnodes)
1782 maxnodes = node->GetNdaughters();
1783 if (next.GetLevel() > maxlevel)
1784 maxlevel = next.GetLevel();
1785 if (node->GetVolume()->GetShape()->IsA() == TGeoXtru::Class()) {
1786 TGeoXtru *xtru = (TGeoXtru *)node->GetVolume()->GetShape();
1787 if (xtru->GetNvert() > maxvertices)
1788 maxvertices = xtru->GetNvert();
1789 }
1790 }
1791 fgMaxLevel = maxlevel;
1792 fgMaxDaughters = maxnodes;
1793 fgMaxXtruVert = maxvertices;
1794 if (fgVerboseLevel > 0)
1795 Info("CountLevels", "max level = %d, max placements = %d", fgMaxLevel, fgMaxDaughters);
1796}
1797
1798////////////////////////////////////////////////////////////////////////////////
1799/// Count the total number of nodes starting from a volume, nlevels down.
1800
1802{
1803 TGeoVolume *top;
1804 if (!vol) {
1805 top = fTopVolume;
1806 } else {
1807 top = (TGeoVolume *)vol;
1808 }
1809 Int_t count = top->CountNodes(nlevels, option);
1810 return count;
1811}
1812
1813////////////////////////////////////////////////////////////////////////////////
1814/// Set default angles for a given view.
1815
1817{
1818 if (fPainter)
1820}
1821
1822////////////////////////////////////////////////////////////////////////////////
1823/// Draw current point in the same view.
1824
1826{
1827 if (fPainter)
1828 fPainter->DrawCurrentPoint(color);
1829}
1830
1831////////////////////////////////////////////////////////////////////////////////
1832/// Draw animation of tracks
1833
1835{
1838 if (tmin < 0 || tmin >= tmax || nframes < 1)
1839 return;
1841 box[0] = box[1] = box[2] = 0;
1842 box[3] = box[4] = box[5] = 100;
1843 Double_t dt = (tmax - tmin) / Double_t(nframes);
1844 Double_t delt = 2E-9;
1845 Double_t t = tmin;
1846 Int_t i, j;
1847 TString opt(option);
1848 Bool_t save = kFALSE, geomanim = kFALSE;
1849 TString fname;
1850 if (opt.Contains("/S"))
1851 save = kTRUE;
1852
1853 if (opt.Contains("/G"))
1854 geomanim = kTRUE;
1855 SetTminTmax(0, 0);
1856 DrawTracks(opt.Data());
1857 Double_t start[6] = {0, 0, 0, 0, 0, 0};
1858 Double_t end[6] = {0, 0, 0, 0, 0, 0};
1859 Double_t dd[6] = {0, 0, 0, 0, 0, 0};
1860 Double_t dlat = 0, dlong = 0, dpsi = 0;
1861 if (geomanim) {
1862 fPainter->EstimateCameraMove(tmin + 5 * dt, tmin + 15 * dt, start, end);
1863 for (i = 0; i < 3; i++) {
1864 start[i + 3] = 20 + 1.3 * start[i + 3];
1865 end[i + 3] = 20 + 0.9 * end[i + 3];
1866 }
1867 for (i = 0; i < 6; i++) {
1868 dd[i] = (end[i] - start[i]) / 10.;
1869 }
1870 memcpy(box, start, 6 * sizeof(Double_t));
1871 fPainter->GetViewAngles(dlong, dlat, dpsi);
1872 dlong = (-206 - dlong) / Double_t(nframes);
1873 dlat = (126 - dlat) / Double_t(nframes);
1874 dpsi = (75 - dpsi) / Double_t(nframes);
1876 }
1877
1878 for (i = 0; i < nframes; i++) {
1879 if (t - delt < 0)
1880 SetTminTmax(t - delt, t);
1881 else
1882 gGeoManager->SetTminTmax(t - delt, t);
1883 if (geomanim) {
1884 for (j = 0; j < 6; j++)
1885 box[j] += dd[j];
1886 fPainter->GrabFocus(1, dlong, dlat, dpsi);
1887 } else {
1888 ModifiedPad();
1889 }
1890 if (save) {
1891 fname = TString::Format("anim%04d.gif", i);
1892 gPad->Print(fname);
1893 }
1894 t += dt;
1895 }
1897}
1898
1899////////////////////////////////////////////////////////////////////////////////
1900/// Draw tracks over the geometry, according to option. By default, only
1901/// primaries are drawn. See TGeoTrack::Draw() for additional options.
1902
1904{
1905 TVirtualGeoTrack *track;
1906 // SetVisLevel(1);
1907 // SetVisOption(1);
1909 for (Int_t i = 0; i < fNtracks; i++) {
1910 track = GetTrack(i);
1911 if (track)
1912 track->Draw(option);
1913 }
1915 ModifiedPad();
1916}
1917
1918////////////////////////////////////////////////////////////////////////////////
1919/// Draw current path
1920
1921void TGeoManager::DrawPath(const char *path, Option_t *option)
1922{
1923 if (!fTopVolume)
1924 return;
1926 GetGeomPainter()->DrawPath(path, option);
1927}
1928
1929////////////////////////////////////////////////////////////////////////////////
1930/// Draw random points in the bounding box of a volume.
1931
1933{
1934 GetGeomPainter()->RandomPoints((TGeoVolume *)vol, npoints, option);
1935}
1936
1937////////////////////////////////////////////////////////////////////////////////
1938/// Check time of finding "Where am I" for n points.
1939
1941{
1942 GetGeomPainter()->Test(npoints, option);
1943}
1944
1945////////////////////////////////////////////////////////////////////////////////
1946/// Geometry overlap checker based on sampling.
1947
1948void TGeoManager::TestOverlaps(const char *path)
1949{
1951}
1952
1953////////////////////////////////////////////////////////////////////////////////
1954/// Fill volume names of current branch into an array.
1955
1957{
1959}
1960
1961////////////////////////////////////////////////////////////////////////////////
1962/// Get name for given pdg code;
1963
1964const char *TGeoManager::GetPdgName(Int_t pdg) const
1965{
1966 static char defaultname[5] = {"XXX"};
1967 if (!fPdgNames || !pdg)
1968 return defaultname;
1969 for (Int_t i = 0; i < fNpdg; i++) {
1970 if (fPdgId[i] == pdg)
1971 return fPdgNames->At(i)->GetName();
1972 }
1973 return defaultname;
1974}
1975
1976////////////////////////////////////////////////////////////////////////////////
1977/// Set a name for a particle having a given pdg.
1978
1979void TGeoManager::SetPdgName(Int_t pdg, const char *name)
1980{
1981 if (!pdg)
1982 return;
1983 if (!fPdgNames) {
1984 fPdgNames = new TObjArray(1024);
1985 }
1986 if (!strcmp(name, GetPdgName(pdg)))
1987 return;
1988 // store pdg name
1989 if (fNpdg > 1023) {
1990 Warning("SetPdgName", "No more than 256 different pdg codes allowed");
1991 return;
1992 }
1993 fPdgId[fNpdg] = pdg;
1994 TNamed *pdgname = new TNamed(name, "");
1995 fPdgNames->AddAtAndExpand(pdgname, fNpdg++);
1996}
1997
1998////////////////////////////////////////////////////////////////////////////////
1999/// Get GDML matrix with a given name;
2000
2002{
2004}
2005
2006////////////////////////////////////////////////////////////////////////////////
2007/// Add GDML matrix;
2009{
2010 if (GetGDMLMatrix(mat->GetName())) {
2011 Error("AddGDMLMatrix", "Matrix %s already added to manager", mat->GetName());
2012 return;
2013 }
2014 fGDMLMatrices->Add(mat);
2015}
2016
2017////////////////////////////////////////////////////////////////////////////////
2018/// Get optical surface with a given name;
2019
2021{
2023}
2024
2025////////////////////////////////////////////////////////////////////////////////
2026/// Add optical surface;
2028{
2029 if (GetOpticalSurface(optsurf->GetName())) {
2030 Error("AddOpticalSurface", "Surface %s already added to manager", optsurf->GetName());
2031 return;
2032 }
2033 fOpticalSurfaces->Add(optsurf);
2034}
2035
2036////////////////////////////////////////////////////////////////////////////////
2037/// Get skin surface with a given name;
2038
2040{
2042}
2043
2044////////////////////////////////////////////////////////////////////////////////
2045/// Add skin surface;
2047{
2048 if (GetSkinSurface(surf->GetName())) {
2049 Error("AddSkinSurface", "Surface %s already added to manager", surf->GetName());
2050 return;
2051 }
2052 fSkinSurfaces->Add(surf);
2053}
2054
2055////////////////////////////////////////////////////////////////////////////////
2056/// Get border surface with a given name;
2057
2059{
2061}
2062
2063////////////////////////////////////////////////////////////////////////////////
2064/// Add border surface;
2066{
2067 if (GetBorderSurface(surf->GetName())) {
2068 Error("AddBorderSurface", "Surface %s already added to manager", surf->GetName());
2069 return;
2070 }
2071 fBorderSurfaces->Add(surf);
2072}
2073
2074////////////////////////////////////////////////////////////////////////////////
2075/// Fill node copy numbers of current branch into an array.
2076
2077void TGeoManager::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
2078{
2079 GetCurrentNavigator()->GetBranchNumbers(copyNumbers, volumeNumbers);
2080}
2081
2082////////////////////////////////////////////////////////////////////////////////
2083/// Fill node copy numbers of current branch into an array.
2084
2086{
2088}
2089
2090////////////////////////////////////////////////////////////////////////////////
2091/// Retrieve cartesian and radial bomb factors.
2092
2093void TGeoManager::GetBombFactors(Double_t &bombx, Double_t &bomby, Double_t &bombz, Double_t &bombr) const
2094{
2095 if (fPainter) {
2096 fPainter->GetBombFactors(bombx, bomby, bombz, bombr);
2097 return;
2098 }
2099 bombx = bomby = bombz = bombr = 1.3;
2100}
2101
2102////////////////////////////////////////////////////////////////////////////////
2103/// Return maximum number of daughters of a volume used in the geometry.
2104
2106{
2107 return fgMaxDaughters;
2108}
2109
2110////////////////////////////////////////////////////////////////////////////////
2111/// Return maximum number of levels used in the geometry.
2112
2114{
2115 return fgMaxLevel;
2116}
2117
2118////////////////////////////////////////////////////////////////////////////////
2119/// Return maximum number of vertices for an xtru shape used.
2120
2122{
2123 return fgMaxXtruVert;
2124}
2125
2126////////////////////////////////////////////////////////////////////////////////
2127/// Returns number of threads that were set to use geometry.
2128
2130{
2131 return fgNumThreads;
2132}
2133
2134////////////////////////////////////////////////////////////////////////////////
2135/// Return stored current matrix (global matrix of the next touched node).
2136
2138{
2139 if (!GetCurrentNavigator())
2140 return NULL;
2141 return GetCurrentNavigator()->GetHMatrix();
2142}
2143
2144////////////////////////////////////////////////////////////////////////////////
2145/// Returns current depth to which geometry is drawn.
2146
2148{
2149 return fVisLevel;
2150}
2151
2152////////////////////////////////////////////////////////////////////////////////
2153/// Returns current depth to which geometry is drawn.
2154
2156{
2157 return fVisOption;
2158}
2159
2160////////////////////////////////////////////////////////////////////////////////
2161/// Find level of virtuality of current overlapping node (number of levels
2162/// up having the same tracking media.
2163
2165{
2167}
2168
2169////////////////////////////////////////////////////////////////////////////////
2170/// Search the track hierarchy to find the track with the
2171/// given id
2172///
2173/// if 'primsFirst' is true, then:
2174/// first tries TGeoManager::GetTrackOfId, then does a
2175/// recursive search if that fails. this would be faster
2176/// if the track is somehow known to be a primary
2177
2179{
2180 TVirtualGeoTrack *trk = 0;
2181 trk = GetTrackOfId(id);
2182 if (trk)
2183 return trk;
2184 // need recursive search
2185 TIter next(fTracks);
2186 TVirtualGeoTrack *prim;
2187 while ((prim = (TVirtualGeoTrack *)next())) {
2188 trk = prim->FindTrackWithId(id);
2189 if (trk)
2190 return trk;
2191 }
2192 return NULL;
2193}
2194
2195////////////////////////////////////////////////////////////////////////////////
2196/// Get track with a given ID.
2197
2199{
2200 TVirtualGeoTrack *track;
2201 for (Int_t i = 0; i < fNtracks; i++) {
2202 if ((track = (TVirtualGeoTrack *)fTracks->UncheckedAt(i))) {
2203 if (track->GetId() == id)
2204 return track;
2205 }
2206 }
2207 return 0;
2208}
2209
2210////////////////////////////////////////////////////////////////////////////////
2211/// Get parent track with a given ID.
2212
2214{
2216 while ((track = track->GetMother())) {
2217 if (track->GetId() == id)
2218 return track;
2219 }
2220 return 0;
2221}
2222
2223////////////////////////////////////////////////////////////////////////////////
2224/// Get index for track id, -1 if not found.
2225
2227{
2228 TVirtualGeoTrack *track;
2229 for (Int_t i = 0; i < fNtracks; i++) {
2230 if ((track = (TVirtualGeoTrack *)fTracks->UncheckedAt(i))) {
2231 if (track->GetId() == id)
2232 return i;
2233 }
2234 }
2235 return -1;
2236}
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Go upwards the tree until a non-overlapping node
2240
2242{
2244}
2245
2246////////////////////////////////////////////////////////////////////////////////
2247/// Go upwards the tree until a non-overlapping node
2248
2250{
2252}
2253
2254////////////////////////////////////////////////////////////////////////////////
2255/// Set default volume colors according to A of material
2256
2258{
2259 const Int_t nmax = 110;
2260 Int_t col[nmax];
2261 for (Int_t i = 0; i < nmax; i++)
2262 col[i] = kGray;
2263
2264 // here we should create a new TColor with the same rgb as in the default
2265 // ROOT colors used below
2266 col[3] = kYellow - 10;
2267 col[4] = col[5] = kGreen - 10;
2268 col[6] = col[7] = kBlue - 7;
2269 col[8] = col[9] = kMagenta - 3;
2270 col[10] = col[11] = kRed - 10;
2271 col[12] = kGray + 1;
2272 col[13] = kBlue - 10;
2273 col[14] = kOrange + 7;
2274 col[16] = kYellow + 1;
2275 col[20] = kYellow - 10;
2276 col[24] = col[25] = col[26] = kBlue - 8;
2277 col[29] = kOrange + 9;
2278 col[79] = kOrange - 2;
2279
2280 TGeoVolume *vol;
2281 TIter next(fVolumes);
2282 while ((vol = (TGeoVolume *)next())) {
2283 TGeoMedium *med = vol->GetMedium();
2284 if (!med)
2285 continue;
2286 TGeoMaterial *mat = med->GetMaterial();
2287 Int_t matZ = (Int_t)mat->GetZ();
2288 vol->SetLineColor(col[matZ]);
2289 if (mat->GetDensity() < 0.1)
2290 vol->SetTransparency(60);
2291 }
2292}
2293
2294////////////////////////////////////////////////////////////////////////////////
2295/// Compute safe distance from the current point. This represent the distance
2296/// from POINT to the closest boundary.
2297
2299{
2300 return GetCurrentNavigator()->Safety(inside);
2301}
2302
2303////////////////////////////////////////////////////////////////////////////////
2304/// Set volume attributes in G3 style.
2305
2306void TGeoManager::SetVolumeAttribute(const char *name, const char *att, Int_t val)
2307{
2308 TGeoVolume *volume;
2309 Bool_t all = kFALSE;
2310 if (strstr(name, "*"))
2311 all = kTRUE;
2312 Int_t ivo = 0;
2313 TIter next(fVolumes);
2314 TString chatt = att;
2315 chatt.ToLower();
2316 while ((volume = (TGeoVolume *)next())) {
2317 if (strcmp(volume->GetName(), name) && !all)
2318 continue;
2319 ivo++;
2320 if (chatt.Contains("colo"))
2321 volume->SetLineColor(val);
2322 if (chatt.Contains("lsty"))
2323 volume->SetLineStyle(val);
2324 if (chatt.Contains("lwid"))
2325 volume->SetLineWidth(val);
2326 if (chatt.Contains("fill"))
2327 volume->SetFillColor(val);
2328 if (chatt.Contains("seen"))
2329 volume->SetVisibility(val);
2330 }
2331 TIter next1(fGVolumes);
2332 while ((volume = (TGeoVolume *)next1())) {
2333 if (strcmp(volume->GetName(), name) && !all)
2334 continue;
2335 ivo++;
2336 if (chatt.Contains("colo"))
2337 volume->SetLineColor(val);
2338 if (chatt.Contains("lsty"))
2339 volume->SetLineStyle(val);
2340 if (chatt.Contains("lwid"))
2341 volume->SetLineWidth(val);
2342 if (chatt.Contains("fill"))
2343 volume->SetFillColor(val);
2344 if (chatt.Contains("seen"))
2345 volume->SetVisibility(val);
2346 }
2347 if (!ivo) {
2348 Warning("SetVolumeAttribute", "volume: %s does not exist", name);
2349 }
2350}
2351
2352////////////////////////////////////////////////////////////////////////////////
2353/// Set factors that will "bomb" all translations in cartesian and cylindrical coordinates.
2354
2356{
2357 if (fPainter)
2358 fPainter->SetBombFactors(bombx, bomby, bombz, bombr);
2359}
2360
2361////////////////////////////////////////////////////////////////////////////////
2362/// Set a user-defined shape as clipping for ray tracing.
2363
2365{
2367 if (shape) {
2368 if (fClippingShape && (fClippingShape != shape))
2370 fClippingShape = shape;
2371 }
2372 painter->SetClippingShape(shape);
2373}
2374
2375////////////////////////////////////////////////////////////////////////////////
2376/// set the maximum number of visible nodes.
2377
2379{
2380 fMaxVisNodes = maxnodes;
2381 if (maxnodes > 0 && fgVerboseLevel > 0)
2382 Info("SetMaxVisNodes", "Automatic visible depth for %d visible nodes", maxnodes);
2383 if (!fPainter)
2384 return;
2386 Int_t level = fPainter->GetVisLevel();
2387 if (level != fVisLevel)
2388 fVisLevel = level;
2389}
2390
2391////////////////////////////////////////////////////////////////////////////////
2392/// make top volume visible on screen
2393
2395{
2397 fPainter->SetTopVisible(vis);
2398}
2399
2400////////////////////////////////////////////////////////////////////////////////
2401/// Assign a given node to be checked for overlaps. Any other overlaps will be ignored.
2402
2404{
2406}
2407
2408////////////////////////////////////////////////////////////////////////////////
2409/// Set the number of points to be generated on the shape outline when checking
2410/// for overlaps.
2411
2413{
2414 GetGeomPainter()->SetNmeshPoints(npoints);
2415}
2416
2417////////////////////////////////////////////////////////////////////////////////
2418/// set drawing mode :
2419/// - option=0 (default) all nodes drawn down to vislevel
2420/// - option=1 leaves and nodes at vislevel drawn
2421/// - option=2 path is drawn
2422/// - option=4 visibility changed
2423
2425{
2426 if ((option >= 0) && (option < 3))
2428 if (fPainter)
2430}
2431
2432////////////////////////////////////////////////////////////////////////////////
2433/// Set visualization option (leaves only OR all volumes)
2434
2436{
2437 if (flag)
2438 SetVisOption(1);
2439 else
2440 SetVisOption(0);
2441}
2442
2443////////////////////////////////////////////////////////////////////////////////
2444/// Set density threshold. Volumes with densities lower than this become
2445/// transparent.
2446
2448{
2449 fVisDensity = density;
2450 if (fPainter)
2452}
2453
2454////////////////////////////////////////////////////////////////////////////////
2455/// set default level down to which visualization is performed
2456
2458{
2459 if (level > 0) {
2460 fVisLevel = level;
2461 fMaxVisNodes = 0;
2462 if (fgVerboseLevel > 0)
2463 Info("SetVisLevel", "Automatic visible depth disabled");
2464 if (fPainter)
2466 } else {
2468 }
2469}
2470
2471////////////////////////////////////////////////////////////////////////////////
2472/// Sort overlaps by decreasing overlap distance. Extrusions comes first.
2473
2475{
2476 fOverlaps->Sort();
2477}
2478
2479////////////////////////////////////////////////////////////////////////////////
2480/// Optimize voxelization type for all volumes. Save best choice in a macro.
2481
2483{
2484 if (!fTopNode) {
2485 Error("OptimizeVoxels", "Geometry must be closed first");
2486 return;
2487 }
2488 std::ofstream out;
2489 TString fname = filename;
2490 if (fname.IsNull())
2491 fname = "tgeovox.C";
2492 out.open(fname, std::ios::out);
2493 if (!out.good()) {
2494 Error("OptimizeVoxels", "cannot open file");
2495 return;
2496 }
2497 // write header
2498 TDatime t;
2499 TString sname(fname);
2500 sname.ReplaceAll(".C", "");
2501 out << sname.Data() << "()" << std::endl;
2502 out << "{" << std::endl;
2503 out << "//=== Macro generated by ROOT version " << gROOT->GetVersion() << " : " << t.AsString() << std::endl;
2504 out << "//=== Voxel optimization for " << GetTitle() << " geometry" << std::endl;
2505 out << "//===== <run this macro JUST BEFORE closing the geometry>" << std::endl;
2506 out << " TGeoVolume *vol = 0;" << std::endl;
2507 out << " // parse all voxelized volumes" << std::endl;
2508 TGeoVolume *vol = 0;
2509 Bool_t cyltype;
2510 TIter next(fVolumes);
2511 while ((vol = (TGeoVolume *)next())) {
2512 if (!vol->GetVoxels())
2513 continue;
2514 out << " vol = gGeoManager->GetVolume(\"" << vol->GetName() << "\");" << std::endl;
2515 cyltype = vol->OptimizeVoxels();
2516 if (cyltype) {
2517 out << " vol->SetCylVoxels();" << std::endl;
2518 } else {
2519 out << " vol->SetCylVoxels(kFALSE);" << std::endl;
2520 }
2521 }
2522 out << "}" << std::endl;
2523 out.close();
2524}
2525////////////////////////////////////////////////////////////////////////////////
2526/// Parse a string boolean expression and do a syntax check. Find top
2527/// level boolean operator and returns its type. Fill the two
2528/// substrings to which this operator applies. The returned integer is :
2529/// - -1 : parse error
2530/// - 0 : no boolean operator
2531/// - 1 : union - represented as '+' in expression
2532/// - 2 : difference (subtraction) - represented as '-' in expression
2533/// - 3 : intersection - represented as '*' in expression.
2534/// Parentheses should be used to avoid ambiguities. For instance :
2535/// - A+B-C will be interpreted as (A+B)-C which is not the same as A+(B-C)
2536/// eliminate not needed parentheses
2537
2538Int_t TGeoManager::Parse(const char *expr, TString &expr1, TString &expr2, TString &expr3)
2539{
2540 TString startstr(expr);
2541 Int_t len = startstr.Length();
2542 Int_t i;
2543 TString e0 = "";
2544 expr3 = "";
2545 // eliminate blanks
2546 for (i = 0; i < len; i++) {
2547 if (startstr(i) == ' ')
2548 continue;
2549 e0 += startstr(i, 1);
2550 }
2551 Int_t level = 0;
2552 Int_t levmin = 999;
2553 Int_t boolop = 0;
2554 Int_t indop = 0;
2555 Int_t iloop = 1;
2556 Int_t lastop = 0;
2557 Int_t lastdp = 0;
2558 Int_t lastpp = 0;
2559 Bool_t foundmat = kFALSE;
2560 // check/eliminate parentheses
2561 while (iloop == 1) {
2562 iloop = 0;
2563 lastop = 0;
2564 lastdp = 0;
2565 lastpp = 0;
2566 len = e0.Length();
2567 for (i = 0; i < len; i++) {
2568 if (e0(i) == '(') {
2569 if (!level)
2570 iloop++;
2571 level++;
2572 continue;
2573 }
2574 if (e0(i) == ')') {
2575 level--;
2576 if (level == 0)
2577 lastpp = i;
2578 continue;
2579 }
2580 if ((e0(i) == '+') || (e0(i) == '-') || (e0(i) == '*')) {
2581 lastop = i;
2582 if (level < levmin) {
2583 levmin = level;
2584 indop = i;
2585 }
2586 continue;
2587 }
2588 if ((e0(i) == ':') && (level == 0)) {
2589 lastdp = i;
2590 continue;
2591 }
2592 }
2593 if (level != 0) {
2594 if (gGeoManager)
2595 gGeoManager->Error("Parse", "parentheses does not match");
2596 return -1;
2597 }
2598 if (iloop == 1 && (e0(0) == '(') && (e0(len - 1) == ')')) {
2599 // eliminate extra parentheses
2600 e0 = e0(1, len - 2);
2601 continue;
2602 }
2603 if (foundmat)
2604 break;
2605 if (((lastop == 0) && (lastdp > 0)) || ((lastpp > 0) && (lastdp > lastpp) && (indop < lastpp))) {
2606 expr3 = e0(lastdp + 1, len - lastdp);
2607 e0 = e0(0, lastdp);
2608 foundmat = kTRUE;
2609 iloop = 1;
2610 continue;
2611 } else
2612 break;
2613 }
2614 // loop expression and search parentheses/operators
2615 levmin = 999;
2616 for (i = 0; i < len; i++) {
2617 if (e0(i) == '(') {
2618 level++;
2619 continue;
2620 }
2621 if (e0(i) == ')') {
2622 level--;
2623 continue;
2624 }
2625 // Take LAST operator at lowest level (revision 28/07/08)
2626 if (level <= levmin) {
2627 if (e0(i) == '+') {
2628 boolop = 1; // union
2629 levmin = level;
2630 indop = i;
2631 }
2632 if (e0(i) == '-') {
2633 boolop = 2; // difference
2634 levmin = level;
2635 indop = i;
2636 }
2637 if (e0(i) == '*') {
2638 boolop = 3; // intersection
2639 levmin = level;
2640 indop = i;
2641 }
2642 }
2643 }
2644 if (indop == 0) {
2645 expr1 = e0;
2646 return indop;
2647 }
2648 expr1 = e0(0, indop);
2649 expr2 = e0(indop + 1, len - indop);
2650 return boolop;
2651}
2652
2653////////////////////////////////////////////////////////////////////////////////
2654/// Save current attributes in a macro
2655
2657{
2658 if (!fTopNode) {
2659 Error("SaveAttributes", "geometry must be closed first\n");
2660 return;
2661 }
2662 std::ofstream out;
2663 TString fname(filename);
2664 if (fname.IsNull())
2665 fname = "tgeoatt.C";
2666 out.open(fname, std::ios::out);
2667 if (!out.good()) {
2668 Error("SaveAttributes", "cannot open file");
2669 return;
2670 }
2671 // write header
2672 TDatime t;
2673 TString sname(fname);
2674 sname.ReplaceAll(".C", "");
2675 out << sname.Data() << "()" << std::endl;
2676 out << "{" << std::endl;
2677 out << "//=== Macro generated by ROOT version " << gROOT->GetVersion() << " : " << t.AsString() << std::endl;
2678 out << "//=== Attributes for " << GetTitle() << " geometry" << std::endl;
2679 out << "//===== <run this macro AFTER loading the geometry in memory>" << std::endl;
2680 // save current top volume
2681 out << " TGeoVolume *top = gGeoManager->GetVolume(\"" << fTopVolume->GetName() << "\");" << std::endl;
2682 out << " TGeoVolume *vol = 0;" << std::endl;
2683 out << " TGeoNode *node = 0;" << std::endl;
2684 out << " // clear all volume attributes and get painter" << std::endl;
2685 out << " gGeoManager->ClearAttributes();" << std::endl;
2686 out << " gGeoManager->GetGeomPainter();" << std::endl;
2687 out << " // set visualization modes and bomb factors" << std::endl;
2688 out << " gGeoManager->SetVisOption(" << GetVisOption() << ");" << std::endl;
2689 out << " gGeoManager->SetVisLevel(" << GetVisLevel() << ");" << std::endl;
2690 out << " gGeoManager->SetExplodedView(" << GetBombMode() << ");" << std::endl;
2691 Double_t bombx, bomby, bombz, bombr;
2692 GetBombFactors(bombx, bomby, bombz, bombr);
2693 out << " gGeoManager->SetBombFactors(" << bombx << "," << bomby << "," << bombz << "," << bombr << ");"
2694 << std::endl;
2695 out << " // iterate volumes container and set new attributes" << std::endl;
2696 // out << " TIter next(gGeoManager->GetListOfVolumes());"<<std::endl;
2697 TGeoVolume *vol = 0;
2699
2700 TIter next(fVolumes);
2701 while ((vol = (TGeoVolume *)next())) {
2702 vol->SetVisStreamed(kFALSE);
2703 }
2704 out << " // draw top volume with new settings" << std::endl;
2705 out << " top->Draw();" << std::endl;
2706 out << " gPad->x3d();" << std::endl;
2707 out << "}" << std::endl;
2708 out.close();
2709}
2710
2711////////////////////////////////////////////////////////////////////////////////
2712/// Returns the deepest node containing fPoint, which must be set a priori.
2713
2715{
2716 return GetCurrentNavigator()->SearchNode(downwards, skipnode);
2717}
2718
2719////////////////////////////////////////////////////////////////////////////////
2720/// Cross next boundary and locate within current node
2721/// The current point must be on the boundary of fCurrentNode.
2722
2724{
2725 return GetCurrentNavigator()->CrossBoundaryAndLocate(downwards, skipnode);
2726}
2727
2728////////////////////////////////////////////////////////////////////////////////
2729/// Compute distance to next boundary within STEPMAX. If no boundary is found,
2730/// propagate current point along current direction with fStep=STEPMAX. Otherwise
2731/// propagate with fStep=SNEXT (distance to boundary) and locate/return the next
2732/// node.
2733
2735{
2736 return GetCurrentNavigator()->FindNextBoundaryAndStep(stepmax, compsafe);
2737}
2738
2739////////////////////////////////////////////////////////////////////////////////
2740/// Find distance to next boundary and store it in fStep. Returns node to which this
2741/// boundary belongs. If PATH is specified, compute only distance to the node to which
2742/// PATH points. If STEPMAX is specified, compute distance only in case fSafety is smaller
2743/// than this value. STEPMAX represent the step to be made imposed by other reasons than
2744/// geometry (usually physics processes). Therefore in this case this method provides the
2745/// answer to the question : "Is STEPMAX a safe step ?" returning a NULL node and filling
2746/// fStep with a big number.
2747/// In case frombdr=kTRUE, the isotropic safety is set to zero.
2748///
2749/// Note : safety distance for the current point is computed ONLY in case STEPMAX is
2750/// specified, otherwise users have to call explicitly TGeoManager::Safety() if
2751/// they want this computed for the current point.
2752
2753TGeoNode *TGeoManager::FindNextBoundary(Double_t stepmax, const char *path, Bool_t frombdr)
2754{
2755 // convert current point and direction to local reference
2756 return GetCurrentNavigator()->FindNextBoundary(stepmax, path, frombdr);
2757}
2758
2759////////////////////////////////////////////////////////////////////////////////
2760/// Computes as fStep the distance to next daughter of the current volume.
2761/// The point and direction must be converted in the coordinate system of the current volume.
2762/// The proposed step limit is fStep.
2763
2765{
2766 return GetCurrentNavigator()->FindNextDaughterBoundary(point, dir, idaughter, compmatrix);
2767}
2768
2769////////////////////////////////////////////////////////////////////////////////
2770/// Reset current state flags.
2771
2773{
2775}
2776
2777////////////////////////////////////////////////////////////////////////////////
2778/// Returns deepest node containing current point.
2779
2781{
2782 return GetCurrentNavigator()->FindNode(safe_start);
2783}
2784
2785////////////////////////////////////////////////////////////////////////////////
2786/// Returns deepest node containing current point.
2787
2789{
2790 return GetCurrentNavigator()->FindNode(x, y, z);
2791}
2792
2793////////////////////////////////////////////////////////////////////////////////
2794/// Computes fast normal to next crossed boundary, assuming that the current point
2795/// is close enough to the boundary. Works only after calling FindNextBoundary.
2796
2798{
2800}
2801
2802////////////////////////////////////////////////////////////////////////////////
2803/// Computes normal vector to the next surface that will be or was already
2804/// crossed when propagating on a straight line from a given point/direction.
2805/// Returns the normal vector cosines in the MASTER coordinate system. The dot
2806/// product of the normal and the current direction is positive defined.
2807
2809{
2810 return GetCurrentNavigator()->FindNormal(forward);
2811}
2812
2813////////////////////////////////////////////////////////////////////////////////
2814/// Checks if point (x,y,z) is still in the current node.
2815
2817{
2818 return GetCurrentNavigator()->IsSameLocation(x, y, z, change);
2819}
2820
2821////////////////////////////////////////////////////////////////////////////////
2822/// Check if a new point with given coordinates is the same as the last located one.
2823
2825{
2826 return GetCurrentNavigator()->IsSamePoint(x, y, z);
2827}
2828
2829////////////////////////////////////////////////////////////////////////////////
2830/// True if current node is in phi range
2831
2833{
2834 if (!fPhiCut)
2835 return kTRUE;
2836 const Double_t *origin;
2838 return kFALSE;
2839 origin = ((TGeoBBox *)GetCurrentNavigator()->GetCurrentVolume()->GetShape())->GetOrigin();
2840 Double_t point[3];
2841 LocalToMaster(origin, &point[0]);
2842 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
2843 if (phi < 0)
2844 phi += 360.;
2845 if ((phi >= fPhimin) && (phi <= fPhimax))
2846 return kFALSE;
2847 return kTRUE;
2848}
2849
2850////////////////////////////////////////////////////////////////////////////////
2851/// Initialize current point and current direction vector (normalized)
2852/// in MARS. Return corresponding node.
2853
2855{
2856 return GetCurrentNavigator()->InitTrack(point, dir);
2857}
2858
2859////////////////////////////////////////////////////////////////////////////////
2860/// Initialize current point and current direction vector (normalized)
2861/// in MARS. Return corresponding node.
2862
2864{
2865 return GetCurrentNavigator()->InitTrack(x, y, z, nx, ny, nz);
2866}
2867
2868////////////////////////////////////////////////////////////////////////////////
2869/// Inspects path and all flags for the current state.
2870
2872{
2874}
2875
2876////////////////////////////////////////////////////////////////////////////////
2877/// Get path to the current node in the form /node0/node1/...
2878
2879const char *TGeoManager::GetPath() const
2880{
2881 return GetCurrentNavigator()->GetPath();
2882}
2883
2884////////////////////////////////////////////////////////////////////////////////
2885/// Get total size of geometry in bytes.
2886
2888{
2889 Int_t count = 0;
2890 TIter next(fVolumes);
2891 TGeoVolume *vol;
2892 while ((vol = (TGeoVolume *)next()))
2893 count += vol->GetByteCount();
2894 TIter next1(fMatrices);
2895 TGeoMatrix *matrix;
2896 while ((matrix = (TGeoMatrix *)next1()))
2897 count += matrix->GetByteCount();
2898 TIter next2(fMaterials);
2899 TGeoMaterial *mat;
2900 while ((mat = (TGeoMaterial *)next2()))
2901 count += mat->GetByteCount();
2902 TIter next3(fMedia);
2903 TGeoMedium *med;
2904 while ((med = (TGeoMedium *)next3()))
2905 count += med->GetByteCount();
2906 if (fgVerboseLevel > 0)
2907 Info("GetByteCount", "Total size of logical tree : %i bytes", count);
2908 return count;
2909}
2910
2911////////////////////////////////////////////////////////////////////////////////
2912/// Make a default painter if none present. Returns pointer to it.
2913
2915{
2916 if (!fPainter) {
2917 const char *kind = "root";
2918 if (gROOT->IsWebDisplay() && !gROOT->IsWebDisplayBatch())
2919 kind = "web";
2920 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualGeoPainter", kind)) {
2921 if (h->LoadPlugin() == -1) {
2922 Error("GetGeomPainter", "could not load plugin for %s geo_painter", kind);
2923 return nullptr;
2924 }
2925 fPainter = (TVirtualGeoPainter *)h->ExecPlugin(1, this);
2926 if (!fPainter) {
2927 Error("GetGeomPainter", "could not create %s geo_painter", kind);
2928 return nullptr;
2929 }
2930 } else {
2931 Error("GetGeomPainter", "not found plugin %s for geo_painter", kind);
2932 }
2933 }
2934 return fPainter;
2935}
2936
2937////////////////////////////////////////////////////////////////////////////////
2938/// Search for a named volume. All trailing blanks stripped.
2939
2941{
2942 TString sname = name;
2943 sname = sname.Strip();
2944 TGeoVolume *vol = (TGeoVolume *)fVolumes->FindObject(sname.Data());
2945 return vol;
2946}
2947
2948////////////////////////////////////////////////////////////////////////////////
2949/// Fast search for a named volume. All trailing blanks stripped.
2950
2952{
2953 if (!fHashVolumes) {
2954 Int_t nvol = fVolumes->GetEntriesFast();
2955 Int_t ngvol = fGVolumes->GetEntriesFast();
2956 fHashVolumes = new THashList(nvol + 1);
2957 fHashGVolumes = new THashList(ngvol + 1);
2958 Int_t i;
2959 for (i = 0; i < ngvol; i++)
2961 for (i = 0; i < nvol; i++)
2963 }
2964 TString sname = name;
2965 sname = sname.Strip();
2966 THashList *list = fHashVolumes;
2967 if (multi)
2968 list = fHashGVolumes;
2969 TGeoVolume *vol = (TGeoVolume *)list->FindObject(sname.Data());
2970 return vol;
2971}
2972
2973////////////////////////////////////////////////////////////////////////////////
2974/// Retrieve unique id for a volume name. Return -1 if name not found.
2975
2976Int_t TGeoManager::GetUID(const char *volname) const
2977{
2978 TGeoManager *geom = (TGeoManager *)this;
2979 TGeoVolume *vol = geom->FindVolumeFast(volname, kFALSE);
2980 if (!vol)
2981 vol = geom->FindVolumeFast(volname, kTRUE);
2982 if (!vol)
2983 return -1;
2984 return vol->GetNumber();
2985}
2986
2987////////////////////////////////////////////////////////////////////////////////
2988/// Find if a given material duplicates an existing one.
2989
2991{
2992 Int_t index = fMaterials->IndexOf(mat);
2993 if (index <= 0)
2994 return 0;
2995 TGeoMaterial *other;
2996 for (Int_t i = 0; i < index; i++) {
2997 other = (TGeoMaterial *)fMaterials->At(i);
2998 if (other == mat)
2999 continue;
3000 if (other->IsEq(mat))
3001 return other;
3002 }
3003 return 0;
3004}
3005
3006////////////////////////////////////////////////////////////////////////////////
3007/// Search for a named material. All trailing blanks stripped.
3008
3009TGeoMaterial *TGeoManager::GetMaterial(const char *matname) const
3010{
3011 TString sname = matname;
3012 sname = sname.Strip();
3014 return mat;
3015}
3016
3017////////////////////////////////////////////////////////////////////////////////
3018/// Search for a named tracking medium. All trailing blanks stripped.
3019
3020TGeoMedium *TGeoManager::GetMedium(const char *medium) const
3021{
3022 TString sname = medium;
3023 sname = sname.Strip();
3024 TGeoMedium *med = (TGeoMedium *)fMedia->FindObject(sname.Data());
3025 return med;
3026}
3027
3028////////////////////////////////////////////////////////////////////////////////
3029/// Search for a tracking medium with a given ID.
3030
3032{
3033 TIter next(fMedia);
3034 TGeoMedium *med;
3035 while ((med = (TGeoMedium *)next())) {
3036 if (med->GetId() == numed)
3037 return med;
3038 }
3039 return 0;
3040}
3041
3042////////////////////////////////////////////////////////////////////////////////
3043/// Return material at position id.
3044
3046{
3047 if (id < 0 || id >= fMaterials->GetSize())
3048 return 0;
3049 TGeoMaterial *mat = (TGeoMaterial *)fMaterials->At(id);
3050 return mat;
3051}
3052
3053////////////////////////////////////////////////////////////////////////////////
3054/// Return index of named material.
3055
3056Int_t TGeoManager::GetMaterialIndex(const char *matname) const
3057{
3058 TIter next(fMaterials);
3059 TGeoMaterial *mat;
3060 Int_t id = 0;
3061 TString sname = matname;
3062 sname = sname.Strip();
3063 while ((mat = (TGeoMaterial *)next())) {
3064 if (!strcmp(mat->GetName(), sname.Data()))
3065 return id;
3066 id++;
3067 }
3068 return -1; // fail
3069}
3070
3071////////////////////////////////////////////////////////////////////////////////
3072/// Randomly shoot nrays and plot intersections with surfaces for current
3073/// top node.
3074
3075void TGeoManager::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz, const char *target_vol,
3076 Bool_t check_norm)
3077{
3078 GetGeomPainter()->RandomRays(nrays, startx, starty, startz, target_vol, check_norm);
3079}
3080
3081////////////////////////////////////////////////////////////////////////////////
3082/// Remove material at given index.
3083
3085{
3086 TObject *obj = fMaterials->At(index);
3087 if (obj)
3088 fMaterials->Remove(obj);
3089}
3090
3091////////////////////////////////////////////////////////////////////////////////
3092/// Sets all pointers TGeoVolume::fField to NULL. User data becomes decoupled
3093/// from geometry. Deletion has to be managed by users.
3094
3096{
3097 TIter next(fVolumes);
3098 TGeoVolume *vol;
3099 while ((vol = (TGeoVolume *)next()))
3100 vol->SetField(0);
3101}
3102
3103////////////////////////////////////////////////////////////////////////////////
3104/// Change raytracing mode.
3105
3107{
3109 if (fPainter && fPainter->IsRaytracing())
3110 ModifiedPad();
3111}
3112
3113////////////////////////////////////////////////////////////////////////////////
3114/// Restore the master volume of the geometry.
3115
3117{
3119 return;
3120 if (fMasterVolume)
3122}
3123
3124////////////////////////////////////////////////////////////////////////////////
3125/// Voxelize all non-divided volumes.
3126
3128{
3129 TGeoVolume *vol;
3130 // TGeoVoxelFinder *vox = 0;
3131 if (!fStreamVoxels && fgVerboseLevel > 0)
3132 Info("Voxelize", "Voxelizing...");
3133 // Int_t nentries = fVolumes->GetSize();
3134 TIter next(fVolumes);
3135 while ((vol = (TGeoVolume *)next())) {
3136 if (!fIsGeomReading)
3137 vol->SortNodes();
3138 if (!fStreamVoxels) {
3139 vol->Voxelize(option);
3140 }
3141 if (!fIsGeomReading)
3142 vol->FindOverlaps();
3143 }
3144}
3145
3146////////////////////////////////////////////////////////////////////////////////
3147/// Send "Modified" signal to painter.
3148
3150{
3151 if (!fPainter)
3152 return;
3154}
3155
3156////////////////////////////////////////////////////////////////////////////////
3157/// Make an TGeoArb8 volume.
3158
3160{
3161 return TGeoBuilder::Instance(this)->MakeArb8(name, medium, dz, vertices);
3162}
3163
3164////////////////////////////////////////////////////////////////////////////////
3165/// Make in one step a volume pointing to a box shape with given medium.
3166
3168{
3169 return TGeoBuilder::Instance(this)->MakeBox(name, medium, dx, dy, dz);
3170}
3171
3172////////////////////////////////////////////////////////////////////////////////
3173/// Make in one step a volume pointing to a parallelepiped shape with given medium.
3174
3176 Double_t alpha, Double_t theta, Double_t phi)
3177{
3178 return TGeoBuilder::Instance(this)->MakePara(name, medium, dx, dy, dz, alpha, theta, phi);
3179}
3180
3181////////////////////////////////////////////////////////////////////////////////
3182/// Make in one step a volume pointing to a sphere shape with given medium
3183
3185 Double_t themax, Double_t phimin, Double_t phimax)
3186{
3187 return TGeoBuilder::Instance(this)->MakeSphere(name, medium, rmin, rmax, themin, themax, phimin, phimax);
3188}
3189
3190////////////////////////////////////////////////////////////////////////////////
3191/// Make in one step a volume pointing to a torus shape with given medium.
3192
3194 Double_t phi1, Double_t dphi)
3195{
3196 return TGeoBuilder::Instance(this)->MakeTorus(name, medium, r, rmin, rmax, phi1, dphi);
3197}
3198
3199////////////////////////////////////////////////////////////////////////////////
3200/// Make in one step a volume pointing to a tube shape with given medium.
3201
3203{
3204 return TGeoBuilder::Instance(this)->MakeTube(name, medium, rmin, rmax, dz);
3205}
3206
3207////////////////////////////////////////////////////////////////////////////////
3208/// Make in one step a volume pointing to a tube segment shape with given medium.
3209/// The segment will be from phiStart to phiEnd, the angles are expressed in degree
3210
3212 Double_t phiStart, Double_t phiEnd)
3213{
3214 return TGeoBuilder::Instance(this)->MakeTubs(name, medium, rmin, rmax, dz, phiStart, phiEnd);
3215}
3216
3217////////////////////////////////////////////////////////////////////////////////
3218/// Make in one step a volume pointing to a tube shape with given medium
3219
3221{
3222 return TGeoBuilder::Instance(this)->MakeEltu(name, medium, a, b, dz);
3223}
3224
3225////////////////////////////////////////////////////////////////////////////////
3226/// Make in one step a volume pointing to a tube shape with given medium
3227
3229 Double_t stout, Double_t dz)
3230{
3231 return TGeoBuilder::Instance(this)->MakeHype(name, medium, rin, stin, rout, stout, dz);
3232}
3233
3234////////////////////////////////////////////////////////////////////////////////
3235/// Make in one step a volume pointing to a tube shape with given medium
3236
3238{
3239 return TGeoBuilder::Instance(this)->MakeParaboloid(name, medium, rlo, rhi, dz);
3240}
3241
3242////////////////////////////////////////////////////////////////////////////////
3243/// Make in one step a volume pointing to a tube segment shape with given medium
3244
3246 Double_t phi1, Double_t phi2, Double_t lx, Double_t ly, Double_t lz, Double_t tx,
3247 Double_t ty, Double_t tz)
3248{
3249 return TGeoBuilder::Instance(this)->MakeCtub(name, medium, rmin, rmax, dz, phi1, phi2, lx, ly, lz, tx, ty, tz);
3250}
3251
3252////////////////////////////////////////////////////////////////////////////////
3253/// Make in one step a volume pointing to a cone shape with given medium.
3254
3256 Double_t rmin2, Double_t rmax2)
3257{
3258 return TGeoBuilder::Instance(this)->MakeCone(name, medium, dz, rmin1, rmax1, rmin2, rmax2);
3259}
3260
3261////////////////////////////////////////////////////////////////////////////////
3262/// Make in one step a volume pointing to a cone segment shape with given medium
3263
3265 Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
3266{
3267 return TGeoBuilder::Instance(this)->MakeCons(name, medium, dz, rmin1, rmax1, rmin2, rmax2, phi1, phi2);
3268}
3269
3270////////////////////////////////////////////////////////////////////////////////
3271/// Make in one step a volume pointing to a polycone shape with given medium.
3272
3274{
3275 return TGeoBuilder::Instance(this)->MakePcon(name, medium, phi, dphi, nz);
3276}
3277
3278////////////////////////////////////////////////////////////////////////////////
3279/// Make in one step a volume pointing to a polygone shape with given medium.
3280
3281TGeoVolume *
3282TGeoManager::MakePgon(const char *name, TGeoMedium *medium, Double_t phi, Double_t dphi, Int_t nedges, Int_t nz)
3283{
3284 return TGeoBuilder::Instance(this)->MakePgon(name, medium, phi, dphi, nedges, nz);
3285}
3286
3287////////////////////////////////////////////////////////////////////////////////
3288/// Make in one step a volume pointing to a TGeoTrd1 shape with given medium.
3289
3290TGeoVolume *
3292{
3293 return TGeoBuilder::Instance(this)->MakeTrd1(name, medium, dx1, dx2, dy, dz);
3294}
3295
3296////////////////////////////////////////////////////////////////////////////////
3297/// Make in one step a volume pointing to a TGeoTrd2 shape with given medium.
3298
3300 Double_t dy2, Double_t dz)
3301{
3302 return TGeoBuilder::Instance(this)->MakeTrd2(name, medium, dx1, dx2, dy1, dy2, dz);
3303}
3304
3305////////////////////////////////////////////////////////////////////////////////
3306/// Make in one step a volume pointing to a trapezoid shape with given medium.
3307
3309 Double_t h1, Double_t bl1, Double_t tl1, Double_t alpha1, Double_t h2, Double_t bl2,
3310 Double_t tl2, Double_t alpha2)
3311{
3312 return TGeoBuilder::Instance(this)->MakeTrap(name, medium, dz, theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2,
3313 alpha2);
3314}
3315
3316////////////////////////////////////////////////////////////////////////////////
3317/// Make in one step a volume pointing to a twisted trapezoid shape with given medium.
3318
3320 Double_t twist, Double_t h1, Double_t bl1, Double_t tl1, Double_t alpha1, Double_t h2,
3321 Double_t bl2, Double_t tl2, Double_t alpha2)
3322{
3323 return TGeoBuilder::Instance(this)->MakeGtra(name, medium, dz, theta, phi, twist, h1, bl1, tl1, alpha1, h2, bl2, tl2,
3324 alpha2);
3325}
3326
3327////////////////////////////////////////////////////////////////////////////////
3328/// Make a TGeoXtru-shaped volume with nz planes
3329
3331{
3332 return TGeoBuilder::Instance(this)->MakeXtru(name, medium, nz);
3333}
3334
3335////////////////////////////////////////////////////////////////////////////////
3336/// Creates an alignable object with unique name corresponding to a path
3337/// and adds it to the list of alignables. An optional unique ID can be
3338/// provided, in which case PN entries can be searched fast by uid.
3339
3340TGeoPNEntry *TGeoManager::SetAlignableEntry(const char *unique_name, const char *path, Int_t uid)
3341{
3342 if (!CheckPath(path))
3343 return NULL;
3344 if (!fHashPNE)
3345 fHashPNE = new THashList(256, 3);
3346 if (!fArrayPNE)
3347 fArrayPNE = new TObjArray(256);
3348 TGeoPNEntry *entry = GetAlignableEntry(unique_name);
3349 if (entry) {
3350 Error("SetAlignableEntry", "An alignable object with name %s already existing. NOT ADDED !", unique_name);
3351 return 0;
3352 }
3353 entry = new TGeoPNEntry(unique_name, path);
3354 Int_t ientry = fHashPNE->GetSize();
3355 fHashPNE->Add(entry);
3356 fArrayPNE->AddAtAndExpand(entry, ientry);
3357 if (uid >= 0) {
3358 Bool_t added = InsertPNEId(uid, ientry);
3359 if (!added)
3360 Error("SetAlignableEntry", "A PN entry: has already uid=%i", uid);
3361 }
3362 return entry;
3363}
3364
3365////////////////////////////////////////////////////////////////////////////////
3366/// Retrieves an existing alignable object.
3367
3369{
3370 if (!fHashPNE)
3371 return 0;
3372 return (TGeoPNEntry *)fHashPNE->FindObject(name);
3373}
3374
3375////////////////////////////////////////////////////////////////////////////////
3376/// Retrieves an existing alignable object at a given index.
3377
3379{
3380 if (!fArrayPNE && !InitArrayPNE())
3381 return 0;
3382 return (TGeoPNEntry *)fArrayPNE->At(index);
3383}
3384
3385////////////////////////////////////////////////////////////////////////////////
3386/// Retrieves an existing alignable object having a preset UID.
3387
3389{
3390 if (!fNPNEId || (!fArrayPNE && !InitArrayPNE()))
3391 return NULL;
3393 if (index < 0 || fKeyPNEId[index] != uid)
3394 return NULL;
3396}
3397
3398////////////////////////////////////////////////////////////////////////////////
3399/// Retrieves number of PN entries with or without UID.
3400
3402{
3403 if (!fHashPNE)
3404 return 0;
3405 if (with_uid)
3406 return fNPNEId;
3407 return fHashPNE->GetSize();
3408}
3409
3410////////////////////////////////////////////////////////////////////////////////
3411/// Insert a PN entry in the sorted array of indexes.
3412
3414{
3415 if (!fSizePNEId) {
3416 // Create the arrays.
3417 fSizePNEId = 128;
3418 fKeyPNEId = new Int_t[fSizePNEId];
3419 memset(fKeyPNEId, 0, fSizePNEId * sizeof(Int_t));
3421 memset(fValuePNEId, 0, fSizePNEId * sizeof(Int_t));
3422 fKeyPNEId[fNPNEId] = uid;
3423 fValuePNEId[fNPNEId++] = ientry;
3424 return kTRUE;
3425 }
3426 // Search id in the existing array and return false if it already exists.
3428 if (index > 0 && fKeyPNEId[index] == uid)
3429 return kFALSE;
3430 // Resize the arrays and insert the value
3431 Bool_t resize = (fNPNEId == fSizePNEId) ? kTRUE : kFALSE;
3432 if (resize) {
3433 // Double the size of the array
3434 fSizePNEId *= 2;
3435 // Create new arrays of keys and values
3436 Int_t *keys = new Int_t[fSizePNEId];
3437 memset(keys, 0, fSizePNEId * sizeof(Int_t));
3438 Int_t *values = new Int_t[fSizePNEId];
3439 memset(values, 0, fSizePNEId * sizeof(Int_t));
3440 // Copy all keys<uid in the new keys array (0 to index)
3441 memcpy(keys, fKeyPNEId, (index + 1) * sizeof(Int_t));
3442 memcpy(values, fValuePNEId, (index + 1) * sizeof(Int_t));
3443 // Insert current key at index+1
3444 keys[index + 1] = uid;
3445 values[index + 1] = ientry;
3446 // Copy all remaining keys from the old to new array
3447 memcpy(&keys[index + 2], &fKeyPNEId[index + 1], (fNPNEId - index - 1) * sizeof(Int_t));
3448 memcpy(&values[index + 2], &fValuePNEId[index + 1], (fNPNEId - index - 1) * sizeof(Int_t));
3449 delete[] fKeyPNEId;
3450 fKeyPNEId = keys;
3451 delete[] fValuePNEId;
3452 fValuePNEId = values;
3453 fNPNEId++;
3454 return kTRUE;
3455 }
3456 // Insert the value in the existing arrays
3457 Int_t i;
3458 for (i = fNPNEId - 1; i > index; i--) {
3459 fKeyPNEId[i + 1] = fKeyPNEId[i];
3460 fValuePNEId[i + 1] = fValuePNEId[i];
3461 }
3462 fKeyPNEId[index + 1] = uid;
3463 fValuePNEId[index + 1] = ientry;
3464 fNPNEId++;
3465 return kTRUE;
3466}
3467
3468////////////////////////////////////////////////////////////////////////////////
3469/// Make a physical node from the path pointed by an alignable object with a given name.
3470
3472{
3474 if (!entry) {
3475 Error("MakeAlignablePN", "No alignable object named %s found !", name);
3476 return 0;
3477 }
3478 return MakeAlignablePN(entry);
3479}
3480
3481////////////////////////////////////////////////////////////////////////////////
3482/// Make a physical node from the path pointed by a given alignable object.
3483
3485{
3486 if (!entry) {
3487 Error("MakeAlignablePN", "No alignable object specified !");
3488 return 0;
3489 }
3490 const char *path = entry->GetTitle();
3491 if (!cd(path)) {
3492 Error("MakeAlignablePN", "Alignable object %s poins to invalid path: %s", entry->GetName(), path);
3493 return 0;
3494 }
3495 TGeoPhysicalNode *node = MakePhysicalNode(path);
3496 entry->SetPhysicalNode(node);
3497 return node;
3498}
3499
3500////////////////////////////////////////////////////////////////////////////////
3501/// Makes a physical node corresponding to a path. If PATH is not specified,
3502/// makes physical node matching current modeller state.
3503
3505{
3506 TGeoPhysicalNode *node;
3507 if (path) {
3508 if (!CheckPath(path)) {
3509 Error("MakePhysicalNode", "path: %s not valid", path);
3510 return NULL;
3511 }
3512 node = new TGeoPhysicalNode(path);
3513 } else {
3514 node = new TGeoPhysicalNode(GetPath());
3515 }
3516 fPhysicalNodes->Add(node);
3517 return node;
3518}
3519
3520////////////////////////////////////////////////////////////////////////////////
3521/// Refresh physical nodes to reflect the actual geometry paths after alignment
3522/// was applied. Optionally locks physical nodes (default).
3523
3525{
3527 TGeoPhysicalNode *pn;
3528 while ((pn = (TGeoPhysicalNode *)next()))
3529 pn->Refresh();
3532 if (lock)
3533 LockGeometry();
3534}
3535
3536////////////////////////////////////////////////////////////////////////////////
3537/// Clear the current list of physical nodes, so that we can start over with a new list.
3538/// If MUSTDELETE is true, delete previous nodes.
3539
3541{
3542 if (mustdelete)
3544 else
3546}
3547
3548////////////////////////////////////////////////////////////////////////////////
3549/// Make an assembly of volumes.
3550
3552{
3554}
3555
3556////////////////////////////////////////////////////////////////////////////////
3557/// Make a TGeoVolumeMulti handling a list of volumes.
3558
3560{
3561 return TGeoBuilder::Instance(this)->MakeVolumeMulti(name, medium);
3562}
3563
3564////////////////////////////////////////////////////////////////////////////////
3565/// Set type of exploding view (see TGeoPainter::SetExplodedView())
3566
3568{
3569 if ((ibomb >= 0) && (ibomb < 4))
3570 fExplodedView = ibomb;
3571 if (fPainter)
3572 fPainter->SetExplodedView(ibomb);
3573}
3574
3575////////////////////////////////////////////////////////////////////////////////
3576/// Set cut phi range
3577
3579{
3580 if ((phimin == 0) && (phimax == 360)) {
3581 fPhiCut = kFALSE;
3582 return;
3583 }
3584 fPhiCut = kTRUE;
3585 fPhimin = phimin;
3586 fPhimax = phimax;
3587}
3588
3589////////////////////////////////////////////////////////////////////////////////
3590/// Set number of segments for approximating circles in drawing.
3591
3593{
3594 if (fNsegments == nseg)
3595 return;
3596 if (nseg > 2)
3597 fNsegments = nseg;
3598 if (fPainter)
3599 fPainter->SetNsegments(nseg);
3600}
3601
3602////////////////////////////////////////////////////////////////////////////////
3603/// Get number of segments approximating circles
3604
3606{
3607 return fNsegments;
3608}
3609
3610////////////////////////////////////////////////////////////////////////////////
3611/// Now just a shortcut for GetElementTable.
3612
3614{
3617}
3618
3619////////////////////////////////////////////////////////////////////////////////
3620/// Returns material table. Creates it if not existing.
3621
3623{
3624 if (!fElementTable)
3626 return fElementTable;
3627}
3628
3629////////////////////////////////////////////////////////////////////////////////
3630/// Make a rectilinear step of length fStep from current point (fPoint) on current
3631/// direction (fDirection). If the step is imposed by geometry, is_geom flag
3632/// must be true (default). The cross flag specifies if the boundary should be
3633/// crossed in case of a geometry step (default true). Returns new node after step.
3634/// Set also on boundary condition.
3635
3637{
3638 return GetCurrentNavigator()->Step(is_geom, cross);
3639}
3640
3641////////////////////////////////////////////////////////////////////////////////
3642/// shoot npoints randomly in a box of 1E-5 around current point.
3643/// return minimum distance to points outside
3644
3645TGeoNode *TGeoManager::SamplePoints(Int_t npoints, Double_t &dist, Double_t epsil, const char *g3path)
3646{
3647 return GetGeomPainter()->SamplePoints(npoints, dist, epsil, g3path);
3648}
3649
3650////////////////////////////////////////////////////////////////////////////////
3651/// Set the top volume and corresponding node as starting point of the geometry.
3652
3654{
3655 if (fTopVolume == vol)
3656 return;
3657
3658 TSeqCollection *brlist = gROOT->GetListOfBrowsers();
3659 TIter next(brlist);
3660 TBrowser *browser = 0;
3661
3662 if (fTopVolume)
3663 fTopVolume->SetTitle("");
3664 fTopVolume = vol;
3665 vol->SetTitle("Top volume");
3666 if (fTopNode) {
3667 TGeoNode *topn = fTopNode;
3668 fTopNode = 0;
3669 while ((browser = (TBrowser *)next()))
3670 browser->RecursiveRemove(topn);
3671 delete topn;
3672 } else {
3673 fMasterVolume = vol;
3676 if (fgVerboseLevel > 0)
3677 Info("SetTopVolume", "Top volume is %s. Master volume is %s", fTopVolume->GetName(), fMasterVolume->GetName());
3678 }
3679 // fMasterVolume->FindMatrixOfDaughterVolume(vol);
3680 // fCurrentMatrix->Print();
3682 fTopNode->SetName(TString::Format("%s_1", vol->GetName()));
3683 fTopNode->SetNumber(1);
3684 fTopNode->SetTitle("Top logical node");
3685 fNodes->AddAt(fTopNode, 0);
3686 if (!GetCurrentNavigator()) {
3688 return;
3689 }
3690 Int_t nnavigators = 0;
3692 if (!arr)
3693 return;
3694 nnavigators = arr->GetEntriesFast();
3695 for (Int_t i = 0; i < nnavigators; i++) {
3696 TGeoNavigator *nav = (TGeoNavigator *)arr->At(i);
3697 nav->ResetAll();
3698 if (fClosed)
3699 nav->GetCache()->BuildInfoBranch();
3700 }
3701}
3702
3703////////////////////////////////////////////////////////////////////////////////
3704/// Define different tracking media.
3705
3707{
3708 /*
3709 Int_t nmat = fMaterials->GetSize();
3710 if (!nmat) {printf(" No materials !\n"); return;}
3711 Int_t *media = new Int_t[nmat];
3712 memset(media, 0, nmat*sizeof(Int_t));
3713 Int_t imedia = 1;
3714 TGeoMaterial *mat, *matref;
3715 mat = (TGeoMaterial*)fMaterials->At(0);
3716 if (mat->GetMedia()) {
3717 for (Int_t i=0; i<nmat; i++) {
3718 mat = (TGeoMaterial*)fMaterials->At(i);
3719 mat->Print();
3720 }
3721 return;
3722 }
3723 mat->SetMedia(imedia);
3724 media[0] = imedia++;
3725 mat->Print();
3726 for (Int_t i=0; i<nmat; i++) {
3727 mat = (TGeoMaterial*)fMaterials->At(i);
3728 for (Int_t j=0; j<i; j++) {
3729 matref = (TGeoMaterial*)fMaterials->At(j);
3730 if (mat->IsEq(matref)) {
3731 mat->SetMedia(media[j]);
3732 break;
3733 }
3734 if (j==(i-1)) {
3735 // different material
3736 mat->SetMedia(imedia);
3737 media[i] = imedia++;
3738 mat->Print();
3739 }
3740 }
3741 }
3742 */
3743}
3744
3745////////////////////////////////////////////////////////////////////////////////
3746/// Check pushes and pulls needed to cross the next boundary with respect to the
3747/// position given by FindNextBoundary. If radius is not mentioned the full bounding
3748/// box will be sampled.
3749
3751{
3752 GetGeomPainter()->CheckBoundaryErrors(ntracks, radius);
3753}
3754
3755////////////////////////////////////////////////////////////////////////////////
3756/// Check the boundary errors reference file created by CheckBoundaryErrors method.
3757/// The shape for which the crossing failed is drawn with the starting point in red
3758/// and the extrapolated point to boundary (+/- failing push/pull) in yellow.
3759
3761{
3763}
3764
3765////////////////////////////////////////////////////////////////////////////////
3766/// Classify a given point. See TGeoChecker::CheckPoint().
3767
3769{
3771}
3772
3773////////////////////////////////////////////////////////////////////////////////
3774/// Test for shape navigation methods. Summary for test numbers:
3775/// - 1: DistFromInside/Outside. Sample points inside the shape. Generate
3776/// directions randomly in cos(theta). Compute DistFromInside and move the
3777/// point with bigger distance. Compute DistFromOutside back from new point.
3778/// Plot d-(d1+d2)
3779///
3780
3782{
3783 GetGeomPainter()->CheckShape(shape, testNo, nsamples, option);
3784}
3785
3786////////////////////////////////////////////////////////////////////////////////
3787/// Geometry checking.
3788/// - if option contains 'o': Optional overlap checkings (by sampling and by mesh).
3789/// - if option contains 'b': Optional boundary crossing check + timing per volume.
3790///
3791/// STAGE 1: extensive overlap checking by sampling per volume. Stdout need to be
3792/// checked by user to get report, then TGeoVolume::CheckOverlaps(0.01, "s") can
3793/// be called for the suspicious volumes.
3794///
3795/// STAGE 2: normal overlap checking using the shapes mesh - fills the list of
3796/// overlaps.
3797///
3798/// STAGE 3: shooting NRAYS rays from VERTEX and counting the total number of
3799/// crossings per volume (rays propagated from boundary to boundary until
3800/// geometry exit). Timing computed and results stored in a histo.
3801///
3802/// STAGE 4: shooting 1 mil. random rays inside EACH volume and calling
3803/// FindNextBoundary() + Safety() for each call. The timing is normalized by the
3804/// number of crossings computed at stage 2 and presented as percentage.
3805/// One can get a picture on which are the most "burned" volumes during
3806/// transportation from geometry point of view. Another plot of the timing per
3807/// volume vs. number of daughters is produced.
3808
3810{
3811 TString opt(option);
3812 opt.ToLower();
3813 if (!opt.Length()) {
3814 Error("CheckGeometryFull", "The option string must contain a letter. See method documentation.");
3815 return;
3816 }
3817 Bool_t checkoverlaps = opt.Contains("o");
3818 Bool_t checkcrossings = opt.Contains("b");
3819 Double_t vertex[3];
3820 vertex[0] = vx;
3821 vertex[1] = vy;
3822 vertex[2] = vz;
3823 GetGeomPainter()->CheckGeometryFull(checkoverlaps, checkcrossings, ntracks, vertex);
3824}
3825
3826////////////////////////////////////////////////////////////////////////////////
3827/// Perform last checks on the geometry
3828
3830{
3831 if (fgVerboseLevel > 0)
3832 Info("CheckGeometry", "Fixing runtime shapes...");
3833 TIter next(fShapes);
3834 TIter nextv(fVolumes);
3835 TGeoShape *shape;
3836 TGeoVolume *vol;
3837 Bool_t has_runtime = kFALSE;
3838 while ((shape = (TGeoShape *)next())) {
3839 if (shape->IsRunTimeShape()) {
3840 has_runtime = kTRUE;
3841 }
3842 if (fIsGeomReading)
3843 shape->AfterStreamer();
3846 shape->ComputeBBox();
3847 }
3848 if (has_runtime)
3850 else if (fgVerboseLevel > 0)
3851 Info("CheckGeometry", "...Nothing to fix");
3852 // Compute bounding box for assemblies
3854 while ((vol = (TGeoVolume *)nextv())) {
3855 if (vol->IsAssembly())
3856 vol->GetShape()->ComputeBBox();
3857 else if (vol->GetMedium() == dummy) {
3858 Warning("CheckGeometry", "Volume \"%s\" has no medium: assigned dummy medium and material", vol->GetName());
3859 vol->SetMedium(dummy);
3860 }
3861 }
3862}
3863
3864////////////////////////////////////////////////////////////////////////////////
3865/// Check all geometry for illegal overlaps within a limit OVLP.
3866
3868{
3869 if (!fTopNode) {
3870 Error("CheckOverlaps", "Top node not set");
3871 return;
3872 }
3874}
3875
3876////////////////////////////////////////////////////////////////////////////////
3877/// Prints the current list of overlaps.
3878
3880{
3881 if (!fOverlaps)
3882 return;
3883 Int_t novlp = fOverlaps->GetEntriesFast();
3884 if (!novlp)
3885 return;
3886 TGeoManager *geom = (TGeoManager *)this;
3887 geom->GetGeomPainter()->PrintOverlaps();
3888}
3889
3890////////////////////////////////////////////////////////////////////////////////
3891/// Estimate weight of volume VOL with a precision SIGMA(W)/W better than PRECISION.
3892/// Option can be "v" - verbose (default)
3893
3895{
3897 TString opt(option);
3898 opt.ToLower();
3899 Double_t weight;
3900 TGeoVolume *volume = fTopVolume;
3901 if (opt.Contains("v")) {
3902 if (opt.Contains("a")) {
3903 if (fgVerboseLevel > 0)
3904 Info("Weight", "Computing analytically weight of %s", volume->GetName());
3905 weight = volume->WeightA();
3906 if (fgVerboseLevel > 0)
3907 Info("Weight", "Computed weight: %f [kg]\n", weight);
3908 return weight;
3909 }
3910 if (fgVerboseLevel > 0) {
3911 Info("Weight", "Estimating weight of %s with %g %% precision", fTopVolume->GetName(), 100. * precision);
3912 printf(" event weight err\n");
3913 printf("========================================\n");
3914 }
3915 }
3916 weight = fPainter->Weight(precision, option);
3917 return weight;
3918}
3919
3920////////////////////////////////////////////////////////////////////////////////
3921/// computes the total size in bytes of the branch starting with node.
3922/// The option can specify if all the branch has to be parsed or only the node
3923
3924ULong_t TGeoManager::SizeOf(const TGeoNode * /*node*/, Option_t * /*option*/)
3925{
3926 return 0;
3927}
3928
3929////////////////////////////////////////////////////////////////////////////////
3930/// Stream an object of class TGeoManager.
3931
3933{
3934 if (R__b.IsReading()) {
3935 R__b.ReadClassBuffer(TGeoManager::Class(), this);
3937 CloseGeometry();
3940 } else {
3942 }
3943}
3944
3945////////////////////////////////////////////////////////////////////////////////
3946/// Execute mouse actions on this manager.
3947
3949{
3950 if (!fPainter)
3951 return;
3952 fPainter->ExecuteManagerEvent(this, event, px, py);
3953}
3954
3955////////////////////////////////////////////////////////////////////////////////
3956/// Export this geometry to a file
3957///
3958/// - Case 1: root file or root/xml file
3959/// if filename end with ".root". The key will be named name
3960/// By default the geometry is saved without the voxelisation info.
3961/// Use option 'v" to save the voxelisation info.
3962/// if filename end with ".xml" a root/xml file is produced.
3963///
3964/// - Case 2: C++ script
3965/// if filename end with ".C"
3966///
3967/// - Case 3: gdml file
3968/// if filename end with ".gdml"
3969/// NOTE that to use this option, the PYTHONPATH must be defined like
3970/// export PYTHONPATH=$ROOTSYS/lib:$ROOTSYS/geom/gdml
3971///
3972
3974{
3975 TString sfile(filename);
3976 if (sfile.Contains(".C")) {
3977 // Save geometry as a C++ script
3978 if (fgVerboseLevel > 0)
3979 Info("Export", "Exporting %s %s as C++ code", GetName(), GetTitle());
3981 return 1;
3982 }
3983 if (sfile.Contains(".gdml")) {
3984 // Save geometry as a gdml file
3985 if (fgVerboseLevel > 0)
3986 Info("Export", "Exporting %s %s as gdml code", GetName(), GetTitle());
3987 // C++ version
3988 TString cmd;
3989 cmd = TString::Format("TGDMLWrite::StartGDMLWriting(gGeoManager,\"%s\",\"%s\")", filename, option);
3990 gROOT->ProcessLineFast(cmd);
3991 return 1;
3992 }
3993 if (sfile.Contains(".root") || sfile.Contains(".xml")) {
3994 // Save geometry as a root file
3995 TFile *f = TFile::Open(filename, "recreate");
3996 if (!f || f->IsZombie()) {
3997 Error("Export", "Cannot open file");
3998 return 0;
3999 }
4000 TString keyname = name;
4001 if (keyname.IsNull())
4002 keyname = GetName();
4003 TString opt = option;
4004 opt.ToLower();
4005 if (opt.Contains("v")) {
4007 if (fgVerboseLevel > 0)
4008 Info("Export", "Exporting %s %s as root file. Optimizations streamed.", GetName(), GetTitle());
4009 } else {
4011 if (fgVerboseLevel > 0)
4012 Info("Export", "Exporting %s %s as root file. Optimizations not streamed.", GetName(), GetTitle());
4013 }
4014
4015 const char *precision_dbl = TBufferText::GetDoubleFormat();
4016 const char *precision_flt = TBufferText::GetFloatFormat();
4017 TString new_format_dbl = TString::Format("%%.%dg", TGeoManager::GetExportPrecision());
4018 if (sfile.Contains(".xml")) {
4019 TBufferText::SetDoubleFormat(new_format_dbl.Data());
4020 TBufferText::SetFloatFormat(new_format_dbl.Data());
4021 }
4022 Int_t nbytes = Write(keyname);
4023 if (sfile.Contains(".xml")) {
4024 TBufferText::SetFloatFormat(precision_dbl);
4025 TBufferText::SetDoubleFormat(precision_flt);
4026 }
4027
4029 delete f;
4030 return nbytes;
4031 }
4032 return 0;
4033}
4034
4035////////////////////////////////////////////////////////////////////////////////
4036/// Lock current geometry so that no other geometry can be imported.
4037
4039{
4040 fgLock = kTRUE;
4041}
4042
4043////////////////////////////////////////////////////////////////////////////////
4044/// Unlock current geometry.
4045
4047{
4048 fgLock = kFALSE;
4049}
4050
4051////////////////////////////////////////////////////////////////////////////////
4052/// Check lock state.
4053
4055{
4056 return fgLock;
4057}
4058
4059////////////////////////////////////////////////////////////////////////////////
4060/// Set verbosity level (static function).
4061/// - 0 - suppress messages related to geom-painter visibility level
4062/// - 1 - default value
4063
4065{
4066 return fgVerboseLevel;
4067}
4068
4069////////////////////////////////////////////////////////////////////////////////
4070/// Return current verbosity level (static function).
4071
4073{
4074 fgVerboseLevel = vl;
4075}
4076
4077////////////////////////////////////////////////////////////////////////////////
4078/// static function
4079/// Import a geometry from a gdml or ROOT file
4080///
4081/// - Case 1: gdml
4082/// if filename ends with ".gdml" the foreign geometry described with gdml
4083/// is imported executing some python scripts in $ROOTSYS/gdml.
4084/// NOTE that to use this option, the PYTHONPATH must be defined like
4085/// export PYTHONPATH=$ROOTSYS/lib:$ROOTSYS/gdml
4086///
4087/// - Case 2: root file (.root) or root/xml file (.xml)
4088/// Import in memory from filename the geometry with key=name.
4089/// if name="" (default), the first TGeoManager object in the file is returned.
4090///
4091/// Note that this function deletes the current gGeoManager (if one)
4092/// before importing the new object.
4093
4094TGeoManager *TGeoManager::Import(const char *filename, const char *name, Option_t * /*option*/)
4095{
4096 if (fgLock) {
4097 ::Warning("TGeoManager::Import", "TGeoMananager in lock mode. NOT IMPORTING new geometry");
4098 return nullptr;
4099 }
4100 if (!filename)
4101 return 0;
4102 if (fgVerboseLevel > 0)
4103 ::Info("TGeoManager::Import", "Reading geometry from file: %s", filename);
4104
4105 if (gGeoManager)
4106 delete gGeoManager;
4107 gGeoManager = nullptr;
4108
4109 if (strstr(filename, ".gdml")) {
4110 // import from a gdml file
4111 new TGeoManager("GDMLImport", "Geometry imported from GDML");
4112 TString cmd = TString::Format("TGDMLParse::StartGDML(\"%s\")", filename);
4113 TGeoVolume *world = (TGeoVolume *)gROOT->ProcessLineFast(cmd);
4114
4115 if (world == nullptr) {
4116 delete gGeoManager;
4117 gGeoManager = nullptr;
4118 ::Error("TGeoManager::Import", "Cannot read file %s", filename);
4119 } else {
4120 gGeoManager->SetTopVolume(world);
4123 }
4124 } else {
4125 // import from a root file
4127 // in case a web file is specified, use the cacheread option to cache
4128 // this file in the cache directory
4129 TFile *f = nullptr;
4130 if (strstr(filename, "http"))
4131 f = TFile::Open(filename, "CACHEREAD");
4132 else
4134 if (!f || f->IsZombie()) {
4135 ::Error("TGeoManager::Import", "Cannot open file");
4136 return nullptr;
4137 }
4138 if (name && strlen(name) > 0) {
4139 gGeoManager = (TGeoManager *)f->Get(name);
4140 } else {
4141 TIter next(f->GetListOfKeys());
4142 TKey *key;
4143 while ((key = (TKey *)next())) {
4144 if (strcmp(key->GetClassName(), "TGeoManager") != 0)
4145 continue;
4146 gGeoManager = (TGeoManager *)key->ReadObj();
4147 break;
4148 }
4149 }
4150 delete f;
4151 }
4152 if (!gGeoManager)
4153 return 0;
4154 if (!gROOT->GetListOfGeometries()->FindObject(gGeoManager))
4155 gROOT->GetListOfGeometries()->Add(gGeoManager);
4156 if (!gROOT->GetListOfBrowsables()->FindObject(gGeoManager))
4157 gROOT->GetListOfBrowsables()->Add(gGeoManager);
4159 return gGeoManager;
4160}
4161
4162////////////////////////////////////////////////////////////////////////////////
4163/// Update element flags when geometry is loaded from a file.
4164
4166{
4167 if (!fElementTable)
4168 return;
4169 TIter next(fMaterials);
4170 TGeoMaterial *mat;
4171 TGeoMixture *mix;
4172 TGeoElement *elem, *elem_table;
4173 Int_t i, nelem;
4174 while ((mat = (TGeoMaterial *)next())) {
4175 if (mat->IsMixture()) {
4176 mix = (TGeoMixture *)mat;
4177 nelem = mix->GetNelements();
4178 for (i = 0; i < nelem; i++) {
4179 elem = mix->GetElement(i);
4180 if (!elem)
4181 continue;
4182 elem_table = fElementTable->GetElement(elem->Z());
4183 if (!elem_table)
4184 continue;
4185 if (elem != elem_table) {
4186 elem_table->SetDefined(elem->IsDefined());
4187 elem_table->SetUsed(elem->IsUsed());
4188 } else {
4189 elem_table->SetDefined();
4190 }
4191 }
4192 } else {
4193 elem = mat->GetElement();
4194 if (!elem)
4195 continue;
4196 elem_table = fElementTable->GetElement(elem->Z());
4197 if (!elem_table)
4198 continue;
4199 if (elem != elem_table) {
4200 elem_table->SetDefined(elem->IsDefined());
4201 elem_table->SetUsed(elem->IsUsed());
4202 } else {
4203 elem_table->SetUsed();
4204 }
4205 }
4206 }
4207}
4208
4209////////////////////////////////////////////////////////////////////////////////
4210/// Initialize PNE array for fast access via index and unique-id.
4211
4213{
4214 if (fHashPNE) {
4216 TIter next(fHashPNE);
4217 TObject *obj;
4218 while ((obj = next())) {
4219 fArrayPNE->Add(obj);
4220 }
4221 return kTRUE;
4222 }
4223 return kFALSE;
4224}
4225
4226////////////////////////////////////////////////////////////////////////////////
4227/// Get time cut for drawing tracks.
4228
4230{
4231 tmin = fTmin;
4232 tmax = fTmax;
4233 return fTimeCut;
4234}
4235
4236////////////////////////////////////////////////////////////////////////////////
4237/// Set time cut interval for drawing tracks. If called with no arguments, time
4238/// cut will be disabled.
4239
4241{
4242 fTmin = tmin;
4243 fTmax = tmax;
4244 if (tmin == 0 && tmax == 999)
4245 fTimeCut = kFALSE;
4246 else
4247 fTimeCut = kTRUE;
4248 if (fTracks && !IsAnimatingTracks())
4249 ModifiedPad();
4250}
4251
4252////////////////////////////////////////////////////////////////////////////////
4253/// Convert coordinates from master volume frame to top.
4254
4255void TGeoManager::MasterToTop(const Double_t *master, Double_t *top) const
4256{
4257 GetCurrentNavigator()->MasterToLocal(master, top);
4258}
4259
4260////////////////////////////////////////////////////////////////////////////////
4261/// Convert coordinates from top volume frame to master.
4262
4263void TGeoManager::TopToMaster(const Double_t *top, Double_t *master) const
4264{
4265 GetCurrentNavigator()->LocalToMaster(top, master);
4266}
4267
4268////////////////////////////////////////////////////////////////////////////////
4269/// Create a parallel world for prioritised navigation. This can be populated
4270/// with physical nodes and can be navigated independently using its API.
4271/// In case the flag SetUseParallelWorldNav is set, any navigation query in the
4272/// main geometry is checked against the parallel geometry, which gets priority
4273/// in case of overlaps with the main geometry volumes.
4274
4276{
4278 return fParallelWorld;
4279}
4280
4281////////////////////////////////////////////////////////////////////////////////
4282/// Activate/deactivate usage of parallel world navigation. Can only be done if
4283/// there is a parallel world. Activating navigation will automatically close
4284/// the parallel geometry.
4285
4287{
4288 if (!fParallelWorld) {
4289 Error("SetUseParallelWorldNav", "No parallel world geometry defined. Use CreateParallelWorld.");
4290 return;
4291 }
4292 if (!flag) {
4293 fUsePWNav = flag;
4294 return;
4295 }
4296 if (!fClosed) {
4297 Error("SetUseParallelWorldNav", "The geometry must be closed first");
4298 return;
4299 }
4300 // Closing the parallel world geometry is mandatory
4302 fUsePWNav = kTRUE;
4303}
4304
4306{
4307 Bool_t val = gGeometryLocked;
4308 gGeometryLocked = new_value;
4309 return val;
4310}
4311
4313{
4314 return fgDefaultUnits;
4315}
4316
4318{
4319 if (fgDefaultUnits == new_value) {
4320 gGeometryLocked = true;
4321 return;
4322 } else if (gGeometryLocked) {
4323 ::Fatal("TGeoManager", "The system of units may only be changed once, \n"
4324 "BEFORE any elements and materials are created! \n"
4325 "Alternatively unlock the default units at own risk.");
4326 } else if (new_value == kG4Units) {
4327 ::Info("TGeoManager", "Changing system of units to Geant4 units (mm, ns, MeV).");
4328 } else if (new_value == kRootUnits) {
4329 ::Info("TGeoManager", "Changing system of units to ROOT units (cm, s, GeV).");
4330 }
4331 fgDefaultUnits = new_value;
4332}
4333
4335{
4336 fgExportPrecision = prec;
4337}
4338
4340{
4341 return fgExportPrecision;
4342}
#define SafeDelete(p)
Definition RConfig.hxx:525
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
unsigned char UChar_t
Definition RtypesCore.h:38
unsigned long ULong_t
Definition RtypesCore.h:55
unsigned int UInt_t
Definition RtypesCore.h:46
float Float_t
Definition RtypesCore.h:57
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:85
#define ClassImp(name)
Definition Rtypes.h:377
@ kGray
Definition Rtypes.h:65
@ kRed
Definition Rtypes.h:66
@ kOrange
Definition Rtypes.h:67
@ kGreen
Definition Rtypes.h:66
@ kMagenta
Definition Rtypes.h:66
@ kBlue
Definition Rtypes.h:66
@ kYellow
Definition Rtypes.h:66
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 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 value
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
Option_t Option_t TPoint TPoint const char mode
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 property
char name[80]
Definition TGX11.cxx:110
TGeoManager * gGeoManager
static Bool_t gGeometryLocked
R__EXTERN TGeoManager * gGeoManager
R__EXTERN TGeoIdentity * gGeoIdentity
Definition TGeoMatrix.h:537
int nentries
#define gROOT
Definition TROOT.h:407
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
#define gPad
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
void RecursiveRemove(TObject *obj) override
Recursively remove obj from browser.
Definition TBrowser.cxx:406
static const char * GetFloatFormat()
return current printf format for float members, default "%e"
static void SetFloatFormat(const char *fmt="%e")
set printf format for float/double members, default "%e" to change format only for doubles,...
static const char * GetDoubleFormat()
return current printf format for double members, default "%.14e"
static void SetDoubleFormat(const char *fmt="%.14e")
set printf format for double members, default "%.14e" use it after SetFloatFormat,...
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
@ kRealNew
Definition TClass.h:107
@ kDummyNew
Definition TClass.h:107
static ENewType IsCallingNew()
Static method returning the defConstructor flag passed to TClass::New().
Definition TClass.cxx:5902
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition TDatime.cxx:102
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
A ROOT file is composed of a header, followed by consecutive data records (TKey instances) with a wel...
Definition TFile.h:53
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4075
This class is used in the process of reading and writing the GDML "matrix" tag.
Definition TGDMLMatrix.h:33
Bool_t IsVisTouched() const
Definition TGeoAtt.h:91
void SetVisStreamed(Bool_t vis=kTRUE)
Mark attributes as "streamed to file".
Definition TGeoAtt.cxx:128
void SetVisTouched(Bool_t vis=kTRUE)
Mark visualization attributes as "modified".
Definition TGeoAtt.cxx:138
void SetVisBranch()
Set branch type visibility.
Definition TGeoAtt.cxx:66
Box class.
Definition TGeoBBox.h:17
void Node(const char *name, Int_t nr, const char *mother, Double_t x, Double_t y, Double_t z, Int_t irot, Bool_t isOnly, Float_t *upar, Int_t npar=0)
Create a node called <name_nr> pointing to the volume called <name> as daughter of the volume called ...
TGeoVolume * MakePgon(const char *name, TGeoMedium *medium, Double_t phi, Double_t dphi, Int_t nedges, Int_t nz)
Make in one step a volume pointing to a polygone shape with given medium.
TGeoVolume * MakeGtra(const char *name, TGeoMedium *medium, Double_t dz, Double_t theta, Double_t phi, Double_t twist, Double_t h1, Double_t bl1, Double_t tl1, Double_t alpha1, Double_t h2, Double_t bl2, Double_t tl2, Double_t alpha2)
Make in one step a volume pointing to a twisted trapezoid shape with given medium.
TGeoVolume * MakeXtru(const char *name, TGeoMedium *medium, Int_t nz)
Make a TGeoXtru-shaped volume with nz planes.
TGeoVolume * MakePcon(const char *name, TGeoMedium *medium, Double_t phi, Double_t dphi, Int_t nz)
Make in one step a volume pointing to a polycone shape with given medium.
TGeoVolume * MakeTrap(const char *name, TGeoMedium *medium, Double_t dz, Double_t theta, Double_t phi, Double_t h1, Double_t bl1, Double_t tl1, Double_t alpha1, Double_t h2, Double_t bl2, Double_t tl2, Double_t alpha2)
Make in one step a volume pointing to a trapezoid shape with given medium.
Int_t AddShape(TGeoShape *shape)
Add a shape to the list. Returns index of the shape in list.
TGeoVolume * MakeTorus(const char *name, TGeoMedium *medium, Double_t r, Double_t rmin, Double_t rmax, Double_t phi1=0, Double_t dphi=360)
Make in one step a volume pointing to a torus shape with given medium.
static TGeoBuilder * Instance(TGeoManager *geom)
Return pointer to singleton.
TGeoVolume * MakeEltu(const char *name, TGeoMedium *medium, Double_t a, Double_t b, Double_t dz)
Make in one step a volume pointing to a tube shape with given medium.
TGeoVolume * MakeHype(const char *name, TGeoMedium *medium, Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
Make in one step a volume pointing to a tube shape with given medium.
TGeoVolume * MakeArb8(const char *name, TGeoMedium *medium, Double_t dz, Double_t *vertices=nullptr)
Make an TGeoArb8 volume.
TGeoMaterial * Material(const char *name, Double_t a, Double_t z, Double_t dens, Int_t uid, Double_t radlen=0, Double_t intlen=0)
Create material with given A, Z and density, having an unique id.
TGeoVolume * MakeTube(const char *name, TGeoMedium *medium, Double_t rmin, Double_t rmax, Double_t dz)
Make in one step a volume pointing to a tube shape with given medium.
TGeoVolume * MakePara(const char *name, TGeoMedium *medium, Double_t dx, Double_t dy, Double_t dz, Double_t alpha, Double_t theta, Double_t phi)
Make in one step a volume pointing to a parallelepiped shape with given medium.
Int_t AddTransformation(TGeoMatrix *matrix)
Add a matrix to the list. Returns index of the matrix in list.
TGeoVolume * MakeSphere(const char *name, TGeoMedium *medium, Double_t rmin, Double_t rmax, Double_t themin=0, Double_t themax=180, Double_t phimin=0, Double_t phimax=360)
Make in one step a volume pointing to a sphere shape with given medium.
TGeoMedium * Medium(const char *name, Int_t numed, Int_t nmat, Int_t isvol, Int_t ifield, Double_t fieldm, Double_t tmaxfd, Double_t stemax, Double_t deemax, Double_t epsil, Double_t stmin)
Create tracking medium.
TGeoVolume * MakeTubs(const char *name, TGeoMedium *medium, Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2)
Make in one step a volume pointing to a tube segment shape with given medium.
TGeoVolume * MakeBox(const char *name, TGeoMedium *medium, Double_t dx, Double_t dy, Double_t dz)
Make in one step a volume pointing to a box shape with given medium.
void Matrix(Int_t index, Double_t theta1, Double_t phi1, Double_t theta2, Double_t phi2, Double_t theta3, Double_t phi3)
Create rotation matrix named 'mat<index>'.
TGeoVolume * Division(const char *name, const char *mother, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed=0, Option_t *option="")
Create a new volume by dividing an existing one (GEANT3 like)
TGeoVolume * MakeParaboloid(const char *name, TGeoMedium *medium, Double_t rlo, Double_t rhi, Double_t dz)
Make in one step a volume pointing to a tube shape with given medium.
TGeoVolume * MakeTrd1(const char *name, TGeoMedium *medium, Double_t dx1, Double_t dx2, Double_t dy, Double_t dz)
Make in one step a volume pointing to a TGeoTrd1 shape with given medium.
TGeoVolumeAssembly * MakeVolumeAssembly(const char *name)
Make an assembly of volumes.
TGeoVolume * MakeCons(const char *name, TGeoMedium *medium, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
Make in one step a volume pointing to a cone segment shape with given medium.
Int_t AddMaterial(TGeoMaterial *material)
Add a material to the list. Returns index of the material in list.
TGeoVolumeMulti * MakeVolumeMulti(const char *name, TGeoMedium *medium)
Make a TGeoVolumeMulti handling a list of volumes.
TGeoVolume * MakeTrd2(const char *name, TGeoMedium *medium, Double_t dx1, Double_t dx2, Double_t dy1, Double_t dy2, Double_t dz)
Make in one step a volume pointing to a TGeoTrd2 shape with given medium.
TGeoVolume * Volume(const char *name, const char *shape, Int_t nmed, Float_t *upar, Int_t npar=0)
Create a volume in GEANT3 style.
TGeoMaterial * Mixture(const char *name, Float_t *a, Float_t *z, Double_t dens, Int_t nelem, Float_t *wmat, Int_t uid)
Create mixture OR COMPOUND IMAT as composed by THE BASIC nelem materials defined by arrays A,...
TGeoVolume * MakeCone(const char *name, TGeoMedium *medium, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Make in one step a volume pointing to a cone shape with given medium.
void RegisterMatrix(TGeoMatrix *matrix)
Register a matrix to the list of matrices.
TGeoVolume * MakeCtub(const char *name, TGeoMedium *medium, Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2, Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
Make in one step a volume pointing to a tube segment shape with given medium.
Class describing rotation + translation.
Definition TGeoMatrix.h:317
Composite shapes are Boolean combinations of two or more shape components.
Table of elements.
TGeoElement * GetElement(Int_t z)
Base class for chemical elements.
Definition TGeoElement.h:36
Bool_t IsDefined() const
Definition TGeoElement.h:81
void SetDefined(Bool_t flag=kTRUE)
Definition TGeoElement.h:85
Int_t Z() const
Definition TGeoElement.h:68
void SetUsed(Bool_t flag=kTRUE)
Definition TGeoElement.h:86
Bool_t IsUsed() const
Definition TGeoElement.h:83
Matrix class used for computing global transformations Should NOT be used for node definition.
Definition TGeoMatrix.h:458
An identity transformation.
Definition TGeoMatrix.h:406
A geometry iterator.
Definition TGeoNode.h:248
Int_t GetLevel() const
Definition TGeoNode.h:294
The manager class for any TGeo geometry.
Definition TGeoManager.h:44
static void UnlockGeometry()
Unlock current geometry.
Double_t fPhimax
lowest range for phi cut
Definition TGeoManager.h:63
TGeoVolume * MakeCone(const char *name, TGeoMedium *medium, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Make in one step a volume pointing to a cone shape with given medium.
void AnimateTracks(Double_t tmin=0, Double_t tmax=5E-8, Int_t nframes=200, Option_t *option="/*")
Draw animation of tracks.
void AddSkinSurface(TGeoSkinSurface *surf)
Add skin surface;.
TGeoVolume * MakeXtru(const char *name, TGeoMedium *medium, Int_t nz)
Make a TGeoXtru-shaped volume with nz planes.
Double_t * FindNormalFast()
Computes fast normal to next crossed boundary, assuming that the current point is close enough to the...
TGeoVolume * MakePcon(const char *name, TGeoMedium *medium, Double_t phi, Double_t dphi, Int_t nz)
Make in one step a volume pointing to a polycone shape with given medium.
Int_t fRaytraceMode
Flag for multi-threading.
Double_t fVisDensity
particles to be drawn
Definition TGeoManager.h:69
TGeoNavigator * AddNavigator()
Add a navigator in the list of navigators.
TVirtualGeoTrack * GetTrackOfId(Int_t id) const
Get track with a given ID.
TGeoMaterial * FindDuplicateMaterial(const TGeoMaterial *mat) const
Find if a given material duplicates an existing one.
TGeoVolume * Division(const char *name, const char *mother, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed=0, Option_t *option="")
Create a new volume by dividing an existing one (GEANT3 like)
TGeoVolume * Volume(const char *name, const char *shape, Int_t nmed, Float_t *upar, Int_t npar=0)
Create a volume in GEANT3 style.
Int_t ReplaceVolume(TGeoVolume *vorig, TGeoVolume *vnew)
Replaces all occurrences of VORIG with VNEW in the geometry tree.
void DoRestoreState()
Restore a backed-up state without affecting the cache stack.
Int_t GetCurrentNodeId() const
Get the unique ID of the current node.
TGeoPNEntry * GetAlignableEntry(const char *name) const
Retrieves an existing alignable object.
TGeoVolume * fMasterVolume
top physical node
TVirtualGeoTrack * FindTrackWithId(Int_t id) const
Search the track hierarchy to find the track with the given id.
TObjArray * fArrayPNE
void TestOverlaps(const char *path="")
Geometry overlap checker based on sampling.
static EDefaultUnits GetDefaultUnits()
void RemoveMaterial(Int_t index)
Remove material at given index.
void Matrix(Int_t index, Double_t theta1, Double_t phi1, Double_t theta2, Double_t phi2, Double_t theta3, Double_t phi3)
Create rotation matrix named 'mat<index>'.
TGeoElementTable * GetElementTable()
Returns material table. Creates it if not existing.
Int_t fNtracks
Definition TGeoManager.h:74
THashList * fHashPNE
hash list of group volumes providing fast search
static Int_t fgVerboseLevel
Lock preventing a second geometry to be loaded.
Definition TGeoManager.h:51
void Init()
Initialize manager class.
Bool_t InitArrayPNE() const
Initialize PNE array for fast access via index and unique-id.
TObjArray * fPhysicalNodes
Definition TGeoManager.h:96
virtual ULong_t SizeOf(const TGeoNode *node, Option_t *option)
computes the total size in bytes of the branch starting with node.
TObjArray * fUniqueVolumes
static UInt_t fgExportPrecision
Maximum number of Xtru vertices.
Definition TGeoManager.h:55
TObjArray * fRegions
void Node(const char *name, Int_t nr, const char *mother, Double_t x, Double_t y, Double_t z, Int_t irot, Bool_t isOnly, Float_t *upar, Int_t npar=0)
Create a node called <name_nr> pointing to the volume called <name> as daughter of the volume called ...
TObjArray * fGShapes
Definition TGeoManager.h:97
TGeoVolume * fPaintVolume
TGeoSkinSurface * GetSkinSurface(const char *name) const
Get skin surface with a given name;.
void UpdateElements()
Update element flags when geometry is loaded from a file.
TGeoManager()
Default constructor.
static TClass * Class()
ConstPropMap_t fProperties
TGeoVolume * MakeTube(const char *name, TGeoMedium *medium, Double_t rmin, Double_t rmax, Double_t dz)
Make in one step a volume pointing to a tube shape with given medium.
void CdUp()
Go one level up in geometry.
void DoBackupState()
Backup the current state without affecting the cache stack.
TList * fMaterials
void CheckBoundaryErrors(Int_t ntracks=1000000, Double_t radius=-1.)
Check pushes and pulls needed to cross the next boundary with respect to the position given by FindNe...
TObjArray * fVolumes
Definition TGeoManager.h:95
Int_t * fValuePNEId
TGeoPNEntry * GetAlignableEntryByUID(Int_t uid) const
Retrieves an existing alignable object having a preset UID.
void AddGDMLMatrix(TGDMLMatrix *mat)
Add GDML matrix;.
Bool_t fTimeCut
Definition TGeoManager.h:85
static void SetExportPrecision(UInt_t prec)
void AddBorderSurface(TGeoBorderSurface *surf)
Add border surface;.
void SetClippingShape(TGeoShape *clip)
Set a user-defined shape as clipping for ray tracing.
TGeoVolume * fCurrentVolume
current navigator
void ClearOverlaps()
Clear the list of overlaps.
TGeoVolume * MakeCons(const char *name, TGeoMedium *medium, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
Make in one step a volume pointing to a cone segment shape with given medium.
THashList * fHashGVolumes
hash list of volumes providing fast search
Int_t fVisOption
Definition TGeoManager.h:71
static std::mutex fgMutex
Definition TGeoManager.h:49
Bool_t IsInPhiRange() const
True if current node is in phi range.
virtual Bool_t cd(const char *path="")
Browse the tree of nodes starting from fTopNode according to pathname.
TGeoNode * SearchNode(Bool_t downwards=kFALSE, const TGeoNode *skipnode=nullptr)
Returns the deepest node containing fPoint, which must be set a priori.
TGeoMaterial * Material(const char *name, Double_t a, Double_t z, Double_t dens, Int_t uid, Double_t radlen=0, Double_t intlen=0)
Create material with given A, Z and density, having an unique id.
void LocalToMaster(const Double_t *local, Double_t *master) const
Double_t fPhimin
Definition TGeoManager.h:62
static Bool_t fgLockNavigators
Number of registered threads.
void SaveAttributes(const char *filename="tgeoatt.C")
Save current attributes in a macro.
void RestoreMasterVolume()
Restore the master volume of the geometry.
Bool_t fDrawExtra
Definition TGeoManager.h:86
TGeoVolume * MakeArb8(const char *name, TGeoMedium *medium, Double_t dz, Double_t *vertices=nullptr)
Make an TGeoArb8 volume.
virtual Int_t Export(const char *filename, const char *name="", Option_t *option="vg")
Export this geometry to a file.
TGeoNode * FindNextDaughterBoundary(Double_t *point, Double_t *dir, Int_t &idaughter, Bool_t compmatrix=kFALSE)
Computes as fStep the distance to next daughter of the current volume.
Int_t GetUID(const char *volname) const
Retrieve unique id for a volume name. Return -1 if name not found.
TGeoShape * fClippingShape
TGeoNavigator * GetCurrentNavigator() const
Returns current navigator for the calling thread.
THashList * fHashVolumes
TObjArray * fMatrices
current painter
Definition TGeoManager.h:93
static Int_t GetNumThreads()
Returns number of threads that were set to use geometry.
TGeoVolumeMulti * MakeVolumeMulti(const char *name, TGeoMedium *medium)
Make a TGeoVolumeMulti handling a list of volumes.
void ClearNavigators()
Clear all navigators.
Int_t AddTransformation(const TGeoMatrix *matrix)
Add a matrix to the list. Returns index of the matrix in list.
TObjArray * fOpticalSurfaces
TVirtualGeoTrack * GetParentTrackOfId(Int_t id) const
Get parent track with a given ID.
void CdNode(Int_t nodeid)
Change current path to point to the node having this id.
UChar_t * fBits
static Int_t GetMaxLevels()
Return maximum number of levels used in the geometry.
Double_t fTmin
highest range for phi cut
Definition TGeoManager.h:64
static Bool_t IsLocked()
Check lock state.
TGeoVolume * fTopVolume
current volume
TGeoVolume * fUserPaintVolume
volume currently painted
TVirtualGeoPainter * GetGeomPainter()
Make a default painter if none present. Returns pointer to it.
void GetBranchOnlys(Int_t *isonly) const
Fill node copy numbers of current branch into an array.
TGeoNode * GetCurrentNode() const
Int_t AddTrack(Int_t id, Int_t pdgcode, TObject *particle=nullptr)
Add a track to the list of tracks.
void SetVisOption(Int_t option=0)
set drawing mode :
void SetPdgName(Int_t pdg, const char *name)
Set a name for a particle having a given pdg.
TObjArray * fBorderSurfaces
Int_t GetNAlignable(Bool_t with_uid=kFALSE) const
Retrieves number of PN entries with or without UID.
void RefreshPhysicalNodes(Bool_t lock=kTRUE)
Refresh physical nodes to reflect the actual geometry paths after alignment was applied.
static Bool_t fgLock
mutex for navigator booking in MT mode
Definition TGeoManager.h:50
TGeoVolume * MakePara(const char *name, TGeoMedium *medium, Double_t dx, Double_t dy, Double_t dz, Double_t alpha, Double_t theta, Double_t phi)
Make in one step a volume pointing to a parallelepiped shape with given medium.
void TopToMaster(const Double_t *top, Double_t *master) const
Convert coordinates from top volume frame to master.
TObjArray * fShapes
Definition TGeoManager.h:94
void AddOpticalSurface(TGeoOpticalSurface *optsurf)
Add optical surface;.
static void SetDefaultUnits(EDefaultUnits new_value)
Bool_t fLoopVolumes
flag that geometry is closed
Definition TGeoManager.h:80
Int_t AddMaterial(const TGeoMaterial *material)
Add a material to the list. Returns index of the material in list.
void ClearAttributes()
Reset all attributes to default ones.
static Int_t fgMaxDaughters
Maximum level in geometry.
Definition TGeoManager.h:53
Bool_t fUsePWNav
Raytrace mode: 0=normal, 1=pass through, 2=transparent.
void SetRTmode(Int_t mode)
Change raytracing mode.
Bool_t CheckPath(const char *path) const
Check if a geometry path is valid without changing the state of the current navigator.
Definition