ROOT logo
// @(#)root/geom:$Id$
// Author: Andrei Gheata   17/02/04

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//_____________________________________________________________________________
// TGeoPhysicalNode, TGeoPNEntry
//
// Physical nodes are the actual 'touchable' objects in the geometry, representing
// a path of positioned volumes starting with the top node:
//    path=/TOP/A_1/B_4/C_3 , where A, B, C represent names of volumes.
// The number of physical nodes is given by the total number of possible of
// branches in the geometry hierarchy. In case of detector geometries and
// specially for calorimeters this number can be of the order 1e6-1e9, therefore
// it is impossible to create all physical nodes as objects in memory. In TGeo,
// physical nodes are represented by the class TGeoPhysicalNode and can be created
// on demand for alignment purposes:
//
//    TGeoPhysicalNode *pn = new TGeoPhysicalNode("path_to_object")
//
// Once created, a physical node can be misaligned, meaning that its position
// or even shape can be changed:
//
//    pn->Align(TGeoMatrix* newmat, TGeoShape* newshape, Bool_t check=kFALSE)
//
// The knowledge of the path to the objects that need to be misaligned is
// essential since there is no other way of identifying them. One can however
// create 'symbolic links' to any complex path to make it more representable
// for the object it designates:
//
//    TGeoPNEntry *pne = new TGeoPNEntry("TPC_SECTOR_2", "path_to_tpc_sect2");
//    pne->SetPhysicalNode(pn)
//
// Such a symbolic link hides the complexity of the path to the align object and
// replaces it with a more meaningful name. In addition, TGeoPNEntry objects are
// faster to search by name and they may optionally store an additional user
// matrix.
//
// For more details please read the misalignment section in the Users Guide.
//_____________________________________________________________________________

#include "TClass.h"
#include "TGeoManager.h"
#include "TGeoVoxelFinder.h"
#include "TGeoCache.h"
#include "TGeoMatrix.h"
#include "TGeoShapeAssembly.h"
#include "TGeoCompositeShape.h"
#include "TGeoBoolNode.h"
#include "TGeoVolume.h"
#include "TVirtualGeoPainter.h"

#include "TGeoPhysicalNode.h"

// statics and globals

ClassImp(TGeoPhysicalNode)

//_____________________________________________________________________________
TGeoPhysicalNode::TGeoPhysicalNode() : TNamed()
{
// Default constructor
   fLevel        = 0;
   fMatrices     = 0;
   fNodes        = 0;
   fMatrixOrig   = 0;
   SetVisibility(kTRUE);
   SetVisibleFull(kFALSE);
   SetIsVolAtt(kTRUE);
   SetAligned(kFALSE);
}

//_____________________________________________________________________________
TGeoPhysicalNode::TGeoPhysicalNode(const char *path) : TNamed(path,"")
{
// Constructor
   if (!path[0]) {
      Error("ctor", "path not valid");
      return;
   }
   fLevel  = 0;
   fMatrices = new TObjArray(30);
   fNodes    = new TObjArray(30);
   fMatrixOrig   = 0;
   SetPath(path);
   SetVisibility(kTRUE);
   SetVisibleFull(kFALSE);
   SetIsVolAtt(kTRUE);
   SetAligned(kFALSE);
}

//_____________________________________________________________________________
TGeoPhysicalNode::TGeoPhysicalNode(const TGeoPhysicalNode& gpn) :
  TNamed(gpn),
  TAttLine(gpn),
  fLevel(gpn.fLevel),
  fMatrices(gpn.fMatrices),
  fNodes(gpn.fNodes),
  fMatrixOrig(gpn.fMatrixOrig)
{
   //copy constructor
}

//_____________________________________________________________________________
TGeoPhysicalNode& TGeoPhysicalNode::operator=(const TGeoPhysicalNode& gpn)
{
   //assignment operator
   if(this!=&gpn) {
      TNamed::operator=(gpn);
      TAttLine::operator=(gpn);
      fLevel=gpn.fLevel;
      fMatrices=gpn.fMatrices;
      fNodes=gpn.fNodes;
      fMatrixOrig=gpn.fMatrixOrig;
   }
   return *this;
}

//_____________________________________________________________________________
TGeoPhysicalNode::~TGeoPhysicalNode()
{
// Destructor
   if (fMatrices) {
      fMatrices->Delete();
      delete fMatrices;
   }
   if (fNodes) delete fNodes;
   if (fMatrixOrig) delete fMatrixOrig;
}

