TGeoManager.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoManager.cxx 36632 2010-11-12 15:57:07Z agheata $
00002 // Author: Andrei Gheata   25/10/01
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 ////////////////////////////////////////////////////////////////////////////////
00013 // General architecture
00014 // --------------------
00015 //
00016 //   The new ROOT geometry package is a tool designed for building, browsing,
00017 // tracking and visualizing a detector geometry. The code is independent from
00018 // other external MC for simulation, therefore it does not contain any
00019 // constraints related to physics. However, the package defines a number of
00020 // hooks for tracking, such as media, materials, magnetic field or track state flags,
00021 // in order to allow interfacing to tracking MC's. The final goal is to be
00022 // able to use the same geometry for several purposes, such as tracking,
00023 // reconstruction or visualization, taking advantage of the ROOT features
00024 // related to bookkeeping, I/O, histograming, browsing and GUI's.
00025 //
00026 //   The geometrical modeler is the most important component of the package and
00027 // it provides answers to the basic questions like "Where am I ?" or "How far
00028 // from the next boundary ?", but also to more complex ones like "How far from
00029 // the closest surface ?" or "Which is the next crossing along a helix ?".
00030 //
00031 //   The architecture of the modeler is a combination between a GEANT-like
00032 // containment scheme and a normal CSG binary tree at the level of shapes. An
00033 // important common feature of all detector geometry descriptions is the
00034 // mother-daughter concept. This is the most natural approach when tracking
00035 // is concerned and imposes a set of constraints to the way geometry is defined.
00036 // Constructive solid geometry composition is used only in order to create more
00037 // complex shapes from an existing set of primitives through boolean operations.
00038 // This feature is not implemented yet but in future full definition of boolean
00039 // expressions will be supported.
00040 //
00041 //   Practically every geometry defined in GEANT style can be mapped by the modeler.
00042 // The basic components used for building the logical hierarchy of the geometry
00043 // are called "volumes" and "nodes". Volumes (sometimes called "solids") are fully
00044 // defined geometrical objects having a given shape and medium and possibly
00045 // containing a list of nodes. Nodes represent just positioned instances of volumes
00046 // inside a container volume and they are not directly defined by user. They are
00047 // automatically created as a result of adding one volume inside other or dividing
00048 // a volume. The geometrical transformation hold by nodes is always defined with
00049 // respect to their mother (relative positioning). Reflection matrices are allowed.
00050 // All volumes have to be fully aware of their containees when the geometry is
00051 // closed. They will build aditional structures (voxels) in order to fasten-up
00052 // the search algorithms. Finally, nodes can be regarded as bidirectional links
00053 // between containers and containees objects.
00054 //
00055 //   The structure defined in this way is a graph structure since volumes are
00056 // replicable (same volume can become daughter node of several other volumes),
00057 // every volume becoming a branch in this graph. Any volume in the logical graph
00058 // can become the actual top volume at run time (see TGeoManager::SetTopVolume()).
00059 // All functionalities of the modeler will behave in this case as if only the
00060 // corresponding branch starting from this volume is the registered geometry.
00061 //
00062 //Begin_Html
00063 /*
00064 <img src="gif/t_graf.jpg">
00065 */
00066 //End_Html
00067 //
00068 //   A given volume can be positioned several times in the geometry. A volume
00069 // can be divided according default or user-defined patterns, creating automatically
00070 // the list of division nodes inside. The elementary volumes created during the
00071 // dividing process follow the same scheme as usual volumes, therefore it is possible
00072 // to position further geometrical structures inside or to divide them further more
00073 // (see TGeoVolume::Divide()).
00074 //
00075 //   The primitive shapes supported by the package are basically the GEANT3
00076 // shapes (see class TGeoShape), arbitrary wedges with eight vertices on two parallel
00077 // planes. All basic primitives inherits from class TGeoBBox since the bounding box
00078 // of a solid is essential for the tracking algorithms. They also implement the
00079 // virtual methods defined in the virtual class TGeoShape (point and segment
00080 // classification). User-defined primitives can be direcly plugged into the modeler
00081 // provided that they override these methods. Composite shapes will be soon supported
00082 // by the modeler. In order to build a TGeoCompositeShape, one will have to define
00083 // first the primitive components. The object that handle boolean
00084 // operations among components is called TGeoBoolCombinator and it has to be
00085 // constructed providing a string boolean expression between the components names.
00086 //
00087 //
00088 // Example for building a simple geometry :
00089 //-----------------------------------------
00090 //
00091 // Begin_Html <a href=http://root.cern.ch/root/html/tutorials/geom/rootgeom.C.html>rootgeom.C</a> //
00092 // End_Html                                                             //
00093 //______________________________________________________________________________
00094 //
00095 //
00096 //Begin_Html
00097 /*
00098 <img src="gif/t_root.jpg">
00099 */
00100 //End_Html
00101 //
00102 //
00103 // TGeoManager - the manager class for the geometry package.
00104 // ---------------------------------------------------------
00105 //
00106 //   TGeoManager class is embedding all the API needed for building and tracking
00107 // a geometry. It defines a global pointer (gGeoManager) in order to be fully
00108 // accessible from external code. The mechanism of handling multiple geometries
00109 // at the same time will be soon implemented.
00110 //
00111 //   TGeoManager is the owner of all geometry objects defined in a session,
00112 // therefore users must not try to control their deletion. It contains lists of
00113 // media, materials, transformations, shapes and volumes. Logical nodes (positioned
00114 // volumes) are created and destroyed by the TGeoVolume class. Physical
00115 // nodes and their global transformations are subjected to a caching mechanism
00116 // due to the sometimes very large memory requirements of logical graph expansion.
00117 // The caching mechanism is triggered by the total number of physical instances
00118 // of volumes and the cache manager is a client of TGeoManager. The manager class
00119 // also controls the painter client. This is linked with ROOT graphical libraries
00120 // loaded on demand in order to control visualization actions.
00121 //
00122 // Rules for building a valid geometry
00123 // -----------------------------------
00124 //
00125 //   A given geometry can be built in various ways, but there are mandatory steps
00126 // that have to be followed in order to be validated by the modeler. There are
00127 // general rules : volumes needs media and shapes in order to be created,
00128 // both container an containee volumes must be created before linking them together,
00129 // and the relative transformation matrix must be provided. All branches must
00130 // have an upper link point otherwise they will not be considered as part of the
00131 // geometry. Visibility or tracking properties of volumes can be provided both
00132 // at build time or after geometry is closed, but global visualization settings
00133 // (see TGeoPainter class) should not be provided at build time, otherwise the
00134 // drawing package will be loaded. There is also a list of specific rules :
00135 // positioned daughters should not extrude their mother or intersect with sisters
00136 // unless this is specified (see TGeoVolume::AddNodeOverlap()), the top volume
00137 // (containing all geometry tree) must be specified before closing the geometry
00138 // and must not be positioned - it represents the global reference frame. After
00139 // building the full geometry tree, the geometry must be closed
00140 // (see TGeoManager::CloseGeometry()). Voxelization can be redone per volume after
00141 // this process.
00142 //
00143 //
00144 //   Below is the general scheme of the manager class.
00145 //
00146 //Begin_Html
00147 /*
00148 <img src="gif/t_mgr.jpg">
00149 */
00150 //End_Html
00151 //
00152 //  An interactive session
00153 // ------------------------
00154 //
00155 //   Provided that a geometry was successfully built and closed (for instance the
00156 // previous example $ROOTSYS/tutorials/geom/rootgeom.C ), the manager class will register
00157 // itself to ROOT and the logical/physical structures will become immediately browsable.
00158 // The ROOT browser will display starting from the geometry folder : the list of
00159 // transformations and media, the top volume and the top logical node. These last
00160 // two can be fully expanded, any intermediate volume/node in the browser being subject
00161 // of direct access context menu operations (right mouse button click). All user
00162 // utilities of classes TGeoManager, TGeoVolume and TGeoNode can be called via the
00163 // context menu.
00164 //
00165 //Begin_Html
00166 /*
00167 <img src="gif/t_browser.jpg">
00168 */
00169 //End_Html
00170 //
00171 //  --- Drawing the geometry
00172 //
00173 //   Any logical volume can be drawn via TGeoVolume::Draw() member function.
00174 // This can be direcly accessed from the context menu of the volume object
00175 // directly from the browser.
00176 //   There are several drawing options that can be set with
00177 // TGeoManager::SetVisOption(Int_t opt) method :
00178 // opt=0 - only the content of the volume is drawn, N levels down (default N=3).
00179 //    This is the default behavior. The number of levels to be drawn can be changed
00180 //    via TGeoManager::SetVisLevel(Int_t level) method.
00181 //
00182 //Begin_Html
00183 /*
00184 <img src="gif/t_frame0.jpg">
00185 */
00186 //End_Html
00187 //
00188 // opt=1 - the final leaves (e.g. daughters with no containment) of the branch
00189 //    starting from volume are drawn down to the current number of levels.
00190 //                                     WARNING : This mode is memory consuming
00191 //    depending of the size of geometry, so drawing from top level within this mode
00192 //    should be handled with care for expensive geometries. In future there will be
00193 //    a limitation on the maximum number of nodes to be visualized.
00194 //
00195 //Begin_Html
00196 /*
00197 <img src="gif/t_frame1.jpg">
00198 */
00199 //End_Html
00200 //
00201 // opt=2 - only the clicked volume is visualized. This is automatically set by
00202 //    TGeoVolume::DrawOnly() method
00203 // opt=3 - only a given path is visualized. This is automatically set by
00204 //    TGeoVolume::DrawPath(const char *path) method
00205 //
00206 //    The current view can be exploded in cartesian, cylindrical or spherical
00207 // coordinates :
00208 //   TGeoManager::SetExplodedView(Int_t opt). Options may be :
00209 // - 0  - default (no bombing)
00210 // - 1  - cartesian coordinates. The bomb factor on each axis can be set with
00211 //        TGeoManager::SetBombX(Double_t bomb) and corresponding Y and Z.
00212 // - 2  - bomb in cylindrical coordinates. Only the bomb factors on Z and R
00213 //        are considered
00214 //
00215 //Begin_Html
00216 /*
00217 <img src="gif/t_frameexp.jpg">
00218 */
00219 //End_Html
00220 //
00221 // - 3  - bomb in radial spherical coordinate : TGeoManager::SetBombR()
00222 //
00223 // Volumes themselves support different visualization settings :
00224 //    - TGeoVolume::SetVisibility() : set volume visibility.
00225 //    - TGeoVolume::VisibleDaughters() : set daughters visibility.
00226 // All these actions automatically updates the current view if any.
00227 //
00228 //  --- Checking the geometry
00229 //
00230 //  Several checking methods are accessible from the volume context menu. They
00231 // generally apply only to the visible parts of the drawn geometry in order to
00232 // ease geometry checking, and their implementation is in the TGeoChecker class
00233 // from the painting package.
00234 //
00235 // 1. Checking a given point.
00236 //   Can be called from TGeoManager::CheckPoint(Double_t x, Double_t y, Double_t z).
00237 // This method is drawing the daughters of the volume containing the point one
00238 // level down, printing the path to the deepest physical node holding this point.
00239 // It also computes the closest distance to any boundary. The point will be drawn
00240 // in red.
00241 //
00242 //Begin_Html
00243 /*
00244 <img src="gif/t_checkpoint.jpg">
00245 */
00246 //End_Html
00247 //
00248 //  2. Shooting random points.
00249 //   Can be called from TGeoVolume::RandomPoints() (context menu function) and
00250 // it will draw this volume with current visualization settings. Random points
00251 // are generated in the bounding box of the top drawn volume. The points are
00252 // classified and drawn with the color of their deepest container. Only points
00253 // in visible nodes will be drawn.
00254 //
00255 //Begin_Html
00256 /*
00257 <img src="gif/t_random1.jpg">
00258 */
00259 //End_Html
00260 //
00261 //
00262 //  3. Raytracing.
00263 //   Can be called from TGeoVolume::RandomRays() (context menu of volumes) and
00264 // will shoot rays from a given point in the local reference frame with random
00265 // directions. The intersections with displayed nodes will appear as segments
00266 // having the color of the touched node. Drawn geometry will be then made invisible
00267 // in order to enhance rays.
00268 //
00269 //Begin_Html
00270 /*
00271 <img src="gif/t_random2.jpg">
00272 */
00273 //End_Html
00274 
00275 #include "Riostream.h"
00276 
00277 #include "TROOT.h"
00278 #include "TGeoManager.h"
00279 #include "TSystem.h"
00280 #include "TStyle.h"
00281 #include "TVirtualPad.h"
00282 #include "TBrowser.h"
00283 #include "TFile.h"
00284 #include "TKey.h"
00285 #include "THashList.h"
00286 #include "TClass.h"
00287 
00288 #include "TGeoVoxelFinder.h"
00289 #include "TGeoElement.h"
00290 #include "TGeoMaterial.h"
00291 #include "TGeoMedium.h"
00292 #include "TGeoMatrix.h"
00293 #include "TGeoNode.h"
00294 #include "TGeoPhysicalNode.h"
00295 #include "TGeoManager.h"
00296 #include "TGeoPara.h"
00297 #include "TGeoParaboloid.h"
00298 #include "TGeoTube.h"
00299 #include "TGeoEltu.h"
00300 #include "TGeoHype.h"
00301 #include "TGeoCone.h"
00302 #include "TGeoSphere.h"
00303 #include "TGeoArb8.h"
00304 #include "TGeoPgon.h"
00305 #include "TGeoTrd1.h"
00306 #include "TGeoTrd2.h"
00307 #include "TGeoTorus.h"
00308 #include "TGeoXtru.h"
00309 #include "TGeoCompositeShape.h"
00310 #include "TGeoBoolNode.h"
00311 #include "TGeoBuilder.h"
00312 #include "TVirtualGeoPainter.h"
00313 #include "TPluginManager.h"
00314 #include "TVirtualGeoTrack.h"
00315 #include "TQObject.h"
00316 #include "TMath.h"
00317 #include "TEnv.h"
00318 
00319 // statics and globals
00320 
00321 TGeoManager *gGeoManager = 0;
00322 
00323 ClassImp(TGeoManager)
00324 
00325 Bool_t TGeoManager::fgLock = kFALSE;
00326 Int_t  TGeoManager::fgVerboseLevel = 1;
00327 
00328 //_____________________________________________________________________________
00329 TGeoManager::TGeoManager()
00330 {
00331 // Default constructor.
00332    if (TClass::IsCallingNew() == TClass::kDummyNew) {
00333       fTimeCut = kFALSE;
00334       fTmin = 0.;
00335       fTmax = 999.;
00336       fPhiCut = kFALSE;
00337       fPhimin = 0;
00338       fPhimax = 360;
00339       fDrawExtra = kFALSE;
00340       fStreamVoxels = kFALSE;
00341       fIsGeomReading = kFALSE;
00342       fClosed = kFALSE;
00343       fLoopVolumes = kFALSE;
00344       fBits = 0;
00345       fCurrentNavigator = 0;
00346       fMaterials = 0;
00347       fHashPNE = 0;
00348       fArrayPNE = 0;
00349       fMatrices = 0;
00350       fNodes = 0;
00351       fOverlaps = 0;
00352       fNNodes = 0;
00353       fMaxVisNodes = 10000;
00354       fVolumes = 0;
00355       fPhysicalNodes = 0;
00356       fShapes = 0;
00357       fGVolumes = 0;
00358       fGShapes = 0;
00359       fTracks = 0;
00360       fMedia = 0;
00361       fNtracks = 0;
00362       fNpdg = 0;
00363       fPdgNames = 0;
00364       memset(fPdgId, 0, 256*sizeof(Int_t));
00365       fNavigators = 0;
00366       fCurrentTrack = 0;
00367       fCurrentVolume = 0;
00368       fTopVolume = 0;
00369       fTopNode = 0;
00370       fMasterVolume = 0;
00371       fPainter = 0;
00372       fActivity = kFALSE;
00373       fIsNodeSelectable = kFALSE;
00374       fVisDensity = 0.;
00375       fVisLevel = 3;
00376       fVisOption = 1;
00377       fExplodedView = 0;
00378       fNsegments = 20;
00379       fNLevel = 0;
00380       fUniqueVolumes = 0;
00381       fNodeIdArray = 0;
00382       fClippingShape = 0;
00383       fIntSize = fDblSize = 1000;
00384       fIntBuffer = 0;
00385       fDblBuffer = 0;
00386       fMatrixTransform = kFALSE;
00387       fMatrixReflection = kFALSE;
00388       fGLMatrix = 0;
00389       fPaintVolume = 0;
00390       fElementTable = 0;
00391       fHashVolumes = 0;
00392       fHashGVolumes = 0;
00393       fSizePNEId = 0;
00394       fNPNEId = 0;
00395       fKeyPNEId = 0;
00396       fValuePNEId = 0;
00397    } else {
00398       Init();
00399       gGeoIdentity = 0;
00400    }
00401 }
00402 
00403 //_____________________________________________________________________________
00404 TGeoManager::TGeoManager(const char *name, const char *title)
00405             :TNamed(name, title)
00406 {
00407 // Constructor.
00408    if (!gROOT->GetListOfGeometries()->FindObject(this)) gROOT->GetListOfGeometries()->Add(this);
00409    if (!gROOT->GetListOfBrowsables()->FindObject(this)) gROOT->GetListOfBrowsables()->Add(this);
00410    Init();
00411    gGeoIdentity = new TGeoIdentity("Identity");
00412    BuildDefaultMaterials();
00413    if (fgVerboseLevel>0) Info("TGeoManager","Geometry %s, %s created", GetName(), GetTitle());
00414 }
00415 
00416 //_____________________________________________________________________________
00417 void TGeoManager::Init()
00418 {
00419 // Initialize manager class.
00420 
00421    if (gGeoManager) {
00422       Warning("Init","Deleting previous geometry: %s/%s",gGeoManager->GetName(),gGeoManager->GetTitle());
00423       delete gGeoManager;
00424       if (fgLock) Fatal("Init", "New geometry created while the old one locked !!!");
00425    }
00426 
00427    gGeoManager = this;
00428    fTimeCut = kFALSE;
00429    fTmin = 0.;
00430    fTmax = 999.;
00431    fPhiCut = kFALSE;
00432    fPhimin = 0;
00433    fPhimax = 360;
00434    fDrawExtra = kFALSE;
00435    fStreamVoxels = kFALSE;
00436    fIsGeomReading = kFALSE;
00437    fClosed = kFALSE;
00438    fLoopVolumes = kFALSE;
00439    fBits = new UChar_t[50000]; // max 25000 nodes per volume
00440    fCurrentNavigator = 0;
00441    fHashPNE = new THashList(256,3);
00442    fArrayPNE = 0;
00443    fMaterials = new THashList(200,3);
00444    fMatrices = new TObjArray(256);
00445    fNodes = new TObjArray(30);
00446    fOverlaps = new TObjArray(256);
00447    fNNodes = 0;
00448    fMaxVisNodes = 10000;
00449    fVolumes = new TObjArray(256);
00450    fPhysicalNodes = new TObjArray(256);
00451    fShapes = new TObjArray(256);
00452    fGVolumes = new TObjArray(256);
00453    fGShapes = new TObjArray(256);
00454    fTracks = new TObjArray(256);
00455    fMedia = new THashList(200,3);
00456    fNtracks = 0;
00457    fNpdg = 0;
00458    fPdgNames = 0;
00459    memset(fPdgId, 0, 256*sizeof(Int_t));
00460    fNavigators = new TObjArray();
00461    fCurrentTrack = 0;
00462    fCurrentVolume = 0;
00463    fTopVolume = 0;
00464    fTopNode = 0;
00465    fMasterVolume = 0;
00466    fPainter = 0;
00467    fActivity = kFALSE;
00468    fIsNodeSelectable = kFALSE;
00469    fVisDensity = 0.;
00470    fVisLevel = 3;
00471    fVisOption = 1;
00472    fExplodedView = 0;
00473    fNsegments = 20;
00474    fNLevel = 0;
00475    fUniqueVolumes = new TObjArray(256);
00476    fNodeIdArray = 0;
00477    fClippingShape = 0;
00478    fIntSize = fDblSize = 1000;
00479    fIntBuffer = new Int_t[1000];
00480    fDblBuffer = new Double_t[1000];
00481    fMatrixTransform = kFALSE;
00482    fMatrixReflection = kFALSE;
00483    fGLMatrix = new TGeoHMatrix();
00484    fPaintVolume = 0;
00485    fElementTable = 0;
00486    fHashVolumes = 0;
00487    fHashGVolumes = 0;
00488    fSizePNEId = 0;
00489    fNPNEId = 0;
00490    fKeyPNEId = 0;
00491    fValuePNEId = 0;
00492 }
00493 
00494 //_____________________________________________________________________________
00495 TGeoManager::TGeoManager(const TGeoManager& gm) :
00496   TNamed(gm),
00497   fPhimin(gm.fPhimin),
00498   fPhimax(gm.fPhimax),
00499   fTmin(gm.fTmin),
00500   fTmax(gm.fTmax),
00501   fNNodes(gm.fNNodes),
00502   fParticleName(gm.fParticleName),
00503   fVisDensity(gm.fVisDensity),
00504   fExplodedView(gm.fExplodedView),
00505   fVisOption(gm.fVisOption),
00506   fVisLevel(gm.fVisLevel),
00507   fNsegments(gm.fNsegments),
00508   fNtracks(gm.fNtracks),
00509   fMaxVisNodes(gm.fMaxVisNodes),
00510   fCurrentTrack(gm.fCurrentTrack),
00511   fNpdg(gm.fNpdg),
00512   fClosed(gm.fClosed),
00513   fLoopVolumes(gm.fLoopVolumes),
00514   fStreamVoxels(gm.fStreamVoxels),
00515   fIsGeomReading(gm.fIsGeomReading),
00516   fPhiCut(gm.fPhiCut),
00517   fTimeCut(gm.fTimeCut),
00518   fDrawExtra(gm.fDrawExtra),
00519   fMatrixTransform(gm.fMatrixTransform),
00520   fMatrixReflection(gm.fMatrixReflection),
00521   fActivity(gm.fActivity),
00522   fIsNodeSelectable(gm.fIsNodeSelectable),
00523   fPainter(gm.fPainter),
00524   fMatrices(gm.fMatrices),
00525   fShapes(gm.fShapes),
00526   fVolumes(gm.fVolumes),
00527   fPhysicalNodes(gm.fPhysicalNodes),
00528   fGShapes(gm.fGShapes),
00529   fGVolumes(gm.fGVolumes),
00530   fTracks(gm.fTracks),
00531   fPdgNames(gm.fPdgNames),
00532   fNavigators(gm.fNavigators),
00533   fMaterials(gm.fMaterials),
00534   fMedia(gm.fMedia),
00535   fNodes(gm.fNodes),
00536   fOverlaps(gm.fOverlaps),
00537   fBits(gm.fBits),
00538   fCurrentNavigator(gm.fCurrentNavigator),
00539   fCurrentVolume(gm.fCurrentVolume),
00540   fTopVolume(gm.fTopVolume),
00541   fTopNode(gm.fTopNode),
00542   fMasterVolume(gm.fMasterVolume),
00543   fGLMatrix(gm.fGLMatrix),
00544   fUniqueVolumes(gm.fUniqueVolumes),
00545   fClippingShape(gm.fClippingShape),
00546   fElementTable(gm.fElementTable),
00547   fNodeIdArray(gm.fNodeIdArray),
00548   fIntSize(gm.fIntSize),
00549   fDblSize(gm.fDblSize),
00550   fIntBuffer(gm.fIntBuffer),
00551   fNLevel(gm.fNLevel),
00552   fDblBuffer(gm.fDblBuffer),
00553   fPaintVolume(gm.fPaintVolume),
00554   fHashVolumes(gm.fHashVolumes),
00555   fHashGVolumes(gm.fHashGVolumes),
00556   fHashPNE(gm.fHashPNE),
00557   fArrayPNE(gm.fArrayPNE),
00558   fSizePNEId(0),
00559   fNPNEId(0),
00560   fKeyPNEId(0),
00561   fValuePNEId(0)
00562 {
00563    //copy constructor
00564    for(Int_t i=0; i<256; i++)
00565       fPdgId[i]=gm.fPdgId[i];
00566 }
00567 
00568 //_____________________________________________________________________________
00569 TGeoManager& TGeoManager::operator=(const TGeoManager& gm)
00570 {
00571    //assignment operator
00572    if(this!=&gm) {
00573       TNamed::operator=(gm);
00574       fPhimin=gm.fPhimin;
00575       fPhimax=gm.fPhimax;
00576       fTmin=gm.fTmin;
00577       fTmax=gm.fTmax;
00578       fNNodes=gm.fNNodes;
00579       fParticleName=gm.fParticleName;
00580       fVisDensity=gm.fVisDensity;
00581       fExplodedView=gm.fExplodedView;
00582       fVisOption=gm.fVisOption;
00583       fVisLevel=gm.fVisLevel;
00584       fNsegments=gm.fNsegments;
00585       fNtracks=gm.fNtracks;
00586       fMaxVisNodes=gm.fMaxVisNodes;
00587       fCurrentTrack=gm.fCurrentTrack;
00588       fNpdg=gm.fNpdg;
00589       for(Int_t i=0; i<256; i++)
00590          fPdgId[i]=gm.fPdgId[i];
00591       fClosed=gm.fClosed;
00592       fLoopVolumes=gm.fLoopVolumes;
00593       fStreamVoxels=gm.fStreamVoxels;
00594       fIsGeomReading=gm.fIsGeomReading;
00595       fPhiCut=gm.fPhiCut;
00596       fTimeCut=gm.fTimeCut;
00597       fDrawExtra=gm.fDrawExtra;
00598       fMatrixTransform=gm.fMatrixTransform;
00599       fMatrixReflection=gm.fMatrixReflection;
00600       fActivity=gm.fActivity;
00601       fIsNodeSelectable=gm.fIsNodeSelectable;
00602       fPainter=gm.fPainter;
00603       fMatrices=gm.fMatrices;
00604       fShapes=gm.fShapes;
00605       fVolumes=gm.fVolumes;
00606       fPhysicalNodes=gm.fPhysicalNodes;
00607       fGShapes=gm.fGShapes;
00608       fGVolumes=gm.fGVolumes;
00609       fTracks=gm.fTracks;
00610       fPdgNames=gm.fPdgNames;
00611       fNavigators=gm.fNavigators;
00612       fMaterials=gm.fMaterials;
00613       fMedia=gm.fMedia;
00614       fNodes=gm.fNodes;
00615       fOverlaps=gm.fOverlaps;
00616       fBits=gm.fBits;
00617       fCurrentNavigator=gm.fCurrentNavigator;
00618       fCurrentVolume = gm.fCurrentVolume;
00619       fTopVolume=gm.fTopVolume;
00620       fTopNode=gm.fTopNode;
00621       fMasterVolume=gm.fMasterVolume;
00622       fGLMatrix=gm.fGLMatrix;
00623       fUniqueVolumes=gm.fUniqueVolumes;
00624       fClippingShape=gm.fClippingShape;
00625       fElementTable=gm.fElementTable;
00626       fNodeIdArray=gm.fNodeIdArray;
00627       fIntSize=gm.fIntSize;
00628       fDblSize=gm.fDblSize;
00629       fIntBuffer=gm.fIntBuffer;
00630       fNLevel=gm.fNLevel;
00631       fDblBuffer=gm.fDblBuffer;
00632       fPaintVolume=gm.fPaintVolume;
00633       fHashVolumes=gm.fHashVolumes;
00634       fHashGVolumes=gm.fHashGVolumes;
00635       fHashPNE=gm.fHashPNE;
00636       fArrayPNE=gm.fArrayPNE;
00637       fSizePNEId = 0;
00638       fNPNEId = 0;
00639       fKeyPNEId = 0;
00640       fValuePNEId = 0;
00641    }
00642    return *this;
00643 }
00644 
00645 //_____________________________________________________________________________
00646 TGeoManager::~TGeoManager()
00647 {
00648 //   Destructor
00649    if (gGeoManager != this) gGeoManager = this;
00650 
00651    if (gROOT->GetListOfFiles()) { //in case this function is called from TROOT destructor
00652       gROOT->GetListOfGeometries()->Remove(this);
00653       gROOT->GetListOfBrowsables()->Remove(this);
00654    }
00655 //   TSeqCollection *brlist = gROOT->GetListOfBrowsers();
00656 //   TIter next(brlist);
00657 //   TBrowser *browser = 0;
00658 //   while ((browser=(TBrowser*)next())) browser->RecursiveRemove(this);
00659    delete TGeoBuilder::Instance(this);
00660    if (fBits)  delete [] fBits;
00661    SafeDelete(fNodes);
00662    SafeDelete(fTopNode);
00663    if (fOverlaps) {fOverlaps->Delete(); SafeDelete(fOverlaps);}
00664    if (fMaterials) {fMaterials->Delete(); SafeDelete(fMaterials);}
00665    SafeDelete(fElementTable);
00666    if (fMedia) {fMedia->Delete(); SafeDelete(fMedia);}
00667    SafeDelete(fHashVolumes);
00668    SafeDelete(fHashGVolumes);
00669    if (fHashPNE) {fHashPNE->Delete(); SafeDelete(fHashPNE);}
00670    if (fArrayPNE) {delete fArrayPNE;}
00671    if (fVolumes) {fVolumes->Delete(); SafeDelete(fVolumes);}
00672    if (fShapes) {fShapes->Delete(); SafeDelete( fShapes );}
00673    if (fPhysicalNodes) {fPhysicalNodes->Delete(); SafeDelete( fPhysicalNodes );}
00674    if (fMatrices) {fMatrices->Delete(); SafeDelete( fMatrices );}
00675    if (fTracks) {fTracks->Delete(); SafeDelete( fTracks );}
00676    SafeDelete( fUniqueVolumes );
00677    if (fPdgNames) {fPdgNames->Delete(); SafeDelete( fPdgNames );}
00678    if (fNavigators) {fNavigators->Delete(); SafeDelete( fNavigators );}
00679    CleanGarbage();
00680    SafeDelete( fPainter ); 
00681    delete [] fDblBuffer;
00682    delete [] fIntBuffer;
00683    SafeDelete( fGLMatrix ); 
00684    if (fSizePNEId) {
00685       delete [] fKeyPNEId;
00686       delete [] fValuePNEId;
00687    }
00688    gGeoIdentity = 0;
00689    gGeoManager = 0;
00690 }
00691 
00692 //_____________________________________________________________________________
00693 Int_t TGeoManager::AddMaterial(const TGeoMaterial *material)
00694 {
00695 // Add a material to the list. Returns index of the material in list.
00696    return TGeoBuilder::Instance(this)->AddMaterial((TGeoMaterial*)material);
00697 }
00698 
00699 //_____________________________________________________________________________
00700 Int_t TGeoManager::AddOverlap(const TNamed *ovlp)
00701 {
00702 // Add an illegal overlap/extrusion to the list.
00703    Int_t size = fOverlaps->GetEntriesFast();
00704    fOverlaps->Add((TObject*)ovlp);
00705    return size;
00706 }
00707 
00708 //_____________________________________________________________________________
00709 Int_t TGeoManager::AddTransformation(const TGeoMatrix *matrix)
00710 {
00711 // Add a matrix to the list. Returns index of the matrix in list.
00712    return TGeoBuilder::Instance(this)->AddTransformation((TGeoMatrix*)matrix);
00713 }
00714 
00715 //_____________________________________________________________________________
00716 Int_t TGeoManager::AddShape(const TGeoShape *shape)
00717 {
00718 // Add a shape to the list. Returns index of the shape in list.
00719    return TGeoBuilder::Instance(this)->AddShape((TGeoShape*)shape);
00720 }
00721 
00722 //_____________________________________________________________________________
00723 Int_t TGeoManager::AddTrack(Int_t id, Int_t pdgcode, TObject *particle)
00724 {
00725 // Add a track to the list of tracks. Use this for primaries only. For secondaries,
00726 // add them to the parent track. The method create objects that are registered
00727 // to the analysis manager but have to be cleaned-up by the user via ClearTracks().
00728    Int_t index = fNtracks;
00729    fTracks->AddAtAndExpand(GetGeomPainter()->AddTrack(id,pdgcode,particle),fNtracks++);
00730    return index;
00731 }
00732 
00733 //_____________________________________________________________________________
00734 Int_t TGeoManager::AddTrack(TVirtualGeoTrack *track)
00735 {
00736 // Add a track to the list of tracks
00737    Int_t index = fNtracks;
00738    fTracks->AddAtAndExpand(track,fNtracks++);
00739    return index;
00740 }
00741 
00742 //_____________________________________________________________________________
00743 TVirtualGeoTrack *TGeoManager::MakeTrack(Int_t id, Int_t pdgcode, TObject *particle)
00744 {
00745 // Makes a primary track but do not attach it to the list of tracks. The track
00746 // can be attached as daughter to another one with TVirtualGeoTrack::AddTrack
00747    TVirtualGeoTrack *track = GetGeomPainter()->AddTrack(id,pdgcode,particle);
00748    return track;
00749 }
00750 
00751 //_____________________________________________________________________________
00752 Int_t TGeoManager::AddVolume(TGeoVolume *volume)
00753 {
00754 // Add a volume to the list. Returns index of the volume in list.
00755    if (!volume) {
00756       Error("AddVolume", "invalid volume");
00757       return -1;
00758    }
00759    Int_t uid = fUniqueVolumes->GetEntriesFast();
00760    if (!uid) uid++;
00761    if (!fCurrentVolume) {
00762       fCurrentVolume = volume;
00763       fUniqueVolumes->AddAtAndExpand(volume,uid);
00764    } else {
00765       if (!strcmp(volume->GetName(), fCurrentVolume->GetName())) {
00766          uid = fCurrentVolume->GetNumber();
00767       } else {
00768          fCurrentVolume = volume;
00769          Int_t olduid = GetUID(volume->GetName());
00770          if (olduid<0) {
00771             fUniqueVolumes->AddAtAndExpand(volume,uid);
00772          } else {
00773             uid = olduid;
00774          }
00775       }
00776    }
00777    volume->SetNumber(uid);
00778    if (!fHashVolumes) {
00779       fHashVolumes = new THashList(256);
00780       fHashGVolumes = new THashList(256);
00781    }
00782    TObjArray *list = fVolumes;
00783    if (!volume->GetShape() || volume->IsRunTime() || volume->IsVolumeMulti()) {
00784       list = fGVolumes;
00785       fHashGVolumes->Add(volume);
00786    } else {
00787       fHashVolumes->Add(volume);
00788    }
00789    Int_t index = list->GetEntriesFast();
00790    list->AddAtAndExpand(volume,index);
00791    return uid;
00792 }
00793 
00794 //_____________________________________________________________________________
00795 Int_t TGeoManager::AddNavigator(TGeoNavigator *navigator)
00796 {
00797 // Add a navigator in the list of navigators. If it is the first one make it
00798 // current navigator.
00799    if (!fCurrentNavigator) fCurrentNavigator = navigator;
00800    Int_t index = fNavigators->GetEntriesFast();
00801    fNavigators->Add(navigator);
00802    if (fClosed) {
00803       navigator->BuildCache(kTRUE,kFALSE);
00804    }
00805    return index;
00806 }
00807 
00808 //_____________________________________________________________________________
00809 Bool_t TGeoManager::SetCurrentNavigator(Int_t index)
00810 {
00811 // Switch to another navigator.
00812    if (index<0 || index>=fNavigators->GetEntriesFast()) {
00813       Error("SetCurrentNavigator", "index %i not in range [0, %d]", index, fNavigators->GetEntriesFast()-1);
00814       return kFALSE;
00815    }
00816    fCurrentNavigator = (TGeoNavigator*) fNavigators->At(index);
00817    return kTRUE;
00818 }
00819 
00820 //_____________________________________________________________________________
00821 void TGeoManager::Browse(TBrowser *b)
00822 {
00823 // Describe how to browse this object.
00824    if (!b) return;
00825    if (fMaterials) b->Add(fMaterials, "Materials");
00826    if (fMedia)     b->Add(fMedia,     "Media");
00827    if (fMatrices)  b->Add(fMatrices, "Local transformations");
00828    if (fOverlaps)  b->Add(fOverlaps, "Illegal overlaps");
00829    if (fTracks)    b->Add(fTracks,   "Tracks");
00830    if (fMasterVolume) b->Add(fMasterVolume, "Master Volume", fMasterVolume->IsVisible());
00831    if (fTopVolume) b->Add(fTopVolume, "Top Volume", fTopVolume->IsVisible());
00832    if (fTopNode)   b->Add(fTopNode);
00833    TString browserImp(gEnv->GetValue("Browser.Name", "TRootBrowserLite"));
00834    TQObject::Connect(browserImp.Data(), "Checked(TObject*,Bool_t)",
00835                      "TGeoManager", this, "SetVisibility(TObject*,Bool_t)");
00836 }
00837 
00838 //_____________________________________________________________________________
00839 void TGeoManager::Edit(Option_t *option) {
00840 // Append a pad for this geometry.
00841    AppendPad("");
00842    GetGeomPainter()->EditGeometry(option);
00843 }
00844 
00845 //_____________________________________________________________________________
00846 void TGeoManager::SetVisibility(TObject *obj, Bool_t vis)
00847 {
00848 // Set visibility for a volume.
00849    if(obj->IsA() == TGeoVolume::Class()) {
00850       TGeoVolume *vol = (TGeoVolume *) obj;
00851       vol->SetVisibility(vis);
00852    } else {
00853       if (obj->InheritsFrom(TGeoNode::Class())) {
00854          TGeoNode *node = (TGeoNode *) obj;
00855          node->SetVisibility(vis);
00856       } else return;
00857    }
00858    GetGeomPainter()->ModifiedPad(kTRUE);
00859 }
00860 
00861 //_____________________________________________________________________________
00862 void TGeoManager::BombTranslation(const Double_t *tr, Double_t *bombtr)
00863 {
00864 // Get the new 'bombed' translation vector according current exploded view mode.
00865    if (fPainter) fPainter->BombTranslation(tr, bombtr);
00866    return;
00867 }
00868 
00869 //_____________________________________________________________________________
00870 void TGeoManager::UnbombTranslation(const Double_t *tr, Double_t *bombtr)
00871 {
00872 // Get the new 'unbombed' translation vector according current exploded view mode.
00873    if (fPainter) fPainter->UnbombTranslation(tr, bombtr);
00874    return;
00875 }
00876 
00877 //_____________________________________________________________________________
00878 void TGeoManager::DoBackupState()
00879 {
00880 // Backup the current state without affecting the cache stack.
00881    fCurrentNavigator->DoBackupState();
00882 }
00883 
00884 //_____________________________________________________________________________
00885 void TGeoManager::DoRestoreState()
00886 {
00887 // Restore a backed-up state without affecting the cache stack.
00888    fCurrentNavigator->DoRestoreState();
00889 }
00890 
00891 //_____________________________________________________________________________
00892 void TGeoManager::RegisterMatrix(const TGeoMatrix *matrix)
00893 {
00894 // Register a matrix to the list of matrices. It will be cleaned-up at the
00895 // destruction TGeoManager.
00896    return TGeoBuilder::Instance(this)->RegisterMatrix((TGeoMatrix*)matrix);
00897 }
00898 
00899 //_____________________________________________________________________________
00900 Int_t TGeoManager::ReplaceVolume(TGeoVolume *vorig, TGeoVolume *vnew)
00901 {
00902 // Replaces all occurences of VORIG with VNEW in the geometry tree. The volume VORIG
00903 // is not replaced from the list of volumes, but all node referencing it will reference
00904 // VNEW instead. Returns number of occurences changed.
00905    Int_t nref = 0;
00906    if (!vorig || !vnew) return nref;
00907    TGeoMedium *morig = vorig->GetMedium();
00908    Bool_t checkmed = kFALSE;
00909    if (morig) checkmed = kTRUE;
00910    TGeoMedium *mnew = vnew->GetMedium();
00911    // Try to limit the damage produced by incorrect usage.
00912    if (!mnew && !vnew->IsAssembly()) {
00913       Error("ReplaceVolume","Replacement volume %s has no medium and it is not an assembly",
00914              vnew->GetName());
00915       return nref;
00916    }
00917    if (mnew && checkmed) {
00918       if (mnew->GetId() != morig->GetId())
00919          Warning("ReplaceVolume","Replacement volume %s has different medium than original volume %s",
00920                  vnew->GetName(), vorig->GetName());
00921       checkmed = kFALSE;
00922    }
00923 
00924    // Medium checking now performed only if replacement is an assembly and old volume a real one.
00925    // Check result is dependent on positioning.
00926    Int_t nvol = fVolumes->GetEntriesFast();
00927    Int_t i,j,nd;
00928    Int_t ierr = 0;
00929    TGeoVolume *vol;
00930    TGeoNode *node;
00931    TGeoVoxelFinder *voxels;
00932    for (i=0; i<nvol; i++) {
00933       vol = (TGeoVolume*)fVolumes->At(i);
00934       if (!vol) continue;
00935       if (vol==vorig || vol==vnew) continue;
00936       nd = vol->GetNdaughters();
00937       for (j=0; j<nd; j++) {
00938          node = vol->GetNode(j);
00939          if (node->GetVolume() == vorig) {
00940             if (checkmed) {
00941                mnew = node->GetMotherVolume()->GetMedium();
00942                if (mnew && mnew->GetId()!=morig->GetId()) ierr++;
00943             }
00944             nref++;
00945             if (node->IsOverlapping()) {
00946                node->SetOverlapping(kFALSE);
00947                Info("ReplaceVolume","%s replaced with assembly and declared NON-OVERLAPPING!",node->GetName());
00948             }
00949             node->SetVolume(vnew);
00950             voxels = node->GetMotherVolume()->GetVoxels();
00951             if (voxels) voxels->SetNeedRebuild();
00952          } else {
00953             if (node->GetMotherVolume() == vorig) {
00954                nref++;
00955                node->SetMotherVolume(vnew);
00956                if (node->IsOverlapping()) {
00957                   node->SetOverlapping(kFALSE);
00958                   Info("ReplaceVolume","%s inside substitute assembly %s declared NON-OVERLAPPING!",node->GetName(),vnew->GetName());
00959                }
00960             }
00961          }
00962       }
00963    }
00964    if (ierr) Warning("ReplaceVolume", "Volumes should not be replaced with assemblies if they are positioned in containers having a different medium ID.\n %i occurences for assembly replacing volume %s",
00965                      ierr, vorig->GetName());
00966    return nref;
00967 }
00968 
00969 //_____________________________________________________________________________
00970 Int_t TGeoManager::TransformVolumeToAssembly(const char *vname)
00971 {
00972 // Transform all volumes named VNAME to assemblies. The volumes must be virtual.
00973    TGeoVolume *toTransform = FindVolumeFast(vname);
00974    if (!toTransform) {
00975       Warning("TransformVolumeToAssembly", "Volume %s not found", vname);
00976       return 0;
00977    }
00978    Int_t index = fVolumes->IndexOf(toTransform);
00979    Int_t count = 0;
00980    Int_t indmax = fVolumes->GetEntries();
00981    Bool_t replace = kTRUE;
00982    TGeoVolume *transformed;
00983    while (index<indmax) {
00984       if (replace) {
00985          replace = kFALSE;
00986          transformed = TGeoVolumeAssembly::MakeAssemblyFromVolume(toTransform);
00987          if (transformed) {
00988             ReplaceVolume(toTransform, transformed);
00989             count++;
00990          } else {
00991             if (toTransform->IsAssembly())
00992                Warning("TransformVolumeToAssembly", "Volume %s already assembly", toTransform->GetName());
00993             if (!toTransform->GetNdaughters())
00994                Warning("TransformVolumeToAssembly", "Volume %s has no daughters, cannot transform", toTransform->GetName());
00995             if (toTransform->IsVolumeMulti())
00996                Warning("TransformVolumeToAssembly", "Volume %s divided, cannot transform", toTransform->GetName());
00997          }
00998       }
00999       index++;
01000       if (index >= indmax) return count;
01001       toTransform = (TGeoVolume*)fVolumes->At(index);
01002       if (!strcmp(toTransform->GetName(),vname)) replace = kTRUE;
01003    }
01004    return count;
01005 }
01006 
01007 //_____________________________________________________________________________
01008 TGeoVolume *TGeoManager::Division(const char *name, const char *mother, Int_t iaxis,
01009                                   Int_t ndiv, Double_t start, Double_t step, Int_t numed, Option_t *option)
01010 {
01011 // Create a new volume by dividing an existing one (GEANT3 like)
01012 //
01013 // Divides MOTHER into NDIV divisions called NAME
01014 // along axis IAXIS starting at coordinate value START
01015 // and having size STEP. The created volumes will have tracking
01016 // media ID=NUMED (if NUMED=0 -> same media as MOTHER)
01017 //    The behavior of the division operation can be triggered using OPTION :
01018 // OPTION (case insensitive) :
01019 //  N  - divide all range in NDIV cells (same effect as STEP<=0) (GSDVN in G3)
01020 //  NX - divide range starting with START in NDIV cells          (GSDVN2 in G3)
01021 //  S  - divide all range with given STEP. NDIV is computed and divisions will be centered
01022 //         in full range (same effect as NDIV<=0)                (GSDVS, GSDVT in G3)
01023 //  SX - same as DVS, but from START position.                   (GSDVS2, GSDVT2 in G3)
01024 
01025    return TGeoBuilder::Instance(this)->Division(name, mother, iaxis, ndiv, start, step, numed, option);
01026 }
01027 
01028 //_____________________________________________________________________________
01029 void TGeoManager::Matrix(Int_t index, Double_t theta1, Double_t phi1,
01030                          Double_t theta2, Double_t phi2,
01031                          Double_t theta3, Double_t phi3)
01032 {
01033 // Create rotation matrix named 'mat<index>'.
01034 //
01035 //  index    rotation matrix number
01036 //  theta1   polar angle for axis X
01037 //  phi1     azimuthal angle for axis X
01038 //  theta2   polar angle for axis Y
01039 //  phi2     azimuthal angle for axis Y
01040 //  theta3   polar angle for axis Z
01041 //  phi3     azimuthal angle for axis Z
01042 //
01043    TGeoBuilder::Instance(this)->Matrix(index, theta1, phi1, theta2, phi2, theta3, phi3);
01044 }
01045 
01046 //_____________________________________________________________________________
01047 TGeoMaterial *TGeoManager::Material(const char *name, Double_t a, Double_t z, Double_t dens, Int_t uid,Double_t radlen, Double_t intlen)
01048 {
01049 // Create material with given A, Z and density, having an unique id.
01050    return TGeoBuilder::Instance(this)->Material(name, a, z, dens, uid, radlen, intlen);
01051 
01052 }
01053 
01054 //_____________________________________________________________________________
01055 TGeoMaterial *TGeoManager::Mixture(const char *name, Float_t *a, Float_t *z, Double_t dens,
01056                                    Int_t nelem, Float_t *wmat, Int_t uid)
01057 {
01058 // Create mixture OR COMPOUND IMAT as composed by THE BASIC nelem
01059 // materials defined by arrays A,Z and WMAT, having an unique id.
01060    return TGeoBuilder::Instance(this)->Mixture(name, a, z, dens, nelem, wmat, uid);
01061 }
01062 
01063 //_____________________________________________________________________________
01064 TGeoMaterial *TGeoManager::Mixture(const char *name, Double_t *a, Double_t *z, Double_t dens,
01065                                    Int_t nelem, Double_t *wmat, Int_t uid)
01066 {
01067 // Create mixture OR COMPOUND IMAT as composed by THE BASIC nelem
01068 // materials defined by arrays A,Z and WMAT, having an unique id.
01069    return TGeoBuilder::Instance(this)->Mixture(name, a, z, dens, nelem, wmat, uid);
01070 }
01071 
01072 //_____________________________________________________________________________
01073 TGeoMedium *TGeoManager::Medium(const char *name, Int_t numed, Int_t nmat, Int_t isvol,
01074                                 Int_t ifield, Double_t fieldm, Double_t tmaxfd,
01075                                 Double_t stemax, Double_t deemax, Double_t epsil,
01076                                 Double_t stmin)
01077 {
01078 // Create tracking medium
01079   //
01080   //  numed      tracking medium number assigned
01081   //  name      tracking medium name
01082   //  nmat      material number
01083   //  isvol     sensitive volume flag
01084   //  ifield    magnetic field
01085   //  fieldm    max. field value (kilogauss)
01086   //  tmaxfd    max. angle due to field (deg/step)
01087   //  stemax    max. step allowed
01088   //  deemax    max. fraction of energy lost in a step
01089   //  epsil     tracking precision (cm)
01090   //  stmin     min. step due to continuous processes (cm)
01091   //
01092   //  ifield = 0 if no magnetic field; ifield = -1 if user decision in guswim;
01093   //  ifield = 1 if tracking performed with g3rkuta; ifield = 2 if tracking
01094   //  performed with g3helix; ifield = 3 if tracking performed with g3helx3.
01095   //
01096    return TGeoBuilder::Instance(this)->Medium(name, numed, nmat, isvol, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
01097 }
01098 
01099 //_____________________________________________________________________________
01100 void TGeoManager::Node(const char *name, Int_t nr, const char *mother,
01101                        Double_t x, Double_t y, Double_t z, Int_t irot,
01102                        Bool_t isOnly, Float_t *upar, Int_t npar)
01103 {
01104 // Create a node called <name_nr> pointing to the volume called <name>
01105 // as daughter of the volume called <mother> (gspos). The relative matrix is
01106 // made of : a translation (x,y,z) and a rotation matrix named <matIROT>.
01107 // In case npar>0, create the volume to be positioned in mother, according
01108 // its actual parameters (gsposp).
01109 //  NAME   Volume name
01110 //  NUMBER Copy number of the volume
01111 //  MOTHER Mother volume name
01112 //  X      X coord. of the volume in mother ref. sys.
01113 //  Y      Y coord. of the volume in mother ref. sys.
01114 //  Z      Z coord. of the volume in mother ref. sys.
01115 //  IROT   Rotation matrix number w.r.t. mother ref. sys.
01116 //  ISONLY ONLY/MANY flag
01117 
01118    TGeoBuilder::Instance(this)->Node(name, nr, mother, x, y, z, irot, isOnly, upar, npar);
01119 }
01120 
01121 //_____________________________________________________________________________
01122 void TGeoManager::Node(const char *name, Int_t nr, const char *mother,
01123                        Double_t x, Double_t y, Double_t z, Int_t irot,
01124                        Bool_t isOnly, Double_t *upar, Int_t npar)
01125 {
01126 // Create a node called <name_nr> pointing to the volume called <name>
01127 // as daughter of the volume called <mother> (gspos). The relative matrix is
01128 // made of : a translation (x,y,z) and a rotation matrix named <matIROT>.
01129 // In case npar>0, create the volume to be positioned in mother, according
01130 // its actual parameters (gsposp).
01131 //  NAME   Volume name
01132 //  NUMBER Copy number of the volume
01133 //  MOTHER Mother volume name
01134 //  X      X coord. of the volume in mother ref. sys.
01135 //  Y      Y coord. of the volume in mother ref. sys.
01136 //  Z      Z coord. of the volume in mother ref. sys.
01137 //  IROT   Rotation matrix number w.r.t. mother ref. sys.
01138 //  ISONLY ONLY/MANY flag
01139    TGeoBuilder::Instance(this)->Node(name, nr, mother, x, y, z, irot, isOnly, upar, npar);
01140 
01141 }
01142 
01143 //_____________________________________________________________________________
01144 TGeoVolume *TGeoManager::Volume(const char *name, const char *shape, Int_t nmed,
01145                                 Float_t *upar, Int_t npar)
01146 {
01147 // Create a volume in GEANT3 style.
01148 //  NAME   Volume name
01149 //  SHAPE  Volume type
01150 //  NMED   Tracking medium number
01151 //  NPAR   Number of shape parameters
01152 //  UPAR   Vector containing shape parameters
01153    return TGeoBuilder::Instance(this)->Volume(name, shape, nmed, upar, npar);
01154 }
01155 
01156 //_____________________________________________________________________________
01157 TGeoVolume *TGeoManager::Volume(const char *name, const char *shape, Int_t nmed,
01158                                 Double_t *upar, Int_t npar)
01159 {
01160 // Create a volume in GEANT3 style.
01161 //  NAME   Volume name
01162 //  SHAPE  Volume type
01163 //  NMED   Tracking medium number
01164 //  NPAR   Number of shape parameters
01165 //  UPAR   Vector containing shape parameters
01166    return TGeoBuilder::Instance(this)->Volume(name, shape, nmed, upar, npar);
01167 }
01168 
01169 //_____________________________________________________________________________
01170 void TGeoManager::SetAllIndex()
01171 {
01172 // Assigns uid's for all materials,media and matrices.
01173    Int_t index = 1;
01174    TIter next(fMaterials);
01175    TGeoMaterial *mater;
01176    while ((mater=(TGeoMaterial*)next())) {
01177       mater->SetUniqueID(index++);
01178       mater->ResetBit(TGeoMaterial::kMatSavePrimitive);
01179    }
01180    index = 1;
01181    TIter next1(fMedia);
01182    TGeoMedium *med;
01183    while ((med=(TGeoMedium*)next1())) {
01184       med->SetUniqueID(index++);
01185       med->ResetBit(TGeoMedium::kMedSavePrimitive);
01186    }
01187    index = 1;
01188    TIter next2(fShapes);
01189    TGeoShape *shape;
01190    while ((shape=(TGeoShape*)next2())) {
01191       shape->SetUniqueID(index++);
01192       if (shape->IsComposite()) ((TGeoCompositeShape*)shape)->GetBoolNode()->RegisterMatrices();
01193    }
01194 
01195    TIter next3(fMatrices);
01196    TGeoMatrix *matrix;
01197    while ((matrix=(TGeoMatrix*)next3())) {
01198       matrix->RegisterYourself();
01199    }
01200    TIter next4(fMatrices);
01201    index = 1;
01202    while ((matrix=(TGeoMatrix*)next4())) {
01203       matrix->SetUniqueID(index++);
01204       matrix->ResetBit(TGeoMatrix::kGeoSavePrimitive);
01205    }
01206    TIter next5(fVolumes);
01207    TGeoVolume *vol;
01208    while ((vol=(TGeoVolume*)next5())) vol->UnmarkSaved();
01209 }
01210 
01211 //_____________________________________________________________________________
01212 void TGeoManager::ClearAttributes()
01213 {
01214 // Reset all attributes to default ones. Default attributes for visualization
01215 // are those defined before closing the geometry.
01216    if (gPad) delete gPad;
01217    gPad = 0;
01218    SetVisOption(0);
01219    SetVisLevel(3);
01220    SetExplodedView(0);
01221    SetBombFactors();
01222    if (!gStyle) return;
01223    TIter next(fVolumes);
01224    TGeoVolume *vol = 0;
01225    while ((vol=(TGeoVolume*)next())) {
01226       if (!vol->IsVisTouched()) continue;
01227       vol->SetVisTouched(kFALSE);
01228    }
01229 }
01230 //_____________________________________________________________________________
01231 void TGeoManager::CloseGeometry(Option_t *option)
01232 {
01233 // Closing geometry implies checking the geometry validity, fixing shapes
01234 // with negative parameters (run-time shapes)building the cache manager,
01235 // voxelizing all volumes, counting the total number of physical nodes and
01236 // registring the manager class to the browser.
01237    if (fClosed) {
01238       Warning("CloseGeometry", "geometry already closed");
01239       return;
01240    }
01241    if (!fMasterVolume) {
01242       Error("CloseGeometry","you MUST call SetTopVolume() first !");
01243       return;
01244    }
01245    if (!gROOT->GetListOfGeometries()->FindObject(this)) gROOT->GetListOfGeometries()->Add(this);
01246    if (!gROOT->GetListOfBrowsables()->FindObject(this)) gROOT->GetListOfBrowsables()->Add(this);
01247 //   TSeqCollection *brlist = gROOT->GetListOfBrowsers();
01248 //   TIter next(brlist);
01249 //   TBrowser *browser = 0;
01250 //   while ((browser=(TBrowser*)next())) browser->Refresh();
01251    TString opt(option);
01252    opt.ToLower();
01253    Bool_t dummy = opt.Contains("d");
01254    Bool_t nodeid = opt.Contains("i");
01255    // Create a geometry navigator if not present
01256    if (!fCurrentNavigator) AddNavigator(new TGeoNavigator(this));
01257    TGeoNavigator *nav = 0;
01258    Int_t nnavigators = fNavigators->GetEntriesFast();
01259    // Check if the geometry is streamed from file
01260    if (fIsGeomReading) {
01261       if (fgVerboseLevel>0) Info("CloseGeometry","Geometry loaded from file...");
01262       gGeoIdentity=(TGeoIdentity *)fMatrices->At(0);
01263       if (!fElementTable) fElementTable = new TGeoElementTable(200);
01264       if (!fTopNode) {
01265          if (!fMasterVolume) {
01266             Error("CloseGeometry", "Master volume not streamed");
01267             return;
01268          }
01269          SetTopVolume(fMasterVolume);
01270          if (fStreamVoxels && fgVerboseLevel>0) Info("CloseGeometry","Voxelization retrieved from file");
01271          Voxelize("ALL");
01272          for (Int_t i=0; i<nnavigators; i++) {
01273             nav = (TGeoNavigator*)fNavigators->At(i);
01274             nav->BuildCache(dummy,nodeid);
01275          }
01276       } else {
01277          Warning("CloseGeometry", "top node was streamed!");
01278          Voxelize("ALL");
01279          for (Int_t i=0; i<nnavigators; i++) {
01280             nav = (TGeoNavigator*)fNavigators->At(i);
01281             nav->BuildCache(dummy,nodeid);
01282          }
01283       }
01284       if (!fHashVolumes) {
01285          Int_t nvol = fVolumes->GetEntriesFast();
01286          Int_t ngvol = fGVolumes->GetEntriesFast();
01287          fHashVolumes = new THashList(nvol+1);
01288          fHashGVolumes = new THashList(ngvol+1);
01289          Int_t i;
01290          for (i=0; i<ngvol; i++) fHashGVolumes->AddLast(fGVolumes->At(i));
01291          for (i=0; i<nvol; i++) fHashVolumes->AddLast(fVolumes->At(i));
01292       }
01293 
01294       if (fgVerboseLevel>0) Info("CloseGeometry","%i nodes/ %i volume UID's in %s", fNNodes, fUniqueVolumes->GetEntriesFast()-1, GetTitle());
01295       if (fgVerboseLevel>0) Info("CloseGeometry","----------------modeler ready----------------");
01296       fClosed = kTRUE;
01297       return;
01298    }
01299 
01300    SelectTrackingMedia();
01301    CheckGeometry();
01302    if (fgVerboseLevel>0) Info("CloseGeometry","Counting nodes...");
01303    fNNodes = CountNodes();
01304    fNLevel = fMasterVolume->CountNodes(1,3)+1;
01305    if (fNLevel<30) fNLevel = 100;
01306 
01307 //   BuildIdArray();
01308    Voxelize("ALL");
01309    if (fgVerboseLevel>0) Info("CloseGeometry","Building cache...");
01310    for (Int_t i=0; i<nnavigators; i++) {
01311       nav = (TGeoNavigator*)fNavigators->At(i);
01312       nav->BuildCache(dummy,nodeid);
01313    }
01314    fClosed = kTRUE;
01315    if (fgVerboseLevel>0) {
01316       Info("CloseGeometry","%i nodes/ %i volume UID's in %s", fNNodes, fUniqueVolumes->GetEntriesFast()-1, GetTitle());
01317       Info("CloseGeometry","----------------modeler ready----------------");
01318    }   
01319 }
01320 
01321 //_____________________________________________________________________________
01322 void TGeoManager::ClearOverlaps()
01323 {
01324 // Clear the list of overlaps.
01325    if (fOverlaps) {
01326       fOverlaps->Delete();
01327       delete fOverlaps;
01328    }
01329    fOverlaps = new TObjArray();
01330 }
01331 
01332 //_____________________________________________________________________________
01333 void TGeoManager::ClearShape(const TGeoShape *shape)
01334 {
01335 // Remove a shape from the list of shapes.
01336    if (fShapes->FindObject(shape)) fShapes->Remove((TGeoShape*)shape);
01337    delete shape;
01338 }
01339 //_____________________________________________________________________________
01340 void TGeoManager::CleanGarbage()
01341 {
01342 // Clean temporary volumes and shapes from garbage collection.
01343    if (!fGVolumes && !fGShapes) return;
01344    Int_t i,nentries;
01345    if (fGVolumes) {
01346       nentries = fGVolumes->GetEntries();
01347       TGeoVolume *vol = 0;
01348       for (i=0; i<nentries; i++) {
01349          vol=(TGeoVolume*)fGVolumes->At(i);
01350          if (vol) vol->SetFinder(0);
01351       }
01352       fGVolumes->Delete();
01353       delete fGVolumes;
01354       fGVolumes = 0;
01355    }
01356    if (fGShapes) {
01357       fGShapes->Delete();
01358       delete fGShapes;
01359       fGShapes = 0;
01360    }
01361 }
01362 
01363 //_____________________________________________________________________________
01364 void TGeoManager::CdNode(Int_t nodeid)
01365 {
01366 // Change current path to point to the node having this id.
01367 // Node id has to be in range : 0 to fNNodes-1 (no check for performance reasons)
01368    fCurrentNavigator->CdNode(nodeid);
01369 }
01370 
01371 //_____________________________________________________________________________
01372 Int_t TGeoManager::GetCurrentNodeId() const
01373 {
01374 // Get the unique ID of the current node.
01375    return fCurrentNavigator->GetCurrentNodeId();
01376 }
01377 
01378 //_____________________________________________________________________________
01379 void TGeoManager::CdTop()
01380 {
01381 // Make top level node the current node. Updates the cache accordingly.
01382 // Determine the overlapping state of current node.
01383    fCurrentNavigator->CdTop();
01384 }
01385 
01386 //_____________________________________________________________________________
01387 void TGeoManager::CdUp()
01388 {
01389 // Go one level up in geometry. Updates cache accordingly.
01390 // Determine the overlapping state of current node.
01391    fCurrentNavigator->CdUp();
01392 }
01393 //_____________________________________________________________________________
01394 void TGeoManager::CdDown(Int_t index)
01395 {
01396 // Make a daughter of current node current. Can be called only with a valid
01397 // daughter index (no check). Updates cache accordingly.
01398    fCurrentNavigator->CdDown(index);
01399 }
01400 
01401 //_____________________________________________________________________________
01402 void TGeoManager::CdNext()
01403 {
01404 // Do a cd to the node found next by FindNextBoundary
01405    fCurrentNavigator->CdNext();
01406 }
01407 
01408 //_____________________________________________________________________________
01409 Bool_t TGeoManager::cd(const char *path)
01410 {
01411 // Browse the tree of nodes starting from fTopNode according to pathname.
01412 // Changes the path accordingly.
01413    return fCurrentNavigator->cd(path);
01414 }
01415 
01416 //_____________________________________________________________________________
01417 Bool_t TGeoManager::CheckPath(const char *path) const
01418 {
01419 // Check if a geometry path is valid without changing the state of the current navigator.
01420    return fCurrentNavigator->CheckPath(path);
01421 }
01422 
01423 //_____________________________________________________________________________
01424 void TGeoManager::ConvertReflections()
01425 {
01426 // Convert all reflections in geometry to normal rotations + reflected shapes.
01427    if (!fTopNode) return;
01428    if (fgVerboseLevel>0) Info("ConvertReflections", "Converting reflections in: %s - %s ...", GetName(), GetTitle());
01429    TGeoIterator next(fTopVolume);
01430    TGeoNode *node;
01431    TGeoNodeMatrix *nodematrix;
01432    TGeoMatrix *matrix, *mclone;
01433    TGeoVolume *reflected;
01434    while ((node=next())) {
01435       matrix = node->GetMatrix();
01436       if (matrix->IsReflection()) {
01437 //         printf("%s before\n", node->GetName());
01438 //         matrix->Print();
01439          mclone = new TGeoCombiTrans(*matrix);
01440          mclone->RegisterYourself();
01441          // Reflect just the rotation component
01442          mclone->ReflectZ(kFALSE, kTRUE);
01443          nodematrix = (TGeoNodeMatrix*)node;
01444          nodematrix->SetMatrix(mclone);
01445 //         printf("%s after\n", node->GetName());
01446 //         node->GetMatrix()->Print();
01447          reflected = node->GetVolume()->MakeReflectedVolume();
01448          node->SetVolume(reflected);
01449       }
01450    }
01451    if (fgVerboseLevel>0) Info("ConvertReflections", "Done");
01452 }
01453 
01454 //_____________________________________________________________________________
01455 Int_t TGeoManager::CountNodes(const TGeoVolume *vol, Int_t nlevels, Int_t option)
01456 {
01457 // Count the total number of nodes starting from a volume, nlevels down.
01458    TGeoVolume *top;
01459    if (!vol) {
01460       top = fTopVolume;
01461    } else {
01462       top = (TGeoVolume*)vol;
01463    }
01464    Int_t count = top->CountNodes(nlevels, option);
01465    return count;
01466 }
01467 
01468 //_____________________________________________________________________________
01469 void TGeoManager::DefaultAngles()
01470 {
01471 // Set default angles for a given view.
01472    if (fPainter) fPainter->DefaultAngles();
01473 }
01474 
01475 //_____________________________________________________________________________
01476 void TGeoManager::DrawCurrentPoint(Int_t color)
01477 {
01478 // Draw current point in the same view.
01479    if (fPainter) fPainter->DrawCurrentPoint(color);
01480 }
01481 
01482 //_____________________________________________________________________________
01483 void TGeoManager::AnimateTracks(Double_t tmin, Double_t tmax, Int_t nframes, Option_t *option)
01484 {
01485 // Draw animation of tracks
01486    SetAnimateTracks();
01487    GetGeomPainter();
01488    if (tmin<0 || tmin>=tmax || nframes<1) return;
01489    Double_t *box = fPainter->GetViewBox();
01490    box[0] = box[1] = box[2] = 0;
01491    box[3] = box[4] = box[5] = 100;
01492    Double_t dt = (tmax-tmin)/Double_t(nframes);
01493    Double_t delt = 2E-9;
01494    Double_t t = tmin;
01495    Int_t i, j;
01496    TString opt(option);
01497    Bool_t save = kFALSE, geomanim=kFALSE;
01498    TString fname;
01499    if (opt.Contains("/S")) save = kTRUE;
01500 
01501    if (opt.Contains("/G")) geomanim = kTRUE;
01502    SetTminTmax(0,0);
01503    DrawTracks(opt.Data());
01504    Double_t start[6], end[6];
01505    Double_t dd[6] = {0,0,0,0,0,0};
01506    Double_t dlat=0, dlong=0, dpsi=0;
01507    if (geomanim) {
01508       fPainter->EstimateCameraMove(tmin+5*dt, tmin+15*dt, start, end);
01509       for (i=0; i<3; i++) {
01510          start[i+3] = 20 + 1.3*start[i+3];
01511          end[i+3] = 20 + 0.9*end[i+3];
01512       }
01513       for (i=0; i<6; i++) {
01514          dd[i] = (end[i]-start[i])/10.;
01515       }
01516       memcpy(box, start, 6*sizeof(Double_t));
01517       fPainter->GetViewAngles(dlong,dlat,dpsi);
01518       dlong = (-206-dlong)/Double_t(nframes);
01519       dlat  = (126-dlat)/Double_t(nframes);
01520       dpsi  = (75-dpsi)/Double_t(nframes);
01521       fPainter->GrabFocus();
01522    }
01523 
01524    for (i=0; i<nframes; i++) {
01525       if (t-delt<0) SetTminTmax(t-delt,t);
01526       else gGeoManager->SetTminTmax(t-delt,t);
01527       if (geomanim) {
01528          for (j=0; j<6; j++) box[j]+=dd[j];
01529          fPainter->GrabFocus(1,dlong,dlat,dpsi);
01530       } else {
01531          ModifiedPad();
01532       }
01533       if (save) {
01534          fname = TString::Format("anim%04d.gif", i);
01535          gPad->Print(fname);
01536       }
01537       t += dt;
01538    }
01539    SetAnimateTracks(kFALSE);
01540 }
01541 
01542 //_____________________________________________________________________________
01543 void TGeoManager::DrawTracks(Option_t *option)
01544 {
01545 // Draw tracks over the geometry, according to option. By default, only
01546 // primaries are drawn. See TGeoTrack::Draw() for additional options.
01547    TVirtualGeoTrack *track;
01548    //SetVisLevel(1);
01549    //SetVisOption(1);
01550    SetAnimateTracks();
01551    for (Int_t i=0; i<fNtracks; i++) {
01552       track = GetTrack(i);
01553       track->Draw(option);
01554    }
01555    SetAnimateTracks(kFALSE);
01556    ModifiedPad();
01557 }
01558 
01559 //_____________________________________________________________________________
01560 void TGeoManager::DrawPath(const char *path)
01561 {
01562 // Draw current path
01563    if (!fTopVolume) return;
01564    fTopVolume->SetVisBranch();
01565    GetGeomPainter()->DrawPath(path);
01566 }
01567 //_____________________________________________________________________________
01568 void TGeoManager::RandomPoints(const TGeoVolume *vol, Int_t npoints, Option_t *option)
01569 {
01570 // Draw random points in the bounding box of a volume.
01571    GetGeomPainter()->RandomPoints((TGeoVolume*)vol, npoints, option);
01572 }
01573 //_____________________________________________________________________________
01574 void TGeoManager::Test(Int_t npoints, Option_t *option)
01575 {
01576 // Check time of finding "Where am I" for n points.
01577    GetGeomPainter()->Test(npoints, option);
01578 }
01579 //_____________________________________________________________________________
01580 void TGeoManager::TestOverlaps(const char* path)
01581 {
01582 // Geometry overlap checker based on sampling.
01583    GetGeomPainter()->TestOverlaps(path);
01584 }
01585 //_____________________________________________________________________________
01586 void TGeoManager::GetBranchNames(Int_t *names) const
01587 {
01588 // Fill volume names of current branch into an array.
01589    fCurrentNavigator->GetBranchNames(names);
01590 }
01591 //_____________________________________________________________________________
01592 const char *TGeoManager::GetPdgName(Int_t pdg) const
01593 {
01594 // Get name for given pdg code;
01595    static char defaultname[5] = { "XXX" };
01596    if (!fPdgNames || !pdg) return defaultname;
01597    for (Int_t i=0; i<fNpdg; i++) {
01598       if (fPdgId[i]==pdg) return fPdgNames->At(i)->GetName();
01599    }
01600    return defaultname;
01601 }
01602 
01603 //_____________________________________________________________________________
01604 void TGeoManager::SetPdgName(Int_t pdg, const char *name)
01605 {
01606 // Set a name for a particle having a given pdg.
01607    if (!pdg) return;
01608    if (!fPdgNames) {
01609       fPdgNames = new TObjArray(256);
01610    }
01611    if (!strcmp(name, GetPdgName(pdg))) return;
01612    // store pdg name
01613    if (fNpdg>255) {
01614       Warning("SetPdgName", "No more than 256 different pdg codes allowed");
01615       return;
01616    }
01617    fPdgId[fNpdg] = pdg;
01618    TNamed *pdgname = new TNamed(name, "");
01619    fPdgNames->AddAtAndExpand(pdgname, fNpdg++);
01620 }
01621 
01622 //_____________________________________________________________________________
01623 void TGeoManager::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
01624 {
01625 // Fill node copy numbers of current branch into an array.
01626    fCurrentNavigator->GetBranchNumbers(copyNumbers, volumeNumbers);
01627 }
01628 
01629 //_____________________________________________________________________________
01630 void TGeoManager::GetBranchOnlys(Int_t *isonly) const
01631 {
01632 // Fill node copy numbers of current branch into an array.
01633    fCurrentNavigator->GetBranchOnlys(isonly);
01634 }
01635 
01636 //_____________________________________________________________________________
01637 void TGeoManager::GetBombFactors(Double_t &bombx, Double_t &bomby, Double_t &bombz, Double_t &bombr) const
01638 {
01639 // Retrieve cartesian and radial bomb factors.
01640    if (fPainter) {
01641       fPainter->GetBombFactors(bombx, bomby, bombz, bombr);
01642       return;
01643    }
01644    bombx = bomby = bombz = bombr = 1.3;
01645 }
01646 
01647 //_____________________________________________________________________________
01648 TGeoHMatrix *TGeoManager::GetHMatrix()
01649 {
01650 // Return stored current matrix (global matrix of the next touched node).
01651    if (!fCurrentNavigator) return NULL;
01652    return fCurrentNavigator->GetHMatrix();
01653 }
01654 
01655 //_____________________________________________________________________________
01656 Int_t TGeoManager::GetVisLevel() const
01657 {
01658 // Returns current depth to which geometry is drawn.
01659    return fVisLevel;
01660 }
01661 
01662 //_____________________________________________________________________________
01663 Int_t TGeoManager::GetVisOption() const
01664 {
01665 // Returns current depth to which geometry is drawn.
01666    return fVisOption;
01667 }
01668 
01669 //_____________________________________________________________________________
01670 Int_t TGeoManager::GetVirtualLevel()
01671 {
01672 // Find level of virtuality of current overlapping node (number of levels
01673 // up having the same tracking media.
01674 
01675    return fCurrentNavigator->GetVirtualLevel();
01676 }
01677 //_____________________________________________________________________________
01678 TVirtualGeoTrack *TGeoManager::FindTrackWithId(Int_t id) const
01679 {
01680 // Search the track hierarchy to find the track with the
01681 // given id
01682 //
01683 // if 'primsFirst' is true, then:
01684 // first tries TGeoManager::GetTrackOfId, then does a
01685 // recursive search if that fails. this would be faster
01686 // if the track is somehow known to be a primary
01687    TVirtualGeoTrack* trk = 0;
01688    trk = GetTrackOfId(id);
01689    if (trk) return trk;
01690    // need recursive search
01691    TIter next(fTracks);
01692    TVirtualGeoTrack* prim;
01693    while ((prim = (TVirtualGeoTrack*)next())) {
01694       trk = prim->FindTrackWithId(id);
01695       if (trk) return trk;
01696    }
01697    return NULL;
01698 }
01699 
01700 //_____________________________________________________________________________
01701 TVirtualGeoTrack *TGeoManager::GetTrackOfId(Int_t id) const
01702 {
01703 // Get track with a given ID.
01704    TVirtualGeoTrack *track;
01705    for (Int_t i=0; i<fNtracks; i++) {
01706       if ((track = (TVirtualGeoTrack *)fTracks->UncheckedAt(i))) {
01707          if (track->GetId() == id) return track;
01708       }
01709    }
01710    return 0;
01711 }
01712 
01713 //_____________________________________________________________________________
01714 TVirtualGeoTrack *TGeoManager::GetParentTrackOfId(Int_t id) const
01715 {
01716 // Get parent track with a given ID.
01717    TVirtualGeoTrack *track = fCurrentTrack;
01718    while ((track=track->GetMother())) {
01719       if (track->GetId()==id) return track;
01720    }
01721    return 0;
01722 }
01723 
01724 //_____________________________________________________________________________
01725 Int_t TGeoManager::GetTrackIndex(Int_t id) const
01726 {
01727 // Get index for track id, -1 if not found.
01728    TVirtualGeoTrack *track;
01729    for (Int_t i=0; i<fNtracks; i++) {
01730       if ((track = (TVirtualGeoTrack *)fTracks->UncheckedAt(i))) {
01731          if (track->GetId() == id) return i;
01732       }
01733    }
01734    return -1;
01735 }
01736 
01737 //_____________________________________________________________________________
01738 Bool_t TGeoManager::GotoSafeLevel()
01739 {
01740 // Go upwards the tree until a non-overlaping node
01741    return fCurrentNavigator->GotoSafeLevel();
01742 }
01743 
01744 //_____________________________________________________________________________
01745 Int_t TGeoManager::GetSafeLevel() const
01746 {
01747 // Go upwards the tree until a non-overlaping node
01748    return fCurrentNavigator->GetSafeLevel();
01749 }
01750 
01751 //_____________________________________________________________________________
01752 void TGeoManager::DefaultColors()
01753 {
01754 // Set default volume colors according to A of material
01755 
01756    const Int_t nmax = 110;
01757    Int_t col[nmax];
01758    for (Int_t i=0;i<nmax;i++) col[i] = kGray;
01759 
01760    //here we should create a new TColor with the same rgb as in the default
01761    //ROOT colors used below
01762    col[ 3] = kYellow-10;
01763    col[ 4] = col[ 5] = kGreen-10;
01764    col[ 6] = col[ 7] = kBlue-7;
01765    col[ 8] = col[ 9] = kMagenta-3;
01766    col[10] = col[11] = kRed-10;
01767    col[12] = kGray+1;
01768    col[13] = kBlue-10;
01769    col[14] = kOrange+7;
01770    col[16] = kYellow+1;
01771    col[20] = kYellow-10;
01772    col[24] = col[25] = col[26] = kBlue-8;
01773    col[29] = kOrange+9;
01774    col[79] = kOrange-2;
01775 
01776    TGeoVolume *vol;
01777    TIter next(fVolumes);
01778    while ((vol=(TGeoVolume*)next())) {
01779       TGeoMedium *med = vol->GetMedium();
01780       if (!med) continue;
01781       TGeoMaterial *mat = med->GetMaterial();
01782       Int_t matZ = (Int_t)mat->GetZ();
01783       vol->SetLineColor(col[matZ]);
01784       if (mat->GetDensity()<0.1) vol->SetTransparency(60);
01785    }
01786 }
01787 
01788 //_____________________________________________________________________________
01789 Double_t TGeoManager::Safety(Bool_t inside)
01790 {
01791 // Compute safe distance from the current point. This represent the distance
01792 // from POINT to the closest boundary.
01793 
01794    return fCurrentNavigator->Safety(inside);
01795 }
01796 
01797 //_____________________________________________________________________________
01798 void TGeoManager::SetVolumeAttribute(const char *name, const char *att, Int_t val)
01799 {
01800 // Set volume attributes in G3 style.
01801    TGeoVolume *volume;
01802    Bool_t all = kFALSE;
01803    if (strstr(name,"*")) all=kTRUE;
01804    Int_t ivo=0;
01805    TIter next(fVolumes);
01806    TString chatt = att;
01807    chatt.ToLower();
01808    while ((volume=(TGeoVolume*)next())) {
01809       if (strcmp(volume->GetName(), name) && !all) continue;
01810       ivo++;
01811       if (chatt.Contains("colo")) volume->SetLineColor(val);
01812       if (chatt.Contains("lsty")) volume->SetLineStyle(val);
01813       if (chatt.Contains("lwid")) volume->SetLineWidth(val);
01814       if (chatt.Contains("fill")) volume->SetFillColor(val);
01815       if (chatt.Contains("seen")) volume->SetVisibility(val);
01816    }
01817    TIter next1(fGVolumes);
01818    while ((volume=(TGeoVolume*)next1())) {
01819       if (strcmp(volume->GetName(), name) && !all) continue;
01820       ivo++;
01821       if (chatt.Contains("colo")) volume->SetLineColor(val);
01822       if (chatt.Contains("lsty")) volume->SetLineStyle(val);
01823       if (chatt.Contains("lwid")) volume->SetLineWidth(val);
01824       if (chatt.Contains("fill")) volume->SetFillColor(val);
01825       if (chatt.Contains("seen")) volume->SetVisibility(val);
01826    }
01827    if (!ivo) {
01828       Warning("SetVolumeAttribute","volume: %s does not exist",name);
01829    }
01830 }
01831 //_____________________________________________________________________________
01832 void TGeoManager::SetBombFactors(Double_t bombx, Double_t bomby, Double_t bombz, Double_t bombr)
01833 {
01834 // Set factors that will "bomb" all translations in cartesian and cylindrical coordinates.
01835    if (fPainter) fPainter->SetBombFactors(bombx, bomby, bombz, bombr);
01836 }
01837 
01838 //_____________________________________________________________________________
01839 void TGeoManager::SetClippingShape(TGeoShape *shape)
01840 {
01841 // Set a user-defined shape as clipping for ray tracing.
01842    TVirtualGeoPainter *painter = GetGeomPainter();
01843    if (shape) {
01844       if (fClippingShape && (fClippingShape!=shape)) ClearShape(fClippingShape);
01845       fClippingShape = shape;
01846    }
01847    painter->SetClippingShape(shape);
01848 }
01849 
01850 //_____________________________________________________________________________
01851 void TGeoManager::SetMaxVisNodes(Int_t maxnodes) {
01852 // set the maximum number of visible nodes.
01853    fMaxVisNodes = maxnodes;
01854    if (maxnodes>0 && fgVerboseLevel>0)
01855       Info("SetMaxVisNodes","Automatic visible depth for %d visible nodes", maxnodes);
01856    if (!fPainter) return;
01857    fPainter->CountVisibleNodes();
01858    Int_t level = fPainter->GetVisLevel();
01859    if (level != fVisLevel) fVisLevel = level;
01860 }
01861 
01862 //_____________________________________________________________________________
01863 void TGeoManager::SetTopVisible(Bool_t vis) {
01864 // make top volume visible on screen
01865    GetGeomPainter();
01866    fPainter->SetTopVisible(vis);
01867 }
01868 
01869 //_____________________________________________________________________________
01870 void TGeoManager::SetCheckedNode(TGeoNode *node) {
01871 // Assign a given node to be checked for ovelaps. Any other overlaps will be ignored.
01872    GetGeomPainter()->SetCheckedNode(node);
01873 }   
01874 //_____________________________________________________________________________
01875 void TGeoManager::SetNmeshPoints(Int_t npoints)
01876 {
01877 // Set the number of points to be generated on the shape outline when checking
01878 // for overlaps.
01879    GetGeomPainter()->SetNmeshPoints(npoints);
01880 }
01881    
01882 //_____________________________________________________________________________
01883 void TGeoManager::SetVisOption(Int_t option) {
01884 // set drawing mode :
01885 // option=0 (default) all nodes drawn down to vislevel
01886 // option=1           leaves and nodes at vislevel drawn
01887 // option=2           path is drawn
01888 // option=4           visibility changed
01889    if ((option>=0) && (option<3)) fVisOption=option;
01890    if (fPainter) fPainter->SetVisOption(option);
01891 }
01892 
01893 //_____________________________________________________________________________
01894 void TGeoManager::ViewLeaves(Bool_t flag)
01895 {
01896 // Set visualization option (leaves only OR all volumes)
01897    if (flag) SetVisOption(1);
01898    else      SetVisOption(0);
01899 }
01900 
01901 //_____________________________________________________________________________
01902 void TGeoManager::SetVisDensity(Double_t density)
01903 {
01904 // Set density threshold. Volumes with densities lower than this become
01905 // transparent.
01906    fVisDensity = density;
01907    if (fPainter) fPainter->ModifiedPad();
01908 }
01909 
01910 //_____________________________________________________________________________
01911 void TGeoManager::SetVisLevel(Int_t level) {
01912 // set default level down to which visualization is performed
01913    if (level>0) {
01914       fVisLevel = level;
01915       fMaxVisNodes = 0;
01916       if (fgVerboseLevel>0)
01917          Info("SetVisLevel","Automatic visible depth disabled");
01918       if (fPainter) fPainter->CountVisibleNodes();
01919    } else {
01920       SetMaxVisNodes();
01921    }
01922 }
01923 
01924 //_____________________________________________________________________________
01925 void TGeoManager::SortOverlaps()
01926 {
01927 // Sort overlaps by decreasing overlap distance. Extrusions comes first.
01928    fOverlaps->Sort();
01929 }
01930 
01931 //_____________________________________________________________________________
01932 void TGeoManager::OptimizeVoxels(const char *filename)
01933 {
01934 // Optimize voxelization type for all volumes. Save best choice in a macro.
01935    if (!fTopNode) {
01936       Error("OptimizeVoxels","Geometry must be closed first");
01937       return;
01938    }
01939    ofstream out;
01940    TString fname = filename;
01941    if (fname.IsNull()) fname = "tgeovox.C";
01942    out.open(fname, ios::out);
01943    if (!out.good()) {
01944       Error("OptimizeVoxels", "cannot open file");
01945       return;
01946    }
01947    // write header
01948    TDatime t;
01949    TString sname(fname);
01950    sname.ReplaceAll(".C", "");
01951    out << sname.Data()<<"()"<<endl;
01952    out << "{" << endl;
01953    out << "//=== Macro generated by ROOT version "<< gROOT->GetVersion()<<" : "<<t.AsString()<<endl;
01954    out << "//=== Voxel optimization for " << GetTitle() << " geometry"<<endl;
01955    out << "//===== <run this macro JUST BEFORE closing the geometry>"<<endl;
01956    out << "   TGeoVolume *vol = 0;"<<endl;
01957    out << "   // parse all voxelized volumes"<<endl;
01958    TGeoVolume *vol = 0;
01959    Bool_t cyltype;
01960    TIter next(fVolumes);
01961    while ((vol=(TGeoVolume*)next())) {
01962       if (!vol->GetVoxels()) continue;
01963       out<<"   vol = gGeoManager->GetVolume(\""<<vol->GetName()<<"\");"<<endl;
01964       cyltype = vol->OptimizeVoxels();
01965       if (cyltype) {
01966          out<<"   vol->SetCylVoxels();"<<endl;
01967       } else {
01968          out<<"   vol->SetCylVoxels(kFALSE);"<<endl;
01969       }
01970    }
01971    out << "}" << endl;
01972    out.close();
01973 }
01974 //_____________________________________________________________________________
01975 Int_t TGeoManager::Parse(const char *expr, TString &expr1, TString &expr2, TString &expr3)
01976 {
01977 // Parse a string boolean expression and do a syntax check. Find top
01978 // level boolean operator and returns its type. Fill the two
01979 // substrings to which this operator applies. The returned integer is :
01980 // -1 : parse error
01981 //  0 : no boolean operator
01982 //  1 : union - represented as '+' in expression
01983 //  2 : difference (subtraction) - represented as '-' in expression
01984 //  3 : intersection - represented as '*' in expression.
01985 // Paranthesys should be used to avoid ambiguites. For instance :
01986 //    A+B-C will be interpreted as (A+B)-C which is not the same as A+(B-C)
01987    // eliminate not needed paranthesys
01988    TString startstr(expr);
01989    Int_t len = startstr.Length();
01990    Int_t i;
01991    TString e0 = "";
01992    expr3 = "";
01993    // eliminate blanks
01994    for (i=0; i< len; i++) {
01995       if (startstr(i)==' ') continue;
01996       e0 += startstr(i, 1);
01997    }
01998    Int_t level = 0;
01999    Int_t levmin = 999;
02000    Int_t boolop = 0;
02001    Int_t indop = 0;
02002    Int_t iloop = 1;
02003    Int_t lastop = 0;
02004    Int_t lastdp = 0;
02005    Int_t lastpp = 0;
02006    Bool_t foundmat = kFALSE;
02007    // check/eliminate paranthesys
02008    while (iloop==1) {
02009       iloop = 0;
02010       lastop = 0;
02011       lastdp = 0;
02012       lastpp = 0;
02013       len = e0.Length();
02014       for (i=0; i<len; i++) {
02015          if (e0(i)=='(') {
02016             if (!level) iloop++;
02017             level++;
02018             continue;
02019          }
02020          if  (e0(i)==')') {
02021             level--;
02022             if (level==0) lastpp=i;
02023             continue;
02024          }
02025          if ((e0(i)=='+') || (e0(i)=='-') || (e0(i)=='*')) {
02026             lastop = i;
02027             if (level<levmin) {
02028                levmin = level;
02029                indop = i;
02030             }
02031             continue;
02032          }
02033          if  ((e0(i)==':') && (level==0)) {
02034             lastdp = i;
02035             continue;
02036          }
02037       }
02038       if (level!=0) {
02039          if (gGeoManager) gGeoManager->Error("Parse","paranthesys does not match");
02040          return -1;
02041       }
02042       if (iloop==1 && (e0(0)=='(') && (e0(len-1)==')')) {
02043          // eliminate extra paranthesys
02044          e0=e0(1, len-2);
02045          continue;
02046       }
02047       if (foundmat) break;
02048       if (((lastop==0) && (lastdp>0)) || ((lastpp>0) && (lastdp>lastpp) && (indop<lastpp))) {
02049          expr3 = e0(lastdp+1, len-lastdp);
02050          e0=e0(0, lastdp);
02051          foundmat = kTRUE;
02052          iloop = 1;
02053          continue;
02054       } else break;
02055    }
02056    // loop expression and search paranthesys/operators
02057    levmin = 999;
02058    for (i=0; i<len; i++) {
02059       if (e0(i)=='(') {
02060          level++;
02061          continue;
02062       }
02063       if  (e0(i)==')') {
02064          level--;
02065          continue;
02066       }
02067       // Take LAST operator at lowest level (revision 28/07/08)
02068       if (level<=levmin) {
02069          if (e0(i)=='+') {
02070             boolop = 1; // union
02071             levmin = level;
02072             indop = i;
02073          }
02074          if (e0(i)=='-') {
02075             boolop = 2; // difference
02076             levmin = level;
02077             indop = i;
02078          }
02079          if (e0(i)=='*') {
02080             boolop = 3; // intersection
02081             levmin = level;
02082             indop = i;
02083          }
02084       }
02085    }
02086    if (indop==0) {
02087       expr1=e0;
02088       return indop;
02089    }
02090    expr1 = e0(0, indop);
02091    expr2 = e0(indop+1, len-indop);
02092    return boolop;
02093 }
02094 
02095 
02096 //_____________________________________________________________________________
02097 void TGeoManager::SaveAttributes(const char *filename)
02098 {
02099 // Save current attributes in a macro
02100    if (!fTopNode) {
02101       Error("SaveAttributes","geometry must be closed first\n");
02102       return;
02103    }
02104    ofstream out;
02105    TString fname(filename);
02106    if (fname.IsNull()) fname = "tgeoatt.C";
02107    out.open(fname, ios::out);
02108    if (!out.good()) {
02109       Error("SaveAttributes", "cannot open file");
02110       return;
02111    }
02112    // write header
02113    TDatime t;
02114    TString sname(fname);
02115    sname.ReplaceAll(".C", "");
02116    out << sname.Data()<<"()"<<endl;
02117    out << "{" << endl;
02118    out << "//=== Macro generated by ROOT version "<< gROOT->GetVersion()<<" : "<<t.AsString()<<endl;
02119    out << "//=== Attributes for " << GetTitle() << " geometry"<<endl;
02120    out << "//===== <run this macro AFTER loading the geometry in memory>"<<endl;
02121    // save current top volume
02122    out << "   TGeoVolume *top = gGeoManager->GetVolume(\""<<fTopVolume->GetName()<<"\");"<<endl;
02123    out << "   TGeoVolume *vol = 0;"<<endl;
02124    out << "   TGeoNode *node = 0;"<<endl;
02125    out << "   // clear all volume attributes and get painter"<<endl;
02126    out << "   gGeoManager->ClearAttributes();"<<endl;
02127    out << "   gGeoManager->GetGeomPainter();"<<endl;
02128    out << "   // set visualization modes and bomb factors"<<endl;
02129    out << "   gGeoManager->SetVisOption("<<GetVisOption()<<");"<<endl;
02130    out << "   gGeoManager->SetVisLevel("<<GetVisLevel()<<");"<<endl;
02131    out << "   gGeoManager->SetExplodedView("<<GetBombMode()<<");"<<endl;
02132    Double_t bombx, bomby, bombz, bombr;
02133    GetBombFactors(bombx, bomby, bombz, bombr);
02134    out << "   gGeoManager->SetBombFactors("<<bombx<<","<<bomby<<","<<bombz<<","<<bombr<<");"<<endl;
02135    out << "   // iterate volumes coontainer and set new attributes"<<endl;
02136 //   out << "   TIter next(gGeoManager->GetListOfVolumes());"<<endl;
02137    TGeoVolume *vol = 0;
02138    fTopNode->SaveAttributes(out);
02139 
02140    TIter next(fVolumes);
02141    while ((vol=(TGeoVolume*)next())) {
02142       vol->SetVisStreamed(kFALSE);
02143    }
02144    out << "   // draw top volume with new settings"<<endl;
02145    out << "   top->Draw();"<<endl;
02146    out << "   gPad->x3d();"<<endl;
02147    out << "}" << endl;
02148    out.close();
02149 }
02150 //_____________________________________________________________________________
02151 TGeoNode *TGeoManager::SearchNode(Bool_t downwards, const TGeoNode *skipnode)
02152 {
02153 // Returns the deepest node containing fPoint, which must be set a priori.
02154 
02155    return fCurrentNavigator->SearchNode(downwards, skipnode);
02156 }
02157 
02158 //_____________________________________________________________________________
02159 TGeoNode *TGeoManager::CrossBoundaryAndLocate(Bool_t downwards, TGeoNode *skipnode)
02160 {
02161 // Cross next boundary and locate within current node
02162 // The current point must be on the boundary of fCurrentNode.
02163    return fCurrentNavigator->CrossBoundaryAndLocate(downwards, skipnode);
02164 }
02165 
02166 //_____________________________________________________________________________
02167 TGeoNode *TGeoManager::FindNextBoundaryAndStep(Double_t stepmax, Bool_t compsafe)
02168 {
02169 // Compute distance to next boundary within STEPMAX. If no boundary is found,
02170 // propagate current point along current direction with fStep=STEPMAX. Otherwise
02171 // propagate with fStep=SNEXT (distance to boundary) and locate/return the next
02172 // node.
02173 
02174    return fCurrentNavigator->FindNextBoundaryAndStep(stepmax, compsafe);
02175 }
02176 
02177 //_____________________________________________________________________________
02178 TGeoNode *TGeoManager::FindNextBoundary(Double_t stepmax, const char *path, Bool_t frombdr)
02179 {
02180 // Find distance to next boundary and store it in fStep. Returns node to which this
02181 // boundary belongs. If PATH is specified, compute only distance to the node to which
02182 // PATH points. If STEPMAX is specified, compute distance only in case fSafety is smaller
02183 // than this value. STEPMAX represent the step to be made imposed by other reasons than
02184 // geometry (usually physics processes). Therefore in this case this method provides the
02185 // answer to the question : "Is STEPMAX a safe step ?" returning a NULL node and filling
02186 // fStep with a big number.
02187 // In case frombdr=kTRUE, the isotropic safety is set to zero.
02188 // Note : safety distance for the current point is computed ONLY in case STEPMAX is
02189 //        specified, otherwise users have to call explicitly TGeoManager::Safety() if
02190 //        they want this computed for the current point.
02191 
02192    // convert current point and direction to local reference
02193    return fCurrentNavigator->FindNextBoundary(stepmax,path, frombdr);
02194 }
02195 
02196 //_____________________________________________________________________________
02197 TGeoNode *TGeoManager::FindNextDaughterBoundary(Double_t *point, Double_t *dir, Int_t &idaughter, Bool_t compmatrix)
02198 {
02199 // Computes as fStep the distance to next daughter of the current volume.
02200 // The point and direction must be converted in the coordinate system of the current volume.
02201 // The proposed step limit is fStep.
02202 
02203    return fCurrentNavigator->FindNextDaughterBoundary(point, dir, idaughter, compmatrix);
02204 }
02205 
02206 //_____________________________________________________________________________
02207 void TGeoManager::ResetState()
02208 {
02209 // Reset current state flags.
02210    fCurrentNavigator->ResetState();
02211 }
02212 
02213 //_____________________________________________________________________________
02214 TGeoNode *TGeoManager::FindNode(Bool_t safe_start)
02215 {
02216 // Returns deepest node containing current point.
02217    return fCurrentNavigator->FindNode(safe_start);
02218 }
02219 
02220 //_____________________________________________________________________________
02221 TGeoNode *TGeoManager::FindNode(Double_t x, Double_t y, Double_t z)
02222 {
02223 // Returns deepest node containing current point.
02224    return fCurrentNavigator->FindNode(x, y, z);
02225 }
02226 
02227 //_____________________________________________________________________________
02228 Double_t *TGeoManager::FindNormalFast()
02229 {
02230 // Computes fast normal to next crossed boundary, assuming that the current point
02231 // is close enough to the boundary. Works only after calling FindNextBoundary.
02232    return fCurrentNavigator->FindNormalFast();
02233 }
02234 
02235 //_____________________________________________________________________________
02236 Double_t *TGeoManager::FindNormal(Bool_t forward)
02237 {
02238 // Computes normal vector to the next surface that will be or was already
02239 // crossed when propagating on a straight line from a given point/direction.
02240 // Returns the normal vector cosines in the MASTER coordinate system. The dot
02241 // product of the normal and the current direction is positive defined.
02242    return fCurrentNavigator->FindNormal(forward);
02243 }
02244 
02245 //_____________________________________________________________________________
02246 Bool_t TGeoManager::IsSameLocation(Double_t x, Double_t y, Double_t z, Bool_t change)
02247 {
02248 // Checks if point (x,y,z) is still in the current node.
02249    return fCurrentNavigator->IsSameLocation(x,y,z,change);
02250 }
02251 
02252 //_____________________________________________________________________________
02253 Bool_t TGeoManager::IsSamePoint(Double_t x, Double_t y, Double_t z) const
02254 {
02255 // Check if a new point with given coordinates is the same as the last located one.
02256    return fCurrentNavigator->IsSamePoint(x,y,z);
02257 }
02258 
02259 //_____________________________________________________________________________
02260 Bool_t TGeoManager::IsInPhiRange() const
02261 {
02262 // True if current node is in phi range
02263    if (!fPhiCut) return kTRUE;
02264    const Double_t *origin;
02265    if (!fCurrentNavigator || !fCurrentNavigator->GetCurrentNode()) return kFALSE;
02266    origin = ((TGeoBBox*)fCurrentNavigator->GetCurrentVolume()->GetShape())->GetOrigin();
02267    Double_t point[3];
02268    LocalToMaster(origin, &point[0]);
02269    Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
02270    if (phi<0) phi+=360.;
02271    if ((phi>=fPhimin) && (phi<=fPhimax)) return kFALSE;
02272    return kTRUE;
02273 }
02274 
02275 //_____________________________________________________________________________
02276 TGeoNode *TGeoManager::InitTrack(const Double_t *point, const Double_t *dir)
02277 {
02278 // Initialize current point and current direction vector (normalized)
02279 // in MARS. Return corresponding node.
02280    return fCurrentNavigator->InitTrack(point, dir);
02281 }
02282 
02283 //_____________________________________________________________________________
02284 TGeoNode *TGeoManager::InitTrack(Double_t x, Double_t y, Double_t z, Double_t nx, Double_t ny, Double_t nz)
02285 {
02286 // Initialize current point and current direction vector (normalized)
02287 // in MARS. Return corresponding node.
02288    return fCurrentNavigator->InitTrack(x,y,z,nx,ny,nz);
02289 }
02290 
02291 //_____________________________________________________________________________
02292 void TGeoManager::InspectState() const
02293 {
02294 // Inspects path and all flags for the current state.
02295    fCurrentNavigator->InspectState();
02296 }
02297 
02298 //_____________________________________________________________________________
02299 const char *TGeoManager::GetPath() const
02300 {
02301 // Get path to the current node in the form /node0/node1/...
02302    return fCurrentNavigator->GetPath();
02303 }
02304 
02305 //_____________________________________________________________________________
02306 Int_t TGeoManager::GetByteCount(Option_t * /*option*/)
02307 {
02308 // Get total size of geometry in bytes.
02309    Int_t count = 0;
02310    TIter next(fVolumes);
02311    TGeoVolume *vol;
02312    while ((vol=(TGeoVolume*)next())) count += vol->GetByteCount();
02313    TIter next1(fMatrices);
02314    TGeoMatrix *matrix;
02315    while ((matrix=(TGeoMatrix*)next1())) count += matrix->GetByteCount();
02316    TIter next2(fMaterials);
02317    TGeoMaterial *mat;
02318    while ((mat=(TGeoMaterial*)next2())) count += mat->GetByteCount();
02319    TIter next3(fMedia);
02320    TGeoMedium *med;
02321    while ((med=(TGeoMedium*)next3())) count += med->GetByteCount();
02322    if (fgVerboseLevel>0) Info("GetByteCount","Total size of logical tree : %i bytes", count);
02323    return count;
02324 }
02325 //_____________________________________________________________________________
02326 TVirtualGeoPainter *TGeoManager::GetGeomPainter()
02327 {
02328 // Make a default painter if none present. Returns pointer to it.
02329    if (!fPainter) {
02330       TPluginHandler *h;
02331       if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualGeoPainter"))) {
02332          if (h->LoadPlugin() == -1)
02333             return 0;
02334          fPainter = (TVirtualGeoPainter*)h->ExecPlugin(1,this);
02335          if (!fPainter) {
02336             Error("GetGeomPainter", "could not create painter");
02337             return 0;
02338          }
02339       }
02340    }
02341    return fPainter;
02342 }
02343 //_____________________________________________________________________________
02344 TGeoVolume *TGeoManager::GetVolume(const char *name) const
02345 {
02346 // Search for a named volume. All trailing blanks stripped.
02347    TString sname = name;
02348    sname = sname.Strip();
02349    TGeoVolume *vol = (TGeoVolume*)fVolumes->FindObject(sname.Data());
02350    return vol;
02351 }
02352 
02353 //_____________________________________________________________________________
02354 TGeoVolume *TGeoManager::FindVolumeFast(const char *name, Bool_t multi)
02355 {
02356 // Fast search for a named volume. All trailing blanks stripped.
02357    if (!fHashVolumes) {
02358       Int_t nvol = fVolumes->GetEntriesFast();
02359       Int_t ngvol = fGVolumes->GetEntriesFast();
02360       fHashVolumes = new THashList(nvol+1);
02361       fHashGVolumes = new THashList(ngvol+1);
02362       Int_t i;
02363       for (i=0; i<ngvol; i++) fHashGVolumes->AddLast(fGVolumes->At(i));
02364       for (i=0; i<nvol; i++) fHashVolumes->AddLast(fVolumes->At(i));
02365    }
02366    TString sname = name;
02367    sname = sname.Strip();
02368    THashList *list = fHashVolumes;
02369    if (multi) list = fHashGVolumes;
02370    TGeoVolume *vol = (TGeoVolume*)list->FindObject(sname.Data());
02371    return vol;
02372 }
02373 
02374 //_____________________________________________________________________________
02375 Int_t TGeoManager::GetUID(const char *volname) const
02376 {
02377 // Retreive unique id for a volume name. Return -1 if name not found.
02378    TGeoManager *geom = (TGeoManager*)this;
02379    TGeoVolume *vol = geom->FindVolumeFast(volname, kFALSE);
02380    if (!vol) vol = geom->FindVolumeFast(volname, kTRUE);
02381    if (!vol) return -1;
02382    return vol->GetNumber();
02383 }
02384 
02385 //_____________________________________________________________________________
02386 TGeoMaterial *TGeoManager::FindDuplicateMaterial(const TGeoMaterial *mat) const
02387 {
02388 // Find if a given material duplicates an existing one.
02389    Int_t index = fMaterials->IndexOf(mat);
02390    if (index <= 0) return 0;
02391    TGeoMaterial *other;
02392    for (Int_t i=0; i<index; i++) {
02393       other = (TGeoMaterial*)fMaterials->At(i);
02394       if (other == mat) continue;
02395       if (other->IsEq(mat)) return other;
02396    }
02397    return 0;
02398 }
02399 
02400 //_____________________________________________________________________________
02401 TGeoMaterial *TGeoManager::GetMaterial(const char *matname) const
02402 {
02403 // Search for a named material. All trailing blanks stripped.
02404    TString sname = matname;
02405    sname = sname.Strip();
02406    TGeoMaterial *mat = (TGeoMaterial*)fMaterials->FindObject(sname.Data());
02407    return mat;
02408 }
02409 
02410 //_____________________________________________________________________________
02411 TGeoMedium *TGeoManager::GetMedium(const char *medium) const
02412 {
02413 // Search for a named tracking medium. All trailing blanks stripped.
02414    TString sname = medium;
02415    sname = sname.Strip();
02416    TGeoMedium *med = (TGeoMedium*)fMedia->FindObject(sname.Data());
02417    return med;
02418 }
02419 
02420 //_____________________________________________________________________________
02421 TGeoMedium *TGeoManager::GetMedium(Int_t numed) const
02422 {
02423 // Search for a tracking medium with a given ID.
02424    TIter next(fMedia);
02425    TGeoMedium *med;
02426    while ((med=(TGeoMedium*)next())) {
02427       if (med->GetId()==numed) return med;
02428    }
02429    return 0;
02430 }
02431 
02432 //_____________________________________________________________________________
02433 TGeoMaterial *TGeoManager::GetMaterial(Int_t id) const
02434 {
02435 // Return material at position id.
02436    if (id<0 || id >= fMaterials->GetSize()) return 0;
02437    TGeoMaterial *mat = (TGeoMaterial*)fMaterials->At(id);
02438    return mat;
02439 }
02440 //_____________________________________________________________________________
02441 Int_t TGeoManager::GetMaterialIndex(const char *matname) const
02442 {
02443 // Return index of named material.
02444    TIter next(fMaterials);
02445    TGeoMaterial *mat;
02446    Int_t id = 0;
02447    TString sname = matname;
02448    sname = sname.Strip();
02449    while ((mat = (TGeoMaterial*)next())) {
02450       if (!strcmp(mat->GetName(),sname.Data()))
02451          return id;
02452       id++;
02453    }
02454    return -1;  // fail
02455 }
02456 //_____________________________________________________________________________
02457 void TGeoManager::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
02458 {
02459 // Randomly shoot nrays and plot intersections with surfaces for current
02460 // top node.
02461    GetGeomPainter()->RandomRays(nrays, startx, starty, startz);
02462 }
02463 
02464 //_____________________________________________________________________________
02465 void TGeoManager::RemoveMaterial(Int_t index)
02466 {
02467 // Remove material at given index.
02468    TObject *obj = fMaterials->At(index);
02469    if (obj) fMaterials->Remove(obj);
02470 }
02471 
02472 //_____________________________________________________________________________
02473 void TGeoManager::ResetUserData()
02474 {
02475 // Sets all pointers TGeoVolume::fField to NULL. User data becomes decoupled
02476 // from geometry. Deletion has to be managed by users.
02477    TIter next(fVolumes);
02478    TGeoVolume *vol;
02479    while ((vol=(TGeoVolume*)next())) vol->SetField(0);
02480 }
02481 
02482 //_____________________________________________________________________________
02483 void TGeoManager::RestoreMasterVolume()
02484 {
02485 // Restore the master volume of the geometry.
02486    if (fTopVolume == fMasterVolume) return;
02487    if (fMasterVolume) SetTopVolume(fMasterVolume);
02488 }
02489 //_____________________________________________________________________________
02490 void TGeoManager::Voxelize(Option_t *option)
02491 {
02492 // Voxelize all non-divided volumes.
02493    TGeoVolume *vol;
02494    TGeoVoxelFinder *vox = 0;
02495    if (!fStreamVoxels && fgVerboseLevel>0) Info("Voxelize","Voxelizing...");
02496 //   Int_t nentries = fVolumes->GetSize();
02497    TIter next(fVolumes);
02498    while ((vol = (TGeoVolume*)next())) {
02499       if (!fIsGeomReading) vol->SortNodes();
02500       if (!fStreamVoxels) {
02501          vol->Voxelize(option);
02502       } else {
02503          vox = vol->GetVoxels();
02504          if (vox) vox->CreateCheckList();
02505       }
02506       if (!fIsGeomReading) vol->FindOverlaps();
02507    }
02508 }
02509 //_____________________________________________________________________________
02510 void TGeoManager::ModifiedPad() const
02511 {
02512 // Send "Modified" signal to painter.
02513    if (!fPainter) return;
02514    fPainter->ModifiedPad();
02515 }
02516 //_____________________________________________________________________________
02517 TGeoVolume *TGeoManager::MakeArb8(const char *name, TGeoMedium *medium,
02518                                   Double_t dz, Double_t *vertices)
02519 {
02520 // Make an TGeoArb8 volume.
02521    return TGeoBuilder::Instance(this)->MakeArb8(name, medium, dz, vertices);
02522 }
02523 
02524 //_____________________________________________________________________________
02525 TGeoVolume *TGeoManager::MakeBox(const char *name, TGeoMedium *medium,
02526                                     Double_t dx, Double_t dy, Double_t dz)
02527 {
02528 // Make in one step a volume pointing to a box shape with given medium.
02529    return TGeoBuilder::Instance(this)->MakeBox(name, medium, dx, dy, dz);
02530 }
02531 
02532 //_____________________________________________________________________________
02533 TGeoVolume *TGeoManager::MakePara(const char *name, TGeoMedium *medium,
02534                                     Double_t dx, Double_t dy, Double_t dz,
02535                                     Double_t alpha, Double_t theta, Double_t phi)
02536 {
02537 // Make in one step a volume pointing to a paralelipiped shape with given medium.
02538    return TGeoBuilder::Instance(this)->MakePara(name, medium, dx, dy, dz, alpha, theta, phi);
02539 }
02540 
02541 //_____________________________________________________________________________
02542 TGeoVolume *TGeoManager::MakeSphere(const char *name, TGeoMedium *medium,
02543                                     Double_t rmin, Double_t rmax, Double_t themin, Double_t themax,
02544                                     Double_t phimin, Double_t phimax)
02545 {
02546 // Make in one step a volume pointing to a sphere shape with given medium
02547    return TGeoBuilder::Instance(this)->MakeSphere(name, medium, rmin, rmax, themin, themax, phimin, phimax);
02548 }
02549 
02550 //_____________________________________________________________________________
02551 TGeoVolume *TGeoManager::MakeTorus(const char *name, TGeoMedium *medium, Double_t r,
02552                                    Double_t rmin, Double_t rmax, Double_t phi1, Double_t dphi)
02553 {
02554 // Make in one step a volume pointing to a torus shape with given medium.
02555    return TGeoBuilder::Instance(this)->MakeTorus(name, medium, r, rmin, rmax, phi1, dphi);
02556 }
02557 
02558 //_____________________________________________________________________________
02559 TGeoVolume *TGeoManager::MakeTube(const char *name, TGeoMedium *medium,
02560                                      Double_t rmin, Double_t rmax, Double_t dz)
02561 {
02562 // Make in one step a volume pointing to a tube shape with given medium.
02563    return TGeoBuilder::Instance(this)->MakeTube(name, medium, rmin, rmax, dz);
02564 }
02565 
02566 //_____________________________________________________________________________
02567 TGeoVolume *TGeoManager::MakeTubs(const char *name, TGeoMedium *medium,
02568                                      Double_t rmin, Double_t rmax, Double_t dz,
02569                                      Double_t phi1, Double_t phi2)
02570 {
02571 // Make in one step a volume pointing to a tube segment shape with given medium.
02572    return TGeoBuilder::Instance(this)->MakeTubs(name, medium, rmin, rmax, dz, phi1, phi2);
02573 }
02574 
02575 //_____________________________________________________________________________
02576 TGeoVolume *TGeoManager::MakeEltu(const char *name, TGeoMedium *medium,
02577                                      Double_t a, Double_t b, Double_t dz)
02578 {
02579 // Make in one step a volume pointing to a tube shape with given medium
02580    return TGeoBuilder::Instance(this)->MakeEltu(name, medium, a, b, dz);
02581 }
02582 
02583 //_____________________________________________________________________________
02584 TGeoVolume *TGeoManager::MakeHype(const char *name, TGeoMedium *medium,
02585                                         Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
02586 {
02587 // Make in one step a volume pointing to a tube shape with given medium
02588    return TGeoBuilder::Instance(this)->MakeHype(name, medium, rin, stin, rout, stout, dz);
02589 }
02590 
02591 //_____________________________________________________________________________
02592 TGeoVolume *TGeoManager::MakeParaboloid(const char *name, TGeoMedium *medium,
02593                                         Double_t rlo, Double_t rhi, Double_t dz)
02594 {
02595 // Make in one step a volume pointing to a tube shape with given medium
02596    return TGeoBuilder::Instance(this)->MakeParaboloid(name, medium, rlo, rhi, dz);
02597 }
02598 
02599 //_____________________________________________________________________________
02600 TGeoVolume *TGeoManager::MakeCtub(const char *name, TGeoMedium *medium,
02601                                      Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
02602                                      Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
02603 {
02604 // Make in one step a volume pointing to a tube segment shape with given medium
02605    return TGeoBuilder::Instance(this)->MakeCtub(name, medium, rmin, rmax, dz, phi1, phi2, lx, ly, lz, tx, ty, tz);
02606 }
02607 
02608 //_____________________________________________________________________________
02609 TGeoVolume *TGeoManager::MakeCone(const char *name, TGeoMedium *medium,
02610                                      Double_t dz, Double_t rmin1, Double_t rmax1,
02611                                      Double_t rmin2, Double_t rmax2)
02612 {
02613 // Make in one step a volume pointing to a cone shape with given medium.
02614    return TGeoBuilder::Instance(this)->MakeCone(name, medium, dz, rmin1, rmax1, rmin2, rmax2);
02615 }
02616 
02617 //_____________________________________________________________________________
02618 TGeoVolume *TGeoManager::MakeCons(const char *name, TGeoMedium *medium,
02619                                      Double_t dz, Double_t rmin1, Double_t rmax1,
02620                                      Double_t rmin2, Double_t rmax2,
02621                                      Double_t phi1, Double_t phi2)
02622 {
02623 // Make in one step a volume pointing to a cone segment shape with given medium
02624    return TGeoBuilder::Instance(this)->MakeCons(name, medium, dz, rmin1, rmax1, rmin2, rmax2, phi1, phi2);
02625 }
02626 
02627 //_____________________________________________________________________________
02628 TGeoVolume *TGeoManager::MakePcon(const char *name, TGeoMedium *medium,
02629                                      Double_t phi, Double_t dphi, Int_t nz)
02630 {
02631 // Make in one step a volume pointing to a polycone shape with given medium.
02632    return TGeoBuilder::Instance(this)->MakePcon(name, medium, phi, dphi, nz);
02633 }
02634 
02635 //_____________________________________________________________________________
02636 TGeoVolume *TGeoManager::MakePgon(const char *name, TGeoMedium *medium,
02637                                      Double_t phi, Double_t dphi, Int_t nedges, Int_t nz)
02638 {
02639 // Make in one step a volume pointing to a polygone shape with given medium.
02640    return TGeoBuilder::Instance(this)->MakePgon(name, medium, phi, dphi, nedges, nz);
02641 }
02642 
02643 //_____________________________________________________________________________
02644 TGeoVolume *TGeoManager::MakeTrd1(const char *name, TGeoMedium *medium,
02645                                   Double_t dx1, Double_t dx2, Double_t dy, Double_t dz)
02646 {
02647 // Make in one step a volume pointing to a TGeoTrd1 shape with given medium.
02648    return TGeoBuilder::Instance(this)->MakeTrd1(name, medium, dx1, dx2, dy, dz);
02649 }
02650 
02651 //_____________________________________________________________________________
02652 TGeoVolume *TGeoManager::MakeTrd2(const char *name, TGeoMedium *medium,
02653                                   Double_t dx1, Double_t dx2, Double_t dy1, Double_t dy2,
02654                                   Double_t dz)
02655 {
02656 // Make in one step a volume pointing to a TGeoTrd2 shape with given medium.
02657    return TGeoBuilder::Instance(this)->MakeTrd2(name, medium, dx1, dx2, dy1, dy2, dz);
02658 }
02659 
02660 //_____________________________________________________________________________
02661 TGeoVolume *TGeoManager::MakeTrap(const char *name, TGeoMedium *medium,
02662                                   Double_t dz, Double_t theta, Double_t phi, Double_t h1,
02663                                   Double_t bl1, Double_t tl1, Double_t alpha1, Double_t h2, Double_t bl2,
02664                                   Double_t tl2, Double_t alpha2)
02665 {
02666 // Make in one step a volume pointing to a trapezoid shape with given medium.
02667    return TGeoBuilder::Instance(this)->MakeTrap(name, medium, dz, theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2);
02668 }
02669 
02670 //_____________________________________________________________________________
02671 TGeoVolume *TGeoManager::MakeGtra(const char *name, TGeoMedium *medium,
02672                                   Double_t dz, Double_t theta, Double_t phi, Double_t twist, Double_t h1,
02673                                   Double_t bl1, Double_t tl1, Double_t alpha1, Double_t h2, Double_t bl2,
02674                                   Double_t tl2, Double_t alpha2)
02675 {
02676 // Make in one step a volume pointing to a twisted trapezoid shape with given medium.
02677    return TGeoBuilder::Instance(this)->MakeGtra(name, medium, dz, theta, phi, twist, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2);
02678 }
02679 
02680 //_____________________________________________________________________________
02681 TGeoVolume *TGeoManager::MakeXtru(const char *name, TGeoMedium *medium, Int_t nz)
02682 {
02683 // Make a TGeoXtru-shaped volume with nz planes
02684    return TGeoBuilder::Instance(this)->MakeXtru(name, medium, nz);
02685 }
02686 
02687 //_____________________________________________________________________________
02688 TGeoPNEntry *TGeoManager::SetAlignableEntry(const char *unique_name, const char *path,
02689                                             Int_t uid)
02690 {
02691 // Creates an aligneable object with unique name corresponding to a path
02692 // and adds it to the list of alignables. An optional unique ID can be
02693 // provided, in which case PN entries can be searched fast by uid.
02694    if (!CheckPath(path)) return NULL;
02695    if (!fHashPNE) fHashPNE = new THashList(256,3);
02696    if (!fArrayPNE) fArrayPNE = new TObjArray(256);
02697    TGeoPNEntry *entry = GetAlignableEntry(unique_name);
02698    if (entry) {
02699       Error("SetAlignableEntry", "An alignable object with name %s already existing. NOT ADDED !", unique_name);
02700       return 0;
02701    }
02702    entry = new TGeoPNEntry(unique_name, path);
02703    Int_t ientry = fHashPNE->GetSize();
02704    fHashPNE->Add(entry);
02705    fArrayPNE->AddAtAndExpand(entry, ientry);
02706    if (uid>=0) {
02707       Bool_t added = InsertPNEId(uid, ientry);
02708       if (!added) Error("SetAlignableEntry", "A PN entry: has already uid=%i", uid);
02709    }
02710    return entry;
02711 }
02712 
02713 //_____________________________________________________________________________
02714 TGeoPNEntry *TGeoManager::GetAlignableEntry(const char *name) const
02715 {
02716 // Retreives an existing alignable object.
02717    if (!fHashPNE) return 0;
02718    return (TGeoPNEntry*)fHashPNE->FindObject(name);
02719 }
02720 
02721 //_____________________________________________________________________________
02722 TGeoPNEntry *TGeoManager::GetAlignableEntry(Int_t index) const
02723 {
02724 // Retreives an existing alignable object at a given index.
02725    if (!fArrayPNE && !InitArrayPNE()) return 0;
02726    return (TGeoPNEntry*)fArrayPNE->At(index);
02727 }
02728 
02729 //_____________________________________________________________________________
02730 TGeoPNEntry *TGeoManager::GetAlignableEntryByUID(Int_t uid) const
02731 {
02732 // Retreives an existing alignable object having a preset UID.
02733    if (!fNPNEId || (!fArrayPNE && !InitArrayPNE())) return NULL;
02734    Int_t index = TMath::BinarySearch(fNPNEId, fKeyPNEId, uid);
02735    if (index<0 || fKeyPNEId[index]!=uid) return NULL;
02736    return (TGeoPNEntry*)fArrayPNE->At(fValuePNEId[index]);
02737 }
02738 
02739 //_____________________________________________________________________________
02740 Int_t TGeoManager::GetNAlignable(Bool_t with_uid) const
02741 {
02742 // Retreives number of PN entries with or without UID.
02743    if (!fHashPNE) return 0;
02744    if (with_uid) return fNPNEId;
02745    return fHashPNE->GetSize();
02746 }
02747 
02748 //_____________________________________________________________________________
02749 Bool_t TGeoManager::InsertPNEId(Int_t uid, Int_t ientry)
02750 {
02751 // Insert a PN entry in the sorted array of indexes.
02752    if (!fSizePNEId) {
02753       // Create the arrays.
02754       fSizePNEId = 128;
02755       fKeyPNEId = new Int_t[fSizePNEId];
02756       memset(fKeyPNEId, 0, fSizePNEId*sizeof(Int_t));
02757       fValuePNEId = new Int_t[fSizePNEId];
02758       memset(fValuePNEId, 0, fSizePNEId*sizeof(Int_t));
02759       fKeyPNEId[fNPNEId] = uid;
02760       fValuePNEId[fNPNEId++] = ientry;
02761       return kTRUE;
02762    }
02763    // Search id in the existing array and return false if it already exists.
02764    Int_t index = TMath::BinarySearch(fNPNEId, fKeyPNEId, uid);
02765    if (index>0 && fKeyPNEId[index]==uid) return kFALSE;
02766    // Resize the arrays and insert the value
02767    Bool_t resize = (fNPNEId==fSizePNEId)?kTRUE:kFALSE;
02768    if (resize) {
02769       // Double the size of the array
02770       fSizePNEId *= 2;
02771       // Create new arrays of keys and values
02772       Int_t *keys = new Int_t[fSizePNEId];
02773       memset(keys, 0, fSizePNEId*sizeof(Int_t));
02774       Int_t *values = new Int_t[fSizePNEId];
02775       memset(values, 0, fSizePNEId*sizeof(Int_t));
02776       // Copy all keys<uid in the new keys array (0 to index)
02777       memcpy(keys,   fKeyPNEId,   (index+1)*sizeof(Int_t));
02778       memcpy(values, fValuePNEId, (index+1)*sizeof(Int_t));
02779       // Insert current key at index+1
02780       keys[index+1]   = uid;
02781       values[index+1] = ientry;
02782       // Copy all remaining keys from the old to new array
02783       memcpy(&keys[index+2],   &fKeyPNEId[index+1],   (fNPNEId-index-1)*sizeof(Int_t));
02784       memcpy(&values[index+2], &fValuePNEId[index+1], (fNPNEId-index-1)*sizeof(Int_t));
02785       delete [] fKeyPNEId;
02786       fKeyPNEId = keys;
02787       delete [] fValuePNEId;
02788       fValuePNEId = values;
02789       fNPNEId++;
02790       return kTRUE;
02791    }
02792    // Insert the value in the existing arrays
02793    Int_t i;
02794    for (i=fNPNEId-1; i>index; i--) {
02795       fKeyPNEId[i+1] = fKeyPNEId[i];
02796       fValuePNEId[i+1] = fValuePNEId[i];
02797    }
02798    fKeyPNEId[index+1] = uid;
02799    fValuePNEId[index+1] = ientry;
02800    fNPNEId++;
02801    return kTRUE;
02802 }
02803 
02804 //_____________________________________________________________________________
02805 TGeoPhysicalNode *TGeoManager::MakeAlignablePN(const char *name)
02806 {
02807 // Make a physical node from the path pointed by an alignable object with a given name.
02808    TGeoPNEntry *entry = GetAlignableEntry(name);
02809    if (!entry) {
02810       Error("MakeAlignablePN","No alignable object named %s found !", name);
02811       return 0;
02812    }
02813    return MakeAlignablePN(entry);
02814 }
02815 
02816 //_____________________________________________________________________________
02817 TGeoPhysicalNode *TGeoManager::MakeAlignablePN(TGeoPNEntry *entry)
02818 {
02819 // Make a physical node from the path pointed by a given alignable object.
02820    if (!entry) {
02821       Error("MakeAlignablePN","No alignable object specified !");
02822       return 0;
02823    }
02824    const char *path = entry->GetTitle();
02825    if (!cd(path)) {
02826       Error("MakeAlignablePN", "Alignable object %s poins to invalid path: %s",
02827             entry->GetName(), path);
02828       return 0;
02829    }
02830    TGeoPhysicalNode *node = MakePhysicalNode(path);
02831    entry->SetPhysicalNode(node);
02832    return node;
02833 }
02834 
02835 //_____________________________________________________________________________
02836 TGeoPhysicalNode *TGeoManager::MakePhysicalNode(const char *path)
02837 {
02838 // Makes a physical node corresponding to a path. If PATH is not specified,
02839 // makes physical node matching current modeller state.
02840    TGeoPhysicalNode *node;
02841    if (path) {
02842       if (!CheckPath(path)) {
02843          Error("MakePhysicalNode", "path: %s not valid", path);
02844          return NULL;
02845       }
02846       node = new TGeoPhysicalNode(path);
02847    } else {
02848       node = new TGeoPhysicalNode(GetPath());
02849    }
02850    fPhysicalNodes->Add(node);
02851    return node;
02852 }
02853 
02854 //_____________________________________________________________________________
02855 void TGeoManager::RefreshPhysicalNodes(Bool_t lock)
02856 {
02857 // Refresh physical nodes to reflect the actual geometry paths after alignment
02858 // was applied. Optionally locks physical nodes (default).
02859    TIter next(gGeoManager->GetListOfPhysicalNodes());
02860    TGeoPhysicalNode *pn;
02861    while ((pn=(TGeoPhysicalNode*)next())) pn->Refresh();
02862    if (lock) LockGeometry();
02863 }
02864 
02865 //_____________________________________________________________________________
02866 void TGeoManager::ClearPhysicalNodes(Bool_t mustdelete)
02867 {
02868 // Clear the current list of physical nodes, so that we can start over with a new list.
02869 // If MUSTDELETE is true, delete previous nodes.
02870    if (mustdelete) fPhysicalNodes->Delete();
02871    else fPhysicalNodes->Clear();
02872 }
02873 
02874 //_____________________________________________________________________________
02875 TGeoVolumeAssembly *TGeoManager::MakeVolumeAssembly(const char *name)
02876 {
02877 // Make an assembly of volumes.
02878    return TGeoBuilder::Instance(this)->MakeVolumeAssembly(name);
02879 }
02880 
02881 //_____________________________________________________________________________
02882 TGeoVolumeMulti *TGeoManager::MakeVolumeMulti(const char *name, TGeoMedium *medium)
02883 {
02884 // Make a TGeoVolumeMulti handling a list of volumes.
02885    return TGeoBuilder::Instance(this)->MakeVolumeMulti(name, medium);
02886 }
02887 
02888 //_____________________________________________________________________________
02889 void TGeoManager::SetExplodedView(Int_t ibomb)
02890 {
02891 // Set type of exploding view (see TGeoPainter::SetExplodedView())
02892    if ((ibomb>=0) && (ibomb<4)) fExplodedView = ibomb;
02893    if (fPainter) fPainter->SetExplodedView(ibomb);
02894 }
02895 
02896 //_____________________________________________________________________________
02897 void TGeoManager::SetPhiRange(Double_t phimin, Double_t phimax)
02898 {
02899 // Set cut phi range
02900    if ((phimin==0) && (phimax==360)) {
02901       fPhiCut = kFALSE;
02902       return;
02903    }
02904    fPhiCut = kTRUE;
02905    fPhimin = phimin;
02906    fPhimax = phimax;
02907 }
02908 
02909 //_____________________________________________________________________________
02910 void TGeoManager::SetNsegments(Int_t nseg)
02911 {
02912 // Set number of segments for approximating circles in drawing.
02913    if (fNsegments==nseg) return;
02914    if (nseg>2) fNsegments = nseg;
02915    if (fPainter) fPainter->SetNsegments(nseg);
02916 }
02917 
02918 //_____________________________________________________________________________
02919 Int_t TGeoManager::GetNsegments() const
02920 {
02921 // Get number of segments approximating circles
02922    return fNsegments;
02923 }
02924 
02925 //_____________________________________________________________________________
02926 void TGeoManager::BuildDefaultMaterials()
02927 {
02928 // Now just a shortcut for GetElementTable.
02929    GetElementTable();
02930 }
02931 
02932 //_____________________________________________________________________________
02933 TGeoElementTable *TGeoManager::GetElementTable()
02934 {
02935 // Returns material table. Creates it if not existing.
02936    if (!fElementTable) fElementTable = new TGeoElementTable(200);
02937    return fElementTable;
02938 }
02939 
02940 //_____________________________________________________________________________
02941 TGeoNode *TGeoManager::Step(Bool_t is_geom, Bool_t cross)
02942 {
02943 // Make a rectiliniar step of length fStep from current point (fPoint) on current
02944 // direction (fDirection). If the step is imposed by geometry, is_geom flag
02945 // must be true (default). The cross flag specifies if the boundary should be
02946 // crossed in case of a geometry step (default true). Returns new node after step.
02947 // Set also on boundary condition.
02948    return fCurrentNavigator->Step(is_geom, cross);
02949 }
02950 
02951 //_____________________________________________________________________________
02952 TGeoNode *TGeoManager::SamplePoints(Int_t npoints, Double_t &dist, Double_t epsil,
02953                                     const char* g3path)
02954 {
02955 // shoot npoints randomly in a box of 1E-5 arround current point.
02956 // return minimum distance to points outside
02957    return GetGeomPainter()->SamplePoints(npoints, dist, epsil, g3path);
02958 }
02959 
02960 //_____________________________________________________________________________
02961 void TGeoManager::SetTopVolume(TGeoVolume *vol)
02962 {
02963 // Set the top volume and corresponding node as starting point of the geometry.
02964    if (fTopVolume==vol) return;
02965 
02966    TSeqCollection *brlist = gROOT->GetListOfBrowsers();
02967    TIter next(brlist);
02968    TBrowser *browser = 0;
02969 
02970    if (fTopVolume) fTopVolume->SetTitle("");
02971    fTopVolume = vol;
02972    vol->SetTitle("Top volume");
02973    if (fTopNode) {
02974       TGeoNode *topn = fTopNode;
02975       fTopNode = 0;
02976       while ((browser=(TBrowser*)next())) browser->RecursiveRemove(topn);
02977       delete topn;
02978    } else {
02979       fMasterVolume = vol;
02980       fUniqueVolumes->AddAtAndExpand(vol,0);
02981       if (fgVerboseLevel>0) Info("SetTopVolume","Top volume is %s. Master volume is %s", fTopVolume->GetName(),
02982            fMasterVolume->GetName());
02983    }
02984 //   fMasterVolume->FindMatrixOfDaughterVolume(vol);
02985 //   fCurrentMatrix->Print();
02986    fTopNode = new TGeoNodeMatrix(vol, gGeoIdentity);
02987    fTopNode->SetName(TString::Format("%s_1",vol->GetName()));
02988    fTopNode->SetNumber(1);
02989    fTopNode->SetTitle("Top logical node");
02990    fNodes->AddAt(fTopNode, 0);
02991    if (!fCurrentNavigator) AddNavigator(new TGeoNavigator(this));
02992    Int_t nnavigators = fNavigators->GetEntriesFast();
02993    for (Int_t i=0; i<nnavigators; i++) {
02994       TGeoNavigator *nav = (TGeoNavigator*)fNavigators->At(i);
02995       nav->ResetAll();
02996    }
02997 }
02998 //_____________________________________________________________________________
02999 void TGeoManager::SelectTrackingMedia()
03000 {
03001 // Define different tracking media.
03002 //   printf("List of materials :\n");
03003 /*
03004    Int_t nmat = fMaterials->GetSize();
03005    if (!nmat) {printf(" No materials !\n"); return;}
03006    Int_t *media = new Int_t[nmat];
03007    memset(media, 0, nmat*sizeof(Int_t));
03008    Int_t imedia = 1;
03009    TGeoMaterial *mat, *matref;
03010    mat = (TGeoMaterial*)fMaterials->At(0);
03011    if (mat->GetMedia()) {
03012       for (Int_t i=0; i<nmat; i++) {
03013          mat = (TGeoMaterial*)fMaterials->At(i);
03014          mat->Print();
03015       }
03016       return;
03017    }
03018    mat->SetMedia(imedia);
03019    media[0] = imedia++;
03020    mat->Print();
03021    for (Int_t i=0; i<nmat; i++) {
03022       mat = (TGeoMaterial*)fMaterials->At(i);
03023       for (Int_t j=0; j<i; j++) {
03024          matref = (TGeoMaterial*)fMaterials->At(j);
03025          if (mat->IsEq(matref)) {
03026             mat->SetMedia(media[j]);
03027             break;
03028          }
03029          if (j==(i-1)) {
03030          // different material
03031             mat->SetMedia(imedia);
03032             media[i] = imedia++;
03033             mat->Print();
03034          }
03035       }
03036    }
03037 */
03038 }
03039 
03040 //_____________________________________________________________________________
03041 void TGeoManager::CheckBoundaryErrors(Int_t ntracks, Double_t radius)
03042 {
03043 // Check pushes and pulls needed to cross the next boundary with respect to the
03044 // position given by FindNextBoundary. If radius is not mentioned the full bounding
03045 // box will be sampled.
03046    GetGeomPainter()->CheckBoundaryErrors(ntracks, radius);
03047 }   
03048 
03049 //_____________________________________________________________________________
03050 void TGeoManager::CheckBoundaryReference(Int_t icheck)
03051 {
03052 // Check the boundary errors reference file created by CheckBoundaryErrors method.
03053 // The shape for which the crossing failed is drawn with the starting point in red
03054 // and the extrapolated point to boundary (+/- failing push/pull) in yellow.
03055    GetGeomPainter()->CheckBoundaryReference(icheck);
03056 }   
03057 
03058 //_____________________________________________________________________________
03059 void TGeoManager::CheckPoint(Double_t x, Double_t y, Double_t z, Option_t *option)
03060 {
03061 // Classify a given point. See TGeoChecker::CheckPoint().
03062    GetGeomPainter()->CheckPoint(x,y,z,option);
03063 }
03064 
03065 //_____________________________________________________________________________
03066 void TGeoManager::CheckGeometryFull(Int_t ntracks, Double_t vx, Double_t vy, Double_t vz, Option_t *option)
03067 {
03068 // Geometry checking.
03069 // - if option contains 'o': Optional overlap checkings (by sampling and by mesh).
03070 // - if option contains 'b': Optional boundary crossing check + timing per volume.
03071 //
03072 // STAGE 1: extensive overlap checking by sampling per volume. Stdout need to be
03073 //  checked by user to get report, then TGeoVolume::CheckOverlaps(0.01, "s") can
03074 //  be called for the suspicious volumes.
03075 // STAGE2 : normal overlap checking using the shapes mesh - fills the list of
03076 //  overlaps.
03077 // STAGE3 : shooting NRAYS rays from VERTEX and counting the total number of
03078 //  crossings per volume (rays propagated from boundary to boundary until
03079 //  geometry exit). Timing computed and results stored in a histo.
03080 // STAGE4 : shooting 1 mil. random rays inside EACH volume and calling
03081 //  FindNextBoundary() + Safety() for each call. The timing is normalized by the
03082 //  number of crossings computed at stage 2 and presented as percentage.
03083 //  One can get a picture on which are the most "burned" volumes during
03084 //  transportation from geometry point of view. Another plot of the timing per
03085 //  volume vs. number of daughters is produced.
03086    TString opt(option);
03087    opt.ToLower();
03088    if (!opt.Length()) {
03089       Error("CheckGeometryFull","The option string must contain a letter. See method documentation.");
03090       return;
03091    }
03092    Bool_t checkoverlaps  = opt.Contains("o");
03093    Bool_t checkcrossings = opt.Contains("b");
03094    Double_t vertex[3];
03095    vertex[0] = vx;
03096    vertex[1] = vy;
03097    vertex[2] = vz;
03098    GetGeomPainter()->CheckGeometryFull(checkoverlaps,checkcrossings,ntracks,vertex);
03099 }
03100 
03101 //_____________________________________________________________________________
03102 void TGeoManager::CheckGeometry(Option_t * /*option*/)
03103 {
03104 // Instanciate a TGeoChecker object and investigates the geometry according to
03105 // option. Not implemented yet.
03106    // check shapes first
03107    if (fgVerboseLevel>0) Info("CheckGeometry","Fixing runtime shapes...");
03108    TIter next(fShapes);
03109    TIter nextv(fVolumes);
03110    TGeoShape *shape;
03111    TGeoVolume *vol;
03112    Bool_t has_runtime = kFALSE;
03113    while ((shape = (TGeoShape*)next())) {
03114       if (shape->IsRunTimeShape()) {
03115          has_runtime = kTRUE;
03116       }
03117       if (shape->TestShapeBit(TGeoShape::kGeoPcon) || shape->TestShapeBit(TGeoShape::kGeoArb8))
03118          if (!shape->TestShapeBit(TGeoShape::kGeoClosedShape)) shape->ComputeBBox();
03119    }
03120    if (has_runtime) fTopNode->CheckShapes();
03121    else if (fgVerboseLevel>0) Info("CheckGeometry","...Nothing to fix");
03122    // Compute bounding  box for assemblies
03123    while ((vol = (TGeoVolume*)nextv())) {
03124       if (vol->IsAssembly()) vol->GetShape()->ComputeBBox();
03125    }   
03126 }
03127 
03128 //_____________________________________________________________________________
03129 void TGeoManager::CheckOverlaps(Double_t ovlp, Option_t * option)
03130 {
03131 // Check all geometry for illegal overlaps within a limit OVLP.
03132    if (!fTopNode) {
03133       Error("CheckOverlaps","Top node not set");
03134       return;
03135    }
03136    fTopNode->CheckOverlaps(ovlp,option);
03137 }
03138 
03139 //_____________________________________________________________________________
03140 void TGeoManager::PrintOverlaps() const
03141 {
03142 // Prints the current list of overlaps.
03143    if (!fOverlaps) return;
03144    Int_t novlp = fOverlaps->GetEntriesFast();
03145    if (!novlp) return;
03146    TGeoManager *geom = (TGeoManager*)this;
03147    geom->GetGeomPainter()->PrintOverlaps();
03148 }
03149 
03150 //_____________________________________________________________________________
03151 Double_t TGeoManager::Weight(Double_t precision, Option_t *option)
03152 {
03153 // Estimate weight of volume VOL with a precision SIGMA(W)/W better than PRECISION.
03154 // Option can be "v" - verbose (default)
03155    GetGeomPainter();
03156    TString opt(option);
03157    opt.ToLower();
03158    Double_t weight;
03159    TGeoVolume *volume = fTopVolume;
03160    if (opt.Contains("v")) {
03161       if (opt.Contains("a")) {
03162          if (fgVerboseLevel>0) Info("Weight", "Computing analytically weight of %s", volume->GetName());
03163          weight = volume->WeightA();
03164          if (fgVerboseLevel>0) Info("Weight", "Computed weight: %f [kg]\n", weight);
03165          return weight;
03166       }
03167       if (fgVerboseLevel>0) {
03168          Info("Weight", "Estimating weight of %s with %g %% precision", fTopVolume->GetName(), 100.*precision);
03169          printf("    event         weight         err\n");
03170          printf("========================================\n");
03171       }   
03172    }
03173    weight = fPainter->Weight(precision, option);
03174    return weight;
03175 }
03176 
03177 //_____________________________________________________________________________
03178 ULong_t TGeoManager::SizeOf(const TGeoNode * /*node*/, Option_t * /*option*/)
03179 {
03180 // computes the total size in bytes of the branch starting with node.
03181 // The option can specify if all the branch has to be parsed or only the node
03182    return 0;
03183 }
03184 
03185 //______________________________________________________________________________
03186 void TGeoManager::Streamer(TBuffer &R__b)
03187 {
03188    // Stream an object of class TGeoManager.
03189    if (R__b.IsReading()) {
03190       R__b.ReadClassBuffer(TGeoManager::Class(), this);
03191       fIsGeomReading = kTRUE;
03192       CloseGeometry();
03193       fStreamVoxels = kFALSE;
03194       fIsGeomReading = kFALSE;
03195    } else {
03196       R__b.WriteClassBuffer(TGeoManager::Class(), this);
03197    }
03198 }
03199 
03200 //_____________________________________________________________________________
03201 void TGeoManager::ExecuteEvent(Int_t event, Int_t px, Int_t py)
03202 {
03203 // Execute mouse actions on this manager.
03204    if (!fPainter) return;
03205    fPainter->ExecuteManagerEvent(this, event, px, py);
03206 }
03207 
03208 //______________________________________________________________________________
03209 Int_t TGeoManager::Export(const char *filename, const char *name, Option_t *option)
03210 {
03211    // Export this geometry to a file
03212    //
03213    // -Case 1: root file or root/xml file
03214    //  if filename end with ".root". The key will be named name
03215    //  By default the geometry is saved without the voxelisation info.
03216    //  Use option 'v" to save the voxelisation info.
03217    //  if filename end with ".xml" a root/xml file is produced.
03218    //
03219    // -Case 2: C++ script
03220    //  if filename end with ".C"
03221    //
03222    // -Case 3: gdml file
03223    //  if filename end with ".gdml"
03224    //  NOTE that to use this option, the PYTHONPATH must be defined like
03225    //      export PYTHONPATH=$ROOTSYS/lib:$ROOTSYS/geom/gdml
03226    //
03227 
03228    TString sfile(filename);
03229    if (sfile.Contains(".C")) {
03230       //Save geometry as a C++ script
03231       if (fgVerboseLevel>0) Info("Export","Exporting %s %s as C++ code", GetName(), GetTitle());
03232       fTopVolume->SaveAs(filename);
03233       return 1;
03234    }
03235    if (sfile.Contains(".gdml")) {
03236       //Save geometry as a gdml file
03237       if (fgVerboseLevel>0) Info("Export","Exporting %s %s as gdml code", GetName(), GetTitle());
03238       gROOT->ProcessLine("TPython::Exec(\"from math import *\")");
03239 
03240       gROOT->ProcessLine("TPython::Exec(\"import writer\")");
03241       gROOT->ProcessLine("TPython::Exec(\"import ROOTwriter\")");
03242 
03243       // get TGeoManager and top volume
03244       gROOT->ProcessLine("TPython::Exec(\"geomgr = ROOT.gGeoManager\")");
03245       gROOT->ProcessLine("TPython::Exec(\"topV = geomgr.GetTopVolume()\")");
03246 
03247       // instanciate writer
03248       const char *cmd=TString::Format("TPython::Exec(\"gdmlwriter = writer.writer('%s')\")",filename);
03249       gROOT->ProcessLine(cmd);
03250       gROOT->ProcessLine("TPython::Exec(\"binding = ROOTwriter.ROOTwriter(gdmlwriter)\")");
03251 
03252       // dump materials
03253       gROOT->ProcessLine("TPython::Exec(\"matlist = geomgr.GetListOfMaterials()\")");
03254       gROOT->ProcessLine("TPython::Exec(\"binding.dumpMaterials(matlist)\")");
03255 
03256       // dump solids
03257       gROOT->ProcessLine("TPython::Exec(\"shapelist = geomgr.GetListOfShapes()\")");
03258       gROOT->ProcessLine("TPython::Exec(\"binding.dumpSolids(shapelist)\")");
03259 
03260       // dump geo tree
03261       gROOT->ProcessLine("TPython::Exec(\"print 'Info in <TPython::Exec>: Traversing geometry tree'\")");
03262       gROOT->ProcessLine("TPython::Exec(\"gdmlwriter.addSetup('default', '1.0', topV.GetName())\")");
03263       gROOT->ProcessLine("TPython::Exec(\"binding.examineVol(topV)\")");
03264 
03265       // write file
03266       gROOT->ProcessLine("TPython::Exec(\"gdmlwriter.writeFile()\")");
03267       if (fgVerboseLevel>0) printf("Info in <TPython::Exec>: GDML Export complete - %s is ready\n", filename);
03268       return 1;
03269    }
03270    if (sfile.Contains(".root") || sfile.Contains(".xml")) {
03271       //Save geometry as a root file
03272       TFile *f = TFile::Open(filename,"recreate");
03273       if (!f || f->IsZombie()) {
03274          Error("Export","Cannot open file");
03275          return 0;
03276       }
03277       TString keyname = name;
03278       if (keyname.IsNull()) keyname = GetName();
03279       TString opt = option;
03280       opt.ToLower();
03281       if (opt.Contains("v")) {
03282          fStreamVoxels = kTRUE;
03283          if (fgVerboseLevel>0) Info("Export","Exporting %s %s as root file. Optimizations streamed.", GetName(), GetTitle());
03284       } else {
03285          fStreamVoxels = kFALSE;
03286          if (fgVerboseLevel>0) Info("Export","Exporting %s %s as root file. Optimizations not streamed.", GetName(), GetTitle());
03287       }
03288       Int_t nbytes = Write(keyname);
03289       fStreamVoxels = kFALSE;
03290       delete f;
03291       return nbytes;
03292    }
03293    return 0;
03294 }
03295 //______________________________________________________________________________
03296 void TGeoManager::LockGeometry()
03297 {
03298 // Lock current geometry so that no other geometry can be imported.
03299    fgLock = kTRUE;
03300 }
03301 
03302 //______________________________________________________________________________
03303 void TGeoManager::UnlockGeometry()
03304 {
03305 // Unlock current geometry.
03306    fgLock = kFALSE;
03307 }
03308 
03309 //______________________________________________________________________________
03310 Bool_t TGeoManager::IsLocked()
03311 {
03312 // Check lock state.
03313    return fgLock;
03314 }
03315 
03316 //______________________________________________________________________________
03317 Int_t TGeoManager::GetVerboseLevel()
03318 {
03319 // Set verbosity level (static function).
03320 // 0 - suppress messages related to geom-painter visibility level
03321 // 1 - default value
03322    return fgVerboseLevel;
03323 }
03324 
03325 //______________________________________________________________________________
03326 void TGeoManager::SetVerboseLevel(Int_t vl)
03327 {
03328 // Return current verbosity level (static function).
03329    fgVerboseLevel = vl;
03330 }
03331 
03332 //______________________________________________________________________________
03333 TGeoManager *TGeoManager::Import(const char *filename, const char *name, Option_t * /*option*/)
03334 {
03335    //static function
03336    //Import a geometry from a gdml or ROOT file
03337    //
03338    // -Case 1: gdml
03339    //  if filename ends with ".gdml" the foreign geometry described with gdml
03340    //  is imported executing some python scripts in $ROOTSYS/gdml.
03341    //  NOTE that to use this option, the PYTHONPATH must be defined like
03342    //      export PYTHONPATH=$ROOTSYS/lib:$ROOTSYS/gdml
03343    //
03344    // -Case 2: root file (.root) or root/xml file (.xml)
03345    //  Import in memory from filename the geometry with key=name.
03346    //  if name="" (default), the first TGeoManager object in the file is returned.
03347    //
03348    //Note that this function deletes the current gGeoManager (if one)
03349    //before importing the new object.
03350 
03351    if (fgLock) {
03352       ::Warning("TGeoManager::Import", "TGeoMananager in lock mode. NOT IMPORTING new geometry");
03353       return NULL;
03354    }
03355    if (!filename) return 0;
03356    if (fgVerboseLevel>0) ::Info("TGeoManager::Import","Reading geometry from file: %s",filename);
03357 
03358    if (gGeoManager) delete gGeoManager;
03359    gGeoManager = 0;
03360 
03361    if (strstr(filename,".gdml")) {
03362       // import from a gdml file
03363       new TGeoManager("GDMLImport", "Geometry imported from GDML");
03364       const char* cmd = TString::Format("TGDMLParse::StartGDML(\"%s\")", filename);
03365       TGeoVolume* world = (TGeoVolume*)gROOT->ProcessLineFast(cmd);
03366 
03367       if(world == 0) {
03368          ::Error("TGeoManager::Import", "Cannot open file");
03369       }
03370       else {
03371          gGeoManager->SetTopVolume(world);
03372          gGeoManager->CloseGeometry();
03373          gGeoManager->DefaultColors();
03374       }
03375    } else {
03376       // import from a root file
03377       TFile *old = gFile;
03378       // in case a web file is specified, use the cacheread option to cache
03379       // this file in the cache directory
03380       TFile *f = 0;
03381       if (strstr(filename,"http")) f = TFile::Open(filename,"CACHEREAD");
03382       else                         f = TFile::Open(filename);
03383       if (!f || f->IsZombie()) {
03384          if (old) old->cd();
03385          ::Error("TGeoManager::Import", "Cannot open file");
03386          return 0;
03387       }
03388       if (name && strlen(name) > 0) {
03389          gGeoManager = (TGeoManager*)f->Get(name);
03390       } else {
03391          TIter next(f->GetListOfKeys());
03392          TKey *key;
03393          while ((key = (TKey*)next())) {
03394             if (strcmp(key->GetClassName(),"TGeoManager") != 0) continue;
03395             gGeoManager = (TGeoManager*)key->ReadObj();
03396             break;
03397          }
03398       }
03399       if (old) old->cd();
03400       delete f;
03401    }
03402    if (!gGeoManager) return 0;
03403    if (!gROOT->GetListOfGeometries()->FindObject(gGeoManager)) gROOT->GetListOfGeometries()->Add(gGeoManager);
03404    if (!gROOT->GetListOfBrowsables()->FindObject(gGeoManager)) gROOT->GetListOfBrowsables()->Add(gGeoManager);
03405    gGeoManager->UpdateElements();
03406    return gGeoManager;
03407 }
03408 
03409 //___________________________________________________________________________
03410 void TGeoManager::UpdateElements()
03411 {
03412 // Update element flags when geometry is loaded from a file.
03413    if (!fElementTable) return;
03414    TIter next(fMaterials);
03415    TGeoMaterial *mat;
03416    TGeoMixture *mix;
03417    TGeoElement *elem, *elem_table;
03418    Int_t i, nelem;
03419    while ((mat=(TGeoMaterial*)next())) {
03420       if (mat->IsMixture()) {
03421          mix = (TGeoMixture*)mat;
03422          nelem = mix->GetNelements();
03423          for (i=0; i<nelem; i++) {
03424             elem = mix->GetElement(i);
03425             elem_table = fElementTable->GetElement(elem->Z());
03426             if (elem != elem_table) {
03427                elem_table->SetDefined(elem->IsDefined());
03428                elem_table->SetUsed(elem->IsUsed());
03429             } else {
03430                elem_table->SetDefined();
03431             }
03432          }
03433       } else {
03434          elem = mat->GetElement();
03435          elem_table = fElementTable->GetElement(elem->Z());
03436          if (elem != elem_table) {
03437             elem_table->SetDefined(elem->IsDefined());
03438             elem_table->SetUsed(elem->IsUsed());
03439          } else {
03440             elem_table->SetUsed();
03441          }
03442       }
03443    }
03444 }
03445 
03446 //___________________________________________________________________________
03447 Bool_t TGeoManager::InitArrayPNE() const
03448 {
03449 // Initialize PNE array for fast access via index and unique-id.
03450    if (fHashPNE) {
03451      fArrayPNE = new TObjArray(fHashPNE->GetSize());
03452      TIter next(fHashPNE);
03453      TObject *obj;
03454      while ((obj = next())) {
03455        fArrayPNE->Add(obj);
03456      }
03457      return kTRUE;
03458    }
03459    return kFALSE;
03460 }
03461 
03462 //___________________________________________________________________________
03463 Int_t *TGeoManager::GetIntBuffer(Int_t length)
03464 {
03465 // Get a temporary buffer of Int_t*
03466    if (length>fIntSize) {
03467       delete [] fIntBuffer;
03468       fIntBuffer = new Int_t[length];
03469       fIntSize = length;
03470    }
03471    return fIntBuffer;
03472 }
03473 
03474 //______________________________________________________________________________
03475 Double_t *TGeoManager::GetDblBuffer(Int_t length)
03476 {
03477 // Get a temporary buffer of Double_t*
03478    if (length>fDblSize) {
03479       delete [] fDblBuffer;
03480       fDblBuffer = new Double_t[length];
03481       fDblSize = length;
03482    }
03483    return fDblBuffer;
03484 }
03485 
03486 //______________________________________________________________________________
03487 Bool_t TGeoManager::GetTminTmax(Double_t &tmin, Double_t &tmax) const
03488 {
03489 // Get time cut for drawing tracks.
03490    tmin = fTmin;
03491    tmax = fTmax;
03492    return fTimeCut;
03493 }
03494 
03495 //______________________________________________________________________________
03496 void TGeoManager::SetTminTmax(Double_t tmin, Double_t tmax)
03497 {
03498 // Set time cut interval for drawing tracks. If called with no arguments, time
03499 // cut will be disabled.
03500    fTmin = tmin;
03501    fTmax = tmax;
03502    if (tmin==0 && tmax==999) fTimeCut = kFALSE;
03503    else fTimeCut = kTRUE;
03504    if (fTracks && !IsAnimatingTracks()) ModifiedPad();
03505 }
03506 
03507 //______________________________________________________________________________
03508 void TGeoManager::MasterToTop(const Double_t *master, Double_t *top) const
03509 {
03510 // Convert coordinates from master volume frame to top.
03511    fCurrentNavigator->MasterToLocal(master, top);
03512 }
03513 
03514 //______________________________________________________________________________
03515 void TGeoManager::TopToMaster(const Double_t *top, Double_t *master) const
03516 {
03517  // Convert coordinates from top volume frame to master.
03518    fCurrentNavigator->LocalToMaster(top, master);
03519 }
03520 
03521 
03522 

Generated on Tue Jul 5 14:12:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1