/*
<img src="gif/t_node.jpg">
*/
//End_Html
#include "Riostream.h"
#include "TBrowser.h"
#include "TObjArray.h"
#include "TStyle.h"
#include "TGeoManager.h"
#include "TGeoMatrix.h"
#include "TGeoShape.h"
#include "TGeoVolume.h"
#include "TVirtualGeoPainter.h"
#include "TGeoNode.h"
#include "TMath.h"
ClassImp(TGeoNode)
TGeoNode::TGeoNode()
{
   fVolume       = 0;
   fMother       = 0;
   fNumber       = 0;
   fOverlaps     = 0;
   fNovlp        = 0;
}
TGeoNode::TGeoNode(const TGeoVolume *vol)
{
   if (!vol) {
      Error("ctor", "volume not specified");
      return;
   }
   fVolume       = (TGeoVolume*)vol;
   if (fVolume->IsAdded()) fVolume->SetReplicated();
   fVolume->SetAdded();
   fMother       = 0;
   fNumber       = 0;
   fOverlaps     = 0;
   fNovlp        = 0;
}
TGeoNode::TGeoNode(const TGeoNode& gn) :
  TNamed(gn),
  TGeoAtt(gn),
  fVolume(gn.fVolume),
  fMother(gn.fMother),
  fNumber(gn.fNumber),
  fNovlp(gn.fNovlp),
  fOverlaps(gn.fOverlaps)
{ 
   
}
TGeoNode& TGeoNode::operator=(const TGeoNode& gn) 
{
   
   if(this!=&gn) {
      TNamed::operator=(gn);
      TGeoAtt::operator=(gn);
      fVolume=gn.fVolume;
      fMother=gn.fMother;
      fNumber=gn.fNumber;
      fNovlp=gn.fNovlp;
      fOverlaps=gn.fOverlaps;
   } 
   return *this;
}
TGeoNode::~TGeoNode()
{
   if (fOverlaps) delete [] fOverlaps;
}
void TGeoNode::Browse(TBrowser *b)
{
   if (!b) return;
   if (!GetNdaughters()) return;
   TGeoNode *daughter;
   TString title;
   for (Int_t i=0; i<GetNdaughters(); i++) {
      daughter = GetDaughter(i);
      b->Add(daughter, daughter->GetName(), daughter->IsVisible());
   }      
}
void TGeoNode::CheckOverlaps(Double_t ovlp, Option_t *option)
{
   static Int_t icall = 0;
   Int_t i, nd;
   Bool_t clear;
   TGeoNode *daughter;
   TGeoManager *geom = fVolume->GetGeoManager();
   if (icall == 0) {
      geom->ClearOverlaps();
      geom->SetCheckingOverlaps(kTRUE);
      Info("CheckOverlaps", "Checking overlaps for %s and daughters within %g", fVolume->GetName(),ovlp);
   }
   icall++;
   if (!fVolume->IsSelected()) {
      
      fVolume->SelectVolume(clear=kFALSE);
      fVolume->CheckOverlaps(ovlp, option);
      nd = GetNdaughters();
      for (i=0; i<nd; i++) {
         daughter = fVolume->GetNode(i);
         daughter->CheckOverlaps(ovlp, option);
      }
   }
   icall--;
   if (icall == 0) {
      
      fVolume->SelectVolume(clear=kTRUE);
      geom->SortOverlaps();
      TObjArray *overlaps = geom->GetListOfOverlaps();
      Int_t novlps = overlaps->GetEntriesFast();     
      TNamed *obj;
      char name[15];
      char num[15];
      Int_t ndigits=1;
      Int_t j, result=novlps;
      while ((result /= 10)) ndigits++;
      for (i=0; i<novlps; i++) {
         obj = (TNamed*)overlaps->At(i);
         result = i;
         name[0] = 'o';
         name[1] = 'v';
         for (j=0; j<ndigits; j++) name[j+2]='0';
         name[ndigits+2] = 0;
         sprintf(num,"%i", i);
         memcpy(name+2+ndigits-strlen(num), num, strlen(num));
         obj->SetName(name);
      }   
      Info("CheckOverlaps", "Number of illegal overlaps/extrusions : %d\n", novlps);
      geom->SetCheckingOverlaps(kFALSE);
   }   
}      
Int_t TGeoNode::DistancetoPrimitive(Int_t px, Int_t py)
{
   Int_t dist = 9999;
   if (!fVolume) return dist;
   if (gGeoManager != fVolume->GetGeoManager()) gGeoManager = fVolume->GetGeoManager();
   TVirtualGeoPainter *painter = gGeoManager->GetPainter();
   if (!painter) return dist;
   dist = painter->DistanceToPrimitiveVol(fVolume, px, py);
   return dist;
}
      
