// @(#)root/geom:$Name:  $:$Id: TGeoVoxelFinder.cxx,v 1.11 2002/12/03 16:01:40 brun Exp $
// Author: Andrei Gheata   04/02/02

/*************************************************************************
 * 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.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////////
// Full description with examples and pictures
//
//
//
//
//
/*



*/
//
#include "TObject.h"
#include "TGeoMatrix.h"
#include "TGeoBBox.h"
#include "TGeoNode.h"
#include "TGeoManager.h"

#include "TGeoVoxelFinder.h"

/*************************************************************************
 * TGeoVoxelFinder - finder class handling voxels 
 *  
 *************************************************************************/

ClassImp(TGeoVoxelFinder)


//-----------------------------------------------------------------------------
TGeoVoxelFinder::TGeoVoxelFinder()
{
// Default constructor
   fVolume  = 0;
   fNboxes  = 0;
   fIbx     = 0;
   fIby     = 0;
   fIbz     = 0;
   fNox     = 0;
   fNoy     = 0;
   fNoz     = 0;
   fNx      = 0;
   fNy      = 0;
   fNz      = 0;
   fBoxes    = 0;
   fXb       = 0;
   fYb       = 0;
   fZb       = 0;
   fOBx      = 0;
   fOBy      = 0;
   fOBz      = 0;
   fIndX      = 0;
   fIndY      = 0;
   fIndZ      = 0;
   fCheckList = 0;
   fNcandidates  = 0;
   fCurrentVoxel = 0;
}
//-----------------------------------------------------------------------------
TGeoVoxelFinder::TGeoVoxelFinder(TGeoVolume *vol)
{
// Default constructor
   if (!vol) return;
   fVolume  = vol;
   fVolume->SetCylVoxels(kFALSE);
   fNboxes   = 0;
   fIbx      = 0;
   fIby      = 0;
   fIbz      = 0;
   fNox      = 0;
   fNoy      = 0;
   fNoz      = 0;
   fNx       = 0;
   fNy       = 0;
   fNz       = 0;
   fBoxes    = 0;
   fXb       = 0;
   fYb       = 0;
   fZb       = 0;
   fOBx      = 0;
   fOBy      = 0;
   fOBz      = 0;
   fIndX     = 0;
   fIndY     = 0;
   fIndZ     = 0;
   fCheckList = 0;
   fNcandidates  = 0;
   fCurrentVoxel = 0;
}
//-----------------------------------------------------------------------------
TGeoVoxelFinder::~TGeoVoxelFinder()
{
// Destructor
//   printf("deleting finder of %sn", fVolume->GetName());
   if (fOBx) delete [] fOBx;
   if (fOBy) delete [] fOBy;
   if (fOBz) delete [] fOBz;
//   printf("OBx OBy OBz...n");
   if (fBoxes) delete fBoxes;
//   printf("boxes...n");
   if (fXb) delete [] fXb;
   if (fYb) delete [] fYb;
   if (fZb) delete [] fZb;
//   printf("Xb Yb Zb...n");
   if (fIndX) delete [] fIndX;
   if (fIndY) delete [] fIndY;
   if (fIndZ) delete [] fIndZ;
//   printf("IndX IndY IndZ...n");
   if (fCheckList) delete [] fCheckList;
//   printf("checklist...n");
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::BuildVoxelLimits()
{
// build the array of bounding boxes of the nodes inside
   Int_t nd = fVolume->GetNdaughters();
   if (!nd) return;
//   printf("building boxes for %s  nd=%in", fVolume->GetName(), nd);
   Int_t id;
   TGeoNode *node;
   if (fBoxes) delete fBoxes;
   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];
//   printf("boundaries for %s :n", GetName());
   TGeoBBox *box = 0;
   for (id=0; id<nd; id++) {
      node = fVolume->GetNode(id);
//      if (!strcmp(node->ClassName(), "TGeoNodeOffset") continue;
      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]); // dX
      fBoxes[6*id+1] = 0.5*(xyz[3]-xyz[2]); // dY
      fBoxes[6*id+2] = 0.5*(xyz[5]-xyz[4]); // dZ
      fBoxes[6*id+3] = 0.5*(xyz[0]+xyz[1]); // Ox
      fBoxes[6*id+4] = 0.5*(xyz[2]+xyz[3]); // Oy
      fBoxes[6*id+5] = 0.5*(xyz[4]+xyz[5]); // Oz
   }
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::CreateCheckList()
{
// Initializes check list.
   if (!fCheckList) {
      Int_t nd = fVolume->GetNdaughters();
      if (nd>0) fCheckList = new Int_t[nd];
   }
}      
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::DaughterToMother(Int_t id, Double_t *local, Double_t *master) const
{
// convert a point from the local reference system of node id to reference
// system of mother volume
   TGeoMatrix *mat = fVolume->GetNode(id)->GetMatrix();
   mat->LocalToMaster(local, master);
}
//-----------------------------------------------------------------------------
Double_t TGeoVoxelFinder::Efficiency()
{
//--- Compute voxelization efficiency.
   printf("Voxelization efficiency for %sn", fVolume->GetName());
   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++) {  // loop on boundaries
         effslice += fIndX[fOBx[id]];
      }
      if (effslice != 0) effslice = nd/effslice;
      else printf("Woops : slice Xn");
   }
   printf("X efficiency : %gn", effslice);
   eff += effslice;
   effslice = 0;
   if (fPriority[1]) {
      for (id=0; id<fIby-1; id++) {  // loop on boundaries
         effslice += fIndY[fOBy[id]];
      }
      if (effslice != 0) effslice = nd/effslice;
      else printf("Woops : slice Xn");
   }
   printf("Y efficiency : %gn", effslice);
   eff += effslice;
   effslice = 0;
   if (fPriority[2]) {
      for (id=0; id<fIbz-1; id++) {  // loop on boundaries
         effslice += fIndZ[fOBz[id]];
      }
      if (effslice != 0) effslice = nd/effslice;
      else printf("Woops : slice Xn");
   }
   printf("Z efficiency : %gn", effslice);
   eff += effslice;
   eff /= 3.;
   printf("Total efficiency : %gn", eff);
   return eff;
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::FindOverlaps(Int_t inode) const
{
// create the list of nodes for which the bboxes overlap with inode's bbox
   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);
//   printf("Finding overlaps for %sn", node->GetName());
   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];
//   printf("overlaps for MANY node %sn", node->GetName());

//   printf("xmin=%g  xmax=%gn", xmin, xmax);
//   printf("ymin=%g  ymax=%gn", ymin, ymax);
//   printf("zmin=%g  zmax=%gn", zmin, zmax);
   Bool_t in = kFALSE;
   //TGeoNode *node1;
   // loop on brothers
   for (Int_t ib=0; ib<nd; ib++) {
      if (ib == inode) continue; // everyone overlaps with itself
      in = kFALSE;
      //node1 = fVolume->GetNode(ib);
      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];
//      printf(" node %sn", node1->GetName());
//      printf("  xmin1=%g  xmax1=%gn", xmin1, xmax1);
//      printf("  ymin1=%g  ymax1=%gn", ymin1, ymax1);
//      printf("  zmin1=%g  zmax1=%gn", zmin1, zmax1);


      ddx1 = TMath::Abs(xmin1-xmax);
      ddx2 = TMath::Abs(xmax1-xmin);
         if ((ddx1<1E-12)||(ddx2<1E-12)) continue;
         if ((xmin1==xmin)||(xmax1==xmax)) in = kTRUE;
         if (((xmin1>xmin)&&(xmin1<xmax))||((xmax1>xmin)&&(xmax1<xmax)) ||
             ((xmin>xmin1)&&(xmin<xmax1))||((xmax>xmin1)&&(xmax<xmax1)))
                in = kTRUE;
      if (!in) continue;
//      printf("x overlap...n");
      in = kFALSE;

      ddx1 = TMath::Abs(ymin1-ymax);
      ddx2 = TMath::Abs(ymax1-ymin);
         if ((ddx1<1E-12)||(ddx2<1E-12)) continue;
         if ((ymin1==ymin)||(ymax1==ymax)) in = kTRUE;
         if (((ymin1>ymin)&&(ymin1<ymax))||((ymax1>ymin)&&(ymax1<ymax)) ||
             ((ymin>ymin1)&&(ymin<ymax1))||((ymax>ymin1)&&(ymax<ymax1)))
                in = kTRUE;
      if (!in) continue;
//      printf("y overlap...n");
      in = kFALSE;

      ddx1 = TMath::Abs(zmin1-zmax);
      ddx2 = TMath::Abs(zmax1-zmin);
         if ((ddx1<1E-12)||(ddx2<1E-12)) continue;
         if ((zmin1==zmin)||(zmax1==zmax)) in = kTRUE;
         if (((zmin1>zmin)&&(zmin1<zmax))||((zmax1>zmin)&&(zmax1<zmax)) ||
             ((zmin>zmin1)&&(zmin<zmax1))||((zmax>zmin1)&&(zmax<zmax1)))
                in = kTRUE;
      if (!in) continue;
//      printf("Overlapping %in", ib);
      otmp[novlp++] = ib;
   }
   if (!novlp) {
//      printf("---no overlaps for MANY node %sn", node->GetName());
      node->SetOverlaps(ovlps, 0);
      return;
   }
   ovlps = new Int_t[novlp];
   memcpy(ovlps, otmp, novlp*sizeof(Int_t));
   delete [] otmp;
   node->SetOverlaps(ovlps, novlp);
