/*
<img src="gif/t_finder.jpg">
<img src="gif/t_voxelfind.jpg">
<img src="gif/t_voxtree.jpg">
*/
//End_Html
#include "TObject.h"
#include "TGeoMatrix.h"
#include "TGeoBBox.h"
#include "TGeoNode.h"
#include "TGeoManager.h"
#include "TMath.h"
#include "TGeoVoxelFinder.h"
ClassImp(TGeoVoxelFinder)
TGeoVoxelFinder::TGeoVoxelFinder()
{
fVolume = 0;
fNboxes = 0;
fIbx = 0;
fIby = 0;
fIbz = 0;
fNox = 0;
fNoy = 0;
fNoz = 0;
fNex = 0;
fNey = 0;
fNez = 0;
fNx = 0;
fNy = 0;
fNz = 0;
fBoxes = 0;
fXb = 0;
fYb = 0;
fZb = 0;
fOBx = 0;
fOBy = 0;
fOBz = 0;
fOEx = 0;
fOEy = 0;
fOEz = 0;
fIndcX = 0;
fIndcY = 0;
fIndcZ = 0;
fExtraX = 0;
fExtraY = 0;
fExtraZ = 0;
fNsliceX = 0;
fNsliceY = 0;
fNsliceZ = 0;
fCheckList = 0;
fNcandidates = 0;
fCurrentVoxel = 0;
fBits1 = 0;
SetInvalid(kFALSE);
}
TGeoVoxelFinder::TGeoVoxelFinder(TGeoVolume *vol)
{
if (!vol) return;
fVolume = vol;
fVolume->SetCylVoxels(kFALSE);
fNboxes = 0;
fIbx = 0;
fIby = 0;
fIbz = 0;
fNox = 0;
fNoy = 0;
fNoz = 0;
fNex = 0;
fNey = 0;
fNez = 0;
fNx = 0;
fNy = 0;
fNz = 0;
fBoxes = 0;
fXb = 0;
fYb = 0;
fZb = 0;
fOBx = 0;
fOBy = 0;
fOBz = 0;
fOEx = 0;
fOEy = 0;
fOEz = 0;
fIndcX = 0;
fIndcY = 0;
fIndcZ = 0;
fExtraX = 0;
fExtraY = 0;
fExtraZ = 0;
fNsliceX = 0;
fNsliceY = 0;
fNsliceZ = 0;
fCheckList = 0;
fNcandidates = 0;
fCurrentVoxel = 0;
fBits1 = 0;
SetNeedRebuild();
}
TGeoVoxelFinder::TGeoVoxelFinder(const TGeoVoxelFinder& vf) :
TObject(vf),
fVolume(vf.fVolume),
fNcandidates(vf.fNcandidates),
fCurrentVoxel(vf.fCurrentVoxel),
fIbx(vf.fIbx),
fIby(vf.fIby),
fIbz(vf.fIbz),
fNboxes(vf.fNboxes),
fNox(vf.fNox),
fNoy(vf.fNoy),
fNoz(vf.fNoz),
fNex(vf.fNex),
fNey(vf.fNey),
fNez(vf.fNez),
fNx(vf.fNx),
fNy(vf.fNy),
fNz(vf.fNz),
fBoxes(vf.fBoxes),
fXb(vf.fXb),
fYb(vf.fYb),
fZb(vf.fZb),
fOBx(vf.fOBx),
fOBy(vf.fOBy),
fOBz(vf.fOBz),
fOEx(vf.fOEx),
fOEy(vf.fOEy),
fOEz(vf.fOEz),
fExtraX(vf.fExtraX),
fExtraY(vf.fExtraY),
fExtraZ(vf.fExtraZ),
fNsliceX(vf.fNsliceX),
fNsliceY(vf.fNsliceY),
fNsliceZ(vf.fNsliceZ),
fIndcX(vf.fIndcX),
fIndcY(vf.fIndcY),
fIndcZ(vf.fIndcZ),
fCheckList(vf.fCheckList),
fBits1(vf.fBits1)
{
for(Int_t i=0; i<3; i++) {
fPriority[i]=vf.fPriority[i];
fSlices[i]=vf.fSlices[i];
fInc[i]=vf.fInc[i];
fInvdir[i]=vf.fInvdir[i];
fLimits[i]=vf.fLimits[i];
}
}
TGeoVoxelFinder& TGeoVoxelFinder::operator=(const TGeoVoxelFinder& vf)
{
if(this!=&vf) {
TObject::operator=(vf);
fVolume=vf.fVolume;
fNcandidates=vf.fNcandidates;
fCurrentVoxel=vf.fCurrentVoxel;
fIbx=vf.fIbx;
fIby=vf.fIby;
fIbz=vf.fIbz;
fNboxes=vf.fNboxes;
fNox=vf.fNox;
fNoy=vf.fNoy;
fNoz=vf.fNoz;
fNex=vf.fNex;
fNey=vf.fNey;
fNez=vf.fNez;
fNx=vf.fNx;
fNy=vf.fNy;
fNz=vf.fNz;
for(Int_t i=0; i<3; i++) {
fPriority[i]=vf.fPriority[i];
fSlices[i]=vf.fSlices[i];
fInc[i]=vf.fInc[i];
fInvdir[i]=vf.fInvdir[i];
fLimits[i]=vf.fLimits[i];
}
fBoxes=vf.fBoxes;
fXb=vf.fXb;
fYb=vf.fYb;
fZb=vf.fZb;
fOBx=vf.fOBx;
fOBy=vf.fOBy;
fOBz=vf.fOBz;
fOEx=vf.fOEx;
fOEy=vf.fOEy;
fOEz=vf.fOEz;
fNsliceX=vf.fNsliceX;
fNsliceY=vf.fNsliceY;
fNsliceZ=vf.fNsliceZ;
fIndcX=vf.fIndcX;
fIndcY=vf.fIndcY;
fIndcZ=vf.fIndcZ;
fExtraX=vf.fExtraX;
fExtraY=vf.fExtraY;
fExtraZ=vf.fExtraZ;
fCheckList=vf.fCheckList;
fBits1=vf.fBits1;
}
return *this;
}
TGeoVoxelFinder::~TGeoVoxelFinder()
{
if (fOBx) delete [] fOBx;
if (fOBy) delete [] fOBy;
if (fOBz) delete [] fOBz;
if (fOEx) delete [] fOEx;
if (fOEy) delete [] fOEy;
if (fOEz) delete [] fOEz;
if (fBoxes) delete [] fBoxes;
if (fXb) delete [] fXb;
if (fYb) delete [] fYb;
if (fZb) delete [] fZb;
if (fNsliceX) delete [] fNsliceX;
if (fNsliceY) delete [] fNsliceY;
if (fNsliceZ) delete [] fNsliceZ;
if (fIndcX) delete [] fIndcX;
if (fIndcY) delete [] fIndcY;
if (fIndcZ) delete [] fIndcZ;
if (fExtraX) delete [] fExtraX;
if (fExtraY) delete [] fExtraY;
if (fExtraZ) delete [] fExtraZ;
if (fCheckList) delete [] fCheckList;
if (fBits1) delete [] fBits1;
}
void TGeoVoxelFinder::BuildVoxelLimits()
{
Int_t nd = fVolume->GetNdaughters();
if (!nd) return;
Int_t id;
TGeoNode *node;
if (fBoxes) delete [] fBoxes;
if (fBits1) delete [] fBits1;
fBits1 = new UChar_t[1+((nd-1)>>3)];
fNboxes = 6*nd;
fBoxes = new Double_t[fNboxes];
if (fCheckList) delete [] fCheckList;
fCheckList = new Int_t[nd];
Double_t vert[24];
Double_t pt[3];
Double_t xyz[6];
TGeoBBox *box = 0;
for (id=0; id<nd; id++) {
node = fVolume->GetNode(id);
box = (TGeoBBox*)node->GetVolume()->GetShape();
box->SetBoxPoints(&vert[0]);
for (Int_t point=0; point<8; point++) {
DaughterToMother(id, &vert[3*point], &pt[0]);
if (!point) {
xyz[0] = xyz[1] = pt[0];
xyz[2] = xyz[3] = pt[1];
xyz[4] = xyz[5] = pt[2];
continue;
}
for (Int_t j=0; j<3; j++) {
if (pt[j] < xyz[2*j]) xyz[2*j]=pt[j];
if (pt[j] > xyz[2*j+1]) xyz[2*j+1]=pt[j];
}
}
fBoxes[6*id] = 0.5*(xyz[1]-xyz[0]);
fBoxes[6*id+1] = 0.5*(xyz[3]-xyz[2]);
fBoxes[6*id+2] = 0.5*(xyz[5]-xyz[4]);
fBoxes[6*id+3] = 0.5*(xyz[0]+xyz[1]);
fBoxes[6*id+4] = 0.5*(xyz[2]+xyz[3]);
fBoxes[6*id+5] = 0.5*(xyz[4]+xyz[5]);
}
}
void TGeoVoxelFinder::CreateCheckList()
{
if (NeedRebuild()) {
Voxelize();
fVolume->FindOverlaps();
}
Int_t nd = fVolume->GetNdaughters();
if (!nd) return;
if (!fCheckList) fCheckList = new Int_t[nd];
if (!fBits1) fBits1 = new UChar_t[1+((nd-1)>>3)];
}
void TGeoVoxelFinder::DaughterToMother(Int_t id, Double_t *local, Double_t *master) const
{
TGeoMatrix *mat = fVolume->GetNode(id)->GetMatrix();
if (!mat) memcpy(master,local,3*sizeof(Double_t));
else mat->LocalToMaster(local, master);
}
Bool_t TGeoVoxelFinder::IsSafeVoxel(Double_t *point, Int_t inode, Double_t minsafe) const
{
if (NeedRebuild()) {
TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
vox->Voxelize();
fVolume->FindOverlaps();
}
Double_t dxyz, minsafe2=minsafe*minsafe;
Int_t ist = 6*inode;
Int_t i;
Double_t rsq = 0;
for (i=0; i<3; i++) {
dxyz = TMath::Abs(point[i]-fBoxes[ist+i+3])-fBoxes[ist+i];
if (dxyz>-1E-6) rsq+=dxyz*dxyz;
if (rsq > minsafe2*(1.+TGeoShape::Tolerance())) return kTRUE;
}
return kFALSE;
}
Double_t TGeoVoxelFinder::Efficiency()
{
printf("Voxelization efficiency for %s\n", fVolume->GetName());
if (NeedRebuild()) {
Voxelize();
fVolume->FindOverlaps();
}
Double_t nd = Double_t(fVolume->GetNdaughters());
Double_t eff = 0;
Double_t effslice = 0;
Int_t id;
if (fPriority[0]) {
for (id=0; id<fIbx-1; id++) {
effslice += fNsliceX[id];
}
if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
else printf("Woops : slice X\n");
}
printf("X efficiency : %g\n", effslice);
eff += effslice;
effslice = 0;
if (fPriority[1]) {
for (id=0; id<fIby-1; id++) {
effslice += fNsliceY[id];
}
if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
else printf("Woops : slice X\n");
}
printf("Y efficiency : %g\n", effslice);
eff += effslice;
effslice = 0;
if (fPriority[2]) {
for (id=0; id<fIbz-1; id++) {
effslice += fNsliceZ[id];
}
if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
else printf("Woops : slice X\n");
}
printf("Z efficiency : %g\n", effslice);
eff += effslice;
eff /= 3.;
printf("Total efficiency : %g\n", eff);
return eff;
}
void TGeoVoxelFinder::FindOverlaps(Int_t inode) const
{
if (!fBoxes) return;
Double_t xmin, xmax, ymin, ymax, zmin, zmax;
Double_t xmin1, xmax1, ymin1, ymax1, zmin1, zmax1;
Double_t ddx1, ddx2;
Int_t nd = fVolume->GetNdaughters();
Int_t *ovlps = 0;
Int_t *otmp = new Int_t[nd-1];
Int_t novlp = 0;
TGeoNode *node = fVolume->GetNode(inode);
xmin = fBoxes[6*inode+3] - fBoxes[6*inode];
xmax = fBoxes[6*inode+3] + fBoxes[6*inode];
ymin = fBoxes[6*inode+4] - fBoxes[6*inode+1];
ymax = fBoxes[6*inode+4] + fBoxes[6*inode+1];
zmin = fBoxes[6*inode+5] - fBoxes[6*inode+2];
zmax = fBoxes[6*inode+5] + fBoxes[6*inode+2];
for (Int_t ib=0; ib<nd; ib++) {
if (ib == inode) continue;
xmin1 = fBoxes[6*ib+3] - fBoxes[6*ib];
xmax1 = fBoxes[6*ib+3] + fBoxes[6*ib];
ymin1 = fBoxes[6*ib+4] - fBoxes[6*ib+1];
ymax1 = fBoxes[6*ib+4] + fBoxes[6*ib+1];
zmin1 = fBoxes[6*ib+5] - fBoxes[6*ib+2];
zmax1 = fBoxes[6*ib+5] + fBoxes[6*ib+2];
ddx1 = xmax-xmin1;
ddx2 = xmax1-xmin;
if (ddx1*ddx2 <= 0.) continue;
ddx1 = ymax-ymin1;
ddx2 = ymax1-ymin;
if (ddx1*ddx2 <= 0.) continue;
ddx1 = zmax-zmin1;
ddx2 = zmax1-zmin;
if (ddx1*ddx2 <= 0.) continue;
otmp[novlp++] = ib;
}
if (!novlp) {
delete [] otmp;
node->SetOverlaps(ovlps, 0);
return;
}
ovlps = new Int_t[novlp];
memcpy(ovlps, otmp, novlp*sizeof(Int_t));
delete [] otmp;
node->SetOverlaps(ovlps, novlp);
}
Bool_t TGeoVoxelFinder::GetIndices(Double_t *point)
{
fSlices[0] = -2;
fSlices[1] = -2;
fSlices[2] = -2;
Bool_t flag=kTRUE;
if (fPriority[0]) {
fSlices[0] = TMath::BinarySearch(fIbx, fXb, point[0]);
if ((fSlices[0]<0) || (fSlices[0]>=fIbx-1)) {
flag=kFALSE;
} else {
if (fPriority[0]==2) {
if (!fNsliceX[fSlices[0]]) flag = kFALSE;
}
}
}
if (fPriority[1]) {
fSlices[1] = TMath::BinarySearch(fIby, fYb, point[1]);
if ((fSlices[1]<0) || (fSlices[1]>=fIby-1)) {
flag=kFALSE;
} else {
if (fPriority[1]==2) {
if (!fNsliceY[fSlices[1]]) flag = kFALSE;
}
}
}
if (fPriority[2]) {
fSlices[2] = TMath::BinarySearch(fIbz, fZb, point[2]);
if ((fSlices[2]<0) || (fSlices[2]>=fIbz-1)) return kFALSE;
if (fPriority[2]==2) {
if (!fNsliceZ[fSlices[2]]) return kFALSE;
}
}
return flag;
}
Int_t *TGeoVoxelFinder::GetExtraX(Int_t islice, Bool_t left, Int_t &nextra) const
{
Int_t *list = 0;
nextra = 0;
if (fPriority[0]!=2) return list;
if (left) {
nextra = fExtraX[fOEx[islice]];
list = &fExtraX[fOEx[islice]+2];
} else {
nextra = fExtraX[fOEx[islice]+1];
list = &fExtraX[fOEx[islice]+2+fExtraX[fOEx[islice]]];
}
return list;
}
Int_t *TGeoVoxelFinder::GetExtraY(Int_t islice, Bool_t left, Int_t &nextra) const
{
Int_t *list = 0;
nextra = 0;
if (fPriority[1]!=2) return list;
if (left) {
nextra = fExtraY[fOEy[islice]];
list = &fExtraY[fOEy[islice]+2];
} else {
nextra = fExtraY[fOEy[islice]+1];
list = &fExtraY[fOEy[islice]+2+fExtraY[fOEy[islice]]];
}
return list;
}
Int_t *TGeoVoxelFinder::GetExtraZ(Int_t islice, Bool_t left, Int_t &nextra) const
{
Int_t *list = 0;
nextra = 0;
if (fPriority[2]!=2) return list;
if (left) {
nextra = fExtraZ[fOEz[islice]];
list = &fExtraZ[fOEz[islice]+2];
} else {
nextra = fExtraZ[fOEz[islice]+1];
list = &fExtraZ[fOEz[islice]+2+fExtraZ[fOEz[islice]]];
}
return list;
}
Int_t *TGeoVoxelFinder::GetValidExtra(Int_t *list, Int_t &ncheck)
{
fNcandidates = 0;
Int_t icand;
UInt_t bitnumber, loc;
UChar_t bit, byte;
for (icand=0; icand<ncheck; icand++) {
bitnumber = (UInt_t)list[icand];
loc = bitnumber>>3;
bit = bitnumber%8;
byte = (~fBits1[loc]) & (1<<bit);
if (byte) fCheckList[fNcandidates++]=list[icand];
}
ncheck = fNcandidates;
return fCheckList;
}
Int_t *TGeoVoxelFinder::GetValidExtra(Int_t , UChar_t *array1, Int_t *list, Int_t &ncheck)
{
fNcandidates = 0;
Int_t icand;
UInt_t bitnumber, loc;
UChar_t bit, byte;
for (icand=0; icand<ncheck; icand++) {
bitnumber = (UInt_t)list[icand];
loc = bitnumber>>3;
bit = bitnumber%8;
byte = (~fBits1[loc]) & array1[loc] & (1<<bit);
if (byte) fCheckList[fNcandidates++]=list[icand];
}
ncheck = fNcandidates;
return fCheckList;
}
Int_t *TGeoVoxelFinder::GetValidExtra(Int_t , UChar_t *array1, Int_t , UChar_t *array2, Int_t *list, Int_t &ncheck)
{
fNcandidates = 0;
Int_t icand;
UInt_t bitnumber, loc;
UChar_t bit, byte;
for (icand=0; icand<ncheck; icand++) {
bitnumber = (UInt_t)list[icand];
loc = bitnumber>>3;
bit = bitnumber%8;
byte = (~fBits1[loc]) & array1[loc] & array2[loc] & (1<<bit);
if (byte) fCheckList[fNcandidates++]=list[icand];
}
ncheck = fNcandidates;
return fCheckList;
}
Int_t *TGeoVoxelFinder::GetNextCandidates(Double_t *point, Int_t &ncheck)
{
if (NeedRebuild()) {
Voxelize();
fVolume->FindOverlaps();
}
ncheck = 0;
if (fLimits[0]<0) return 0;
if (fLimits[1]<0) return 0;
if (fLimits[2]<0) return 0;
Int_t dind[3];
memcpy(&dind[0], &fSlices[0], 3*sizeof(Int_t));
Double_t dmin[3];
dmin[0] = dmin[1] = dmin[2] = TGeoShape::Big();
Double_t maxstep = TMath::Min(gGeoManager->GetStep(), fLimits[TMath::LocMin(3, fLimits)]);
Bool_t isXlimit=kFALSE, isYlimit=kFALSE, isZlimit=kFALSE;
Bool_t isForcedX=kFALSE, isForcedY=kFALSE, isForcedZ=kFALSE;
Double_t dforced[3];
dforced[0] = dforced[1] = dforced[2] = TGeoShape::Big();
Int_t iforced = 0;
if (fPriority[0] && fInc[0]) {
dind[0] += fInc[0];
if (fInc[0]==1) {
if (dind[0]<0 || dind[0]>fIbx-1) return 0;
dmin[0] = (fXb[dind[0]]-point[0])*fInvdir[0];
} else {
if (fSlices[0]<0 || fSlices[0]>fIbx-1) return 0;
dmin[0] = (fXb[fSlices[0]]-point[0])*fInvdir[0];
}
isXlimit = (dmin[0]>maxstep)?kTRUE:kFALSE;
if ((fSlices[0]==-1) || (fSlices[0]==fIbx-1)) {
isForcedX = kTRUE;
dforced[0] = dmin[0];
iforced++;
if (isXlimit) return 0;
} else {
if (fPriority[0]==2) {
if (fNsliceX[fSlices[0]]==0) {
isForcedX = kTRUE;
dforced[0] = dmin[0];
iforced++;
if (isXlimit) return 0;
}
}
}
} else {
dmin[0] = fLimits[0];
isXlimit = kTRUE;
}
if (fPriority[1] && fInc[1]) {
dind[1] += fInc[1];
if (fInc[1]==1) {
if (dind[1]<0 || dind[1]>fIby-1) return 0;
dmin[1] = (fYb[dind[1]]-point[1])*fInvdir[1];
} else {
if (fSlices[1]<0 || fSlices[1]>fIby-1) return 0;
dmin[1] = (fYb[fSlices[1]]-point[1])*fInvdir[1];
}
isYlimit = (dmin[1]>maxstep)?kTRUE:kFALSE;
if ((fSlices[1]==-1) || (fSlices[1]==fIby-1)) {
isForcedY = kTRUE;
dforced[1] = dmin[1];
iforced++;
if (isYlimit) return 0;
} else {
if (fPriority[1]==2) {
if (fNsliceY[fSlices[1]]==0) {
isForcedY = kTRUE;
dforced[1] = dmin[1];
iforced++;
if (isYlimit) return 0;
}
}
}
} else {
dmin[1] = fLimits[1];
isYlimit = kTRUE;
}
if (fPriority[2] && fInc[2]) {
dind[2] += fInc[2];
if (fInc[2]==1) {
if (dind[2]<0 || dind[2]>fIbz-1) return 0;
dmin[2] = (fZb[dind[2]]-point[2])*fInvdir[2];
} else {
if (fSlices[2]<0 || fSlices[2]>fIbz-1) return 0;
dmin[2] = (fZb[fSlices[2]]-point[2])*fInvdir[2];
}
isZlimit = (dmin[2]>maxstep)?kTRUE:kFALSE;
if ((fSlices[2]==-1) || (fSlices[2]==fIbz-1)) {
isForcedZ = kTRUE;
dforced[2] = dmin[2];
iforced++;
if (isZlimit) return 0;
} else {
if (fPriority[2]==2) {
if (fNsliceZ[fSlices[2]]==0) {
isForcedZ = kTRUE;
dforced[2] = dmin[2];
iforced++;
if (isZlimit) return 0;
}
}
}
} else {
dmin[2] = fLimits[2];
isZlimit = kTRUE;
}
Double_t dslice = 0;
Int_t islice = 0;
if (iforced) {
if (isForcedX) {
dslice = dforced[0];
islice = 0;
if (isForcedY) {
if (dforced[1]>dslice) {
dslice = dforced[1];
islice = 1;
}
if (isForcedZ) {
if (dforced[2]>dslice) {
dslice = dforced[2];
islice = 2;
}
}
} else {
if (isForcedZ) {
if (dforced[2]>dslice) {
dslice = dforced[2];
islice = 2;
}
}
}
} else {
if (isForcedY) {
dslice = dforced[1];
islice = 1;
if (isForcedZ) {
if (dforced[2]>dslice) {
dslice = dforced[2];
islice = 2;
}
}
} else {
dslice = dforced[2];
islice = 2;
}
}
} else {
islice = TMath::LocMin(3, dmin);
dslice = dmin[islice];
if (dslice>=maxstep) {
return 0;
}
}
Double_t xptnew;
Int_t *new_list;
UChar_t *slice1 = 0;
UChar_t *slice2 = 0;
Int_t ndd[2] = {0,0};
Int_t islices = 0;
Bool_t left;
switch (islice) {
case 0:
if (isXlimit) return 0;
fSlices[0]=dind[0];
if (iforced) {
if (dslice>fLimits[1]) return 0;
if (dslice>fLimits[2]) return 0;
if ((dslice>dmin[1]) && fInc[1]) {
xptnew = point[1]+dslice/fInvdir[1];
while (1) {
fSlices[1] += fInc[1];
if (fInc[1]==1) {
if (fSlices[1]<-1 || fSlices[1]>fIby-2) break;
if (fYb[fSlices[1]+1]>=xptnew) break;
} else {
if (fSlices[1]<0 || fSlices[1]>fIby-1) break;
if (fYb[fSlices[1]]<= xptnew) break;
}
}
}
if ((dslice>dmin[2]) && fInc[2]) {
xptnew = point[2]+dslice/fInvdir[2];
while (1) {
fSlices[2] += fInc[2];
if (fInc[2]==1) {
if (fSlices[2]<-1 || fSlices[2]>fIbz-2) break;
if (fZb[fSlices[2]+1]>=xptnew) break;
} else {
if (fSlices[2]<0 || fSlices[2]>fIbz-1) break;
if (fZb[fSlices[2]]<= xptnew) break;
}
}
}
}
if (fPriority[0]==1) {
if (fPriority[1]==2) {
if (fSlices[1]<0 || fSlices[1]>=fIby-1) return fCheckList;
ndd[0] = fNsliceY[fSlices[1]];
if (!ndd[0]) return fCheckList;
slice1 = &fIndcY[fOBy[fSlices[1]]];
islices++;
}
if (fPriority[2]==2) {
if (fSlices[2]<0 || fSlices[2]>=fIbz-1) return fCheckList;
ndd[1] = fNsliceZ[fSlices[2]];
if (!ndd[1]) return fCheckList;
islices++;
if (slice1) {
slice2 = &fIndcZ[fOBz[fSlices[2]]];
} else {
slice1 = &fIndcZ[fOBz[fSlices[2]]];
ndd[0] = ndd[1];
}
}
if (islices==1) {
IntersectAndStore(ndd[0], slice1);
} else {
IntersectAndStore(ndd[0], slice1, ndd[1], slice2);
}
ncheck = fNcandidates;
return fCheckList;
}
left = (fInc[0]>0)?kTRUE:kFALSE;
new_list = GetExtraX(fSlices[0], left, ncheck);
if (!ncheck) return fCheckList;
if (fPriority[1]==2) {
if (fSlices[1]<0 || fSlices[1]>=fIby-1) {
ncheck = 0;
return fCheckList;
}
ndd[0] = fNsliceY[fSlices[1]];
if (!ndd[0]) {
ncheck = 0;
return fCheckList;
}
slice1 = &fIndcY[fOBy[fSlices[1]]];
islices++;
}
if (fPriority[2]==2) {
if (fSlices[2]<0 || fSlices[2]>=fIbz-1) {
ncheck = 0;
return fCheckList;
}
ndd[1] = fNsliceZ[fSlices[2]];
if (!ndd[1]) {
ncheck = 0;
return fCheckList;
}
islices++;
if (slice1) {
slice2 = &fIndcZ[fOBz[fSlices[2]]];
} else {
slice1 = &fIndcZ[fOBz[fSlices[2]]];
ndd[0] = ndd[1];
}
}
if (!islices) return GetValidExtra(new_list, ncheck);
if (islices==1) {
return GetValidExtra(ndd[0], slice1, new_list, ncheck);
} else {
return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck);
}
case 1:
if (isYlimit) return 0;
fSlices[1]=dind[1];
if (iforced) {
if (dslice>fLimits[0]) return 0;
if (dslice>fLimits[2]) return 0;
if ((dslice>dmin[0]) && fInc[0]) {
xptnew = point[0]+dslice/fInvdir[0];
while (1) {
fSlices[0] += fInc[0];
if (fInc[0]==1) {
if (fSlices[0]<-1 || fSlices[0]>fIbx-2) break;
if (fXb[fSlices[0]+1]>=xptnew) break;
} else {
if (fSlices[0]<0 || fSlices[0]>fIbx-1) break;
if (fXb[fSlices[0]]<= xptnew) break;
}
}
}
if ((dslice>dmin[2]) && fInc[2]) {
xptnew = point[2]+dslice/fInvdir[2];
while (1) {
fSlices[2] += fInc[2];
if (fInc[2]==1) {
if (fSlices[2]<-1 || fSlices[2]>fIbz-2) break;
if (fZb[fSlices[2]+1]>=xptnew) break;
} else {
if (fSlices[2]<0 || fSlices[2]>fIbz-1) break;
if (fZb[fSlices[2]]<= xptnew) break;
}
}
}
}
if (fPriority[1]==1) {
if (fPriority[0]==2) {
if (fSlices[0]<0 || fSlices[0]>=fIbx-1) return fCheckList;
ndd[0] = fNsliceX[fSlices[0]];
if (!ndd[0]) return fCheckList;
slice1 = &fIndcX[fOBx[fSlices[0]]];
islices++;
}
if (fPriority[2]==2) {
if (fSlices[2]<0 || fSlices[2]>=fIbz-1) return fCheckList;
ndd[1] = fNsliceZ[fSlices[2]];
if (!ndd[1]) return fCheckList;
islices++;
if (slice1) {
slice2 = &fIndcZ[fOBz[fSlices[2]]];
} else {
slice1 = &fIndcZ[fOBz[fSlices[2]]];
ndd[0] = ndd[1];
}
}
if (islices==1) {
IntersectAndStore(ndd[0], slice1);
} else {
IntersectAndStore(ndd[0], slice1, ndd[1], slice2);
}
ncheck = fNcandidates;
return fCheckList;
}
left = (fInc[1]>0)?kTRUE:kFALSE;
new_list = GetExtraY(fSlices[1], left, ncheck);
if (!ncheck) return fCheckList;
if (fPriority[0]==2) {
if (fSlices[0]<0 || fSlices[0]>=fIbx-1) {
ncheck = 0;
return fCheckList;
}
ndd[0] = fNsliceX[fSlices[0]];
if (!ndd[0]) {
ncheck = 0;
return fCheckList;
}
slice1 = &fIndcX[fOBx[fSlices[0]]];
islices++;
}
if (fPriority[2]==2) {
if (fSlices[2]<0 || fSlices[2]>=fIbz-1) {
ncheck = 0;
return fCheckList;
}
ndd[1] = fNsliceZ[fSlices[2]];
if (!ndd[1]) {
ncheck = 0;
return fCheckList;
}
islices++;
if (slice1) {
slice2 = &fIndcZ[fOBz[fSlices[2]]];
} else {
slice1 = &fIndcZ[fOBz[fSlices[2]]];
ndd[0] = ndd[1];
}
}
if (!islices) return GetValidExtra(new_list, ncheck);
if (islices==1) {
return GetValidExtra(ndd[0], slice1, new_list, ncheck);
} else {
return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck);
}
case 2:
if (isZlimit) return 0;
fSlices[2]=dind[2];
if (iforced) {
if (dslice>fLimits[1]) return 0;
if (dslice>fLimits[0]) return 0;
if ((dslice>dmin[1]) && fInc[1]) {
xptnew = point[1]+dslice/fInvdir[1];
while (1) {
fSlices[1] += fInc[1];
if (fInc[1]==1) {
if (fSlices[1]<-1 || fSlices[1]>fIby-2) break;
if (fYb[fSlices[1]+1]>=xptnew) break;
} else {
if (fSlices[1]<0 || fSlices[1]>fIby-1) break;
if (fYb[fSlices[1]]<= xptnew) break;
}
}
}
if ((dslice>dmin[0]) && fInc[0]) {
xptnew = point[0]+dslice/fInvdir[0];
while (1) {
fSlices[0] += fInc[0];
if (fInc[0]==1) {
if (fSlices[0]<-1 || fSlices[0]>fIbx-2) break;
if (fXb[fSlices[0]+1]>=xptnew) break;
} else {
if (fSlices[0]<0 || fSlices[0]>fIbx-1) break;
if (fXb[fSlices[0]]<= xptnew) break;
}
}
}
}
if (fPriority[2]==1) {
if (fPriority[1]==2) {
if (fSlices[1]<0 || fSlices[1]>=fIby-1) return fCheckList;
ndd[0] = fNsliceY[fSlices[1]];
if (!ndd[0]) return fCheckList;
slice1 = &fIndcY[fOBy[fSlices[1]]];
islices++;
}
if (fPriority[0]==2) {
if (fSlices[0]<0 || fSlices[0]>=fIbx-1) return fCheckList;
ndd[1] = fNsliceX[fSlices[0]];
if (!ndd[1]) return fCheckList;
islices++;
if (slice1) {
slice2 = &fIndcX[fOBx[fSlices[0]]];
} else {
slice1 = &fIndcX[fOBx[fSlices[0]]];
ndd[0] = ndd[1];
}
}
if (islices==1) {
IntersectAndStore(ndd[0], slice1);
} else {
IntersectAndStore(ndd[0], slice1, ndd[1], slice2);
}
ncheck = fNcandidates;
return fCheckList;
}
left = (fInc[2]>0)?kTRUE:kFALSE;
new_list = GetExtraZ(fSlices[2], left, ncheck);
if (!ncheck) return fCheckList;
if (fPriority[1]==2) {
if (fSlices[1]<0 || fSlices[1]>=fIby-1) {
ncheck = 0;
return fCheckList;
}
ndd[0] = fNsliceY[fSlices[1]];
if (!ndd[0]) {
ncheck = 0;
return fCheckList;
}
slice1 = &fIndcY[fOBy[fSlices[1]]];
islices++;
}
if (fPriority[0]==2) {
if (fSlices[0]<0 || fSlices[0]>=fIbx-1) {
ncheck = 0;
return fCheckList;
}
ndd[1] = fNsliceX[fSlices[0]];
if (!ndd[1]) {
ncheck = 0;
return fCheckList;
}
islices++;
if (slice1) {
slice2 = &fIndcX[fOBx[fSlices[0]]];
} else {
slice1 = &fIndcX[fOBx[fSlices[0]]];
ndd[0] = ndd[1];
}
}
if (!islices) return GetValidExtra(new_list, ncheck);
if (islices==1) {
return GetValidExtra(ndd[0], slice1, new_list, ncheck);
} else {
return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck);
}
default:
Error("GetNextCandidates", "Invalid islice=%i inside %s", islice, fVolume->GetName());
}
return 0;
}
void TGeoVoxelFinder::SortCrossedVoxels(Double_t *point, Double_t *dir)
{
if (NeedRebuild()) {
TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
vox->Voxelize();
fVolume->FindOverlaps();
}
fCurrentVoxel = 0;
fNcandidates = 0;
Int_t loc = 1+((fVolume->GetNdaughters()-1)>>3);
memset(fBits1, 0, loc);
memset(fInc, 0, 3*sizeof(Int_t));
for (Int_t i=0; i<3; i++) {
fInvdir[i] = TGeoShape::Big();
if (TMath::Abs(dir[i])<1E-10) continue;
fInc[i] = (dir[i]>0)?1:-1;
fInvdir[i] = 1./dir[i];
}
Bool_t flag = GetIndices(point);
TGeoBBox *box = (TGeoBBox*)(fVolume->GetShape());
const Double_t *box_orig = box->GetOrigin();
if (fInc[0]==0) {
fLimits[0] = TGeoShape::Big();
} else {
if (fSlices[0]==-2) {
fLimits[0] = (box_orig[0]-point[0]+fInc[0]*box->GetDX())*fInvdir[0];
} else {
if (fInc[0]==1) {
fLimits[0] = (fXb[fIbx-1]-point[0])*fInvdir[0];
} else {
fLimits[0] = (fXb[0]-point[0])*fInvdir[0];
}
}
}
if (fInc[1]==0) {
fLimits[1] = TGeoShape::Big();
} else {
if (fSlices[1]==-2) {
fLimits[1] = (box_orig[1]-point[1]+fInc[1]*box->GetDY())*fInvdir[1];
} else {
if (fInc[1]==1) {
fLimits[1] = (fYb[fIby-1]-point[1])*fInvdir[1];
} else {
fLimits[1] = (fYb[0]-point[1])*fInvdir[1];
}
}
}
if (fInc[2]==0) {
fLimits[2] = TGeoShape::Big();
} else {
if (fSlices[2]==-2) {
fLimits[2] = (box_orig[2]-point[2]+fInc[2]*box->GetDZ())*fInvdir[2];
} else {
if (fInc[2]==1) {
fLimits[2] = (fZb[fIbz-1]-point[2])*fInvdir[2];
} else {
fLimits[2] = (fZb[0]-point[2])*fInvdir[2];
}
}
}
if (!flag) {
return;
}
Int_t nd[3];
Int_t islices = 0;
memset(&nd[0], 0, 3*sizeof(Int_t));
UChar_t *slicex = 0;
if (fPriority[0]==2) {
nd[0] = fNsliceX[fSlices[0]];
slicex=&fIndcX[fOBx[fSlices[0]]];
islices++;
}
UChar_t *slicey = 0;
if (fPriority[1]==2) {
nd[1] = fNsliceY[fSlices[1]];
islices++;
if (slicex) {
slicey=&fIndcY[fOBy[fSlices[1]]];
} else {
slicex=&fIndcY[fOBy[fSlices[1]]];
nd[0] = nd[1];
}
}
UChar_t *slicez = 0;
if (fPriority[2]==2) {
nd[2] = fNsliceZ[fSlices[2]];
islices++;
if (slicex && slicey) {
slicez=&fIndcZ[fOBz[fSlices[2]]];
} else {
if (slicex) {
slicey=&fIndcZ[fOBz[fSlices[2]]];
nd[1] = nd[2];
} else {
slicex=&fIndcZ[fOBz[fSlices[2]]];
nd[0] = nd[2];
}
}
}
switch (islices) {
case 0:
Error("SortCrossedVoxels", "no slices for %s", fVolume->GetName());
return;
case 1:
IntersectAndStore(nd[0], slicex);
break;
case 2:
IntersectAndStore(nd[0], slicex, nd[1], slicey);
break;
default:
IntersectAndStore(nd[0], slicex, nd[1], slicey, nd[2], slicez);
}
}
Int_t *TGeoVoxelFinder::GetCheckList(Double_t *point, Int_t &nelem)
{
if (NeedRebuild()) {
Voxelize();
fVolume->FindOverlaps();
}
if (fVolume->GetNdaughters() == 1) {
if (fXb) {
if (point[0]<fXb[0] || point[0]>fXb[1]) return 0;
}
if (fYb) {
if (point[1]<fYb[0] || point[1]>fYb[1]) return 0;
}
if (fZb) {
if (point[2]<fZb[0] || point[2]>fZb[1]) return 0;
}
fCheckList[0] = 0;
nelem = 1;
return fCheckList;
}
Int_t nslices = 0;
UChar_t *slice1 = 0;
UChar_t *slice2 = 0;
UChar_t *slice3 = 0;
Int_t nd[3] = {0,0,0};
Int_t im;
if (fPriority[0]) {
im = TMath::BinarySearch(fIbx, fXb, point[0]);
if ((im==-1) || (im==fIbx-1)) return 0;
if (fPriority[0]==2) {
nd[0] = fNsliceX[im];
if (!nd[0]) return 0;
nslices++;
slice1 = &fIndcX[fOBx[im]];
}
}
if (fPriority[1]) {
im = TMath::BinarySearch(fIby, fYb, point[1]);
if ((im==-1) || (im==fIby-1)) return 0;
if (fPriority[1]==2) {
nd[1] = fNsliceY[im];
if (!nd[1]) return 0;
nslices++;
if (slice1) {
slice2 = &fIndcY[fOBy[im]];
} else {
slice1 = &fIndcY[fOBy[im]];
nd[0] = nd[1];
}
}
}
if (fPriority[2]) {
im = TMath::BinarySearch(fIbz, fZb, point[2]);
if ((im==-1) || (im==fIbz-1)) return 0;
if (fPriority[2]==2) {
nd[2] = fNsliceZ[im];
if (!nd[2]) return 0;
nslices++;
if (slice1 && slice2) {
slice3 = &fIndcZ[fOBz[im]];
} else {
if (slice1) {
slice2 = &fIndcZ[fOBz[im]];
nd[1] = nd[2];
} else {
slice1 = &fIndcZ[fOBz[im]];
nd[0] = nd[2];
}
}
}
}
nelem = 0;
Bool_t intersect = kFALSE;
switch (nslices) {
case 0:
Error("GetCheckList", "No slices for %s", fVolume->GetName());
return 0;
case 1:
intersect = Intersect(nd[0], slice1, nelem, fCheckList);
break;
case 2:
intersect = Intersect(nd[0], slice1, nd[1], slice2, nelem, fCheckList);
break;
default:
intersect = Intersect(nd[0], slice1, nd[1], slice2, nd[2], slice3, nelem, fCheckList);
}
if (intersect) return fCheckList;
return 0;
}
Int_t *TGeoVoxelFinder::GetVoxelCandidates(Int_t i, Int_t j, Int_t k, Int_t &ncheck)
{
UChar_t *slice1 = 0;
UChar_t *slice2 = 0;
UChar_t *slice3 = 0;
Int_t nd[3] = {0,0,0};
Int_t nslices = 0;
if (fPriority[0]==2) {
nd[0] = fNsliceX[i];
if (!nd[0]) return 0;
nslices++;
slice1 = &fIndcX[fOBx[i]];
}
if (fPriority[1]==2) {
nd[1] = fNsliceY[j];
if (!nd[1]) return 0;
nslices++;
if (slice1) {
slice2 = &fIndcY[fOBy[j]];
} else {
slice1 = &fIndcY[fOBy[j]];
nd[0] = nd[1];
}
}
if (fPriority[2]==2) {
nd[2] = fNsliceZ[k];
if (!nd[2]) return 0;
nslices++;
if (slice1 && slice2) {
slice3 = &fIndcZ[fOBz[k]];
} else {
if (slice1) {
slice2 = &fIndcZ[fOBz[k]];
nd[1] = nd[2];
} else {
slice1 = &fIndcZ[fOBz[k]];
nd[0] = nd[2];
}
}
}
Bool_t intersect = kFALSE;
switch (nslices) {
case 0:
Error("GetCheckList", "No slices for %s", fVolume->GetName());
return 0;
case 1:
intersect = Intersect(nd[0], slice1, ncheck, fCheckList);
break;
case 2:
intersect = Intersect(nd[0], slice1, nd[1], slice2, ncheck, fCheckList);
break;
default:
intersect = Intersect(nd[0], slice1, nd[1], slice2, nd[2], slice3, ncheck, fCheckList);
}
if (intersect) return fCheckList;
return 0;
}
Int_t *TGeoVoxelFinder::GetNextVoxel(Double_t *point, Double_t * , Int_t &ncheck)
{
if (NeedRebuild()) {
Voxelize();
fVolume->FindOverlaps();
}
if (fCurrentVoxel==0) {
fCurrentVoxel++;
ncheck = fNcandidates;
return fCheckList;
}
fCurrentVoxel++;
return GetNextCandidates(point, ncheck);
}
Bool_t TGeoVoxelFinder::Intersect(Int_t n1, UChar_t *array1, Int_t &nf, Int_t *result)
{
Int_t nd = fVolume->GetNdaughters();
nf = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
UChar_t byte;
Bool_t ibreak = kFALSE;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = array1[current_byte];
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
result[nf++] = (current_byte<<3)+current_bit;
if (nf==n1) {
ibreak = kTRUE;
break;
}
}
}
if (ibreak) return kTRUE;
}
return kTRUE;
}
Bool_t TGeoVoxelFinder::IntersectAndStore(Int_t n1, UChar_t *array1)
{
Int_t nd = fVolume->GetNdaughters();
fNcandidates = 0;
Int_t nbytes = 1+((nd-1)>>3);
memcpy(fBits1, array1, nbytes*sizeof(UChar_t));
Int_t current_byte;
Int_t current_bit;
UChar_t byte;
Bool_t ibreak = kFALSE;
Int_t icand;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = array1[current_byte];
icand = current_byte<<3;
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
fCheckList[fNcandidates++] = icand+current_bit;
if (fNcandidates==n1) {
ibreak = kTRUE;
break;
}
}
}
if (ibreak) return kTRUE;
}
return kTRUE;
}
Bool_t TGeoVoxelFinder::Union(Int_t n1, UChar_t *array1)
{
Int_t nd = fVolume->GetNdaughters();
fNcandidates = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
UChar_t byte;
Bool_t ibreak = kFALSE;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = (~fBits1[current_byte]) & array1[current_byte];
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
fCheckList[fNcandidates++] = (current_byte<<3)+current_bit;
if (fNcandidates==n1) {
ibreak = kTRUE;
break;
}
}
}
fBits1[current_byte] |= byte;
if (ibreak) return kTRUE;
}
return (fNcandidates>0);
}
Bool_t TGeoVoxelFinder::Union(Int_t , UChar_t *array1, Int_t , UChar_t *array2)
{
Int_t nd = fVolume->GetNdaughters();
fNcandidates = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
UChar_t byte;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = (~fBits1[current_byte]) & (array1[current_byte] & array2[current_byte]);
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
fCheckList[fNcandidates++] = (current_byte<<3)+current_bit;
}
}
fBits1[current_byte] |= byte;
}
return (fNcandidates>0);
}
Bool_t TGeoVoxelFinder::Union(Int_t , UChar_t *array1, Int_t , UChar_t *array2, Int_t , UChar_t *array3)
{
Int_t nd = fVolume->GetNdaughters();
fNcandidates = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
UChar_t byte;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = (~fBits1[current_byte]) & (array1[current_byte] & array2[current_byte] & array3[current_byte]);
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
fCheckList[fNcandidates++] = (current_byte<<3)+current_bit;
}
}
fBits1[current_byte] |= byte;
}
return (fNcandidates>0);
}
Bool_t TGeoVoxelFinder::Intersect(Int_t n1, UChar_t *array1, Int_t n2, UChar_t *array2, Int_t &nf, Int_t *result)
{
Int_t nd = fVolume->GetNdaughters();
nf = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
UChar_t byte;
Bool_t ibreak = kFALSE;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = array1[current_byte] & array2[current_byte];
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
result[nf++] = (current_byte<<3)+current_bit;
if ((nf==n1) || (nf==n2)) {
ibreak = kTRUE;
break;
}
}
}
if (ibreak) return kTRUE;
}
return (nf>0);
}
Bool_t TGeoVoxelFinder::IntersectAndStore(Int_t , UChar_t *array1, Int_t , UChar_t *array2)
{
Int_t nd = fVolume->GetNdaughters();
fNcandidates = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
Int_t icand;
UChar_t byte;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = array1[current_byte] & array2[current_byte];
icand = current_byte<<3;
fBits1[current_byte] = byte;
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
fCheckList[fNcandidates++] = icand+current_bit;
}
}
}
return (fNcandidates>0);
}
Bool_t TGeoVoxelFinder::Intersect(Int_t n1, UChar_t *array1, Int_t n2, UChar_t *array2, Int_t n3, UChar_t *array3, Int_t &nf, Int_t *result)
{
Int_t nd = fVolume->GetNdaughters();
nf = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
UChar_t byte;
Bool_t ibreak = kFALSE;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = array1[current_byte] & array2[current_byte] & array3[current_byte];
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
result[nf++] = (current_byte<<3)+current_bit;
if ((nf==n1) || (nf==n2) || (nf==n3)) {
ibreak = kTRUE;
break;
}
}
}
if (ibreak) return kTRUE;
}
return (nf>0);
}
Bool_t TGeoVoxelFinder::IntersectAndStore(Int_t , UChar_t *array1, Int_t , UChar_t *array2, Int_t , UChar_t *array3)
{
Int_t nd = fVolume->GetNdaughters();
fNcandidates = 0;
Int_t nbytes = 1+((nd-1)>>3);
Int_t current_byte;
Int_t current_bit;
Int_t icand;
UChar_t byte;
for (current_byte=0; current_byte<nbytes; current_byte++) {
byte = array1[current_byte] & array2[current_byte] & array3[current_byte];
icand = current_byte<<3;
fBits1[current_byte] = byte;
if (!byte) continue;
for (current_bit=0; current_bit<8; current_bit++) {
if (byte & (1<<current_bit)) {
fCheckList[fNcandidates++] = icand+current_bit;
}
}
}
return (fNcandidates>0);
}
void TGeoVoxelFinder::SortAll(Option_t *)
{
Int_t nd = fVolume->GetNdaughters();
Int_t nperslice = 1+(nd-1)/(8*sizeof(UChar_t));
Int_t nmaxslices = 2*nd+1;
Double_t *boundaries = new Double_t[6*nd];
Double_t xmin, xmax, ymin, ymax, zmin, zmax;
TGeoBBox *box = (TGeoBBox*)fVolume->GetShape();
xmin = (box->GetOrigin())[0] - box->GetDX();
xmax = (box->GetOrigin())[0] + box->GetDX();
ymin = (box->GetOrigin())[1] - box->GetDY();
ymax = (box->GetOrigin())[1] + box->GetDY();
zmin = (box->GetOrigin())[2] - box->GetDZ();
zmax = (box->GetOrigin())[2] + box->GetDZ();
if ((xmin>=xmax) || (ymin>=ymax) || (zmin>=zmax)) {
Error("SortAll", "Wrong bounding box for volume %s", fVolume->GetName());
return;
}
Int_t id;
for (id=0; id<nd; id++) {
boundaries[2*id] = fBoxes[6*id+3]-fBoxes[6*id];
boundaries[2*id+1] = fBoxes[6*id+3]+fBoxes[6*id];
boundaries[2*id+2*nd] = fBoxes[6*id+4]-fBoxes[6*id+1];
boundaries[2*id+2*nd+1] = fBoxes[6*id+4]+fBoxes[6*id+1];
boundaries[2*id+4*nd] = fBoxes[6*id+5]-fBoxes[6*id+2];
boundaries[2*id+4*nd+1] = fBoxes[6*id+5]+fBoxes[6*id+2];
}
Int_t *index = new Int_t[2*nd];
UChar_t *ind = new UChar_t[nmaxslices*nperslice];
Int_t *extra = new Int_t[nmaxslices*4];
Double_t *temp = new Double_t[2*nd];
Int_t current = 0;
Int_t indextra = 0;
Int_t nleft, nright;
Int_t *extra_left = new Int_t[nd];
Int_t *extra_right = new Int_t[nd];
Double_t xxmin, xxmax, xbmin, xbmax, ddx1, ddx2;
UChar_t *bits;
UInt_t loc, bitnumber;
UChar_t bit;
Int_t ib = 0;
TMath::Sort(2*nd, &boundaries[0], &index[0], kFALSE);
for (id=0; id<2*nd; id++) {
if (!ib) {temp[ib++] = boundaries[index[id]]; continue;}
if (TMath::Abs(temp[ib-1]-boundaries[index[id]])>1E-10)
temp[ib++] = boundaries[index[id]];
}
if (ib < 2) {
Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on X", fVolume->GetName());
delete [] index;
delete [] ind;
delete [] temp;
delete [] extra;
delete [] extra_left;
delete [] extra_right;
SetInvalid();
return;
}
if (ib == 2) {
if (((temp[0]-xmin)<1E-10) && ((temp[1]-xmax)>-1E-10)) {
fPriority[0] = 0;
if (fIndcX) delete [] fIndcX;
fIndcX = 0;
fNx = 0;
if (fXb) delete [] fXb;
fXb = 0;
fIbx = 0;
if (fOBx) delete [] fOBx;
fOBx = 0;
fNox = 0;
} else {
fPriority[0] = 1;
}
} else {
fPriority[0] = 2;
}
if (fPriority[0]) {
if (fXb) delete [] fXb;
fXb = new Double_t[ib];
memcpy(fXb, &temp[0], ib*sizeof(Double_t));
fIbx = ib;
}
if (fPriority[0]==2) {
memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
if (fOBx) delete [] fOBx;
fNox = fIbx-1;
fOBx = new Int_t[fNox];
if (fOEx) delete [] fOEx;
fOEx = new Int_t[fNox];
if (fNsliceX) delete [] fNsliceX;
fNsliceX = new Int_t[fNox];
current = 0;
indextra = 0;
for (id=0; id<fNox; id++) {
fOBx[id] = current;
fOEx[id] = indextra;
fNsliceX[id] = 0;
extra[indextra] = extra[indextra+1] = 0;
nleft = nright = 0;
bits = &ind[current];
xxmin = fXb[id];
xxmax = fXb[id+1];
for (Int_t ic=0; ic<nd; ic++) {
xbmin = fBoxes[6*ic+3]-fBoxes[6*ic];
xbmax = fBoxes[6*ic+3]+fBoxes[6*ic];
ddx1 = xbmin-xxmax;
if (ddx1>-1E-10) continue;
ddx2 = xbmax-xxmin;
if (ddx2<1E-10) continue;
fNsliceX[id]++;
bitnumber = (UInt_t)ic;
loc = bitnumber/8;
bit = bitnumber%8;
bits[loc] |= 1<<bit;
ddx1 = xbmin-xxmin;
ddx2 = xbmax-xxmax;
if ((id==0) || (ddx1>-1E-10)) {
extra_left[nleft++] = ic;
}
if ((id==(fNoz-1)) || (ddx2<1E-10)) {
extra_right[nright++] = ic;
}
}
if (fNsliceX[id]>0) current += nperslice;
extra[indextra] = nleft;
extra[indextra+1] = nright;
if (nleft) memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));
indextra += 2+nleft+nright;
}
if (fIndcX) delete [] fIndcX;
fNx = current;
fIndcX = new UChar_t[current];
memcpy(fIndcX, ind, current*sizeof(UChar_t));
if (fExtraX) delete [] fExtraX;
fNex = indextra;
if (indextra>nmaxslices*4) printf("Woops!!!\n");
fExtraX = new Int_t[indextra];
memcpy(fExtraX, extra, indextra*sizeof(Int_t));
}
ib = 0;
TMath::Sort(2*nd, &boundaries[2*nd], &index[0], kFALSE);
for (id=0; id<2*nd; id++) {
if (!ib) {temp[ib++] = boundaries[2*nd+index[id]]; continue;}
if (TMath::Abs(temp[ib-1]-boundaries[2*nd+index[id]])>1E-10)
temp[ib++]=boundaries[2*nd+index[id]];
}
if (ib < 2) {
Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on Y", fVolume->GetName());
delete [] index;
delete [] ind;
delete [] temp;
delete [] extra;
delete [] extra_left;
delete [] extra_right;
SetInvalid();
return;
}
if (ib == 2) {
if (((temp[0]-ymin)<1E-10) && ((temp[1]-ymax)>-1E-10)) {
fPriority[1] = 0;
if (fIndcY) delete [] fIndcY;
fIndcY = 0;
fNy = 0;
if (fYb) delete [] fYb;
fYb = 0;
fIby = 0;
if (fOBy) delete [] fOBy;
fOBy = 0;
fNoy = 0;
} else {
fPriority[1] = 1;
}
} else {
fPriority[1] = 2;
}
if (fPriority[1]) {
if (fYb) delete [] fYb;
fYb = new Double_t[ib];
memcpy(fYb, &temp[0], ib*sizeof(Double_t));
fIby = ib;
}
if (fPriority[1]==2) {
memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
if (fOBy) delete [] fOBy;
fNoy = fIby-1;
fOBy = new Int_t[fNoy];
if (fOEy) delete [] fOEy;
fOEy = new Int_t[fNoy];
if (fNsliceY) delete [] fNsliceY;
fNsliceY = new Int_t[fNoy];
current = 0;
indextra = 0;
for (id=0; id<fNoy; id++) {
fOBy[id] = current;
fOEy[id] = indextra;
fNsliceY[id] = 0;
extra[indextra] = extra[indextra+1] = 0;
nleft = nright = 0;
bits = &ind[current];
xxmin = fYb[id];
xxmax = fYb[id+1];
for (Int_t ic=0; ic<nd; ic++) {
xbmin = fBoxes[6*ic+4]-fBoxes[6*ic+1];
xbmax = fBoxes[6*ic+4]+fBoxes[6*ic+1];
ddx1 = xbmin-xxmax;
if (ddx1>-1E-10) continue;
ddx2 = xbmax-xxmin;
if (ddx2<1E-10) continue;
fNsliceY[id]++;
bitnumber = (UInt_t)ic;
loc = bitnumber/8;
bit = bitnumber%8;
bits[loc] |= 1<<bit;
ddx1 = xbmin-xxmin;
ddx2 = xbmax-xxmax;
if ((id==0) || (ddx1>-1E-10)) {
extra_left[nleft++] = ic;
}
if ((id==(fNoz-1)) || (ddx2<1E-10)) {
extra_right[nright++] = ic;
}
}
if (fNsliceY[id]>0) current += nperslice;
extra[indextra] = nleft;
extra[indextra+1] = nright;
if (nleft) memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));
indextra += 2+nleft+nright;
}
if (fIndcY) delete [] fIndcY;
fNy = current;
fIndcY = new UChar_t[current];
memcpy(fIndcY, &ind[0], current*sizeof(UChar_t));
if (fExtraY) delete [] fExtraY;
fNey = indextra;
if (indextra>nmaxslices*4) printf("Woops!!!\n");
fExtraY = new Int_t[indextra];
memcpy(fExtraY, extra, indextra*sizeof(Int_t));
}
ib = 0;
TMath::Sort(2*nd, &boundaries[4*nd], &index[0], kFALSE);
for (id=0; id<2*nd; id++) {
if (!ib) {temp[ib++] = boundaries[4*nd+index[id]]; continue;}
if ((TMath::Abs(temp[ib-1]-boundaries[4*nd+index[id]]))>1E-10)
temp[ib++]=boundaries[4*nd+index[id]];
}
if (ib < 2) {
Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on Z", fVolume->GetName());
delete [] index;
delete [] ind;
delete [] temp;
delete [] extra;
delete [] extra_left;
delete [] extra_right;
SetInvalid();
return;
}
if (ib == 2) {
if (((temp[0]-zmin)<1E-10) && ((temp[1]-zmax)>-1E-10)) {
fPriority[2] = 0;
if (fIndcZ) delete [] fIndcZ;
fIndcZ = 0;
fNz = 0;
if (fZb) delete [] fZb;
fZb = 0;
fIbz = 0;
if (fOBz) delete [] fOBz;
fOBz = 0;
fNoz = 0;
} else {
fPriority[2] = 1;
}
} else {
fPriority[2] = 2;
}
if (fPriority[2]) {
if (fZb) delete [] fZb;
fZb = new Double_t[ib];
memcpy(fZb, &temp[0], ib*sizeof(Double_t));
fIbz = ib;
}
if (fPriority[2]==2) {
memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
if (fOBz) delete [] fOBz;
fNoz = fIbz-1;
fOBz = new Int_t[fNoz];
if (fOEz) delete [] fOEz;
fOEz = new Int_t[fNoz];
if (fNsliceZ) delete [] fNsliceZ;
fNsliceZ = new Int_t[fNoz];
current = 0;
indextra = 0;
for (id=0; id<fNoz; id++) {
fOBz[id] = current;
fOEz[id] = indextra;
fNsliceZ[id] = 0;
extra[indextra] = extra[indextra+1] = 0;
nleft = nright = 0;
bits = &ind[current];
xxmin = fZb[id];
xxmax = fZb[id+1];
for (Int_t ic=0; ic<nd; ic++) {
xbmin = fBoxes[6*ic+5]-fBoxes[6*ic+2];
xbmax = fBoxes[6*ic+5]+fBoxes[6*ic+2];
ddx1 = xbmin-xxmax;
if (ddx1>-1E-10) continue;
ddx2 = xbmax-xxmin;
if (ddx2<1E-10) continue;
fNsliceZ[id]++;
bitnumber = (UInt_t)ic;
loc = bitnumber/8;
bit = bitnumber%8;
bits[loc] |= 1<<bit;
ddx1 = xbmin-xxmin;
ddx2 = xbmax-xxmax;
if ((id==0) || (ddx1>-1E-10)) {
extra_left[nleft++] = ic;
}
if ((id==(fNoz-1)) || (ddx2<1E-10)) {
extra_right[nright++] = ic;
}
}
if (fNsliceZ[id]>0) current += nperslice;
extra[indextra] = nleft;
extra[indextra+1] = nright;
if (nleft) memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));
indextra += 2+nleft+nright;
}
if (fIndcZ) delete [] fIndcZ;
fNz = current;
fIndcZ = new UChar_t[current];
memcpy(fIndcZ, &ind[0], current*sizeof(UChar_t));
if (fExtraZ) delete [] fExtraZ;
fNez = indextra;
if (indextra>nmaxslices*4) printf("Woops!!!\n");
fExtraZ = new Int_t[indextra];
memcpy(fExtraZ, extra, indextra*sizeof(Int_t));
}
delete [] boundaries;
delete [] index;
delete [] temp;
delete [] ind;
delete [] extra;
delete [] extra_left;
delete [] extra_right;
if ((!fPriority[0]) && (!fPriority[1]) && (!fPriority[2])) {
SetInvalid();
if (nd>1) Error("SortAll", "Volume %s: Cannot make slices on any axis", fVolume->GetName());
}
}
void TGeoVoxelFinder::Print(Option_t *) const
{
if (NeedRebuild()) {
TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
vox->Voxelize();
fVolume->FindOverlaps();
}
Int_t id, i;
Int_t nd = fVolume->GetNdaughters();
printf("Voxels for volume %s (nd=%i)\n", fVolume->GetName(), fVolume->GetNdaughters());
printf("priority : x=%i y=%i z=%i\n", fPriority[0], fPriority[1], fPriority[2]);
Int_t nextra;
Int_t nbytes = 1+((fVolume->GetNdaughters()-1)>>3);
UChar_t byte, bit;
UChar_t *slice;
printf("XXX\n");
if (fPriority[0]==2) {
for (id=0; id<fIbx; id++) {
printf("%15.10f\n",fXb[id]);
if (id == (fIbx-1)) break;
printf("slice %i : %i\n", id, fNsliceX[id]);
if (fNsliceX[id]) {
slice = &fIndcX[fOBx[id]];
for (i=0; i<nbytes; i++) {
byte = slice[i];
for (bit=0; bit<8; bit++) {
if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
}
}
printf("\n");
}
GetExtraX(id,kTRUE,nextra);
printf(" extra_about_left = %i\n", nextra);
GetExtraX(id,kFALSE,nextra);
printf(" extra_about_right = %i\n", nextra);
}
} else if (fPriority[0]==1) {
printf("%15.10f\n",fXb[0]);
for (id=0; id<nd; id++) printf(" %i ",id);
printf("\n");
printf("%15.10f\n",fXb[1]);
}
printf("YYY\n");
if (fPriority[1]==2) {
for (id=0; id<fIby; id++) {
printf("%15.10f\n", fYb[id]);
if (id == (fIby-1)) break;
printf("slice %i : %i\n", id, fNsliceY[id]);
if (fNsliceY[id]) {
slice = &fIndcY[fOBy[id]];
for (i=0; i<nbytes; i++) {
byte = slice[i];
for (bit=0; bit<8; bit++) {
if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
}
}
}
GetExtraY(id,kTRUE,nextra);
printf(" extra_about_left = %i\n", nextra);
GetExtraY(id,kFALSE,nextra);
printf(" extra_about_right = %i\n", nextra);
}
} else if (fPriority[1]==1) {
printf("%15.10f\n",fYb[0]);
for (id=0; id<nd; id++) printf(" %i ",id);
printf("\n");
printf("%15.10f\n",fYb[1]);
}
printf("ZZZ\n");
if (fPriority[2]==2) {
for (id=0; id<fIbz; id++) {
printf("%15.10f\n", fZb[id]);
if (id == (fIbz-1)) break;
printf("slice %i : %i\n", id, fNsliceZ[id]);
if (fNsliceZ[id]) {
slice = &fIndcZ[fOBz[id]];
for (i=0; i<nbytes; i++) {
byte = slice[i];
for (bit=0; bit<8; bit++) {
if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
}
}
printf("\n");
}
GetExtraZ(id,kTRUE,nextra);
printf(" extra_about_left = %i\n", nextra);
GetExtraZ(id,kFALSE,nextra);
printf(" extra_about_right = %i\n", nextra);
}
} else if (fPriority[2]==1) {
printf("%15.10f\n",fZb[0]);
for (id=0; id<nd; id++) printf(" %i ",id);
printf("\n");
printf("%15.10f\n",fZb[1]);
}
}
void TGeoVoxelFinder::PrintVoxelLimits(Double_t *point) const
{
if (NeedRebuild()) {
TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
vox->Voxelize();
fVolume->FindOverlaps();
}
Int_t im=0;
if (fPriority[0]) {
im = TMath::BinarySearch(fIbx, fXb, point[0]);
if ((im==-1) || (im==fIbx-1)) {
printf("Voxel X limits: OUT\n");
} else {
printf("Voxel X limits: %g %g\n", fXb[im], fXb[im+1]);
}
}
if (fPriority[1]) {
im = TMath::BinarySearch(fIby, fYb, point[1]);
if ((im==-1) || (im==fIby-1)) {
printf("Voxel Y limits: OUT\n");
} else {
printf("Voxel Y limits: %g %g\n", fYb[im], fYb[im+1]);
}
}
if (fPriority[2]) {
im = TMath::BinarySearch(fIbz, fZb, point[2]);
if ((im==-1) || (im==fIbz-1)) {
printf("Voxel Z limits: OUT\n");
} else {
printf("Voxel Z limits: %g %g\n", fZb[im], fZb[im+1]);
}
}
}
void TGeoVoxelFinder::Voxelize(Option_t * )
{
BuildVoxelLimits();
SortAll();
SetNeedRebuild(kFALSE);
}
void TGeoVoxelFinder::Streamer(TBuffer &R__b)
{
if (R__b.IsReading()) {
UInt_t R__s, R__c;
Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
if (R__v > 2) {
R__b.ReadClassBuffer(TGeoVoxelFinder::Class(), this, R__v, R__s, R__c);
return;
}
UChar_t *dummy = new UChar_t[R__c-2];
R__b.ReadFastArray(dummy, R__c-2);
delete [] dummy;
SetInvalid(kTRUE);
} else {
R__b.WriteClassBuffer(TGeoVoxelFinder::Class(), this);
}
}