void TGeoNode::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
   if (!fVolume) return;
   TVirtualGeoPainter *painter = fVolume->GetGeoManager()->GetPainter();
   if (!painter) return;
   painter->ExecuteVolumeEvent(fVolume, event, px, py);
}
char *TGeoNode::GetObjectInfo(Int_t px, Int_t py) const
{
   if (!fVolume) return 0;
   TVirtualGeoPainter *painter = fVolume->GetGeoManager()->GetPainter();
   if (!painter) return 0;
   return painter->GetVolumeInfo(fVolume, px, py);
}
Bool_t TGeoNode::IsOnScreen() const
{
   
   if (fVolume->TestAttBit(TGeoAtt::kVisOnScreen)) return kTRUE;
   return kFALSE;
}
void TGeoNode::InspectNode() const
{
   Info("InspectNode","Inspecting node %s", GetName());
   if (IsOverlapping()) Info("InspectNode","node is MANY");
   if (fOverlaps && fMother) {
      Info("InspectNode","possibly overlaping with :");
      for (Int_t i=0; i<fNovlp; i++)
         Info("InspectNode","   node %s", fMother->GetNode(fOverlaps[i])->GetName());
   }
   Info("InspectNode","Transformation matrix:\n");
   TGeoMatrix *matrix = GetMatrix();
   if (matrix) matrix->Print();
   if (fMother)
      Info("InspectNode","Mother volume %s\n", fMother->GetName());
   fVolume->InspectShape();
}
void TGeoNode::CheckShapes()
{
   fVolume->CheckShapes();
   Int_t nd = GetNdaughters();
   if (!nd) return;
   for (Int_t i=0; i<nd; i++) fVolume->GetNode(i)->CheckShapes();
}
void TGeoNode::DrawOnly(Option_t *option)
{
   fVolume->DrawOnly(option);
}
void TGeoNode::Draw(Option_t *option)
{
   gGeoManager->FindNode();
   gGeoManager->CdUp();
   Double_t point[3];
   gGeoManager->MasterToLocal(gGeoManager->GetCurrentPoint(), &point[0]);
   gGeoManager->SetCurrentPoint(&point[0]);
   gGeoManager->GetCurrentVolume()->Draw(option);
}
void TGeoNode::DrawOverlaps()
{
   if (!fNovlp) {printf("node %s is ONLY\n", GetName()); return;}
   if (!fOverlaps) {printf("node %s no overlaps\n", GetName()); return;}
   TGeoNode *node;
   Int_t i;
   Int_t nd = fMother->GetNdaughters();
   for (i=0; i<nd; i++) {
      node = fMother->GetNode(i);
      node->GetVolume()->SetVisibility(kFALSE);
   }   
   fVolume->SetVisibility(kTRUE);
   for (i=0; i<fNovlp; i++) {
      node = fMother->GetNode(fOverlaps[i]);
      node->GetVolume()->SetVisibility(kTRUE);
   }
   gGeoManager->SetVisLevel(1);
   fMother->Draw();
}
void TGeoNode::FillIdArray(Int_t &ifree, Int_t &nodeid, Int_t *array) const
{
   Int_t nd = GetNdaughters();
   if (!nd) return;
   TGeoNode *daughter;
   Int_t istart = ifree; 
   ifree += nd;
   for (Int_t id=0; id<nd; id++) {
      daughter = GetDaughter(id);
      array[istart+id] = ifree;
      array[ifree++] = ++nodeid;
      daughter->FillIdArray(ifree, nodeid, array);
   }
}      
   
