#include "TGeoBranchArray.h"
#include "TMath.h"
#include "TThread.h"
#include "TString.h"
#include "TGeoMatrix.h"
#include "TGeoNavigator.h"
#include "TGeoManager.h"
ClassImp(TGeoBranchArray)
TGeoBranchArray::TGeoBranchArray(UShort_t level)
:fLevel(level),
fArray(NULL),
fMatrix(NULL),
fClient(NULL)
{
fArray = new UShort_t[level];
}
TGeoBranchArray::~TGeoBranchArray()
{
delete [] fArray;
delete fMatrix;
}
TGeoBranchArray::TGeoBranchArray(const TGeoBranchArray& other)
:TObject(other),
fLevel(other.fLevel),
fArray(NULL),
fMatrix(NULL),
fClient(other.fClient)
{
if (fLevel) fArray = new UShort_t[fLevel];
if (other.fMatrix) fMatrix = new TGeoHMatrix(*(other.fMatrix));
}
TGeoBranchArray& TGeoBranchArray::operator=(const TGeoBranchArray& other)
{
if (&other == this) return *this;
TThread::Lock();
fLevel = other.fLevel;
if (fLevel) fArray = new UShort_t[fLevel];
if (other.fMatrix) {
fMatrix = new TGeoHMatrix();
fMatrix->CopyFrom(other.fMatrix);
}
fClient = other.fClient;
TThread::UnLock();
return *this;
}
void TGeoBranchArray::AddLevel(UShort_t dindex)
{
if (!fLevel) {
Error("AddLevel", "You must initialize from navigator or copy from another branch array first.");
return;
}
fLevel++;
UShort_t *array = new UShort_t[fLevel];
memcpy(array, fArray, (fLevel-1)*sizeof(UShort_t));
array[fLevel-1] = dindex;
delete [] fArray;
fArray = array;
}
Bool_t TGeoBranchArray::operator ==(const TGeoBranchArray& other) const
{
Int_t value = Compare(&other);
if (value==0) return kTRUE;
return kFALSE;
}
Bool_t TGeoBranchArray::operator !=(const TGeoBranchArray& other) const
{
Int_t value = Compare(&other);
if (value!=0) return kTRUE;
return kFALSE;
}
Bool_t TGeoBranchArray::operator >(const TGeoBranchArray& other) const
{
Int_t value = Compare(&other);
if (value>0) return kTRUE;
return kFALSE;
}
Bool_t TGeoBranchArray::operator <(const TGeoBranchArray& other) const
{
Int_t value = Compare(&other);
if (value<0) return kTRUE;
return kFALSE;
}
Bool_t TGeoBranchArray::operator >=(const TGeoBranchArray& other) const
{
Int_t value = Compare(&other);
if (value>=0) return kTRUE;
return kFALSE;
}
Bool_t TGeoBranchArray::operator <=(const TGeoBranchArray& other) const
{
Int_t value = Compare(&other);
if (value<=0) return kTRUE;
return kFALSE;
}
Long64_t TGeoBranchArray::BinarySearch(Long64_t n, const TGeoBranchArray **array, TGeoBranchArray *value)
{
Long64_t nabove, nbelow, middle;
const TGeoBranchArray *pind;
nabove = n+1;
nbelow = 0;
while(nabove-nbelow > 1) {
middle = (nabove+nbelow)/2;
pind = array[middle-1];
if (*value == *pind) return middle-1;
if (*value < *pind) nabove = middle;
else nbelow = middle;
}
return nbelow-1;
}
Int_t TGeoBranchArray::Compare(const TObject *obj) const
{
UShort_t i;
TGeoBranchArray *other = (TGeoBranchArray*)obj;
UShort_t otherLevel = other->GetLevel();
UShort_t maxLevel = TMath::Min(fLevel, otherLevel);
UShort_t *otherArray = other->GetArray();
for (i=0; i<maxLevel; i++) {
if (fArray[i]==otherArray[i]) continue;
if (fArray[i]<otherArray[i]) return -1;
return 1;
}
if (fLevel==otherLevel) return 0;
if (fLevel<otherLevel) return -1;
return 1;
}
void TGeoBranchArray::CleanMatrix()
{
delete fMatrix; fMatrix = 0;
}
TGeoNode *TGeoBranchArray::GetNode(UShort_t level) const
{
TGeoNode *node = gGeoManager->GetTopNode();
if (!level) return node;
if (level>fLevel) return NULL;
for (Int_t i=0; i<level; i++) node = node->GetVolume()->GetNode(fArray[i]);
return node;
}
void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
{
TThread::Lock();
UShort_t level = (UShort_t)nav->GetLevel();
if (!fMatrix) fMatrix = new TGeoHMatrix();
fMatrix->CopyFrom(nav->GetCurrentMatrix());
if (!level) {
fLevel = 0;
TThread::UnLock();
return;
}
if (!fArray || level>fLevel) {
delete [] fArray;
fArray = new UShort_t[level];
}
fLevel = level;
TGeoNode *mother = nav->GetMother(fLevel);
for (Int_t i=fLevel-1; i>=0; i--) {
TGeoNode *node = nav->GetMother(i);
Int_t index = mother->GetVolume()->GetIndex(node);
fArray[fLevel-i-1] = index;
mother = node;
}
TThread::UnLock();
}
void TGeoBranchArray::GetPath(TString &path) const
{
path = "/";
TGeoNode *node = GetNode(0);
path += node->GetName();
for (Int_t i=0; i<fLevel; i++) {
path += "/";
node = node->GetVolume()->GetNode(fArray[i]);
path += node->GetName();
}
}
void TGeoBranchArray::Print(Option_t *) const
{
TString path;
GetPath(path);
printf("branch: %s\n", path.Data());
}
void TGeoBranchArray::Sort(Int_t n, TGeoBranchArray **array, Int_t *index, Bool_t down)
{
for (Int_t i=0; i<n; i++) index[i] = i;
if (down)
std::sort(index, index + n, compareBAdesc(array));
else
std::sort(index, index + n, compareBAasc(array));
}
void TGeoBranchArray::UpdateNavigator(TGeoNavigator *nav) const
{
nav->CdTop();
for (Int_t i=0; i<fLevel; i++) nav->CdDown(fArray[i]);
}