//_____________________________________________________________________________
Bool_t TGeoPhysicalNode::Align(TGeoMatrix *newmat, TGeoShape *newshape, Bool_t check, Double_t ovlp)
{
   // Align a physical node with a new relative matrix/shape.
   // Example: /TOP_1/A_1/B_1/C_1
   //    node->Align(transl_1, box) will perform:
   //    - change RELATIVE translation of C_1 node (with respect to its
   //      container volume B) to transl_1
   //    - change the shape of the C volume
   // *NOTE* The operations will affect ONLY the LAST node in the branch. All
   //   volumes/nodes in the branch represented by this physical node are
   //   CLONED so the operation does not affect other possible replicas.
   if (!newmat && !newshape) return kFALSE;
   if (TGeoManager::IsLocked()) {
      Error("Align", "Not performed. Geometry in LOCKED mode !");
      return kFALSE;
   }
   if (newmat == gGeoIdentity) {
      Error("Align", "Cannot align using gGeoIdentity. Use some default matrix constructor to represent identities.");
      return kFALSE;
   }   
   TGeoNode *node = GetNode();
   if (node->IsOffset()) {
      Error("Align", "Cannot align division nodes: %s\n",node->GetName());
      return kFALSE;
   }
   // Refresh the node since other Align calls may have altered the stored nodes
   Refresh();
   TGeoNode *nnode = 0;
   TGeoVolume *vm = GetVolume(0);
   TGeoVolume *vd = 0;
   Int_t i;
   if (!IsAligned()) {
      Int_t *id = new Int_t[fLevel];
      for (i=0; i<fLevel; i++) {
         // Store daughter indexes
         vd = GetVolume(i);
         node = GetNode(i+1);
         id[i] = vd->GetIndex(node);
         if (id[i]<0) {
            Error("Align","%s cannot align node %s",GetName(), node->GetName());
            delete [] id;
            return kFALSE;
         }
      }
      for (i=0; i<fLevel; i++) {
         // Get daughter node and its id inside vm
         node = GetNode(i+1);
         // Clone daughter volume and node if not done yet
         if (node->IsCloned()) {
            vd = node->GetVolume();
            nnode = node;
         } else {
            vd = node->GetVolume()->CloneVolume();
            if (!vd) {
               delete [] id;
               Fatal("Align", "Cannot clone volume %s", node->GetVolume()->GetName());
               return kFALSE;
            }
            nnode = node->MakeCopyNode();
            if (!nnode) {
               delete [] id;
               Fatal("Align", "Cannot make copy node for %s", node->GetName());
               return kFALSE;
            }   
            // Correct pointers to mother and volume
            nnode->SetVolume(vd);
            nnode->SetMotherVolume(vm);
            // Decouple old node from mother volume and connect new one
            if (vm->TestBit(TGeoVolume::kVolumeImportNodes)) {
               gGeoManager->GetListOfGShapes()->Add(nnode);
            }   
            vm->GetNodes()->RemoveAt(id[i]);
            vm->GetNodes()->AddAt(nnode,id[i]);
            fNodes->RemoveAt(i+1);
            fNodes->AddAt(nnode,i+1);
     //       node->GetVolume()->Release();
         }   
         // Consider new cloned volume as mother and continue
         vm = vd;
      }
      delete [] id;
   } else {
      nnode = GetNode();
   }
   // Now nnode is a cloned node of the one that need to be aligned
   TGeoNodeMatrix *aligned = (TGeoNodeMatrix*)nnode;
   vm = nnode->GetMotherVolume();
   vd = nnode->GetVolume();
   if (newmat) {
      // Check if the old matrix for this node was shared
      Bool_t shared = kFALSE;
      Int_t nd = vm->GetNdaughters();
      TGeoCompositeShape *cs;
      if (nnode->GetMatrix()->IsShared()) {
         // Now find the node having a composite shape using this shared matrix
         for (i=0; i<nd; i++) {
            node = vm->GetNode(i);
            if (node==nnode) continue;
            if (node->IsOffset()) continue;
            if (!node->GetVolume()->GetShape()->IsComposite()) continue;
            // We found a node having a composite shape, scan for the shared matrix
            cs = (TGeoCompositeShape*)node->GetVolume()->GetShape();
            if (cs->GetBoolNode()->GetRightMatrix() != nnode->GetMatrix()) continue;
            // The composite uses the matrix -> replace it
            TGeoCompositeShape *ncs = new TGeoCompositeShape(cs->GetName(), cs->GetBoolNode()->MakeClone());
            ncs->GetBoolNode()->ReplaceMatrix(nnode->GetMatrix(), newmat);
            // We have to clone the node/volume having the composite shape
            TGeoVolume *newvol = node->GetVolume()->CloneVolume();
            if (!newvol) {
               Error("Align", "Cannot clone volume %s", node->GetVolume()->GetName());
               return kFALSE;
            }
            newvol->SetShape(ncs);
            TGeoNode *newnode = node->MakeCopyNode();
            if (!newnode) {
               Error("Align", "Cannot clone node %s", node->GetName());
               return kFALSE;
            }
            newnode->SetVolume(newvol);
            newnode->SetMotherVolume(vm);
            if (vm->TestBit(TGeoVolume::kVolumeImportNodes)) {
               gGeoManager->GetListOfGShapes()->Add(newnode);
            }
            vm->GetNodes()->RemoveAt(i);
            vm->GetNodes()->AddAt(newnode,i);
            shared = kTRUE;
         }
         if (!shared) Error("Align", "The matrix replaced for %s is not actually shared", GetName());
      } else {
         // The aligned node may have a composite shape containing a shared matrix
         if (vd->GetShape()->IsComposite()) {
            cs = (TGeoCompositeShape*)vd->GetShape();
            if (cs->GetBoolNode()->GetRightMatrix()->IsShared()) {
               if (!nnode->GetMatrix()->IsIdentity()) {
                  Error("Align", "The composite shape having a shared matrix on the subtracted branch must be positioned using identity matrix.");
                  return kFALSE;
               }
               // We have to put the alignment matrix on top of the left branch
               // of the composite shape. The node is already decoupled from logical tree.
               TGeoCompositeShape *ncs = new TGeoCompositeShape(cs->GetName(), cs->GetBoolNode()->MakeClone());
               TGeoMatrix *oldmat = ncs->GetBoolNode()->GetLeftMatrix();
               TGeoHMatrix *newmat1 = new TGeoHMatrix(*newmat);
               newmat1->Multiply(oldmat);
               ncs->GetBoolNode()->ReplaceMatrix(oldmat, newmat1);
               vd->SetShape(ncs);
               // The right-side matrix pointer is preserved, so no need to update nodes.
               aligned = 0; // to prevent updating its matrix
            }
         }
      }      
      // Register matrix and make it the active one
      if (!newmat->IsRegistered()) newmat->RegisterYourself();
      if (aligned) {
         aligned->SetMatrix(newmat);
         // Update the global matrix for the aligned node
         TGeoHMatrix *global = GetMatrix();
         TGeoHMatrix *up = GetMatrix(fLevel-1);
         *global = up;
         global->Multiply(newmat);
      }   
   }
   // Change the shape for the aligned node
   if (newshape) vd->SetShape(newshape);

   // Re-compute bounding box of mother(s) if needed
   for (i=fLevel-1; i>0; i--) {
      Bool_t dassm = vd->IsAssembly(); // is daughter assembly ?
      vd = GetVolume(i);
      if (!vd) break;
      Bool_t cassm = vd->IsAssembly(); // is current assembly ?
      if (cassm) ((TGeoShapeAssembly*)vd->GetShape())->NeedsBBoxRecompute();
      if ((cassm || dassm) && vd->GetVoxels()) vd->GetVoxels()->SetNeedRebuild();
      if (!cassm) break;
   }

   // Now we have to re-voxelize the mother volume
   TGeoVoxelFinder *voxels = vm->GetVoxels();
   if (voxels) voxels->SetNeedRebuild();
   // Eventually check for overlaps
   if (check) {
      if (voxels) {
         voxels->Voxelize();
         vm->FindOverlaps();
      }
      // Set aligned node to be checked
      i = fLevel;
      node = GetNode(i);
      if (!node) return kTRUE;
      if (node->IsOverlapping()) {
         Info("Align", "The check for overlaps for node: \n%s\n cannot be performed since the node is declared possibly overlapping",
              GetName());
      } else {
         gGeoManager->SetCheckedNode(node);
         // Check overlaps for the first non-assembly parent node
         while ((node=GetNode(--i))) {
            if (!node->GetVolume()->IsAssembly()) break;
         }
         if (node && node->IsOverlapping()) {
            Info("Align", "The check for overlaps for assembly node: \n%s\n cannot be performed since the parent %s is declared possibly overlapping",
                 GetName(), node->GetName());
            node = 0;
         }
         if (node) node->CheckOverlaps(ovlp);
         gGeoManager->SetCheckedNode(0);
      }
   }
   // Clean current matrices from cache
   gGeoManager->CdTop();
   SetAligned(kTRUE);
   return kTRUE;
}