Int_t TGeoNode::FindNode(const TGeoNode *node, Int_t level)
{
   Int_t nd = GetNdaughters();
   if (!nd) return -1;
   TIter next(fVolume->GetNodes());
   TGeoNode *daughter;
   while ((daughter=(TGeoNode*)next())) {
      if (daughter==node) {
         gGeoManager->GetListOfNodes()->AddAt(daughter,level+1);
         return (level+1);
      }
   }
   next.Reset();
   Int_t new_level;
   while ((daughter=(TGeoNode*)next())) {
      new_level = daughter->FindNode(node, level+1);
      if (new_level>=0) {
         gGeoManager->GetListOfNodes()->AddAt(daughter, level+1);
         return new_level;
      }
   }
   return -1;
}
void TGeoNode::SaveAttributes(ostream &out)
{
   if (IsVisStreamed()) return;
   SetVisStreamed(kTRUE);
   char quote='"';
   Bool_t voldef = kFALSE;
   if ((fVolume->IsVisTouched()) && (!fVolume->IsVisStreamed())) {
      fVolume->SetVisStreamed(kTRUE);
      out << "   vol = gGeoManager->GetVolume("<<quote<<fVolume->GetName()<<quote<<");"<<endl;
      voldef = kTRUE;
      if (!fVolume->IsVisDaughters())
         out << "   vol->SetVisDaughters(kFALSE);"<<endl;
      if (fVolume->IsVisible()) {
      } else {
         out <<"   vol->SetVisibility(kFALSE);"<<endl;
      }
   }
   if (!IsVisDaughters()) return;
   Int_t nd = GetNdaughters();
   if (!nd) return;
   TGeoNode *node;
   for (Int_t i=0; i<nd; i++) {
      node = GetDaughter(i);
      if (node->IsVisStreamed()) continue;
      if (node->IsVisTouched()) {
         if (!voldef)
            out << "   vol = gGeoManager->GetVolume("<<quote<<fVolume->GetName()<<quote<<");"<<endl;
         out<<"   node = vol->GetNode("<<i<<");"<<endl;
         if (!node->IsVisDaughters()) {
            out<<"   node->VisibleDaughters(kFALSE);"<<endl;
            node->SetVisStreamed(kTRUE);
            continue;
         }
         if (!node->IsVisible()) 
            out<<"   node->SetVisibility(kFALSE);"<<endl;
      }         
      node->SaveAttributes(out);
      node->SetVisStreamed(kTRUE);
   }
}
Bool_t TGeoNode::MayOverlap(Int_t iother) const 
{
   if (!fOverlaps) return kFALSE;
   for (Int_t i=0; i<fNovlp; i++) if (fOverlaps[i]==iother) return kTRUE;
   return kFALSE;
}   
void TGeoNode::MasterToLocal(const Double_t *master, Double_t *local) const
{
   GetMatrix()->MasterToLocal(master, local);
}
void TGeoNode::MasterToLocalVect(const Double_t *master, Double_t *local) const
{
   GetMatrix()->MasterToLocalVect(master, local);
}
void TGeoNode::LocalToMaster(const Double_t *local, Double_t *master) const
{
   GetMatrix()->LocalToMaster(local, master);
}
void TGeoNode::LocalToMasterVect(const Double_t *local, Double_t *master) const
{
   GetMatrix()->LocalToMasterVect(local, master);
}
void TGeoNode::ls(Option_t * ) const
{
}
void TGeoNode::Paint(Option_t *option)
{
   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
   if (!painter) return;
   painter->PaintNode(this, option);
}
void TGeoNode::PrintCandidates() const
{
   Double_t point[3];
   gGeoManager->MasterToLocal(gGeoManager->GetCurrentPoint(), &point[0]);
   printf("   Local : %g, %g, %g\n", point[0], point[1], point[2]);
   if (!fVolume->Contains(&point[0])) {
      printf("current point not inside this\n");
      return;
   }
   TGeoPatternFinder *finder = fVolume->GetFinder();
   TGeoNode *node;
   if (finder) {
      printf("current node divided\n");
      node = finder->FindNode(&point[0]);
      if (!node) {
         printf("point not inside division element\n");
         return;
      }
      printf("inside division element %s\n", node->GetName());
      return;
   }
   TGeoVoxelFinder *voxels = fVolume->GetVoxels();
   if (!voxels) {
      printf("volume not voxelized\n");
      return;
   }
   Int_t ncheck = 0;
   Int_t *check_list = voxels->GetCheckList(&point[0], ncheck);
   voxels->PrintVoxelLimits(&point[0]);
   if (!check_list) {
      printf("no candidates for current point\n");
      return;
   }
   TString overlap = "ONLY";
   for (Int_t id=0; id<ncheck; id++) {
      node = fVolume->GetNode(check_list[id]);
      if (node->IsOverlapping()) overlap = "MANY";
      else overlap = "ONLY";
      printf("%i %s %s\n", check_list[id], node->GetName(), overlap.Data());
   }
   PrintOverlaps();
}
void TGeoNode::PrintOverlaps() const
{
   if (!fOverlaps) {printf("node %s no overlaps\n", GetName()); return;}
   printf("Overlaps for node %s :\n", GetName());
   TGeoNode *node;
   for (Int_t i=0; i<fNovlp; i++) {
      node = fMother->GetNode(fOverlaps[i]);
      printf("   %s\n", node->GetName());
   }
}
Double_t TGeoNode::Safety(Double_t *point, Bool_t in) const
{
   Double_t local[3];
   GetMatrix()->MasterToLocal(point,local);
   return fVolume->GetShape()->Safety(local,in);
}
void TGeoNode::SetOverlaps(Int_t *ovlp, Int_t novlp)
{
   if (fOverlaps) delete [] fOverlaps;
   fOverlaps = ovlp;
   fNovlp = novlp;
}
void TGeoNode::SetVisibility(Bool_t vis)
{
   if (gGeoManager->IsClosed()) SetVisTouched(kTRUE);
   TGeoAtt::SetVisibility(vis);
   if (vis && !fVolume->IsVisible()) fVolume->SetVisibility(vis);
   gGeoManager->ModifiedPad();
}
void TGeoNode::VisibleDaughters(Bool_t vis)
{
   if (gGeoManager->IsClosed()) SetVisTouched(kTRUE);
   SetVisDaughters(vis);
   gGeoManager->ModifiedPad();
}
/*
<img src=".gif">
*/
//End_Html
ClassImp(TGeoNodeMatrix)
TGeoNodeMatrix::TGeoNodeMatrix()
{
   fMatrix       = 0;
}
TGeoNodeMatrix::TGeoNodeMatrix(const TGeoVolume *vol, const TGeoMatrix *matrix) :
             TGeoNode(vol)
{
   fMatrix = (TGeoMatrix*)matrix;
   if (!fMatrix) fMatrix = gGeoIdentity;
}
TGeoNodeMatrix::~TGeoNodeMatrix()
{
}
Int_t TGeoNodeMatrix::GetByteCount() const
{
   Int_t count = 40 + 4; 
   return count;
}
Int_t TGeoNodeMatrix::GetOptimalVoxels() const
{
   Bool_t type = fVolume->GetShape()->IsCylType();
   if (!type) return 0;
   if (!fMatrix->IsRotAboutZ()) return 0;
   const Double_t *transl = fMatrix->GetTranslation();
   if (TMath::Abs(transl[0])>1E-10) return 0;
   if (TMath::Abs(transl[1])>1E-10) return 0;
   return 1;
}   
TGeoNode *TGeoNodeMatrix::MakeCopyNode() const
{
   TGeoNodeMatrix *node = new TGeoNodeMatrix(fVolume, fMatrix);
   node->SetName(GetName());
   
   node->SetMotherVolume(fMother);
   
   node->SetNumber(fNumber);
   
   if (fNovlp>0) {
      if (fOverlaps) {
         Int_t *ovlps = new Int_t[fNovlp];
         memcpy(ovlps, fOverlaps, fNovlp*sizeof(Int_t));
         node->SetOverlaps(ovlps, fNovlp);
      } else {
         node->SetOverlaps(fOverlaps, fNovlp);
      }
   }
   
   if (IsVirtual()) node->SetVirtual();
   return node;
}
ClassImp(TGeoNodeOffset)
TGeoNodeOffset::TGeoNodeOffset()
{
   TObject::SetBit(kGeoNodeOffset);
   fOffset = 0;
   fIndex = 0;
   fFinder = 0;
}
TGeoNodeOffset::TGeoNodeOffset(const TGeoVolume *vol, Int_t index, Double_t offset) :
           TGeoNode(vol)
{
   TObject::SetBit(kGeoNodeOffset);
   fOffset = offset;
   fIndex = index;
   fFinder = 0;
}
TGeoNodeOffset::TGeoNodeOffset(const TGeoNodeOffset& gno) :
  TGeoNode(gno),
  fOffset(gno.fOffset),
  fIndex(gno.fIndex),
  fFinder(gno.fFinder)
{ 
   
}
TGeoNodeOffset& TGeoNodeOffset::operator=(const TGeoNodeOffset& gno)
{
   
   if(this!=&gno) {
      TGeoNode::operator=(gno);
      fOffset=gno.fOffset;
      fIndex=gno.fIndex;
      fFinder=gno.fFinder;
   } 
   return *this;
}
TGeoNodeOffset::~TGeoNodeOffset()
{
}
Int_t TGeoNodeOffset::GetIndex() const
{
   return (fIndex+fFinder->GetDivIndex());
}
TGeoNode *TGeoNodeOffset::MakeCopyNode() const
{
   TGeoNodeOffset *node = new TGeoNodeOffset(fVolume, GetIndex(), fOffset);
   node->SetName(GetName());
   
   node->SetMotherVolume(fMother);
   
   node->SetNumber(fNumber);
   if (IsVirtual()) node->SetVirtual();
   
   node->SetFinder(GetFinder());
   return node;
}
ClassImp(TGeoIterator)
TGeoIterator::TGeoIterator(TGeoVolume *top)
{
   fTop = top;
   fLevel = 0;
   fMustResume = kFALSE;
   fMustStop = kFALSE;
   fType = 0;
   fArray = new Int_t[30];
   fMatrix = new TGeoHMatrix();
   fTopName = fTop->GetName();
}   
TGeoIterator::TGeoIterator(const TGeoIterator &iter)
{
   fTop = iter.GetTopVolume();
   fLevel = iter.GetLevel();
   fMustResume = kFALSE;
   fMustStop = kFALSE;
   fType = iter.GetType();
   fArray = new Int_t[30+ 30*Int_t(fLevel/30)];
   for (Int_t i=0; i<fLevel+1; i++) fArray[i] = iter.GetIndex(i);
   fMatrix = new TGeoHMatrix(*iter.GetCurrentMatrix());
   fTopName = fTop->GetName();
}
TGeoIterator::~TGeoIterator()
{
   if (fArray) delete [] fArray;
   delete fMatrix;
}   
TGeoIterator &TGeoIterator::operator=(const TGeoIterator &iter)
{
   fTop = iter.GetTopVolume();
   fLevel = iter.GetLevel();
   fMustResume = kFALSE;
   fMustStop = kFALSE;
   fType = iter.GetType();
   if (fArray) delete [] fArray;
   fArray = new Int_t[30+ 30*Int_t(fLevel/30)];
   for (Int_t i=0; i<fLevel+1; i++) fArray[i] = iter.GetIndex(i);
   if (!fMatrix) fMatrix = new TGeoHMatrix();
   *fMatrix = *iter.GetCurrentMatrix();
   fTopName = fTop->GetName();
   return *this;   
}   
TGeoNode *TGeoIterator::Next()
{
   if (fMustStop) return 0;
   TGeoNode *mother = 0;
   TGeoNode *next = 0;
   Int_t i;
   Int_t nd = fTop->GetNdaughters();
   if (!nd) {
      fMustStop = kTRUE;
      return 0;
   }   
   if (!fLevel) {
      fArray[++fLevel] = 0;
      next = fTop->GetNode(0);
      return next;
   }   
   next = fTop->GetNode(fArray[1]);
   
   for (i=2; i<fLevel+1; i++) {
      mother = next;
      next = mother->GetDaughter(fArray[i]);
   }   
   if (fMustResume) {
      fMustResume = kFALSE;
      return next;
   }   
   
   switch (fType) {
      case 0:  
         nd = next->GetNdaughters();
         if (nd) {
            
            fLevel++;
            if ((fLevel%30)==0) IncreaseArray();
            fArray[fLevel] = 0;
            return next->GetDaughter(0);
         }
         
         while (next) {
            next = GetNode(fLevel-1);
            if (!next) {
               nd = fTop->GetNdaughters();
               if (fArray[fLevel]<nd-1) return fTop->GetNode(++fArray[fLevel]);
               fMustStop = kTRUE;
               return 0;
            } else {
               nd = next->GetNdaughters();
               if (fArray[fLevel]<nd-1) return next->GetDaughter(++fArray[fLevel]);
            }   
            fLevel--;
         }   
         break;
      case 1:  
         if (mother) nd = mother->GetNdaughters();
         if (fArray[fLevel]<nd-1) {
            if (!mother) return fTop->GetNode(++fArray[fLevel]);
            else return mother->GetDaughter(++fArray[fLevel]);
         }
   }
   fMustStop = kTRUE;
   return 0;
}
   
