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