//_____________________________________________________________________________
void TGeoPhysicalNode::cd() const
{
   if (GetNode(0) != gGeoManager->GetTopNode()) return;
   gGeoManager->cd(fName.Data());
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Draw(Option_t * /*option*/)
{
// Draw this node.
}

//_____________________________________________________________________________
TGeoNode *TGeoPhysicalNode::GetMother(Int_t levup) const
{
// Return parent at LEVUP generation
   Int_t ind = fLevel-levup;
   if (ind<0) return 0;
   return (TGeoNode*)fNodes->UncheckedAt(ind);
}

//_____________________________________________________________________________
TGeoHMatrix *TGeoPhysicalNode::GetMatrix(Int_t level) const
{
// Return global matrix for node at LEVEL.
   if (level<0) return (TGeoHMatrix*)fMatrices->UncheckedAt(fLevel);
   if (level>fLevel) return 0;
   return (TGeoHMatrix*)fMatrices->UncheckedAt(level);
}

//_____________________________________________________________________________
TGeoNode *TGeoPhysicalNode::GetNode(Int_t level) const
{
// Return node in branch at LEVEL. If not specified, return last leaf.
   if (level<0) return (TGeoNode*)fNodes->UncheckedAt(fLevel);
   if (level>fLevel) return 0;
   return (TGeoNode*)fNodes->UncheckedAt(level);
}

//_____________________________________________________________________________
TGeoVolume *TGeoPhysicalNode::GetVolume(Int_t level) const
{
// Return volume associated with node at LEVEL in the branch
   TGeoNode *node = GetNode(level);
   if (node) return node->GetVolume();
   return 0;
}

//_____________________________________________________________________________
TGeoShape *TGeoPhysicalNode::GetShape(Int_t level) const
{
// Return shape associated with volume.
   TGeoVolume *vol = GetVolume(level);
   if (vol) return vol->GetShape();
   return 0;
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Paint(Option_t * /*option*/)
{
// Paint this node and its content according to visualization settings.
   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
   if (!painter) return;
//   painter->PaintNode(this, option);
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Print(Option_t * /*option*/) const
{
// Print info about this node.
   printf("TGeoPhysicalNode: %s level=%d aligned=%d\n", fName.Data(), fLevel, IsAligned());
   for (Int_t i=0; i<=fLevel; i++) {
      printf(" level %d: node %s\n", i, GetNode(i)->GetName());
      printf(" local matrix:\n");
      if (GetNode(i)->GetMatrix()->IsIdentity()) printf("   IDENTITY\n");
      else GetNode(i)->GetMatrix()->Print();
      printf(" global matrix:\n");
      if (GetMatrix(i)->IsIdentity()) printf("   IDENTITY\n");
      else GetMatrix(i)->Print();
   }
   if (IsAligned() && fMatrixOrig) {
      printf(" original local matrix:\n");
      fMatrixOrig->Print();
   }
}

//_____________________________________________________________________________
void TGeoPhysicalNode::Refresh()
{
// Refresh this physical node. Called for all registered physical nodes
// after an Align() call.
   SetPath(fName.Data());
}

//_____________________________________________________________________________
void TGeoPhysicalNode::SetBranchAsState()
{
// Set node branch according to current state
   TGeoNodeCache *cache = gGeoManager->GetCache();
   if (!cache) {
      Error("SetBranchAsState","no state available");
      return;
   }
   if (!cache->IsDummy()) {
      Error("SetBranchAsState", "not implemented for full cache");
      return;
   }
   if (!fNodes)    fNodes = new TObjArray(30);
   if (!fMatrices) fMatrices = new TObjArray(30);
   TGeoHMatrix **matrices = (TGeoHMatrix **) cache->GetMatrices();
   TGeoNode **branch = (TGeoNode **) cache->GetBranch();

   Bool_t refresh = (fLevel>0)?kTRUE:kFALSE;
   if (refresh) {
      TGeoHMatrix *current;
      for (Int_t i=0; i<=fLevel; i++) {
         fNodes->AddAtAndExpand(branch[i],i);
         current = (TGeoHMatrix*)fMatrices->UncheckedAt(i);
         *current = *matrices[i];
      }
      return;
   }
   fLevel = gGeoManager->GetLevel();
   for (Int_t i=0; i<=fLevel; i++) {
      fNodes->AddAtAndExpand(branch[i],i);
      fMatrices->AddAtAndExpand(new TGeoHMatrix(*matrices[i]),i);
   }
   TGeoNode *node = (TGeoNode*)fNodes->UncheckedAt(fLevel);
   if (!fMatrixOrig) fMatrixOrig = new TGeoHMatrix();
   *fMatrixOrig = node->GetMatrix();
}

//_____________________________________________________________________________
void TGeoPhysicalNode::SetMatrixOrig(const TGeoMatrix *local)
{
// Allows PN entries (or users) to preset the local original matrix for the
// last node pointed by the path.
   if (!fMatrixOrig) fMatrixOrig = new TGeoHMatrix();
   if (!local) fMatrixOrig->Clear();
   *fMatrixOrig = local;
}

//_____________________________________________________________________________
Bool_t TGeoPhysicalNode::SetPath(const char *path)
{
// Specify the path for this node.
   if (!gGeoManager->cd(path)) {
      Error("SetPath","wrong path -> maybe RestoreMasterVolume");
      return kFALSE;
   }
   SetBranchAsState();
   return kTRUE;
}

//_____________________________________________________________________________
Bool_t TGeoPhysicalNode::IsMatchingState(TGeoNavigator *nav) const
{
// Checks if a given navigator state matches this physical node
   TGeoNodeCache *cache = nav->GetCache();
   if (!cache) {
      Fatal("SetBranchAsState","no state available");
      return kFALSE;
   }
   TGeoNode **branch = (TGeoNode **) cache->GetBranch();
   for (Int_t i=1; i<=fLevel; i++)
      if (fNodes->At(i) != branch[i]) return kFALSE;
   return kTRUE;   
}   

ClassImp(TGeoPNEntry)

//_____________________________________________________________________________
TGeoPNEntry::TGeoPNEntry()
{
// Default constructor
   fNode = 0;
   fMatrix = 0;
   fGlobalOrig = 0;
}

//_____________________________________________________________________________
TGeoPNEntry::TGeoPNEntry(const char *name, const char *path)
            :TNamed(name, path)
{
// Default constructor
   if (!gGeoManager || !gGeoManager->IsClosed() || !gGeoManager->CheckPath(path)) {
      TString errmsg("Cannot define a physical node link without a closed geometry and a valid path !");
      Error("ctor", "%s", errmsg.Data());
      throw errmsg;
      return;
   }
   gGeoManager->PushPath();
   gGeoManager->cd(path);
   fGlobalOrig = new TGeoHMatrix();
   *fGlobalOrig = gGeoManager->GetCurrentMatrix();
   gGeoManager->PopPath();
   fNode = 0;
   fMatrix = 0;
}

//_____________________________________________________________________________
TGeoPNEntry::~TGeoPNEntry()
{
// Destructor
   if (fMatrix && !fMatrix->IsRegistered()) delete fMatrix;
   delete fGlobalOrig;
}

//_____________________________________________________________________________
void TGeoPNEntry::SetPhysicalNode(TGeoPhysicalNode *node)
{
// Setter for the corresponding physical node.
   if (fNode && node) {
      Warning("SetPhysicalNode", "Physical node changed for entry %s", GetName());
      Warning("SetPhysicalNode", "=== New path: %s", node->GetName());
   }
   fNode = node;
}

//_____________________________________________________________________________
void TGeoPNEntry::SetMatrix(const TGeoHMatrix *mat)
{
// Set the additional matrix for this node entry. The matrix will be deleted
// by this class unless registered by the user to gGeoManager
   fMatrix = mat;
}
 TGeoPhysicalNode.cxx:1
 TGeoPhysicalNode.cxx:2
 TGeoPhysicalNode.cxx:3
 TGeoPhysicalNode.cxx:4
 TGeoPhysicalNode.cxx:5
 TGeoPhysicalNode.cxx:6
 TGeoPhysicalNode.cxx:7
 TGeoPhysicalNode.cxx:8
 TGeoPhysicalNode.cxx:9
 TGeoPhysicalNode.cxx:10
 TGeoPhysicalNode.cxx:11
 TGeoPhysicalNode.cxx:12
 TGeoPhysicalNode.cxx:13
 TGeoPhysicalNode.cxx:14
 TGeoPhysicalNode.cxx:15
 TGeoPhysicalNode.cxx:16
 TGeoPhysicalNode.cxx:17
 TGeoPhysicalNode.cxx:18
 TGeoPhysicalNode.cxx:19
 TGeoPhysicalNode.cxx:20
 TGeoPhysicalNode.cxx:21
 TGeoPhysicalNode.cxx:22
 TGeoPhysicalNode.cxx:23
 TGeoPhysicalNode.cxx:24
 TGeoPhysicalNode.cxx:25
 TGeoPhysicalNode.cxx:26
 TGeoPhysicalNode.cxx:27
 TGeoPhysicalNode.cxx:28
 TGeoPhysicalNode.cxx:29
 TGeoPhysicalNode.cxx:30
 TGeoPhysicalNode.cxx:31
 TGeoPhysicalNode.cxx:32
 TGeoPhysicalNode.cxx:33
 TGeoPhysicalNode.cxx:34
 TGeoPhysicalNode.cxx:35
 TGeoPhysicalNode.cxx:36
 TGeoPhysicalNode.cxx:37
 TGeoPhysicalNode.cxx:38
 TGeoPhysicalNode.cxx:39
 TGeoPhysicalNode.cxx:40
 TGeoPhysicalNode.cxx:41
 TGeoPhysicalNode.cxx:42
 TGeoPhysicalNode.cxx:43
 TGeoPhysicalNode.cxx:44
 TGeoPhysicalNode.cxx:45
 TGeoPhysicalNode.cxx:46
 TGeoPhysicalNode.cxx:47
 TGeoPhysicalNode.cxx:48
 TGeoPhysicalNode.cxx:49
 TGeoPhysicalNode.cxx:50
 TGeoPhysicalNode.cxx:51
 TGeoPhysicalNode.cxx:52
 TGeoPhysicalNode.cxx:53
 TGeoPhysicalNode.cxx:54
 TGeoPhysicalNode.cxx:55
 TGeoPhysicalNode.cxx:56
 TGeoPhysicalNode.cxx:57
 TGeoPhysicalNode.cxx:58
 TGeoPhysicalNode.cxx:59
 TGeoPhysicalNode.cxx:60
 TGeoPhysicalNode.cxx:61
 TGeoPhysicalNode.cxx:62
 TGeoPhysicalNode.cxx:63
 TGeoPhysicalNode.cxx:64
 TGeoPhysicalNode.cxx:65
 TGeoPhysicalNode.cxx:66
 TGeoPhysicalNode.cxx:67
 TGeoPhysicalNode.cxx:68
 TGeoPhysicalNode.cxx:69
 TGeoPhysicalNode.cxx:70
 TGeoPhysicalNode.cxx:71
 TGeoPhysicalNode.cxx:72
 TGeoPhysicalNode.cxx:73
 TGeoPhysicalNode.cxx:74
 TGeoPhysicalNode.cxx:75
 TGeoPhysicalNode.cxx:76
 TGeoPhysicalNode.cxx:77
 TGeoPhysicalNode.cxx:78
 TGeoPhysicalNode.cxx:79
 TGeoPhysicalNode.cxx:80
 TGeoPhysicalNode.cxx:81
 TGeoPhysicalNode.cxx:82
 TGeoPhysicalNode.cxx:83
 TGeoPhysicalNode.cxx:84
 TGeoPhysicalNode.cxx:85
 TGeoPhysicalNode.cxx:86
 TGeoPhysicalNode.cxx:87
 TGeoPhysicalNode.cxx:88
 TGeoPhysicalNode.cxx:89
 TGeoPhysicalNode.cxx:90
 TGeoPhysicalNode.cxx:91
 TGeoPhysicalNode.cxx:92
 TGeoPhysicalNode.cxx:93
 TGeoPhysicalNode.cxx:94
 TGeoPhysicalNode.cxx:95
 TGeoPhysicalNode.cxx:96
 TGeoPhysicalNode.cxx:97
 TGeoPhysicalNode.cxx:98
 TGeoPhysicalNode.cxx:99
 TGeoPhysicalNode.cxx:100
 TGeoPhysicalNode.cxx:101
 TGeoPhysicalNode.cxx:102
 TGeoPhysicalNode.cxx:103
 TGeoPhysicalNode.cxx:104
 TGeoPhysicalNode.cxx:105
 TGeoPhysicalNode.cxx:106
 TGeoPhysicalNode.cxx:107
 TGeoPhysicalNode.cxx:108
 TGeoPhysicalNode.cxx:109
 TGeoPhysicalNode.cxx:110
 TGeoPhysicalNode.cxx:111
 TGeoPhysicalNode.cxx:112
 TGeoPhysicalNode.cxx:113
 TGeoPhysicalNode.cxx:114
 TGeoPhysicalNode.cxx:115
 TGeoPhysicalNode.cxx:116
 TGeoPhysicalNode.cxx:117
 TGeoPhysicalNode.cxx:118
 TGeoPhysicalNode.cxx:119
 TGeoPhysicalNode.cxx:120
 TGeoPhysicalNode.cxx:121
 TGeoPhysicalNode.cxx:122
 TGeoPhysicalNode.cxx:123
 TGeoPhysicalNode.cxx:124
 TGeoPhysicalNode.cxx:125
 TGeoPhysicalNode.cxx:126
 TGeoPhysicalNode.cxx:127
 TGeoPhysicalNode.cxx:128
 TGeoPhysicalNode.cxx:129
 TGeoPhysicalNode.cxx:130
 TGeoPhysicalNode.cxx:131
 TGeoPhysicalNode.cxx:132
 TGeoPhysicalNode.cxx:133
 TGeoPhysicalNode.cxx:134
 TGeoPhysicalNode.cxx:135
 TGeoPhysicalNode.cxx:136
 TGeoPhysicalNode.cxx:137
 TGeoPhysicalNode.cxx:138
 TGeoPhysicalNode.cxx:139
 TGeoPhysicalNode.cxx:140
 TGeoPhysicalNode.cxx:141
 TGeoPhysicalNode.cxx:142
 TGeoPhysicalNode.cxx:143
 TGeoPhysicalNode.cxx:144
 TGeoPhysicalNode.cxx:145
 TGeoPhysicalNode.cxx:146
 TGeoPhysicalNode.cxx:147
 TGeoPhysicalNode.cxx:148
 TGeoPhysicalNode.cxx:149
 TGeoPhysicalNode.cxx:150
 TGeoPhysicalNode.cxx:151
 TGeoPhysicalNode.cxx:152
 TGeoPhysicalNode.cxx:153
 TGeoPhysicalNode.cxx:154
 TGeoPhysicalNode.cxx:155
 TGeoPhysicalNode.cxx:156
 TGeoPhysicalNode.cxx:157
 TGeoPhysicalNode.cxx:158
 TGeoPhysicalNode.cxx:159
 TGeoPhysicalNode.cxx:160
 TGeoPhysicalNode.cxx:161
 TGeoPhysicalNode.cxx:162
 TGeoPhysicalNode.cxx:163
 TGeoPhysicalNode.cxx:164
 TGeoPhysicalNode.cxx:165
 TGeoPhysicalNode.cxx:166
 TGeoPhysicalNode.cxx:167
 TGeoPhysicalNode.cxx:168
 TGeoPhysicalNode.cxx:169
 TGeoPhysicalNode.cxx:170
 TGeoPhysicalNode.cxx:171
 TGeoPhysicalNode.cxx:172
 TGeoPhysicalNode.cxx:173
 TGeoPhysicalNode.cxx:174
 TGeoPhysicalNode.cxx:175
 TGeoPhysicalNode.cxx:176
 TGeoPhysicalNode.cxx:177
 TGeoPhysicalNode.cxx:178
 TGeoPhysicalNode.cxx:179
 TGeoPhysicalNode.cxx:180
 TGeoPhysicalNode.cxx:181
 TGeoPhysicalNode.cxx:182
 TGeoPhysicalNode.cxx:183
 TGeoPhysicalNode.cxx:184
 TGeoPhysicalNode.cxx:185
 TGeoPhysicalNode.cxx:186
 TGeoPhysicalNode.cxx:187
 TGeoPhysicalNode.cxx:188
 TGeoPhysicalNode.cxx:189
 TGeoPhysicalNode.cxx:190
 TGeoPhysicalNode.cxx:191
 TGeoPhysicalNode.cxx:192
 TGeoPhysicalNode.cxx:193
 TGeoPhysicalNode.cxx:194
 TGeoPhysicalNode.cxx:195
 TGeoPhysicalNode.cxx:196
 TGeoPhysicalNode.cxx:197
 TGeoPhysicalNode.cxx:198
 TGeoPhysicalNode.cxx:199
 TGeoPhysicalNode.cxx:200
 TGeoPhysicalNode.cxx:201
 TGeoPhysicalNode.cxx:202
 TGeoPhysicalNode.cxx:203
 TGeoPhysicalNode.cxx:204
 TGeoPhysicalNode.cxx:205
 TGeoPhysicalNode.cxx:206
 TGeoPhysicalNode.cxx:207
 TGeoPhysicalNode.cxx:208
 TGeoPhysicalNode.cxx:209
 TGeoPhysicalNode.cxx:210
 TGeoPhysicalNode.cxx:211
 TGeoPhysicalNode.cxx:212
 TGeoPhysicalNode.cxx:213
 TGeoPhysicalNode.cxx:214
 TGeoPhysicalNode.cxx:215
 TGeoPhysicalNode.cxx:216
 TGeoPhysicalNode.cxx:217
 TGeoPhysicalNode.cxx:218
 TGeoPhysicalNode.cxx:219
 TGeoPhysicalNode.cxx:220
 TGeoPhysicalNode.cxx:221
 TGeoPhysicalNode.cxx:222
 TGeoPhysicalNode.cxx:223
 TGeoPhysicalNode.cxx:224
 TGeoPhysicalNode.cxx:225
 TGeoPhysicalNode.cxx:226
 TGeoPhysicalNode.cxx:227
 TGeoPhysicalNode.cxx:228
 TGeoPhysicalNode.cxx:229
 TGeoPhysicalNode.cxx:230
 TGeoPhysicalNode.cxx:231
 TGeoPhysicalNode.cxx:232
 TGeoPhysicalNode.cxx:233
 TGeoPhysicalNode.cxx:234
 TGeoPhysicalNode.cxx:235
 TGeoPhysicalNode.cxx:236
 TGeoPhysicalNode.cxx:237
 TGeoPhysicalNode.cxx:238
 TGeoPhysicalNode.cxx:239
 TGeoPhysicalNode.cxx:240
 TGeoPhysicalNode.cxx:241
 TGeoPhysicalNode.cxx:242
 TGeoPhysicalNode.cxx:243
 TGeoPhysicalNode.cxx:244
 TGeoPhysicalNode.cxx:245
 TGeoPhysicalNode.cxx:246
 TGeoPhysicalNode.cxx:247
 TGeoPhysicalNode.cxx:248
 TGeoPhysicalNode.cxx:249
 TGeoPhysicalNode.cxx:250
 TGeoPhysicalNode.cxx:251
 TGeoPhysicalNode.cxx:252
 TGeoPhysicalNode.cxx:253
 TGeoPhysicalNode.cxx:254
 TGeoPhysicalNode.cxx:255
 TGeoPhysicalNode.cxx:256
 TGeoPhysicalNode.cxx:257
 TGeoPhysicalNode.cxx:258
 TGeoPhysicalNode.cxx:259
 TGeoPhysicalNode.cxx:260
 TGeoPhysicalNode.cxx:261
 TGeoPhysicalNode.cxx:262
 TGeoPhysicalNode.cxx:263
 TGeoPhysicalNode.cxx:264
 TGeoPhysicalNode.cxx:265
 TGeoPhysicalNode.cxx:266
 TGeoPhysicalNode.cxx:267
 TGeoPhysicalNode.cxx:268
 TGeoPhysicalNode.cxx:269
 TGeoPhysicalNode.cxx:270
 TGeoPhysicalNode.cxx:271
 TGeoPhysicalNode.cxx:272
 TGeoPhysicalNode.cxx:273
 TGeoPhysicalNode.cxx:274
 TGeoPhysicalNode.cxx:275
 TGeoPhysicalNode.cxx:276
 TGeoPhysicalNode.cxx:277
 TGeoPhysicalNode.cxx:278
 TGeoPhysicalNode.cxx:279
 TGeoPhysicalNode.cxx:280
 TGeoPhysicalNode.cxx:281
 TGeoPhysicalNode.cxx:282
 TGeoPhysicalNode.cxx:283
 TGeoPhysicalNode.cxx:284
 TGeoPhysicalNode.cxx:285
 TGeoPhysicalNode.cxx:286
 TGeoPhysicalNode.cxx:287
 TGeoPhysicalNode.cxx:288
 TGeoPhysicalNode.cxx:289
 TGeoPhysicalNode.cxx:290
 TGeoPhysicalNode.cxx:291
 TGeoPhysicalNode.cxx:292
 TGeoPhysicalNode.cxx:293
 TGeoPhysicalNode.cxx:294
 TGeoPhysicalNode.cxx:295
 TGeoPhysicalNode.cxx:296
 TGeoPhysicalNode.cxx:297
 TGeoPhysicalNode.cxx:298
 TGeoPhysicalNode.cxx:299
 TGeoPhysicalNode.cxx:300
 TGeoPhysicalNode.cxx:301
 TGeoPhysicalNode.cxx:302
 TGeoPhysicalNode.cxx:303
 TGeoPhysicalNode.cxx:304
 TGeoPhysicalNode.cxx:305
 TGeoPhysicalNode.cxx:306
 TGeoPhysicalNode.cxx:307
 TGeoPhysicalNode.cxx:308
 TGeoPhysicalNode.cxx:309
 TGeoPhysicalNode.cxx:310
 TGeoPhysicalNode.cxx:311
 TGeoPhysicalNode.cxx:312
 TGeoPhysicalNode.cxx:313
 TGeoPhysicalNode.cxx:314
 TGeoPhysicalNode.cxx:315
 TGeoPhysicalNode.cxx:316
 TGeoPhysicalNode.cxx:317
 TGeoPhysicalNode.cxx:318
 TGeoPhysicalNode.cxx:319
 TGeoPhysicalNode.cxx:320
 TGeoPhysicalNode.cxx:321
 TGeoPhysicalNode.cxx:322
 TGeoPhysicalNode.cxx:323
 TGeoPhysicalNode.cxx:324
 TGeoPhysicalNode.cxx:325
 TGeoPhysicalNode.cxx:326
 TGeoPhysicalNode.cxx:327
 TGeoPhysicalNode.cxx:328
 TGeoPhysicalNode.cxx:329
 TGeoPhysicalNode.cxx:330
 TGeoPhysicalNode.cxx:331
 TGeoPhysicalNode.cxx:332
 TGeoPhysicalNode.cxx:333
 TGeoPhysicalNode.cxx:334
 TGeoPhysicalNode.cxx:335
 TGeoPhysicalNode.cxx:336
 TGeoPhysicalNode.cxx:337
 TGeoPhysicalNode.cxx:338
 TGeoPhysicalNode.cxx:339
 TGeoPhysicalNode.cxx:340
 TGeoPhysicalNode.cxx:341
 TGeoPhysicalNode.cxx:342
 TGeoPhysicalNode.cxx:343
 TGeoPhysicalNode.cxx:344
 TGeoPhysicalNode.cxx:345
 TGeoPhysicalNode.cxx:346
 TGeoPhysicalNode.cxx:347
 TGeoPhysicalNode.cxx:348
 TGeoPhysicalNode.cxx:349
 TGeoPhysicalNode.cxx:350
 TGeoPhysicalNode.cxx:351
 TGeoPhysicalNode.cxx:352
 TGeoPhysicalNode.cxx:353
 TGeoPhysicalNode.cxx:354
 TGeoPhysicalNode.cxx:355
 TGeoPhysicalNode.cxx:356
 TGeoPhysicalNode.cxx:357
 TGeoPhysicalNode.cxx:358
 TGeoPhysicalNode.cxx:359
 TGeoPhysicalNode.cxx:360
 TGeoPhysicalNode.cxx:361
 TGeoPhysicalNode.cxx:362
 TGeoPhysicalNode.cxx:363
 TGeoPhysicalNode.cxx:364
 TGeoPhysicalNode.cxx:365
 TGeoPhysicalNode.cxx:366
 TGeoPhysicalNode.cxx:367
 TGeoPhysicalNode.cxx:368
 TGeoPhysicalNode.cxx:369
 TGeoPhysicalNode.cxx:370
 TGeoPhysicalNode.cxx:371
 TGeoPhysicalNode.cxx:372
 TGeoPhysicalNode.cxx:373
 TGeoPhysicalNode.cxx:374
 TGeoPhysicalNode.cxx:375
 TGeoPhysicalNode.cxx:376
 TGeoPhysicalNode.cxx:377
 TGeoPhysicalNode.cxx:378
 TGeoPhysicalNode.cxx:379
 TGeoPhysicalNode.cxx:380
 TGeoPhysicalNode.cxx:381
 TGeoPhysicalNode.cxx:382
 TGeoPhysicalNode.cxx:383
 TGeoPhysicalNode.cxx:384
 TGeoPhysicalNode.cxx:385
 TGeoPhysicalNode.cxx:386
 TGeoPhysicalNode.cxx:387
 TGeoPhysicalNode.cxx:388
 TGeoPhysicalNode.cxx:389
 TGeoPhysicalNode.cxx:390
 TGeoPhysicalNode.cxx:391
 TGeoPhysicalNode.cxx:392
 TGeoPhysicalNode.cxx:393
 TGeoPhysicalNode.cxx:394
 TGeoPhysicalNode.cxx:395
 TGeoPhysicalNode.cxx:396
 TGeoPhysicalNode.cxx:397
 TGeoPhysicalNode.cxx:398
 TGeoPhysicalNode.cxx:399
 TGeoPhysicalNode.cxx:400
 TGeoPhysicalNode.cxx:401
 TGeoPhysicalNode.cxx:402
 TGeoPhysicalNode.cxx:403
 TGeoPhysicalNode.cxx:404
 TGeoPhysicalNode.cxx:405
 TGeoPhysicalNode.cxx:406
 TGeoPhysicalNode.cxx:407
 TGeoPhysicalNode.cxx:408
 TGeoPhysicalNode.cxx:409
 TGeoPhysicalNode.cxx:410
 TGeoPhysicalNode.cxx:411
 TGeoPhysicalNode.cxx:412
 TGeoPhysicalNode.cxx:413
 TGeoPhysicalNode.cxx:414
 TGeoPhysicalNode.cxx:415
 TGeoPhysicalNode.cxx:416
 TGeoPhysicalNode.cxx:417
 TGeoPhysicalNode.cxx:418
 TGeoPhysicalNode.cxx:419
 TGeoPhysicalNode.cxx:420
 TGeoPhysicalNode.cxx:421
 TGeoPhysicalNode.cxx:422
 TGeoPhysicalNode.cxx:423
 TGeoPhysicalNode.cxx:424
 TGeoPhysicalNode.cxx:425
 TGeoPhysicalNode.cxx:426
 TGeoPhysicalNode.cxx:427
 TGeoPhysicalNode.cxx:428
 TGeoPhysicalNode.cxx:429
 TGeoPhysicalNode.cxx:430
 TGeoPhysicalNode.cxx:431
 TGeoPhysicalNode.cxx:432
 TGeoPhysicalNode.cxx:433
 TGeoPhysicalNode.cxx:434
 TGeoPhysicalNode.cxx:435
 TGeoPhysicalNode.cxx:436
 TGeoPhysicalNode.cxx:437
 TGeoPhysicalNode.cxx:438
 TGeoPhysicalNode.cxx:439
 TGeoPhysicalNode.cxx:440
 TGeoPhysicalNode.cxx:441
 TGeoPhysicalNode.cxx:442
 TGeoPhysicalNode.cxx:443
 TGeoPhysicalNode.cxx:444
 TGeoPhysicalNode.cxx:445
 TGeoPhysicalNode.cxx:446
 TGeoPhysicalNode.cxx:447
 TGeoPhysicalNode.cxx:448
 TGeoPhysicalNode.cxx:449
 TGeoPhysicalNode.cxx:450
 TGeoPhysicalNode.cxx:451
 TGeoPhysicalNode.cxx:452
 TGeoPhysicalNode.cxx:453
 TGeoPhysicalNode.cxx:454
 TGeoPhysicalNode.cxx:455
 TGeoPhysicalNode.cxx:456
 TGeoPhysicalNode.cxx:457
 TGeoPhysicalNode.cxx:458
 TGeoPhysicalNode.cxx:459
 TGeoPhysicalNode.cxx:460
 TGeoPhysicalNode.cxx:461
 TGeoPhysicalNode.cxx:462
 TGeoPhysicalNode.cxx:463
 TGeoPhysicalNode.cxx:464
 TGeoPhysicalNode.cxx:465
 TGeoPhysicalNode.cxx:466
 TGeoPhysicalNode.cxx:467
 TGeoPhysicalNode.cxx:468
 TGeoPhysicalNode.cxx:469
 TGeoPhysicalNode.cxx:470
 TGeoPhysicalNode.cxx:471
 TGeoPhysicalNode.cxx:472
 TGeoPhysicalNode.cxx:473
 TGeoPhysicalNode.cxx:474
 TGeoPhysicalNode.cxx:475
 TGeoPhysicalNode.cxx:476
 TGeoPhysicalNode.cxx:477
 TGeoPhysicalNode.cxx:478
 TGeoPhysicalNode.cxx:479
 TGeoPhysicalNode.cxx:480
 TGeoPhysicalNode.cxx:481
 TGeoPhysicalNode.cxx:482
 TGeoPhysicalNode.cxx:483
 TGeoPhysicalNode.cxx:484
 TGeoPhysicalNode.cxx:485
 TGeoPhysicalNode.cxx:486
 TGeoPhysicalNode.cxx:487
 TGeoPhysicalNode.cxx:488
 TGeoPhysicalNode.cxx:489
 TGeoPhysicalNode.cxx:490
 TGeoPhysicalNode.cxx:491
 TGeoPhysicalNode.cxx:492
 TGeoPhysicalNode.cxx:493
 TGeoPhysicalNode.cxx:494
 TGeoPhysicalNode.cxx:495
 TGeoPhysicalNode.cxx:496
 TGeoPhysicalNode.cxx:497
 TGeoPhysicalNode.cxx:498
 TGeoPhysicalNode.cxx:499
 TGeoPhysicalNode.cxx:500
 TGeoPhysicalNode.cxx:501
 TGeoPhysicalNode.cxx:502
 TGeoPhysicalNode.cxx:503
 TGeoPhysicalNode.cxx:504
 TGeoPhysicalNode.cxx:505
 TGeoPhysicalNode.cxx:506
 TGeoPhysicalNode.cxx:507
 TGeoPhysicalNode.cxx:508
 TGeoPhysicalNode.cxx:509
 TGeoPhysicalNode.cxx:510
 TGeoPhysicalNode.cxx:511
 TGeoPhysicalNode.cxx:512
 TGeoPhysicalNode.cxx:513
 TGeoPhysicalNode.cxx:514
 TGeoPhysicalNode.cxx:515
 TGeoPhysicalNode.cxx:516
 TGeoPhysicalNode.cxx:517
 TGeoPhysicalNode.cxx:518
 TGeoPhysicalNode.cxx:519
 TGeoPhysicalNode.cxx:520
 TGeoPhysicalNode.cxx:521
 TGeoPhysicalNode.cxx:522
 TGeoPhysicalNode.cxx:523
 TGeoPhysicalNode.cxx:524
 TGeoPhysicalNode.cxx:525
 TGeoPhysicalNode.cxx:526
 TGeoPhysicalNode.cxx:527
 TGeoPhysicalNode.cxx:528
 TGeoPhysicalNode.cxx:529
 TGeoPhysicalNode.cxx:530
 TGeoPhysicalNode.cxx:531
 TGeoPhysicalNode.cxx:532
 TGeoPhysicalNode.cxx:533
 TGeoPhysicalNode.cxx:534
 TGeoPhysicalNode.cxx:535
 TGeoPhysicalNode.cxx:536
 TGeoPhysicalNode.cxx:537
 TGeoPhysicalNode.cxx:538
 TGeoPhysicalNode.cxx:539
 TGeoPhysicalNode.cxx:540
 TGeoPhysicalNode.cxx:541
 TGeoPhysicalNode.cxx:542
 TGeoPhysicalNode.cxx:543
 TGeoPhysicalNode.cxx:544
 TGeoPhysicalNode.cxx:545
 TGeoPhysicalNode.cxx:546
 TGeoPhysicalNode.cxx:547
 TGeoPhysicalNode.cxx:548
 TGeoPhysicalNode.cxx:549
 TGeoPhysicalNode.cxx:550
 TGeoPhysicalNode.cxx:551
 TGeoPhysicalNode.cxx:552
 TGeoPhysicalNode.cxx:553
 TGeoPhysicalNode.cxx:554
 TGeoPhysicalNode.cxx:555
 TGeoPhysicalNode.cxx:556
 TGeoPhysicalNode.cxx:557
 TGeoPhysicalNode.cxx:558
 TGeoPhysicalNode.cxx:559
 TGeoPhysicalNode.cxx:560
 TGeoPhysicalNode.cxx:561
 TGeoPhysicalNode.cxx:562
 TGeoPhysicalNode.cxx:563
 TGeoPhysicalNode.cxx:564
 TGeoPhysicalNode.cxx:565
 TGeoPhysicalNode.cxx:566
 TGeoPhysicalNode.cxx:567
 TGeoPhysicalNode.cxx:568
 TGeoPhysicalNode.cxx:569
 TGeoPhysicalNode.cxx:570
 TGeoPhysicalNode.cxx:571
 TGeoPhysicalNode.cxx:572
 TGeoPhysicalNode.cxx:573
 TGeoPhysicalNode.cxx:574
 TGeoPhysicalNode.cxx:575
 TGeoPhysicalNode.cxx:576