TGeoNode *TGeoIterator::operator()()
{
   return Next();
}   
const TGeoMatrix *TGeoIterator::GetCurrentMatrix() const
{
   fMatrix->Clear();
   if (!fLevel) return fMatrix;
   TGeoNode *node = fTop->GetNode(fArray[1]);
   fMatrix->Multiply(node->GetMatrix());
   for (Int_t i=2; i<fLevel+1; i++) {
      node = node->GetDaughter(fArray[i]);
      fMatrix->Multiply(node->GetMatrix());
   }
   return fMatrix;   
}   
TGeoNode *TGeoIterator::GetNode(Int_t level) const
{
   if (!level || level>fLevel) return 0;
   TGeoNode *node = fTop->GetNode(fArray[1]);
   for (Int_t i=2; i<level+1; i++) node = node->GetDaughter(fArray[i]);
   return node;
}
void TGeoIterator::GetPath(TString &path) const
{
   path = fTopName;
   if (!fLevel) return;
   TGeoNode *node = fTop->GetNode(fArray[1]);
   path += "/";
   path += node->GetName();
   for (Int_t i=2; i<fLevel+1; i++) {
      node = node->GetDaughter(fArray[i]);
      path += "/";
      path += node->GetName();
   }   
}      
void TGeoIterator::IncreaseArray() 
{
   Int_t *array = new Int_t[fLevel+30];
   memcpy(array, fArray, fLevel*sizeof(Int_t));
   delete [] fArray;
   fArray = array;
}   
 
void TGeoIterator::Reset(TGeoVolume *top)
{
   if (top) fTop = top;
   fLevel = 0;
   fMustResume = kFALSE;
   fMustStop = kFALSE;
}      
void TGeoIterator::SetTopName(const char *name)
{
   fTopName = name;
}   
void TGeoIterator::Skip()
{
   fMustResume = kTRUE;
   TGeoNode *next = GetNode(fLevel);
   if (!next) return;
   Int_t nd;
   switch (fType) {
      case 0:  
         
         while (next) {
            next = GetNode(fLevel-1);
            nd = (next==0)?fTop->GetNdaughters():next->GetNdaughters();
            if (fArray[fLevel]<nd-1) {
               ++fArray[fLevel];
               return;
            }
            fLevel--;
            if (!fLevel) {
               fMustStop = kTRUE;
               return;
            }   
         }     
         break;
      case 1:  
         next = GetNode(fLevel-1);
         nd = (next==0)?fTop->GetNdaughters():next->GetNdaughters();
         if (fArray[fLevel]<nd-1) {
            ++fArray[fLevel];
            return;
         }
         fMustStop = kTRUE;   
         break;
   }
}         
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.