//   printf("Overlaps for MANY node %s : %in", node->GetName(), novlp);
}
//-----------------------------------------------------------------------------
Bool_t TGeoVoxelFinder::GetIndices(Double_t *point)
{
// Getindices for current slices on x, y, z
   fSlices[0] = -2; // -2 means 'all daughters in slice'
   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 (!fIndX[fOBx[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 (!fIndY[fOBy[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 (!fIndZ[fOBz[fSlices[2]]]) return kFALSE;
      }
   }       
   return flag;
}
//-----------------------------------------------------------------------------
Bool_t TGeoVoxelFinder::GetNextIndices(Double_t *point, Double_t *dir)
{
// Get indices for next voxel
   Int_t dind[3];
   memcpy(&dind[0], &fSlices[0], 3*sizeof(Int_t));
   Double_t dmin[3];
//   printf("GetNextIndices current slices : %i %i %in", fSlices[0], fSlices[1], fSlices[2]);
   dmin[0] = dmin[1] = dmin[2] = TGeoShape::kBig;
   TGeoBBox *box = (TGeoBBox*)fVolume->GetShape();
   Double_t limit = TGeoShape::kBig;
   Bool_t isXlimit=kFALSE, isYlimit=kFALSE, isZlimit=kFALSE;
   Double_t dmstep = gGeoManager->GetStep();   
//   printf("dmstep=%fn", dmstep);
   if (dir[0]!=0) {
      if (fSlices[0]!=-2) {
      // if there are slices on this axis, get distance to next slice.
         dind[0]+=(dir[0]<0)?-1:1;
         if (dind[0]<-1) return kFALSE;
         if (dind[0]>fIbx-1) return kFALSE;
//         printf("next slicex=%i : x= %f  point[0]=%f dir[0]=%fn",dind[0],fXb[dind[0]+((dind[0]>fSlices[0])?0:1)], point[0], dir[0]); 
         dmin[0] = (fXb[dind[0]+((dind[0]>fSlices[0])?0:1)]-point[0])/dir[0];
//         printf("dx=%fn", dmin[0]);
         isXlimit = (dmin[0]>dmstep)?kTRUE:kFALSE;
      } else {
      // if no slicing on this axis, get distance to mother limit
         limit = (box->GetOrigin())[0] + box->GetDX()*((dir[0]<0)?-1:1);
         dmin[0] = (limit-point[0])/dir[0];
         isXlimit = kTRUE;
      }
   }      
   if (dir[1]!=0) {
      if (fSlices[1]!=-2) {
      // if there are slices on this axis, get distance to next slice.
         dind[1]+=(dir[1]<0)?-1:1;
         if (dind[1]<-1) return kFALSE;
         if (dind[1]>fIby-1) return kFALSE;
//         printf("next slicey=%i : y= %f  point[1]=%f dir[1]=%fn",dind[1], fYb[dind[1]+((dind[1]>fSlices[1])?0:1)], point[1], dir[1]); 
         dmin[1] = (fYb[dind[1]+((dind[1]>fSlices[1])?0:1)]-point[1])/dir[1];
//         printf("dy=%fn", dmin[1]);
         isYlimit = (dmin[1]>dmstep)?kTRUE:kFALSE;
      } else {
      // if no slicing on this axis, get distance to mother limit
         limit = (box->GetOrigin())[1] + box->GetDY()*((dir[1]<0)?-1:1);
         dmin[1] = (limit-point[1])/dir[1];
         isYlimit = kTRUE;
      }
   }      
   if (dir[2]!=0) {
      if (fSlices[2]!=-2) {
      // if there are slices on this axis, get distance to next slice.
         dind[2]+=(dir[2]<0)?-1:1;
         if (dind[2]<-1) return kFALSE;
         if (dind[2]>fIbz-1) return kFALSE;
//         printf("next slicez=%i : z= %f  point[2]=%f dir[2]=%fn",dind[2],fZb[dind[2]+((dind[2]>fSlices[2])?0:1)], point[2], dir[2]); 
         dmin[2] = (fZb[dind[2]+((dind[2]>fSlices[2])?0:1)]-point[2])/dir[2];
//         printf("dz=%fn", dmin[2]);
         isZlimit = (dmin[2]>dmstep)?kTRUE:kFALSE;
      } else {
      // if no slicing on this axis, get distance to mother limit
         limit = (box->GetOrigin())[2] + box->GetDZ()*((dir[2]<0)?-1:1);
         dmin[2] = (limit-point[2])/dir[2];
         isZlimit = kTRUE;
      }
   }      
   // now find minimum distance
//   printf("dmin : %f %f %fn", dmin[0], dmin[1], dmin[2]);
   if (dmin[0]<dmin[1]) {
      if (dmin[0]<dmin[2]) {
      // next X
//         printf("next slicex : %i isXlimit=%in", dind[0],(Int_t)isXlimit);
         if (isXlimit) return kFALSE;
         if (dind[0]<0) return kFALSE;
         if (dind[0]>fIbx-2) return kFALSE;
         fSlices[0] = dind[0];
         if (fSlices[1]!=-2) {
            if (fSlices[1]<0) return GetNextIndices(point, dir);
            if (fSlices[1]>fIby-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[2]!=-2) {
            if (fSlices[2]<0) return GetNextIndices(point, dir);
            if (fSlices[2]>fIbz-2) return GetNextIndices(point, dir);
         }   
         if (fIndX[fOBx[fSlices[0]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      } else {
      // next Z
//         printf("next slicez : %i isZlimit=%in", dind[2],(Int_t)isZlimit);
         if (isZlimit) return kFALSE;
         if (dind[2]<0) return kFALSE;
         if (dind[2]>fIbz-2) return kFALSE;
         fSlices[2] = dind[2];
         if (fSlices[0]!=-2) {
            if (fSlices[0]<0) return GetNextIndices(point, dir);
            if (fSlices[0]>fIbx-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[1]!=-2) {
            if (fSlices[1]<0) return GetNextIndices(point, dir);
            if (fSlices[1]>fIby-2) return GetNextIndices(point, dir);
         }   
         if (fIndZ[fOBz[fSlices[2]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      }
   } else {
      if (dmin[1]<dmin[2]) {   
      // next Y
//         printf("next slicey : %i isYlimit=%in", dind[1], (Int_t)isYlimit);
         if (isYlimit) return kFALSE;
         if (dind[1]<0) return kFALSE;
         if (dind[1]>fIby-2) return kFALSE;
         fSlices[1] = dind[1];
         if (fSlices[0]!=-2) {
            if (fSlices[0]<0) return GetNextIndices(point, dir);
            if (fSlices[0]>fIbx-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[2]!=-2) {
            if (fSlices[2]<0) return GetNextIndices(point, dir);
            if (fSlices[2]>fIbz-2) return GetNextIndices(point, dir);
         }   
         if (fIndY[fOBy[fSlices[1]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      } else {
      // next Z
//         printf("next slicez : %i isZlimit=%in", dind[2], (Int_t)isZlimit);
         if (isZlimit) return kFALSE;
         if (dind[2]<0) return kFALSE;
         if (dind[2]>fIbz-2) return kFALSE;
         fSlices[2] = dind[2];
         if (fSlices[0]!=-2) {
            if (fSlices[0]<0) return GetNextIndices(point, dir);
            if (fSlices[0]>fIbx-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[1]!=-2) {
            if (fSlices[1]<0) return GetNextIndices(point, dir);
            if (fSlices[1]>fIby-2) return GetNextIndices(point, dir);
         }   
         if (fIndZ[fOBz[fSlices[2]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      }
   }
}

//-----------------------------------------------------------------------------
void TGeoVoxelFinder::SortCrossedVoxels(Double_t *point, Double_t * /*dir*/)
{
// get the list in the next voxel crossed by a ray
   fCurrentVoxel = 0;
//   printf("###Sort crossed voxels for %sn", fVolume->GetName());
   if (!GetIndices(point)) {
      fNcandidates = 0;
      UInt_t  loc = 2+((UInt_t)fVolume->GetNdaughters())/8;
      UChar_t *bits = gGeoManager->GetBits() + loc;
      memset(bits, 0, (loc+1)*sizeof(UChar_t));
//      printf("   no candidates in first voxeln");
      return;
   }
//   printf("   current slices : %i   %i  %in", fSlices[0], fSlices[1], fSlices[2]);
   Int_t nd[3];
   memset(&nd[0], 0, 3*sizeof(Int_t));
   Int_t *slicex = 0;
   if (fSlices[0]!=-2) {
      nd[0] = fIndX[fOBx[fSlices[0]]];
      slicex=&fIndX[fOBx[fSlices[0]]+1];
   }   
   Int_t *slicey = 0;
   if (fSlices[1]!=-2) {
      nd[1] = fIndY[fOBy[fSlices[1]]];
      slicey=&fIndY[fOBy[fSlices[1]]+1];
   }   
   Int_t *slicez = 0;
   if (fSlices[2]!=-2) {
      nd[2] = fIndZ[fOBz[fSlices[2]]];
      slicez=&fIndZ[fOBz[fSlices[2]]+1];
   } 
//   printf("Ndaughters in first voxel : %i %i %in", nd[0], nd[1], nd[2]);
   IntersectAndStore(nd[0], slicex, nd[1], slicey, nd[2], slicez);  
//   printf("   candidates for first voxel :n");
//   for (Int_t i=0; i<fNcandidates; i++) printf("    %in", fCheckList[i]);
}   
//-----------------------------------------------------------------------------
Int_t *TGeoVoxelFinder::GetCheckList(Double_t *point, Int_t &nelem)
{
// get the list of daughter indices for which point is inside their bbox
   if (!fBoxes) return 0;
   Bool_t one_daughter = kFALSE;
   if (fVolume->GetNdaughters() == 1) {
      fCheckList[0] = 0;
      nelem = 1;
      one_daughter = kTRUE;
   }
   Int_t *slicex = 0;
   Int_t *slicey = 0; 
   Int_t *slicez = 0;
   Int_t nd[3];
   memset(&nd[0], 0, 3*sizeof(Int_t));
   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] = fIndX[fOBx[im]];
         if (!nd[0]) return 0;
         slicex = &fIndX[fOBx[im]+1];
      }   
   }

   if (fPriority[1]) {
      im = TMath::BinarySearch(fIby, fYb, point[1]);
      if ((im==-1) || (im==fIby-1)) return 0;
      if (fPriority[1]==2) {
         nd[1] = fIndY[fOBy[im]];
         if (!nd[1]) return 0;
         slicey = &fIndY[fOBy[im]+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] = fIndZ[fOBz[im]];
         if (!nd[2]) return 0;
         slicez = &fIndZ[fOBz[im]+1];
      }   
   }
   if (one_daughter) return fCheckList;
   nelem = 0;
//   Int_t i = 0;

   if (Intersect(nd[0], slicex, nd[1], slicey, nd[2], slicez, nelem, fCheckList)) 
      return fCheckList;
   return 0;   
}
//-----------------------------------------------------------------------------
Int_t *TGeoVoxelFinder::GetNextVoxel(Double_t *point, Double_t *dir, Int_t &ncheck)
{
// get the list of new candidates for the next voxel crossed by current ray
//   printf("### GetNextVoxeln");
   Int_t *list = fCheckList;
   ncheck = fNcandidates;
   if (fCurrentVoxel==0) {
//      printf(">>> first voxel, %i candidatesn", ncheck);
      fCurrentVoxel++;
      return fCheckList;
   }
   fCurrentVoxel++;
//   printf(">>> voxel %in", fCurrentVoxel);
   // Get slices for next voxel
//   printf("before - fSices : %i %i %in", fSlices[0], fSlices[1], fSlices[2]);
   if (!GetNextIndices(point, dir)) {
//      printf("exitn");
      ncheck = 0;
//      printf(">>> nothing else to check, ENDn");
      return 0;
   }   
//   printf("next slices : %i   %i  %in", fSlices[0], fSlices[1], fSlices[2]);
   Int_t nd[3];
   memset(&nd[0], 0, 3*sizeof(Int_t));
   Int_t *slicex = 0;
   if (fSlices[0]!=-2) {
      nd[0] = fIndX[fOBx[fSlices[0]]];
      slicex=&fIndX[fOBx[fSlices[0]]+1];
//      printf("x: %i %xn", nd[0], (UInt_t)slicex);
   }   
   Int_t *slicey = 0;
   if (fSlices[1]!=-2) {
      nd[1] = fIndY[fOBy[fSlices[1]]];
      slicey=&fIndY[fOBy[fSlices[1]]+1];
//      printf("y: %i %xn", nd[1], (UInt_t)slicey);
   }   
   Int_t *slicez = 0;
   if (fSlices[2]!=-2) {
      nd[2] = fIndZ[fOBz[fSlices[2]]];
      slicez=&fIndZ[fOBz[fSlices[2]]+1];
//      printf("z: %i %xn", nd[2], (UInt_t)slicez);
   } 
   
   if (Union(nd[0], slicex, nd[1], slicey, nd[2], slicez)) {
      list += ncheck; 
//      printf(">>> new candidates : %i-%in", fNcandidates, ncheck);
      ncheck = fNcandidates - ncheck;
//      for (Int_t i=0; i<ncheck; i++) printf("    %in", list[i]);
      return list;
   }
//   printf("No new candidatesn");
   ncheck = 0;
   return list;
}   
//-----------------------------------------------------------------------------
Bool_t TGeoVoxelFinder::Union(Int_t n1, Int_t *array1, 
                              Int_t n2, Int_t *array2, 
                              Int_t n3, Int_t *array3)
{
// make the union of fCheckList with the result of the intersection of the 3 arrays
   // first reset bits
/*
   if (array1) {
      printf("   X slice :n");
      for (Int_t i=0; i<n1; i++) printf("   %in", array1[i]);
   }   
   if (array2) {
      printf("   Y slice :n");
      for (Int_t i=0; i<n2; i++) printf("   %in", array2[i]);
   }   
   if (array3) {
      printf("   Z slice :n");
      for (Int_t i=0; i<n3; i++) printf("   %in", array3[i]);
   }   
*/
   Int_t nd = fVolume->GetNdaughters();
//   printf("Nd=%i, nx=%i ny=%i nz=%in", nd, n1,n2,n3); 
   Bool_t is_eff[3];
   memset(&is_eff[0], 0, 3*sizeof(Bool_t));
   Int_t ni[3];
   ni[0] = n1;
   ni[1] = n2;
   ni[2] = n3;
   
   Int_t i;
//   if (nd>10) {
      Int_t mins=nd;
      if (array1) {
         mins = n1;
         is_eff[0] = kTRUE;
      }   
      if (array2) {
         if (n2<mins) mins=n2;
         is_eff[1] = kTRUE;
      }   
      if (array3) {
         if (n3<mins) mins=n3;
         is_eff[2] = kTRUE;
      }   
      mins*=10;
      for (i=0; i<3; i++) {
         if (is_eff[i]) {
            if (ni[i]>mins) is_eff[i]=kFALSE;      
         }
      }
//   } else {
//      is_eff[0] = (array1!=0);
//      is_eff[1] = (array2!=0);
//      is_eff[2] = (array3!=0);
//   }         
//   if ((nd<n1) || (nd<n2) || (nd<n3)) {printf("Woops %s nd=%in", fVolume->GetName(), nd);
//      printf("%sn", gGeoManager->GetPath()); exit(0);}
   UInt_t  loc = 2+((UInt_t)nd)/8;
   UChar_t *bits = gGeoManager->GetBits();
   UChar_t *pbits = bits+loc;
   UChar_t *tbits = bits+2*loc;
//   memset(pbits, 0, (loc+1)*sizeof(UChar_t));
   UChar_t bit = 0;
   UInt_t bitnumber = 0;
   UChar_t value = 0;
   Int_t *a1, *a2;
   Int_t nn1=0;
   Int_t nn2=0;
   Int_t maxval = -1;
   Int_t candidates = fNcandidates;
   Bool_t last = kFALSE;
   if (!is_eff[0]) {
      if (!is_eff[1]) {
         if (!is_eff[2]) return kFALSE;
         // test 3-rd array against old bits 
         for (i=0; i<n3; i++) {
            bitnumber = (UInt_t) (array3[i]);
            loc = bitnumber/8;
            value = pbits[loc];
            bit = bitnumber%8;
            // if not set, add new bit
            if ((value & (1<<bit)) == 0) {
               fCheckList[fNcandidates++] = array3[i];
               pbits[loc] |= (1<<bit);   
            }   
         }
         return kTRUE;
      }
      if (!is_eff[2]) {
         for (i=0; i<n2; i++) {
            bitnumber = (UInt_t) (array2[i]);
            loc = bitnumber/8;
            value = pbits[loc];
            bit = bitnumber%8;
            // if not set, add new bit
            if ((value & (1<<bit)) == 0) {
               fCheckList[fNcandidates++] = array2[i];
               pbits[loc] |= (1<<bit);   
            }   
         }
         return kTRUE;
      }   
      a1 = array2;
      nn1 = n2;
      a2 = array3;
      nn2 = n3;
      maxval = TMath::Max(array2[n2-1], array3[n3-1]);
      last = kTRUE;
   } else {
      maxval = array1[n1-1];   
      if (!is_eff[1]) {
         if (!is_eff[2]) {
            for (i=0; i<n1; i++) {
               bitnumber = (UInt_t) (array1[i]);
               loc = bitnumber/8;
               value = pbits[loc];
               bit = bitnumber%8;
               // if not set, add new bit
               if ((value & (1<<bit)) == 0) {
                  fCheckList[fNcandidates++] = array1[i];
                  pbits[loc] |= (1<<bit);   
               }   
            }
            return kTRUE;
         }
         a1 = array1;
         nn1 = n1;
         a2 = array3;
         nn2 = n3;
         maxval = TMath::Max(maxval, array3[n3-1]);
         last = kTRUE;
      } else {
         a1 = array1;
         nn1 = n1;
         a2 = array2;
         nn2 = n2;
         maxval = TMath::Max(array1[n1-1], array2[n2-1]);
         if (is_eff[2]) 
            maxval = TMath::Max(maxval, array3[n3-1]);
         else
            last = kTRUE;   
      }   
   }          
   if (maxval<0) return kFALSE;
   // reset bits
   loc = ((UInt_t)maxval)/8;
   memset(bits, 0, (loc+1)*sizeof(UChar_t));
   if (!last)
      memset(tbits, 0, (loc+1)*sizeof(UChar_t));
   for (i=0; i<nn1; i++) {
   // set bits according to first array
      bitnumber = (UInt_t) (a1[i]);
      loc = bitnumber/8;
      bit = bitnumber%8;
      bits[loc] |= (1<<bit);   
   }
   // test elements of second array
   UChar_t cbit=0;
   for (i=0; i<nn2; i++) {
      bitnumber = (UInt_t) (a2[i]);
      // test if bit is set
      loc = bitnumber/8;
      value = bits[loc];
      bit = bitnumber%8;
      cbit = 1<<bit;
      if ((value & cbit) != 0) {
      // element of second array was also in first array.
      // now check if it is already in the union list
         if ((pbits[loc] & cbit) == 0) {
//            printf("possible candidate : %in", a2[i]);
         // this is a new possible candidate (if also in third list) - mark it
            if (last) {
//               printf("is OKn");
               pbits[loc] |= cbit;
               fCheckList[fNcandidates++] = a2[i];
            } else {
//               printf("set tbitsn");
               tbits[loc] |= cbit;
            }   
         }   
      }   
   }
//   if (fNcandidates==candidates) return kFALSE;
   if (last) return kTRUE;
   loc = ((UInt_t)maxval)/8;
   // test elements of third array
   for (i=0; i<n3; i++) {
      bitnumber = (UInt_t) (array3[i]);
      // test if bit is set
      loc = bitnumber/8;
      value = tbits[loc];
      bit = bitnumber%8;
      cbit = 1<<bit;
      if ((value & cbit) != 0) {
         fCheckList[fNcandidates++] = array3[i];
         pbits[loc] |= cbit;
      }   
   }
   if (fNcandidates==candidates) return kFALSE;
   return kTRUE;
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::IntersectAndStore(Int_t n1, Int_t *array1, 
                                        Int_t n2, Int_t *array2, 
                                        Int_t n3, Int_t *array3)
{
   // first reset bits
   fNcandidates = 0;
   Int_t nd = fVolume->GetNdaughters();
//   printf("Nd=%i, nx=%i ny=%i nz=%in", nd, n1,n2,n3); 
   Bool_t is_eff[3];
   memset(&is_eff[0], 0, 3*sizeof(Bool_t));
   Int_t ni[3];
   ni[0] = n1;
   ni[1] = n2;
   ni[2] = n3;
   
   Int_t i;
//   if (nd>10) {
      Int_t mins=nd;
      if (array1) {
         mins = n1;
         is_eff[0] = kTRUE;
      }   
      if (array2) {
         if (n2<mins) mins=n2;
         is_eff[1] = kTRUE;
      }   
      if (array3) {
         if (n3<mins) mins=n3;
         is_eff[2] = kTRUE;
      }   
      mins*=10;
      for (i=0; i<3; i++) {
         if (is_eff[i]) {
            if (ni[i]>mins) is_eff[i]=kFALSE;      
         }
      }
   UInt_t  loc = 2+((UInt_t)nd)/8;
   UChar_t *bits = gGeoManager->GetBits();
   UChar_t *pbits = bits+loc;
   memset(pbits, 0, (loc+1)*sizeof(UChar_t));
   UChar_t bit = 0;
   UInt_t bitnumber = 0;
   UChar_t value = 0;
   Int_t *a1, *a2;
   Int_t nn1=0;
   Int_t nn2=0;
   Int_t maxval = -1;
//   Int_t i;
   Bool_t last = kFALSE;
   if (!is_eff[0]) {
      if (!is_eff[1]) {
         if (!is_eff[2]) return; 
         memcpy(fCheckList, array3, n3*sizeof(Int_t));
         for (i=0; i<n3; i++) {
            bitnumber = (UInt_t) (array3[i]);
            loc = bitnumber/8;
            bit = bitnumber%8;
            pbits[loc] |= (1<<bit);   
         }
         fNcandidates = n3;
         return;
      }
      if (!is_eff[2]) {
         memcpy(fCheckList, array2, n2*sizeof(Int_t));
         for (i=0; i<n2; i++) {
            bitnumber = (UInt_t) (array2[i]);
            loc = bitnumber/8;
            bit = bitnumber%8;
            pbits[loc] |= (1<<bit);   
         }
         fNcandidates = n2;
         return;
      }   
      a1 = array2;
      nn1 = n2;
      a2 = array3;
      nn2 = n3;
      maxval = TMath::Max(array2[n2-1], array3[n3-1]);
      last = kTRUE;
   } else {
      maxval = array1[n1-1];   
      if (!is_eff[1]) {
         if (!is_eff[2]) {
            memcpy(fCheckList, array1, n1*sizeof(Int_t));
            for (i=0; i<n1; i++) {
               bitnumber = (UInt_t) (array1[i]);
               loc = bitnumber/8;
               bit = bitnumber%8;
               pbits[loc] |= (1<<bit);   
            }
            fNcandidates = n1;
            return;
         }
         a1 = array1;
         nn1 = n1;
         a2 = array3;
         nn2 = n3;
         maxval = TMath::Max(maxval, array3[n3-1]);
         last = kTRUE;
      } else {
         a1 = array1;
         nn1 = n1;
         a2 = array2;
         nn2 = n2;
         maxval = TMath::Max(array1[n1-1], array2[n2-1]);
         if (is_eff[2]) maxval = TMath::Max(maxval, array3[n3-1]);
         else last=kTRUE;
      }   
   }          
   if (maxval<0) return;
   // reset bits
   loc = ((UInt_t)maxval)/8;
   memset(bits, 0, (loc+1)*sizeof(UChar_t));
   for (i=0; i<nn1; i++) {
   // set bits according to first array
      bitnumber = (UInt_t) (a1[i]);
      loc = bitnumber/8;
      bit = bitnumber%8;
      bits[loc] |= (1<<bit);   
   }
   // test elements of second array
   for (i=0; i<nn2; i++) {
      bitnumber = (UInt_t) (a2[i]);
      // test if bit is set
      loc = bitnumber/8;
      value = bits[loc];
      bit = bitnumber%8;
      if ((value & (1<<bit)) != 0) {
         fCheckList[fNcandidates++] = a2[i];
         if (last || (!array3)) pbits[loc] |= (1<<bit);
      }   
   }
   if (!fNcandidates) return;
   if (last) return;

   loc = ((UInt_t)maxval)/8;
   memset(bits, 0, (loc+1)*sizeof(UChar_t));
   for (i=0; i<fNcandidates; i++) {
   // set bits according to first result
      bitnumber = (UInt_t) (fCheckList[i]);
      loc = bitnumber/8;
      bit = bitnumber%8;
      bits[loc] |= (1<<bit);   
   }
   // reset result
   fNcandidates = 0;
   // test elements of third array
   for (i=0; i<n3; i++) {
      bitnumber = (UInt_t) (array3[i]);
      // test if bit is set
      loc = bitnumber/8;
      value = bits[loc];
      bit = bitnumber%8;
      if ((value & (1<<bit)) != 0) {
         fCheckList[fNcandidates++] = array3[i];
         pbits[loc] |= (1<<bit);
      }   
   }
   return;
}
//-----------------------------------------------------------------------------
Bool_t TGeoVoxelFinder::Intersect(Int_t n1, Int_t *array1, 
                                  Int_t n2, Int_t *array2, 
                                  Int_t n3, Int_t *array3, Int_t &nf, Int_t *result)
{
// return the intersection of three ordered lists
   Int_t nd = fVolume->GetNdaughters();
//   printf("Nd=%i, nx=%i ny=%i nz=%in", nd, n1,n2,n3); 
   Bool_t is_eff[3];
   memset(&is_eff[0], 0, 3*sizeof(Bool_t));
   Int_t ni[3];
   ni[0] = n1;
   ni[1] = n2;
   ni[2] = n3;
   
   Int_t i;
//   if (nd>10) {

      Int_t mins=nd;
      if (array1) {
         mins = n1;
         is_eff[0] = kTRUE;
      }   
      if (array2) {
         if (n2<mins) mins=n2;
         is_eff[1] = kTRUE;
      }   
      if (array3) {
         if (n3<mins) mins=n3;
         is_eff[2] = kTRUE;
      }   
      mins*=10;
      for (i=0; i<3; i++) {
         if (is_eff[i]) {
            if (ni[i]>mins) is_eff[i]=kFALSE;      
         }
      }

//   } else {
//      is_eff[0] = (array1!=0);
//      is_eff[1] = (array2!=0);
//      is_eff[2] = (array3!=0);
//   }         


   Int_t *a1, *a2;
   Int_t nn1=0;
   Int_t nn2=0;
   Int_t maxval = -1;
   Bool_t last = kFALSE;
   if (!is_eff[0]) {
      if (!is_eff[1]) {
         if (!is_eff[2]) return kTRUE; 
         memcpy(result, array3, n3*sizeof(Int_t));
         nf = n3;
         return kTRUE;
      }
      if (!is_eff[2]) {
         memcpy(result, array2, n2*sizeof(Int_t));
         nf = n2;
         return kTRUE;
      }   
      a1 = array2;
      nn1 = n2;
      a2 = array3;
      nn2 = n3;
      maxval = TMath::Max(array2[n2-1], array3[n3-1]);
      last = kTRUE;
   } else {
      maxval = array1[n1-1];   
      if (!is_eff[1]) {
         if (!is_eff[2]) {
            memcpy(result, array1, n1*sizeof(Int_t));
            nf = n1;
            return kTRUE;
         }
         a1 = array1;
         nn1 = n1;
         a2 = array3;
         nn2 = n3;
         maxval = TMath::Max(maxval, array3[n3-1]);
         last = kTRUE;
      } else {
         a1 = array1;
         nn1 = n1;
         a2 = array2;
         nn2 = n2;
         maxval = TMath::Max(array1[n1-1], array2[n2-1]);
         if (is_eff[2]) {
            maxval = TMath::Max(maxval, array3[n3-1]);
         } else last=kTRUE;   
      }   
   }          
   if (maxval<0) return kFALSE;
      
   UChar_t *bits = gGeoManager->GetBits();
   UInt_t  loc = 0;
   UChar_t bit = 0;
   UInt_t bitnumber = 0;
   UChar_t value = 0;
   // reset bits
   loc = ((UInt_t)maxval)/8;
   memset(bits, 0, (loc+1)*sizeof(UChar_t));
//   printf("%s intersecting %i with %in", fVolume->GetName(),nn1, nn2);
   for (i=0; i<nn1; i++) {
   // set bits according to first array
      bitnumber = (UInt_t) (a1[i]);
      loc = bitnumber/8;
      bit = bitnumber%8;
      bits[loc] |= (1<<bit);   
   }
   // test elements of second array
   for (i=0; i<nn2; i++) {
      bitnumber = (UInt_t) (a2[i]);
      // test if bit is set
      loc = bitnumber/8;
      value = bits[loc];
      bit = bitnumber%8;
      if ((value & (1<<bit)) != 0)
         result[nf++] = a2[i];
   }
//   printf("   result : %in", nf);
   if (!nf) return kFALSE;
   if (last) return kTRUE;

//   printf("    with : n3=%in", n3);
   loc = ((UInt_t)maxval)/8;
   memset(bits, 0, (loc+1)*sizeof(UChar_t));
   for (i=0; i<nf; i++) {
   // set bits according to first result
      bitnumber = (UInt_t) (result[i]);
      loc = bitnumber/8;
      bit = bitnumber%8;
      bits[loc] |= (1<<bit);   
   }
   // reset result
   nf = 0;
   // test elements of third array
   for (i=0; i<n3; i++) {
      bitnumber = (UInt_t) (array3[i]);
      // test if bit is set
      loc = bitnumber/8;
      value = bits[loc];
      bit = bitnumber%8;
      if ((value & (1<<bit)) != 0)
         result[nf++] = array3[i];
   }
//   printf("   result : %in", nf);
   if (!nf) return kFALSE;
   return kTRUE;
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::SortAll(Option_t *)
{
// order bounding boxes along x, y, z
   Int_t nd = fVolume->GetNdaughters();
   if (!nd) return;
//   printf("sorting boxes for %s  nd=%in", fVolume->GetName(), nd);
   Double_t *boundaries = new Double_t[6*nd];
   Double_t xmin, xmax, ymin, ymax, zmin, zmax;
   TGeoBBox *box = (TGeoBBox*)fVolume->GetShape();
   // compute ranges on X, Y, Z according to volume bounding box
   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");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   Int_t id;
   // compute boundaries coordinates on X,Y,Z
   for (id=0; id<nd; id++) {
      // x boundaries
      boundaries[2*id] = fBoxes[6*id+3]-fBoxes[6*id];
      boundaries[2*id+1] = fBoxes[6*id+3]+fBoxes[6*id];
      // y boundaries
      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];
      // z boundaries
      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];
   Int_t *ind = new Int_t[(nd+1)*(nd+1)]; // ind[fOBx[i]] = ndghts in slice fInd[i]--fInd[i+1]
   Double_t *temp = new Double_t[2*nd];
   Int_t current = 0;
   Double_t xxmin, xxmax, xbmin, xbmax, ddx1, ddx2;
   // sort x boundaries
   Int_t ib = 0;
   TMath::Sort(2*nd, &boundaries[0], &index[0], kFALSE);
   // compact common boundaries
   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]];
   }
   // now find priority
   if (ib < 2) {
      Error("SortAll", "less than 2 boundaries on X !");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   if (ib == 2) {
   // check range
      if (((temp[0]-xmin)<1E-10) && ((temp[1]-xmax)>-1E-10)) {
      // ordering on this axis makes no sense. Clear all arrays.
         fPriority[0] = 0;
         if (fIndX) delete [] fIndX; 
         fIndX = 0;
         fNx = 0;
         if (fXb) delete [] fXb;   
         fXb = 0;
         fIbx = 0;
         if (fOBx) delete [] fOBx;  
         fOBx = 0;
         fNox = 0;
      } else {
         fPriority[0] = 1; // all in one slice
      }
   } else {
      fPriority[0] = 2;    // check all
   }
   // store compacted boundaries
   if (fPriority[0]) {
      if (fXb) delete [] fXb;
      fXb = new Double_t[ib];
      memcpy(fXb, &temp[0], ib*sizeof(Double_t));
      fIbx = ib;   

      //now build the lists of nodes in each slice
      memset(ind, 0, (nd+1)*(nd+1)*sizeof(Int_t));
                     // ind[fOBx[i]+k] = index of dght k (k<ndghts)
      if (fOBx) delete [] fOBx;
      fNox = fIbx-1;
      fOBx = new Int_t[fNox]; // offsets in ind
      for (id=0; id<fNox; id++) {
         fOBx[id] = current; // offset of dght list
         ind[current] = 0; // ndght in this slice
         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 = TMath::Abs(xbmin-xxmax);
            ddx2 = TMath::Abs(xbmax-xxmin);
            if ((xbmin==xxmin)||(xbmax==xxmax)) {
               ind[current]++;
               ind[current+ind[current]] = ic;
               continue;
            }
            if ((ddx1<1E-12)||(ddx2<1E-12)) continue;
            if (((xbmin>xxmin)&&(xbmin<xxmax))||((xbmax>xxmin)&&(xbmax<xxmax)) ||
                ((xxmin>xbmin)&&(xxmin<xbmax))||((xxmax>xbmin)&&(xxmax<xbmax))) {
               // daughter ic in interval
               ind[current]++;
               ind[current+ind[current]] = ic;
            }
         }
         current += ind[current]+1;
      }
      if (fIndX) delete [] fIndX;
      fNx = current;
      fIndX = new Int_t[current];
      memcpy(fIndX, &ind[0], current*sizeof(Int_t));
   }   

   // sort y boundaries
   ib = 0;
   TMath::Sort(2*nd, &boundaries[2*nd], &index[0], kFALSE);
   // compact common boundaries
   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]];
   }
   // now find priority on Y
   if (ib < 2) {
      Error("SortAll", "less than 2 boundaries on Y !");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   if (ib == 2) {
   // check range
      if (((temp[0]-ymin)<1E-10) && ((temp[1]-ymax)>-1E-10)) {
      // ordering on this axis makes no sense. Clear all arrays.
         fPriority[1] = 0;
         if (fIndY) delete [] fIndY; 
         fIndY = 0;
         fNy = 0;
         if (fYb) delete [] fYb;   
         fYb = 0;
         fIby = 0;
         if (fOBy) delete [] fOBy;  
         fOBy = 0;
         fNoy = 0;
      } else {
         fPriority[1] = 1; // all in one slice
      }
   } else {
      fPriority[1] = 2;    // check all
   }
   if (fPriority[1]) {
      // store compacted boundaries
      if (fYb) delete [] fYb;
      fYb = new Double_t[ib];
      memcpy(fYb, &temp[0], ib*sizeof(Double_t));
      fIby = ib;

      memset(ind, 0, (nd+1)*(nd+1)*sizeof(Int_t));
      current = 0;
      if (fOBy) delete [] fOBy;
      fNoy = fIby-1;
      fOBy = new Int_t[fNoy]; // offsets in ind
      for (id=0; id<fNoy; id++) {
         fOBy[id] = current; // offset of dght list
         ind[current] = 0; // ndght in this slice
         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 = TMath::Abs(xbmin-xxmax);
            ddx2 = TMath::Abs(xbmax-xxmin);
            if ((xbmin==xxmin)||(xbmax==xxmax)) {
               ind[current]++;
               ind[current+ind[current]] = ic;
               continue;
            }
            if ((ddx1<1E-12)||(ddx2<1E-12)) continue;  
            if (((xbmin>xxmin)&&(xbmin<xxmax))||((xbmax>xxmin)&&(xbmax<xxmax)) ||
                ((xxmin>xbmin)&&(xxmin<xbmax))||((xxmax>xbmin)&&(xxmax<xbmax))) {
               // daughter ic in interval
               ind[current]++;
               ind[current+ind[current]] = ic;
            }
         }
         current += ind[current]+1;
      }
      if (fIndY) delete [] fIndY;
      fNy = current;
      fIndY = new Int_t[current];
      memcpy(fIndY, &ind[0], current*sizeof(Int_t));
   }
   
   // sort z boundaries
   ib = 0;
   TMath::Sort(2*nd, &boundaries[4*nd], &index[0], kFALSE);
   // compact common boundaries
   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]];
   }      
   // now find priority on Z
   if (ib < 2) {
      Error("SortAll", "less than 2 boundaries on Z !");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   if (ib == 2) {
   // check range
      if (((temp[0]-zmin)<1E-10) && ((temp[1]-zmax)>-1E-10)) {
      // ordering on this axis makes no sense. Clear all arrays.
         fPriority[2] = 0;
         if (fIndZ) delete [] fIndZ; 
         fIndZ = 0;
         fNz = 0;
         if (fZb) delete [] fZb;   
         fZb = 0;
         fIbz = 0;
         if (fOBz) delete [] fOBz;  
         fOBz = 0;
         fNoz = 0;
      } else {
         fPriority[2] = 1; // all in one slice
      }
   } else {
      fPriority[2] = 2;    // check all
   }

   if (fPriority[2]) {
      // store compacted boundaries
      if (fZb) delete [] fZb;
      fZb = new Double_t[ib];
      memcpy(fZb, &temp[0], (ib)*sizeof(Double_t));
      fIbz = ib;
      
      memset(ind, 0, (nd+1)*(nd+1)*sizeof(Int_t));
      current = 0;
      if (fOBz) delete [] fOBz;
      fNoz = fIbz-1;
      fOBz = new Int_t[fNoz]; // offsets in ind
      for (id=0; id<fNoz; id++) {
         fOBz[id] = current; // offset of dght list
         ind[current] = 0; // ndght in this slice
         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 = TMath::Abs(xbmin-xxmax);
            ddx2 = TMath::Abs(xbmax-xxmin);
            if ((xbmin==xxmin)||(xbmax==xxmax)) {
               ind[current]++;
               ind[current+ind[current]] = ic;
               continue;
            }
            if ((ddx1<1E-12)||(ddx2<1E-12)) continue;
            if (((xbmin>xxmin)&&(xbmin<xxmax))||((xbmax>xxmin)&&(xbmax<xxmax)) ||
                ((xxmin>xbmin)&&(xxmin<xbmax))||((xxmax>xbmin)&&(xxmax<xbmax))) {
               // daughter ic in interval
               ind[current]++;
               ind[current+ind[current]] = ic;
            }
         }
         current += ind[current]+1;
      }
      if (fIndZ) delete [] fIndZ;
      fNz = current;
      fIndZ = new Int_t[current];
      memcpy(fIndZ, &ind[0], current*sizeof(Int_t));
   }   
   delete [] boundaries; boundaries=0;   
   delete [] index; index=0;
   delete [] temp; temp=0;
   delete [] ind;

//   Print();
   if ((!fPriority[0]) && (!fPriority[1]) && (!fPriority[2])) {
      fVolume->SetVoxelFinder(0);
      delete this;
   } else {
//      Efficiency();
   }   
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::Print(Option_t *) const
{
   Int_t id;
   printf("Voxels for volume %s (nd=%i)n", fVolume->GetName(), fVolume->GetNdaughters());
   printf("priority : x=%i y=%i z=%in", fPriority[0], fPriority[1], fPriority[2]);
//   return;

   printf("XXXn");
   if (fPriority[0]) {
      for (id=0; id<fIbx; id++) {
//         printf("%15.10fn",fXb[id]);
         if (id == (fIbx-1)) break;
         printf("slice %i : %in", id, fIndX[fOBx[id]]);
/*
         for (Int_t j=0;j<fIndX[fOBx[id]]; j++) {
            printf("%s  low, high:  %15.10f --- %15.10f n", 
            fVolume->GetNode(fIndX[fOBx[id]+j+1])->GetName(),
            fBoxes[6*fIndX[fOBx[id]+j+1]+3]-fBoxes[6*fIndX[fOBx[id]+j+1]],
            fBoxes[6*fIndX[fOBx[id]+j+1]+3]+fBoxes[6*fIndX[fOBx[id]+j+1]]);
         }
*/
      }
   }
   printf("YYYn"); 
   if (fPriority[1]) { 
      for (id=0; id<fIby; id++) {
//         printf("%15.10fn", fYb[id]);
         if (id == (fIby-1)) break;
         printf("slice %i : %in", id, fIndY[fOBy[id]]);
/*
         for (Int_t j=0;j<fIndY[fOBy[id]]; j++) {
            printf("%s  low, high:  %15.10f --- %15.10f n", 
            fVolume->GetNode(fIndY[fOBy[id]+j+1])->GetName(),
            fBoxes[6*fIndY[fOBy[id]+j+1]+4]-fBoxes[6*fIndY[fOBy[id]+j+1]+1],
            fBoxes[6*fIndY[fOBy[id]+j+1]+4]+fBoxes[6*fIndY[fOBy[id]+j+1]+1]);
         }
*/
      }
   }
   
   printf("ZZZn"); 
   if (fPriority[2]) { 
      for (id=0; id<fIbz; id++) {
//         printf("%15.10fn", fZb[id]);
         if (id == (fIbz-1)) break;
         printf("slice %i : %in", id, fIndZ[fOBz[id]]);
/*
         for (Int_t j=0;j<fIndZ[fOBz[id]]; j++) {
            printf("%s  low, high:  %15.10f --- %15.10f n", 
            fVolume->GetNode(fIndZ[fOBz[id]+j+1])->GetName(),
            fBoxes[6*fIndZ[fOBz[id]+j+1]+5]-fBoxes[6*fIndZ[fOBz[id]+j+1]+2],
            fBoxes[6*fIndZ[fOBz[id]+j+1]+5]+fBoxes[6*fIndZ[fOBz[id]+j+1]+2]);
         }
*/
      }
   }
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::PrintVoxelLimits(Double_t *point) const
{
// print the voxel containing point
   Int_t im=0;
   if (fPriority[0]) {
      im = TMath::BinarySearch(fIbx, fXb, point[0]);
      if ((im==-1) || (im==fIbx-1)) {
         printf("Voxel X limits: OUTn");
      } else {
         printf("Voxel X limits: %g  %gn", 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: OUTn");
      } else {
         printf("Voxel Y limits: %g  %gn", 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: OUTn");
      } else {
         printf("Voxel Z limits: %g  %gn", fZb[im], fZb[im+1]);
      }
   }
}
//-----------------------------------------------------------------------------
void TGeoVoxelFinder::Voxelize(Option_t * /*option*/)
{
// Voxelize attached volume according to option
   BuildVoxelLimits();
   SortAll();
}
//-----------------------------------------------------------------------------

ClassImp(TGeoCylVoxels)


//-----------------------------------------------------------------------------
 TGeoCylVoxels::TGeoCylVoxels()
{
// Default constructor
}
//-----------------------------------------------------------------------------
 TGeoCylVoxels::TGeoCylVoxels(TGeoVolume *vol)
              :TGeoVoxelFinder(vol)
{
// Constructor
   fVolume->SetCylVoxels(kTRUE);
}
//-----------------------------------------------------------------------------
 TGeoCylVoxels::~TGeoCylVoxels()
{
// Destructor
}
//-----------------------------------------------------------------------------
 void TGeoCylVoxels::BuildVoxelLimits()
{
//--- Compute boundary limits in R, Phi and Z coordinates for all daughters
// of fVolume
   Int_t id;
   Int_t nd = fVolume->GetNdaughters();
   TGeoNode *node;
   Double_t bcyl[4];
   if (fBoxes) delete [] fBoxes;
   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];
   const Double_t *translation;
   TGeoBBox *box = 0;
//   Double_t *origin;
   Double_t dx, dy, dz, x0, y0;
   Double_t orig[3];
   TGeoShape *shape = 0;
   TGeoMatrix *matrix = 0;
   // loop all daughters
   for (id=0; id<nd; id++) {
      node = fVolume->GetNode(id);
//      printf(" --%s--n", node->GetName());
      shape = node->GetVolume()->GetShape();
//      shape->InspectShape();
      box = (TGeoBBox*)shape;
//      origin = box->GetOrigin();
      matrix = node->GetMatrix();
      box->SetBoxPoints(&vert[0]);
      for (Int_t point=0; point<8; point++) {
         matrix->LocalToMaster(&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];
         }
      }
      dx = 0.5*(xyz[1]-xyz[0]);
      dy = 0.5*(xyz[3]-xyz[2]);
      dz = 0.5*(xyz[5]-xyz[4]);
      x0 = 0.5*(xyz[0]+xyz[1]);
      y0 = 0.5*(xyz[2]+xyz[3]);
      orig[0] = TMath::Abs(x0);
      orig[1] = TMath::Abs(y0);
      orig[2] = 0.5*(xyz[4]+xyz[5]);
      fBoxes[6*id+4] = orig[2]-dz;
      fBoxes[6*id+5] = orig[2]+dz;

      if (matrix->IsIdentity()) {
      // node has no rotation
//         printf(" identityn");
         shape->GetBoundingCylinder(&bcyl[0]);
         memcpy(fBoxes+6*id, &bcyl[0], 4*sizeof(Double_t));
      } else {
//         matrix->Print();
         if (matrix->IsRotAboutZ()) {
//            printf(" rotzn");
         // no rotation about other axis than Z
            translation = matrix->GetTranslation();
            if ((TMath::Abs(translation[0])<1E-10) && (TMath::Abs(translation[1])<1E-10)) {
               // there is just a translation on Z (and possibly a rot. about Z)
//               printf(" Z transl.n");
               shape->GetBoundingCylinder(&bcyl[0]);
               // check if any rotation about Z
               if (matrix->IsRotation()) {
//                  printf(" + rotn");
                  // find phi rotation
                  if ((bcyl[3]-bcyl[2])!=360) {
                     Double_t phi = ((TGeoRotation *)matrix)->GetPhiRotation();
                     bcyl[2] += phi;
                     bcyl[3] += phi;
                     if (bcyl[2]<0) {
                        bcyl[2] += 360.;
                        bcyl[3] += 360.;
                     } else {
                        if (bcyl[2]>360.) {   
                           bcyl[2] -= 360.;
                           bcyl[3] -=360.;
                        }
                     }      
                  }
               }
            } else {
            // translation is other than Z
//               printf(" gen. translationn");
               memset(&xyz[0], 0, 6*sizeof(Double_t));
               // origin of mother to local frame
               matrix->MasterToLocal(&xyz[0], &xyz[3]);
               x0 = TMath::Abs(xyz[3]);
               y0 = TMath::Abs(xyz[4]);
               dx = box->GetDX();
               dy = box->GetDY();
               bcyl[1] = (x0+dx)*(x0+dx)+(y0+dy)*(y0+dy);
               if (x0<dx) {
               // origin in X range
//                  printf("   inside Xn");
                  if (y0<dy) {
                  // origin also in Y range
                     bcyl[0] = 0.;
                     bcyl[2] = 0.;
                     bcyl[3] = 360.;
                  } else {
                  // origin outside Y range   
//                     printf("   outside Yn");
                     bcyl[0] = y0-dy;
                     bcyl[0] *= bcyl[0];
                     // convert phi limits to MARS
                     if (xyz[4]>0) {
                        xyz[3] = -dx;
                        xyz[4] = dy;
                     } else {
                        xyz[3] = dx;
                        xyz[4] = -dy;
                     }      
                     matrix->LocalToMaster(&xyz[3], &xyz[0]);
//                     printf("  at phi1: %g %gn", xyz[0], xyz[1]);
                     bcyl[2] = TMath::ATan2(xyz[1], xyz[0])*TGeoShape::kRadDeg;
                     xyz[3] = -xyz[3];
                     matrix->LocalToMaster(&xyz[3], &xyz[0]);
//                     printf("  at phi2: %g %gn", xyz[0], xyz[1]);
                     bcyl[3] = TMath::ATan2(xyz[1], xyz[0])*TGeoShape::kRadDeg;
                     if (bcyl[2]<0) bcyl[2]+=360.;
                     while (bcyl[3]<bcyl[2]) bcyl[3]+=360.;   
                  }   
               } else {
               // origin outside X range
//                  printf("   outside Xn");
                  if (y0<dy) {
                  // origin in Y range
//                     printf("   inside Yn");
                     bcyl[0] = x0-dx;
                     bcyl[0] *= bcyl[0];
                     // convert phi limits to MARS
                     if (xyz[3]>0) {
                        xyz[3] = dx;
                        xyz[4] = dy;
                     } else {
                        xyz[3] = -dx;
                        xyz[4] = -dy;
                     }      
                     matrix->LocalToMaster(&xyz[3], &xyz[0]);
//                     printf("  at phi1: %g %gn", xyz[0], xyz[1]);
                     bcyl[2] = TMath::ATan2(xyz[1], xyz[0])*TGeoShape::kRadDeg;
                     xyz[4] = -xyz[4];
                     matrix->LocalToMaster(&xyz[3], &xyz[0]);
//                     printf("  at phi2: %g %gn", xyz[0], xyz[1]);
                     bcyl[3] = TMath::ATan2(xyz[1], xyz[0])*TGeoShape::kRadDeg;
                     if (bcyl[2]<0) bcyl[2]+=360.;
                     while (bcyl[3]<bcyl[2]) bcyl[3]+=360.;   
                  } else {
                  // origin outside both X and Y range
//                     printf("   outside XYn");
                     bcyl[0] = (x0-dx)*(x0-dx)+(y0-dy)*(y0-dy);  
                     // convert phi limits to MARS
                     if (xyz[3]>0) {
                        xyz[3] = xyz[4];
                        xyz[4] = dy;
                        xyz[3]=(xyz[3]>0)?-dx:dx;
                     } else {   
                        xyz[3] = xyz[4];
                        xyz[4] = -dy;
                        xyz[3]=(xyz[3]>0)?-dx:dx;
                     }   
                     matrix->LocalToMaster(&xyz[3], &xyz[0]);
//                     printf("  at phi1: %g %gn", xyz[0], xyz[1]);
                     bcyl[2] = TMath::ATan2(xyz[1], xyz[0])*TGeoShape::kRadDeg;
                     xyz[3] = -xyz[3];
                     xyz[4] = -xyz[4];
                     matrix->LocalToMaster(&xyz[3], &xyz[0]);
//                     printf("  at phi2: %g %gn", xyz[0], xyz[1]);
                     bcyl[3] = TMath::ATan2(xyz[1], xyz[0])*TGeoShape::kRadDeg;
                     if (bcyl[2]<0) bcyl[2]+=360.;
                     while (bcyl[3]<bcyl[2]) bcyl[3]+=360.;   
                  }   
               }
            }
//            printf(" ---copy paramn");      
            memcpy(&fBoxes[6*id], &bcyl[0], 4*sizeof(Double_t));
         } else {
         // general rotation matrix (not only about Z)
//            printf("General tranformation for node %sn", node->GetName());
            bcyl[1] = (orig[0]+dx)*(orig[0]+dx)+(orig[1]+dy)*(orig[1]+dy);
            if (orig[0]<dx) {
               if (orig[1]<dy) {
                  bcyl[0] = 0.;
                  bcyl[2] = 0.;
                  bcyl[3] = 360.;
               } else {
                  bcyl[0] = orig[1]-dy;
                  bcyl[0] *= bcyl[0];
                  if (y0>0) {
                     bcyl[2] = TGeoShape::kRadDeg*TMath::ATan2(xyz[2], xyz[1]);   
                     bcyl[3] = TGeoShape::kRadDeg*TMath::ATan2(xyz[2], xyz[0]);
                  } else {    
                     bcyl[2] = TGeoShape::kRadDeg*TMath::ATan2(xyz[3], xyz[0]);   
                     bcyl[3] = TGeoShape::kRadDeg*TMath::ATan2(xyz[3], xyz[1]);
                  }
                  if (bcyl[2]<0) bcyl[2]+=360.;
                  while (bcyl[3]<bcyl[2]) bcyl[3]+=360.;
               }
            } else {
               if (orig[1]<dy) {
                  bcyl[0] = orig[0]-dx;
                  bcyl[0] *= bcyl[0];
                  if (x0>0) {
                     bcyl[2] = TGeoShape::kRadDeg*TMath::ATan2(xyz[2], xyz[0]);   
                     bcyl[3] = TGeoShape::kRadDeg*TMath::ATan2(xyz[3], xyz[0]);
                  } else {    
                     bcyl[2] = TGeoShape::kRadDeg*TMath::ATan2(xyz[3], xyz[1]);   
                     bcyl[3] = TGeoShape::kRadDeg*TMath::ATan2(xyz[2], xyz[1]);
                  }
                  if (bcyl[2]<0) bcyl[2]+=360.;
                  while (bcyl[3]<bcyl[2]) bcyl[3]+=360.;
               } else {
                  bcyl[0] = (orig[0]-dx)*(orig[0]-dx)+(orig[1]-dy)*(orig[1]-dy);
                  Int_t indx, indy;
                  indy = (x0>0)?0:1;
                  indx = (y0>0)?1:0; 
                  bcyl[2] = TGeoShape::kRadDeg*TMath::ATan2(xyz[indy+2], xyz[indx]);
                  bcyl[3] = TGeoShape::kRadDeg*TMath::ATan2(xyz[3-indy], xyz[1-indx]);
                  if (bcyl[2]<0) bcyl[2]+=360.;
                  while (bcyl[3]<bcyl[2]) bcyl[3]+=360.;
               }
            }         
         }
         memcpy(&fBoxes[6*id], &bcyl[0], 4*sizeof(Double_t));
      }   
//      printf("Limits for %sn", node->GetName());
//      printf(" R   : %g %gn", fBoxes[6*id], fBoxes[6*id+1]);
//      printf(" Phi : %g %gn", fBoxes[6*id+2], fBoxes[6*id+3]);
//      printf(" Z   : %g %gn", fBoxes[6*id+4], fBoxes[6*id+5]);
   }
}
//-----------------------------------------------------------------------------
 Double_t TGeoCylVoxels::Efficiency()
{
//--- Compute voxelization efficiency.
   return 0;
}
//-----------------------------------------------------------------------------
 void TGeoCylVoxels::FindOverlaps(Int_t inode) const
{
// create the list of nodes for which the bboxes overlap with inode's bbox
   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];
   xmax = fBoxes[6*inode+1];
   ymin = fBoxes[6*inode+2];
   ymax = fBoxes[6*inode+3];
   zmin = fBoxes[6*inode+4];
   zmax = fBoxes[6*inode+5];
//   printf("overlaps for MANY node %sn", node->GetName());

//   printf("xmin=%g  xmax=%gn", xmin, xmax);
//   printf("ymin=%g  ymax=%gn", ymin, ymax);
//   printf("zmin=%g  zmax=%gn", zmin, zmax);
   Bool_t in = kFALSE;
   //TGeoNode *node1;
   // loop on brothers
   for (Int_t ib=0; ib<nd; ib++) {
      if (ib == inode) continue; // everyone overlaps with itself
      in = kFALSE;
      //node1 = fVolume->GetNode(ib);
      xmin1 = fBoxes[6*ib];
      xmax1 = fBoxes[6*ib+1];
      ymin1 = fBoxes[6*ib+2];
      ymax1 = fBoxes[6*ib+3];
      zmin1 = fBoxes[6*ib+4];
      zmax1 = fBoxes[6*ib+5];
//      printf(" node %sn", node1->GetName());
//      printf("  xmin1=%g  xmax1=%gn", xmin1, xmax1);
//      printf("  ymin1=%g  ymax1=%gn", ymin1, ymax1);
//      printf("  zmin1=%g  zmax1=%gn", zmin1, zmax1);


      ddx1 = TMath::Abs(xmin1-xmax);
      ddx2 = TMath::Abs(xmax1-xmin);
         if ((ddx1<1E-6)||(ddx2<1E-6)) continue;
//         if ((xmin1==xmin)||(xmax1==xmax)) in = kTRUE;
         if (((xmin1>xmin)&&(xmin1<xmax))||((xmax1>xmin)&&(xmax1<xmax)) ||
             ((xmin>xmin1)&&(xmin<xmax1))||((xmax>xmin1)&&(xmax<xmax1)))
                in = kTRUE;
      if (!in) continue;
//      printf("x overlap...n");
      in = kFALSE;

      if (ymax<360.) {
         in = (IntersectIntervals(ymin, ymax, ymin1, ymax1)>0)?kTRUE:kFALSE;
      } else {
         if (ymax1<360.) {
            in = (IntersectIntervals(ymin1, ymax1, ymin, ymax)>0)?kTRUE:kFALSE;  
         } else {
            in = (IntersectIntervals(ymin1, 360., ymin, ymax)>0)?kTRUE:kFALSE;
            if (!in) in = (IntersectIntervals(360., ymax1, ymin, ymax)>0)?kTRUE:kFALSE;  
         }
      }         
      if (!in) continue;
//      printf("y overlap...n");
      in = kFALSE;

      ddx1 = TMath::Abs(zmin1-zmax);
      ddx2 = TMath::Abs(zmax1-zmin);
         if ((ddx1<1E-12)||(ddx2<1E-12)) continue;
//         if ((zmin1==zmin)||(zmax1==zmax)) in = kTRUE;
         if (((zmin1>zmin)&&(zmin1<zmax))||((zmax1>zmin)&&(zmax1<zmax)) ||
             ((zmin>zmin1)&&(zmin<zmax1))||((zmax>zmin1)&&(zmax<zmax1)))
                in = kTRUE;
      if (!in) continue;
//      printf("Overlapping %in", ib);
      otmp[novlp++] = ib;
   }
   if (!novlp) {
//      printf("---no overlaps for MANY node %sn", node->GetName());
      node->SetOverlaps(ovlps, 1);
      return;
   }
   ovlps = new Int_t[novlp];
   memcpy(ovlps, otmp, novlp*sizeof(Int_t));
   delete [] otmp;
   node->SetOverlaps(ovlps, novlp);
//   printf("Overlaps for MANY node %s : %in", node->GetName(), novlp);
}
//-----------------------------------------------------------------------------
 Int_t *TGeoCylVoxels::GetCheckList(Double_t *point, Int_t &nelem)
{
//--- Get the list of nodes possibly containing a given point.
   // convert the point to cylindrical coordinates
   Double_t ptcyl[3];
   ptcyl[0] = point[0]*point[0]+point[1]*point[1];
   if (fPriority[1]) {
      ptcyl[1] = TMath::ATan2(point[1], point[0])*TGeoShape::kRadDeg;
      if (ptcyl[1]<0) ptcyl[1]+=360.;
   }   
   ptcyl[2] = point[2];
   return TGeoVoxelFinder::GetCheckList(&ptcyl[0], nelem);
}
//-----------------------------------------------------------------------------
 Bool_t TGeoCylVoxels::GetNextIndices(Double_t * /*point*/, Double_t * /*dir*/)
{
// Get indices for next voxel
   return kFALSE;
/*
   Int_t dind[3];
   memcpy(&dind[0], &fSlices[0], 3*sizeof(Int_t));
   Double_t dmin[3];
   Double_t dircyl[3];
   
//   printf("GetNextIndices current slices : %i %i %in", fSlices[0], fSlices[1], fSlices[2]);
   dmin[0] = dmin[1] = dmin[2] = TGeoShape::kBig;
   TGeoBBox *box = (TGeoBBox*)fVolume->GetShape();
   Double_t limit = TGeoShape::kBig;
   Bool_t isXlimit=kFALSE, isYlimit=kFALSE, isZlimit=kFALSE;
   Double_t dmstep = gGeoManager->GetStep();   
   Double_t step = dmstep;
//   printf("dmstep=%fn", dmstep);
   // first check Z
   if (dir[2]!=0) {
      if (fSlices[2]!=-2) {
      // if there are slices on this axis, get distance to next slice.
         dind[2]+=(dir[2]<0)?-1:1;
         if (dind[2]<-1) return kFALSE;
         if (dind[2]>fIbz-1) return kFALSE;
//         printf("next slicez=%i : z= %f  point[2]=%f dir[2]=%fn",dind[2],fZb[dind[2]+((dind[2]>fSlices[2])?0:1)], point[2], dir[2]); 
         dmin[2] = (fZb[dind[2]+((dind[2]>fSlices[2])?0:1)]-point[2])/dir[2];
//         printf("dz=%fn", dmin[2]);
         if (dmin[2]<dmstep) {
            step = dmin[2];
         } else    
            isZlimit = kTRUE;
         }   
      } else {
      // if no slicing on this axis, get distance to mother limit
         limit = (box->GetOrigin())[2] + box->GetDZ()*((dir[2]<0)?-1:1);
         dmin[2] = (limit-point[2])/dir[2];
         isZlimit = kTRUE;
      }
   } 
   // then check phi
        
   if (fSlices[1]!=-2) {
   // if there are slices on this axis, get distance to next slice.
      Double_t phi, a, t;
      
      // find target slice on phi accordind to cross product of position and direction vectors
      Int_t shift = ((point[0]*dir[1]+point[1]*dir[0])>0)?1:-1;
      dind[1] += shift;
      if (dind[1]<0) dind[1]=fIby-1;
      if (dind[1]>fIby-1) dind[1]=0;
      if (shift<0) {
         // target is second limit of previous voxel
         phi = fYb[dind[1]+1];
      } else {
         phi = fYb[dind[1]];
      }
      t = TMath::Tan(phi*TGeoShape::kDegRad); 
      a = dir[1]-dir[0]*t;
      if (a!=0) {
         dmin[1] = (point[0]*t-point[1])/a;
         if (dmin[1]<0) dmin[1]=TGeoShape::kBig;
      }   
//      printf("next slicex=%i : x= %f  point[0]=%f dir[0]=%fn",dind[0],fXb[dind[0]+((dind[0]>fSlices[0])?0:1)], point[0], dir[0]); 
//      printf("dx=%fn", dmin[0]);
      isYlimit = (dmin[1]>dmstep)?kTRUE:kFALSE;
   }
   
   // last check R !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   if (fSlices[0]!=-2) {
   // if there are slices on this axis, get distance to next slice.
      dind[0]+=(dir[0]<0)?-1:1;
      if (dind[0]<-1) return kFALSE;
      if (dind[0]>fIbx-1) return kFALSE;
//         printf("next slicey=%i : y= %f  point[1]=%f dir[1]=%fn",dind[1], fYb[dind[1]+((dind[1]>fSlices[1])?0:1)], point[1], dir[1]); 
      dmin[0] = (fXb[dind[0]+((dind[0]>fSlices[0])?0:1)]-point[0])/dir[0];
//         printf("dy=%fn", dmin[1]);
      isXlimit = (dmin[0]>dmstep)?kTRUE:kFALSE;
   } else {
   // if no slicing on this axis, get distance to mother limit
      limit = (box->GetOrigin())[0] + box->GetDX()*((dir[0]<0)?-1:1);
      dmin[0] = (limit-point[0])/dir[0];
      isXlimit = kTRUE;
   }
   // now find minimum distance
//   printf("dmin : %f %f %fn", dmin[0], dmin[1], dmin[2]);
   if (dmin[0]<dmin[1]) {
      if (dmin[0]<dmin[2]) {
      // next X
//         printf("next slicex : %i isXlimit=%in", dind[0],(Int_t)isXlimit);
         if (isXlimit) return kFALSE;
         if (dind[0]<0) return kFALSE;
         if (dind[0]>fIbx-2) return kFALSE;
         fSlices[0] = dind[0];
         if (fSlices[1]!=-2) {
            if (fSlices[1]<0) return GetNextIndices(point, dir);
            if (fSlices[1]>fIby-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[2]!=-2) {
            if (fSlices[2]<0) return GetNextIndices(point, dir);
            if (fSlices[2]>fIbz-2) return GetNextIndices(point, dir);
         }   
         if (fIndX[fOBx[fSlices[0]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      } else {
      // next Z
//         printf("next slicez : %i isZlimit=%in", dind[2],(Int_t)isZlimit);
         if (isZlimit) return kFALSE;
         if (dind[2]<0) return kFALSE;
         if (dind[2]>fIbz-2) return kFALSE;
         fSlices[2] = dind[2];
         if (fSlices[0]!=-2) {
            if (fSlices[0]<0) return GetNextIndices(point, dir);
            if (fSlices[0]>fIbx-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[1]!=-2) {
            if (fSlices[1]<0) return GetNextIndices(point, dir);
            if (fSlices[1]>fIby-2) return GetNextIndices(point, dir);
         }   
         if (fIndZ[fOBz[fSlices[2]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      }
   } else {
      if (dmin[1]<dmin[2]) {   
      // next Y
//         printf("next slicey : %i isYlimit=%in", dind[1], (Int_t)isYlimit);
         if (isYlimit) return kFALSE;
         if (dind[1]<0) return kFALSE;
         if (dind[1]>fIby-2) return kFALSE;
         fSlices[1] = dind[1];
         if (fSlices[0]!=-2) {
            if (fSlices[0]<0) return GetNextIndices(point, dir);
            if (fSlices[0]>fIbx-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[2]!=-2) {
            if (fSlices[2]<0) return GetNextIndices(point, dir);
            if (fSlices[2]>fIbz-2) return GetNextIndices(point, dir);
         }   
         if (fIndY[fOBy[fSlices[1]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      } else {
      // next Z
//         printf("next slicez : %i isZlimit=%in", dind[2], (Int_t)isZlimit);
         if (isZlimit) return kFALSE;
         if (dind[2]<0) return kFALSE;
         if (dind[2]>fIbz-2) return kFALSE;
         fSlices[2] = dind[2];
         if (fSlices[0]!=-2) {
            if (fSlices[0]<0) return GetNextIndices(point, dir);
            if (fSlices[0]>fIbx-2) return GetNextIndices(point, dir);
         }   
         if (fSlices[1]!=-2) {
            if (fSlices[1]<0) return GetNextIndices(point, dir);
            if (fSlices[1]>fIby-2) return GetNextIndices(point, dir);
         }   
         if (fIndZ[fOBz[fSlices[2]]]>0) return kTRUE;
         return GetNextIndices(point, dir);
      }
   }
*/   
}

//-----------------------------------------------------------------------------
 Int_t *TGeoCylVoxels::GetNextVoxel(Double_t * /*point*/, Double_t * /*dir*/, Int_t & /*ncheck*/)
{
//--- Get the list of nodes possibly crossed by a given ray.
   return 0;
}
//-----------------------------------------------------------------------------
 Int_t TGeoCylVoxels::IntersectIntervals(Double_t vox1, Double_t vox2, Double_t phi1, Double_t phi2) const
{
// Intersect a phi voxel interval in range (0,360) with a node phi interval of
// extended range. Returns 0 if no intersection, 1 if they do intersect and
// 2 if they are identical.
   if ((vox2-vox1)==360.) {
      if ((phi2-phi1)==360.) return 2;
      return 1;
   }  
   Double_t d11, d12; 
   // check if first phi limit correspond to voxel
   d11 = phi1-vox1;
   if (TMath::Abs(d11)<1E-8) d11=0;
   d12 = phi1-vox2;
   if (TMath::Abs(d12)<1E-8) d12=0;
   // check if second phi limit is in range (0, 360)
   if (phi2>360.) {
      if (d11>=0) {
         if (d12<0) return 1;
         d11 = vox1-phi2+360.;
         if (d11>=0) return 0;
         return 1;
      }
      return 1;
   }
   // both intervals are in range (0, 360)   
   Double_t d22 = phi2-vox2;
   if (TMath::Abs(d22)<1E-8) d22=0;
   if ((d11==0.) && (d22==0.)) return 2;
   if (d11>=0) {
      if (d12<0) return 1;
      return 0;
   }
   Double_t d21 = phi2-vox1;
   if (TMath::Abs(d21)<1E-8) d21=0;
   if (d21>0) return 1;
   return 0;   
}
//-----------------------------------------------------------------------------
 void TGeoCylVoxels::Print(Option_t *) const
{
// Print info about voxels.
   Int_t id;
   printf("Voxels for volume %s (nd=%i)n", fVolume->GetName(), fVolume->GetNdaughters());
   printf("priority : x=%i y=%i z=%in", fPriority[0], fPriority[1], fPriority[2]);
//   return;

   printf("--- R voxels ---n");
   if (fPriority[0]) {
      for (id=0; id<fIbx; id++) {
         printf("%15.10fn",TMath::Sqrt(fXb[id]));
         if (id == (fIbx-1)) break;
         printf("slice %i : %in", id, fIndX[fOBx[id]]);
         for (Int_t j=0;j<fIndX[fOBx[id]]; j++) {
            printf("%s  low, high:  %15.10f --- %15.10f n", 
            fVolume->GetNode(fIndX[fOBx[id]+j+1])->GetName(),
            TMath::Sqrt(fBoxes[6*fIndX[fOBx[id]+j+1]]), 
            TMath::Sqrt(fBoxes[6*fIndX[fOBx[id]+j+1]+1]));
         }
      }
   }
   printf("--- Phi voxels ---n"); 
   if (fPriority[1]) { 
      for (id=0; id<fIby; id++) {
         printf("%15.10fn", fYb[id]);
         if (id == (fIby-1)) break;
         printf("slice %i : %in", id, fIndY[fOBy[id]]);
         for (Int_t j=0;j<fIndY[fOBy[id]]; j++) {
            printf("%s  low, high:  %15.10f --- %15.10f n", 
            fVolume->GetNode(fIndY[fOBy[id]+j+1])->GetName(),
            fBoxes[6*fIndY[fOBy[id]+j+1]+2], fBoxes[6*fIndY[fOBy[id]+j+1]+3]);
         }
      }
   }
   
   printf(" ---Z voxels---n"); 
   if (fPriority[2]) { 
      for (id=0; id<fIbz; id++) {
         printf("%15.10fn", fZb[id]);
         if (id == (fIbz-1)) break;
         printf("slice %i : %in", id, fIndZ[fOBz[id]]);
         for (Int_t j=0;j<fIndZ[fOBz[id]]; j++) {
            printf("%s  low, high:  %15.10f --- %15.10f n", 
            fVolume->GetNode(fIndZ[fOBz[id]+j+1])->GetName(),
            fBoxes[6*fIndZ[fOBz[id]+j+1]+4], fBoxes[6*fIndZ[fOBz[id]+j+1]+5]);
         }
      }
   }
}
//-----------------------------------------------------------------------------
 void TGeoCylVoxels::SortAll(Option_t *)
{
// Order voxels along R, Phi, Z.
//   printf("Sorting voxels for %sn", fVolume->GetName());
   Int_t nd = fVolume->GetNdaughters();
   if (!nd) return;
   Double_t *boundaries = new Double_t[6*nd];
   Double_t rmin, rmax, pmin, pmax, zmin, zmax;
   Double_t phi2;
   Double_t bcyl[4];
   TGeoShape *shape = fVolume->GetShape();
   shape->GetBoundingCylinder(&bcyl[0]);
   TGeoBBox *box = (TGeoBBox*)fVolume->GetShape();
   // compute ranges on R, Phi, Z according to volume cylindrical limits
   rmin = bcyl[0];
   rmax = bcyl[1];
   pmin = bcyl[2];
   pmax = bcyl[3];
   zmin = (box->GetOrigin())[2] - box->GetDZ();
   zmax = (box->GetOrigin())[2] + box->GetDZ();
   if ((rmin>=rmax) || (pmin>=pmax) || (zmin>=zmax)) {
      Error("SortAll", "wrong bounding cylinder");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   Int_t id;
   // compute boundaries coordinates on R, Phi and Z
   for (id=0; id<nd; id++) {
      // r boundaries
      boundaries[2*id] = fBoxes[6*id];
      boundaries[2*id+1] = fBoxes[6*id+1];
      // phi boundaries
      boundaries[2*id+2*nd] = fBoxes[6*id+2];
      phi2 = fBoxes[6*id+3];
      if (phi2>360.) phi2-=360.;
      boundaries[2*id+2*nd+1] = phi2;
      // z boundaries
      boundaries[2*id+4*nd] = fBoxes[6*id+4];
      boundaries[2*id+4*nd+1] = fBoxes[6*id+5];
   }
   Int_t *index = new Int_t[2*nd];
   Int_t *ind = new Int_t[(2*nd+2)*(nd+1)]; // ind[fOBx[i]] = ndghts in slice fInd[i]--fInd[i+1]
   Double_t *temp = new Double_t[2*nd+2];
   Int_t current = 0;
   Double_t xxmin, xxmax, xbmin, xbmax, ddx1, ddx2;
   Int_t last;
   Double_t db, dbv;
   // sort r boundaries
   Int_t ib = 0;
   TMath::Sort(2*nd, &boundaries[0], &index[0], kFALSE);
   last = index[0];
   db = boundaries[last+1-2*last%2]-boundaries[last];
   temp[ib++] = boundaries[last]; 
   // compact common boundaries
   for (id=1; id<2*nd; id++) {
      dbv = boundaries[index[id]]-boundaries[last]; 
      last = index[id];
      if (dbv>1E-6) {
      // we have to generate a new boundary
         temp[ib++] = boundaries[last];
         db = boundaries[last+1-2*last%2]-boundaries[last];
      } else {
         if (db<0) {
      // just ignore this boundary that have to be compacted with an other
            temp[ib-1] = boundaries[last];
         }   
      }   
   }

   // now find priority
   if (ib < 2) {
      Error("SortAll", "less than 2 boundaries on R !");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   if (ib == 2) {
   // check range
      if (((temp[0]-rmin)<1E-8) && ((temp[1]-rmax)>-1E-8)) {
      // ordering on this axis makes no sense. Clear all arrays.
         fPriority[0] = 0;
         if (fIndX) delete [] fIndX; 
         fIndX = 0;
         fNx = 0;
         if (fXb) delete [] fXb;   
         fXb = 0;
         fIbx = 0;
         if (fOBx) delete [] fOBx;  
         fOBx = 0;
         fNox = 0;
      } else {
         fPriority[0] = 1; // all in one slice
      }
   } else {
      fPriority[0] = 2;    // check all
   }
   // store compacted boundaries
   if (fPriority[0]) {
      if (fXb) delete [] fXb;
      fXb = new Double_t[ib];
      memcpy(fXb, &temp[0], ib*sizeof(Double_t));
      fIbx = ib;   

      //now build the lists of nodes in each slice
      memset(ind, 0, (2*nd+2)*(nd+1)*sizeof(Int_t));
                     // ind[fOBx[i]+k] = index of dght k (k<ndghts)
      if (fOBx) delete [] fOBx;
      fNox = fIbx-1;
      fOBx = new Int_t[fNox]; // offsets in ind
      for (id=0; id<fNox; id++) {
         fOBx[id] = current; // offset of dght list
         ind[current] = 0; // ndght in this slice
         xxmin = fXb[id];
         xxmax = fXb[id+1];
         for (Int_t ic=0; ic<nd; ic++) {
            xbmin = fBoxes[6*ic];   
            xbmax = fBoxes[6*ic+1];
            ddx1 = TMath::Abs(xbmin-xxmax);
            ddx2 = TMath::Abs(xbmax-xxmin);
            if ((xbmin==xxmin)||(xbmax==xxmax)) {
               ind[current]++;
               ind[current+ind[current]] = ic;
               continue;
            }
            if ((ddx1<1E-8)||(ddx2<1E-8)) continue;
            if (((xbmin>xxmin)&&(xbmin<xxmax))||((xbmax>xxmin)&&(xbmax<xxmax)) ||
                ((xxmin>xbmin)&&(xxmin<xbmax))||((xxmax>xbmin)&&(xxmax<xbmax))) {
               // daughter ic in interval
               ind[current]++;
               ind[current+ind[current]] = ic;
            }
         }
         current += ind[current]+1;
      }
      
      if (fIndX) delete [] fIndX;
      fNx = current;
      fIndX = new Int_t[current];
      memcpy(fIndX, &ind[0], current*sizeof(Int_t));
   }   

   // sort Phi boundaries
   Int_t intersect;
   ib = 0;
   TMath::Sort(2*nd, &boundaries[2*nd], &index[0], kFALSE);
   temp[ib++] = 0.; // always store phi=0 and phi=360 boundaries
   // compact common boundaries
   for (id=0; id<2*nd; id++) {
      if (TMath::Abs(temp[ib-1]-boundaries[2*nd+index[id]])>1E-8) 
         temp[ib++]=boundaries[2*nd+index[id]];
   }
   if (temp[ib-1]!=360.) temp[ib++]=360.;
   // now find priority on Phi
   if (ib < 2) {
      Error("SortAll", "less than 2 boundaries on Phi !");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   if (ib == 2) {
   // check range
      intersect = IntersectIntervals(temp[0], temp[1], pmin, pmax);
      if (intersect==2) {
      // ordering on this axis makes no sense. Clear all arrays.
         fPriority[1] = 0;
         if (fIndY) delete [] fIndY; 
         fIndY = 0;
         fNy = 0;
         if (fYb) delete [] fYb;   
         fYb = 0;
         fIby = 0;
         if (fOBy) delete [] fOBy;  
         fOBy = 0;
         fNoy = 0;
      } else {
         fPriority[1] = 1; // all in one slice
      }
   } else {
      fPriority[1] = 2;    // check all
   }
   if (fPriority[1]) {
      // store compacted boundaries
      if (fYb) delete [] fYb;
      fYb = new Double_t[ib];
      memcpy(fYb, &temp[0], ib*sizeof(Double_t));
      fIby = ib;

      memset(ind, 0, (2*nd+2)*(nd+1)*sizeof(Int_t));
      current = 0;
      if (fOBy) delete [] fOBy;
      fNoy = fIby-1;
      fOBy = new Int_t[fNoy]; // offsets in ind
      for (id=0; id<fNoy; id++) {
      // loop voxels
         fOBy[id] = current; // offset of dght list
         ind[current] = 0; // ndght in this slice
         xxmin = fYb[id];  // voxel limits
         xxmax = fYb[id+1];
         for (Int_t ic=0; ic<nd; ic++) {
         // loop daughters
            xbmin = fBoxes[6*ic+2];   
            xbmax = fBoxes[6*ic+3];
            intersect = IntersectIntervals(xxmin, xxmax, xbmin, xbmax);
            if (intersect) {
               ind[current]++;
               ind[current+ind[current]] = ic;
            }   
         }
         current += ind[current]+1;
      }
      if (fIndY) delete [] fIndY;
      fNy = current;
      fIndY = new Int_t[current];
      memcpy(fIndY, &ind[0], current*sizeof(Int_t));
   }
   
   // sort z boundaries
   ib = 0;
   TMath::Sort(2*nd, &boundaries[4*nd], &index[0], kFALSE);
   temp[ib++] = boundaries[4*nd+index[0]];
   // compact common boundaries
   for (id=1; id<2*nd; id++) {
      if ((TMath::Abs(temp[ib-1]-boundaries[4*nd+index[id]]))>1E-10) 
          temp[ib++]=boundaries[4*nd+index[id]];
   }      
   // now find priority on Z
   if (ib < 2) {
      Error("SortAll", "less than 2 boundaries on Z !");
      printf("### volume was : %sn", fVolume->GetName());
      return;
   }   
   if (ib == 2) {
   // check range
      if (((temp[0]-zmin)<1E-10) && ((temp[1]-zmax)>-1E-10)) {
      // ordering on this axis makes no sense. Clear all arrays.
         fPriority[2] = 0;
         if (fIndZ) delete [] fIndZ; 
         fIndZ = 0;
         fNz = 0;
         if (fZb) delete [] fZb;   
         fZb = 0;
         fIbz = 0;
         if (fOBz) delete [] fOBz;  
         fOBz = 0;
         fNoz = 0;
      } else {
         fPriority[2] = 1; // all in one slice
      }
   } else {
      fPriority[2] = 2;    // check all
   }

   if (fPriority[2]) {
      // store compacted boundaries
      if (fZb) delete [] fZb;
      fZb = new Double_t[ib];
      memcpy(fZb, &temp[0], (ib)*sizeof(Double_t));
      fIbz = ib;
      
      memset(ind, 0, (2*nd+2)*(nd+1)*sizeof(Int_t));
      current = 0;
      if (fOBz) delete [] fOBz;
      fNoz = fIbz-1;
      fOBz = new Int_t[fNoz]; // offsets in ind
      for (id=0; id<fNoz; id++) {
         fOBz[id] = current; // offset of dght list
         ind[current] = 0; // ndght in this slice
         xxmin = fZb[id];
         xxmax = fZb[id+1];
         for (Int_t ic=0; ic<nd; ic++) {
            xbmin = fBoxes[6*ic+4];   
            xbmax = fBoxes[6*ic+5];   
            ddx1 = TMath::Abs(xbmin-xxmax);
            ddx2 = TMath::Abs(xbmax-xxmin);
            if ((xbmin==xxmin)||(xbmax==xxmax)) {
               ind[current]++;
               ind[current+ind[current]] = ic;
               continue;
            }
            if ((ddx1<1E-12)||(ddx2<1E-12)) continue;
            if (((xbmin>xxmin)&&(xbmin<xxmax))||((xbmax>xxmin)&&(xbmax<xxmax)) ||
                ((xxmin>xbmin)&&(xxmin<xbmax))||((xxmax>xbmin)&&(xxmax<xbmax))) {
               // daughter ic in interval
               ind[current]++;
               ind[current+ind[current]] = ic;
            }
         }
         current += ind[current]+1;
      }
      if (fIndZ) delete [] fIndZ;
      fNz = current;
      fIndZ = new Int_t[current];
      memcpy(fIndZ, &ind[0], current*sizeof(Int_t));
   }   

   delete [] boundaries; boundaries=0;   
   delete [] index; index=0;
   delete [] temp; temp=0;
   delete [] ind;

//   Print();
   if ((!fPriority[0]) && (!fPriority[1]) && (!fPriority[2])) {
      fVolume->SetVoxelFinder(0);
      delete this;
   } else {
//      Efficiency();
   }   
}
//-----------------------------------------------------------------------------
 void TGeoCylVoxels::Voxelize(Option_t *)
{
//--- Voxelize fVolume.
//   printf("Voxelizing %sn", fVolume->GetName());
   Int_t nd = fVolume->GetNdaughters();
   if (!nd) return;
   BuildVoxelLimits();
   SortAll();
}


ROOT page - Class index - Top of the page

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.