/*
<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 "TGeoVoxelFinder.h"
#include "TGeoNode.h"
#include "TMath.h"
#include "TStopwatch.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());
}
}
Int_t TGeoNode::CountDaughters(Bool_t unique_volumes)
{
static Int_t icall = 0;
Int_t counter = 0;
if (unique_volumes) {
if (!fVolume->IsSelected()) {
counter++;
fVolume->SelectVolume(kFALSE);
}
} else counter++;
icall++;
Int_t nd = fVolume->GetNdaughters();
for (Int_t i=0; i<nd; i++) counter += GetDaughter(i)->CountDaughters(unique_volumes);
icall--;
if (icall == 0) fVolume->SelectVolume(kTRUE);
return counter;
}
void TGeoNode::CheckOverlaps(Double_t ovlp, Option_t *option)
{
Int_t icheck = 0;
Int_t ncheck = 0;
TStopwatch *timer;
Int_t i;
Bool_t sampling = kFALSE;
TString opt(option);
opt.ToLower();
if (opt.Contains("s")) sampling = kTRUE;
TGeoManager *geom = fVolume->GetGeoManager();
ncheck = CountDaughters(kFALSE);
timer = new TStopwatch();
geom->ClearOverlaps();
geom->SetCheckingOverlaps(kTRUE);
Info("CheckOverlaps", "Checking overlaps for %s and daughters within %g", fVolume->GetName(),ovlp);
if (sampling) {
Info("CheckOverlaps", "Checking overlaps by sampling <%s> for %s and daughters", option, fVolume->GetName());
Info("CheckOverlaps", "=== NOTE: Extrusions NOT checked with sampling option ! ===");
}
timer->Start();
geom->GetGeomPainter()->OpProgress(fVolume->GetName(),icheck,ncheck,timer,kFALSE);
fVolume->CheckOverlaps(ovlp,option);
icheck++;
TGeoIterator next(fVolume);
TGeoNode *node;
TString path;
while ((node=next())) {
next.GetPath(path);
icheck++;
if (!node->GetVolume()->IsSelected()) {
geom->GetGeomPainter()->OpProgress(node->GetVolume()->GetName(),icheck,ncheck,timer,kFALSE);
node->GetVolume()->SelectVolume(kFALSE);
node->GetVolume()->CheckOverlaps(ovlp,option);
}
}
fVolume->SelectVolume(kTRUE);
geom->SetCheckingOverlaps(kFALSE);
geom->SortOverlaps();
TObjArray *overlaps = geom->GetListOfOverlaps();
Int_t novlps = overlaps->GetEntriesFast();
TNamed *obj;
for (i=0; i<novlps; i++) {
obj = (TNamed*)overlaps->At(i);
obj->SetName(Form("ov%05d",i));
}
geom->GetGeomPainter()->OpProgress("Check overlaps:",icheck,ncheck,timer,kTRUE);
Info("CheckOverlaps", "Number of illegal overlaps/extrusions : %d\n", novlps);
delete timer;
}
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(const TGeoNodeMatrix& gnm)
:TGeoNode(gnm),
fMatrix(gnm.fMatrix)
{
}
TGeoNodeMatrix& TGeoNodeMatrix::operator=(const TGeoNodeMatrix& gnm)
{
if (this!=&gnm) {
TGeoNode::operator=(gnm);
fMatrix=gnm.fMatrix;
}
return *this;
}
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;
}
void TGeoNodeMatrix::SetMatrix(const TGeoMatrix *matrix)
{
fMatrix = (TGeoMatrix*)matrix;
if (!fMatrix) fMatrix = gGeoIdentity;
}
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;
}
}