TGeoVoxelFinder.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoVoxelFinder.cxx 35702 2010-09-24 09:10:38Z agheata $
00002 // Author: Andrei Gheata   04/02/02
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 ////////////////////////////////////////////////////////////////////////////////
00013 // Full description with examples and pictures
00014 //
00015 //
00016 //
00017 //
00018 //Begin_Html
00019 /*
00020 <img src="gif/t_finder.jpg">
00021 <img src="gif/t_voxelfind.jpg">
00022 <img src="gif/t_voxtree.jpg">
00023 */
00024 //End_Html
00025 #include "TObject.h"
00026 #include "TGeoMatrix.h"
00027 #include "TGeoBBox.h"
00028 #include "TGeoNode.h"
00029 #include "TGeoManager.h"
00030 #include "TMath.h"
00031 
00032 #include "TGeoVoxelFinder.h"
00033 
00034 /*************************************************************************
00035  * TGeoVoxelFinder - finder class handling voxels 
00036  *  
00037  *************************************************************************/
00038 
00039 ClassImp(TGeoVoxelFinder)
00040 
00041 
00042 //_____________________________________________________________________________
00043 TGeoVoxelFinder::TGeoVoxelFinder()
00044 {
00045 // Default constructor
00046    fVolume  = 0;
00047    fNboxes  = 0;
00048    fIbx     = 0;
00049    fIby     = 0;
00050    fIbz     = 0;
00051    fNox     = 0;
00052    fNoy     = 0;
00053    fNoz     = 0;
00054    fNex     = 0;
00055    fNey     = 0;
00056    fNez     = 0;
00057    fNx      = 0;
00058    fNy      = 0;
00059    fNz      = 0;
00060    fBoxes   = 0;
00061    fXb      = 0;
00062    fYb      = 0;
00063    fZb      = 0;
00064    fOBx     = 0;
00065    fOBy     = 0;
00066    fOBz     = 0;
00067    fOEx     = 0;
00068    fOEy     = 0;
00069    fOEz     = 0;
00070    fIndcX   = 0;
00071    fIndcY   = 0;
00072    fIndcZ   = 0;
00073    fExtraX  = 0;
00074    fExtraY  = 0;
00075    fExtraZ  = 0;
00076    fNsliceX = 0;
00077    fNsliceY = 0;
00078    fNsliceZ = 0;
00079    fCheckList    = 0;
00080    fNcandidates  = 0;
00081    fCurrentVoxel = 0;
00082    fBits1    = 0;
00083    for (Int_t i=0; i<3; i++) {
00084       fPriority[i] = 0;
00085       fSlices[i] = 0;
00086       fInc[i] = 0;
00087       fInvdir[i] = 0.;
00088       fLimits[i] = 0.;
00089    }   
00090    SetInvalid(kFALSE);
00091 }
00092 //_____________________________________________________________________________
00093 TGeoVoxelFinder::TGeoVoxelFinder(TGeoVolume *vol)
00094 {
00095 // Default constructor
00096    if (!vol) {
00097       Fatal("TGeoVoxelFinder", "Null pointer for volume");
00098       return; // To make code checkers happy
00099    }   
00100    fVolume  = vol;
00101    fVolume->SetCylVoxels(kFALSE);
00102    fNboxes   = 0;
00103    fIbx      = 0;
00104    fIby      = 0;
00105    fIbz      = 0;
00106    fNox      = 0;
00107    fNoy      = 0;
00108    fNoz      = 0;
00109    fNex     = 0;
00110    fNey     = 0;
00111    fNez     = 0;
00112    fNx       = 0;
00113    fNy       = 0;
00114    fNz       = 0;
00115    fBoxes    = 0;
00116    fXb       = 0;
00117    fYb       = 0;
00118    fZb       = 0;
00119    fOBx      = 0;
00120    fOBy      = 0;
00121    fOBz      = 0;
00122    fOEx     = 0;
00123    fOEy     = 0;
00124    fOEz     = 0;
00125    fIndcX   = 0;
00126    fIndcY   = 0;
00127    fIndcZ   = 0;
00128    fExtraX  = 0;
00129    fExtraY  = 0;
00130    fExtraZ  = 0;
00131    fNsliceX = 0;
00132    fNsliceY = 0;
00133    fNsliceZ = 0;
00134    fCheckList = 0;
00135    fNcandidates  = 0;
00136    fCurrentVoxel = 0;
00137    fBits1    = 0;
00138    for (Int_t i=0; i<3; i++) {
00139       fPriority[i] = 0;
00140       fSlices[i] = 0;
00141       fInc[i] = 0;
00142       fInvdir[i] = 0.;
00143       fLimits[i] = 0.;
00144    }   
00145    SetNeedRebuild();
00146 }
00147 
00148 //_____________________________________________________________________________
00149 TGeoVoxelFinder::TGeoVoxelFinder(const TGeoVoxelFinder& vf) :
00150   TObject(vf),
00151   fVolume(vf.fVolume),
00152   fNcandidates(vf.fNcandidates),
00153   fCurrentVoxel(vf.fCurrentVoxel),
00154   fIbx(vf.fIbx),
00155   fIby(vf.fIby),
00156   fIbz(vf.fIbz),
00157   fNboxes(vf.fNboxes),
00158   fNox(vf.fNox),
00159   fNoy(vf.fNoy),
00160   fNoz(vf.fNoz),
00161   fNex(vf.fNex),
00162   fNey(vf.fNey),
00163   fNez(vf.fNez),
00164   fNx(vf.fNx),
00165   fNy(vf.fNy),
00166   fNz(vf.fNz),
00167   fBoxes(vf.fBoxes),
00168   fXb(vf.fXb),
00169   fYb(vf.fYb),
00170   fZb(vf.fZb),
00171   fOBx(vf.fOBx),
00172   fOBy(vf.fOBy),
00173   fOBz(vf.fOBz),
00174   fOEx(vf.fOEx),
00175   fOEy(vf.fOEy),
00176   fOEz(vf.fOEz),
00177   fExtraX(vf.fExtraX),
00178   fExtraY(vf.fExtraY),
00179   fExtraZ(vf.fExtraZ),
00180   fNsliceX(vf.fNsliceX),
00181   fNsliceY(vf.fNsliceY),
00182   fNsliceZ(vf.fNsliceZ),
00183   fIndcX(vf.fIndcX),
00184   fIndcY(vf.fIndcY),
00185   fIndcZ(vf.fIndcZ),
00186   fCheckList(vf.fCheckList),
00187   fBits1(vf.fBits1)
00188 {
00189    //copy constructor
00190    for(Int_t i=0; i<3; i++) {
00191       fPriority[i]=vf.fPriority[i];
00192       fSlices[i]=vf.fSlices[i];
00193       fInc[i]=vf.fInc[i];
00194       fInvdir[i]=vf.fInvdir[i];
00195       fLimits[i]=vf.fLimits[i];
00196    }
00197 }
00198 
00199 //_____________________________________________________________________________
00200 TGeoVoxelFinder& TGeoVoxelFinder::operator=(const TGeoVoxelFinder& vf)
00201 {
00202    //assignment operator
00203    if(this!=&vf) {
00204       TObject::operator=(vf);
00205       fVolume=vf.fVolume;
00206       fNcandidates=vf.fNcandidates;
00207       fCurrentVoxel=vf.fCurrentVoxel;
00208       fIbx=vf.fIbx;
00209       fIby=vf.fIby;
00210       fIbz=vf.fIbz;
00211       fNboxes=vf.fNboxes;
00212       fNox=vf.fNox;
00213       fNoy=vf.fNoy;
00214       fNoz=vf.fNoz;
00215       fNex=vf.fNex;
00216       fNey=vf.fNey;
00217       fNez=vf.fNez;
00218       fNx=vf.fNx;
00219       fNy=vf.fNy;
00220       fNz=vf.fNz;
00221       for(Int_t i=0; i<3; i++) {
00222          fPriority[i]=vf.fPriority[i];
00223          fSlices[i]=vf.fSlices[i];
00224          fInc[i]=vf.fInc[i];
00225          fInvdir[i]=vf.fInvdir[i];
00226          fLimits[i]=vf.fLimits[i];
00227       }
00228       fBoxes=vf.fBoxes;
00229       fXb=vf.fXb;
00230       fYb=vf.fYb;
00231       fZb=vf.fZb;
00232       fOBx=vf.fOBx;
00233       fOBy=vf.fOBy;
00234       fOBz=vf.fOBz;
00235       fOEx=vf.fOEx;
00236       fOEy=vf.fOEy;
00237       fOEz=vf.fOEz;
00238       fNsliceX=vf.fNsliceX;
00239       fNsliceY=vf.fNsliceY;
00240       fNsliceZ=vf.fNsliceZ;
00241       fIndcX=vf.fIndcX;
00242       fIndcY=vf.fIndcY;
00243       fIndcZ=vf.fIndcZ;
00244       fExtraX=vf.fExtraX;
00245       fExtraY=vf.fExtraY;
00246       fExtraZ=vf.fExtraZ;
00247       fCheckList=vf.fCheckList;
00248       fBits1=vf.fBits1;
00249    } 
00250    return *this;
00251 }
00252 
00253 //_____________________________________________________________________________
00254 TGeoVoxelFinder::~TGeoVoxelFinder()
00255 {
00256 // Destructor
00257 //   printf("deleting finder of %s\n", fVolume->GetName());
00258    if (fOBx) delete [] fOBx;
00259    if (fOBy) delete [] fOBy;
00260    if (fOBz) delete [] fOBz;
00261    if (fOEx) delete [] fOEx;
00262    if (fOEy) delete [] fOEy;
00263    if (fOEz) delete [] fOEz;
00264 //   printf("OBx OBy OBz...\n");
00265    if (fBoxes) delete [] fBoxes;
00266 //   printf("boxes...\n");
00267    if (fXb) delete [] fXb;
00268    if (fYb) delete [] fYb;
00269    if (fZb) delete [] fZb;
00270 //   printf("Xb Yb Zb...\n");
00271    if (fNsliceX) delete [] fNsliceX;
00272    if (fNsliceY) delete [] fNsliceY;
00273    if (fNsliceZ) delete [] fNsliceZ;
00274    if (fIndcX) delete [] fIndcX;
00275    if (fIndcY) delete [] fIndcY;
00276    if (fIndcZ) delete [] fIndcZ;
00277    if (fExtraX) delete [] fExtraX;
00278    if (fExtraY) delete [] fExtraY;
00279    if (fExtraZ) delete [] fExtraZ;
00280 //   printf("IndX IndY IndZ...\n");
00281    if (fCheckList) delete [] fCheckList;
00282    if (fBits1) delete [] fBits1;
00283 //   printf("checklist...\n");
00284 }
00285 //_____________________________________________________________________________
00286 void TGeoVoxelFinder::BuildVoxelLimits()
00287 {
00288 // build the array of bounding boxes of the nodes inside
00289    Int_t nd = fVolume->GetNdaughters();
00290    if (!nd) return;
00291    Int_t id;
00292    TGeoNode *node;
00293    if (fBoxes) delete [] fBoxes;
00294    if (fBits1) delete [] fBits1;
00295    fBits1 = new UChar_t[1+((nd-1)>>3)];
00296    fNboxes = 6*nd;
00297    fBoxes = new Double_t[fNboxes];
00298    if (fCheckList) delete [] fCheckList;
00299    fCheckList = new Int_t[nd];
00300    Double_t vert[24];
00301    Double_t pt[3];
00302    Double_t xyz[6];
00303 //   printf("boundaries for %s :\n", GetName());
00304    TGeoBBox *box = 0;
00305    for (id=0; id<nd; id++) {
00306       node = fVolume->GetNode(id);
00307 //      if (!strcmp(node->ClassName(), "TGeoNodeOffset") continue;
00308       box = (TGeoBBox*)node->GetVolume()->GetShape();
00309       box->SetBoxPoints(&vert[0]);
00310       for (Int_t point=0; point<8; point++) {
00311          DaughterToMother(id, &vert[3*point], &pt[0]);
00312          if (!point) {
00313             xyz[0] = xyz[1] = pt[0];
00314             xyz[2] = xyz[3] = pt[1];
00315             xyz[4] = xyz[5] = pt[2];
00316             continue;
00317          }
00318          for (Int_t j=0; j<3; j++) {
00319             if (pt[j] < xyz[2*j]) xyz[2*j]=pt[j];
00320             if (pt[j] > xyz[2*j+1]) xyz[2*j+1]=pt[j];
00321          }
00322       }
00323       fBoxes[6*id]   = 0.5*(xyz[1]-xyz[0]); // dX
00324       fBoxes[6*id+1] = 0.5*(xyz[3]-xyz[2]); // dY
00325       fBoxes[6*id+2] = 0.5*(xyz[5]-xyz[4]); // dZ
00326       fBoxes[6*id+3] = 0.5*(xyz[0]+xyz[1]); // Ox
00327       fBoxes[6*id+4] = 0.5*(xyz[2]+xyz[3]); // Oy
00328       fBoxes[6*id+5] = 0.5*(xyz[4]+xyz[5]); // Oz
00329    }
00330 }
00331 //_____________________________________________________________________________
00332 void TGeoVoxelFinder::CreateCheckList()
00333 {
00334 // Initializes check list.
00335    if (NeedRebuild()) {
00336       Voxelize();
00337       fVolume->FindOverlaps();
00338    }   
00339    Int_t nd = fVolume->GetNdaughters();
00340    if (!nd) return;
00341    if (!fCheckList) fCheckList = new Int_t[nd];
00342    if (!fBits1) fBits1 = new UChar_t[1+((nd-1)>>3)];
00343 }      
00344 //_____________________________________________________________________________
00345 void TGeoVoxelFinder::DaughterToMother(Int_t id, Double_t *local, Double_t *master) const
00346 {
00347 // convert a point from the local reference system of node id to reference
00348 // system of mother volume
00349    TGeoMatrix *mat = fVolume->GetNode(id)->GetMatrix();
00350    if (!mat) memcpy(master,local,3*sizeof(Double_t));
00351    else      mat->LocalToMaster(local, master);
00352 }
00353 //_____________________________________________________________________________
00354 Bool_t TGeoVoxelFinder::IsSafeVoxel(Double_t *point, Int_t inode, Double_t minsafe) const
00355 {
00356 // Computes squared distance from POINT to the voxel(s) containing node INODE. Returns 0
00357 // if POINT inside voxel(s).
00358    if (NeedRebuild()) {
00359       TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
00360       vox->Voxelize();
00361       fVolume->FindOverlaps();
00362    }   
00363    Double_t dxyz, minsafe2=minsafe*minsafe;
00364    Int_t ist = 6*inode;
00365    Int_t i;
00366    Double_t rsq = 0;
00367    for (i=0; i<3; i++) {
00368       dxyz = TMath::Abs(point[i]-fBoxes[ist+i+3])-fBoxes[ist+i];
00369       if (dxyz>-1E-6) rsq+=dxyz*dxyz;
00370       if (rsq > minsafe2*(1.+TGeoShape::Tolerance())) return kTRUE;
00371    }
00372    return kFALSE;
00373 }      
00374 
00375 //_____________________________________________________________________________
00376 Double_t TGeoVoxelFinder::Efficiency()
00377 {
00378 //--- Compute voxelization efficiency.
00379    printf("Voxelization efficiency for %s\n", fVolume->GetName());
00380    if (NeedRebuild()) {
00381       Voxelize();
00382       fVolume->FindOverlaps();
00383    }   
00384    Double_t nd = Double_t(fVolume->GetNdaughters());
00385    Double_t eff = 0;
00386    Double_t effslice = 0;
00387    Int_t id;
00388    if (fPriority[0]) {
00389       for (id=0; id<fIbx-1; id++) {  // loop on boundaries
00390          effslice += fNsliceX[id];
00391       }
00392       if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
00393       else printf("Woops : slice X\n");
00394    }
00395    printf("X efficiency : %g\n", effslice);
00396    eff += effslice;
00397    effslice = 0;
00398    if (fPriority[1]) {
00399       for (id=0; id<fIby-1; id++) {  // loop on boundaries
00400          effslice += fNsliceY[id];
00401       }
00402       if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
00403       else printf("Woops : slice X\n");
00404    }
00405    printf("Y efficiency : %g\n", effslice);
00406    eff += effslice;
00407    effslice = 0;
00408    if (fPriority[2]) {
00409       for (id=0; id<fIbz-1; id++) {  // loop on boundaries
00410          effslice += fNsliceZ[id];
00411       }
00412       if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
00413       else printf("Woops : slice X\n");
00414    }
00415    printf("Z efficiency : %g\n", effslice);
00416    eff += effslice;
00417    eff /= 3.;
00418    printf("Total efficiency : %g\n", eff);
00419    return eff;
00420 }
00421 //_____________________________________________________________________________
00422 void TGeoVoxelFinder::FindOverlaps(Int_t inode) const
00423 {
00424 // create the list of nodes for which the bboxes overlap with inode's bbox
00425    if (!fBoxes) return;
00426    Double_t xmin, xmax, ymin, ymax, zmin, zmax;
00427    Double_t xmin1, xmax1, ymin1, ymax1, zmin1, zmax1;
00428    Double_t ddx1, ddx2;
00429    Int_t nd = fVolume->GetNdaughters();
00430    Int_t *ovlps = 0;
00431    Int_t *otmp = new Int_t[nd-1]; 
00432    Int_t novlp = 0;
00433    TGeoNode *node = fVolume->GetNode(inode);
00434    xmin = fBoxes[6*inode+3] - fBoxes[6*inode];
00435    xmax = fBoxes[6*inode+3] + fBoxes[6*inode];
00436    ymin = fBoxes[6*inode+4] - fBoxes[6*inode+1];
00437    ymax = fBoxes[6*inode+4] + fBoxes[6*inode+1];
00438    zmin = fBoxes[6*inode+5] - fBoxes[6*inode+2];
00439    zmax = fBoxes[6*inode+5] + fBoxes[6*inode+2];
00440    // loop on brothers
00441    for (Int_t ib=0; ib<nd; ib++) {
00442       if (ib == inode) continue; // everyone overlaps with itself
00443       xmin1 = fBoxes[6*ib+3] - fBoxes[6*ib];
00444       xmax1 = fBoxes[6*ib+3] + fBoxes[6*ib];
00445       ymin1 = fBoxes[6*ib+4] - fBoxes[6*ib+1];
00446       ymax1 = fBoxes[6*ib+4] + fBoxes[6*ib+1];
00447       zmin1 = fBoxes[6*ib+5] - fBoxes[6*ib+2];
00448       zmax1 = fBoxes[6*ib+5] + fBoxes[6*ib+2];
00449 
00450       ddx1 = xmax-xmin1;
00451       ddx2 = xmax1-xmin;
00452       if (ddx1*ddx2 <= 0.) continue;
00453       ddx1 = ymax-ymin1;
00454       ddx2 = ymax1-ymin;
00455       if (ddx1*ddx2 <= 0.) continue;
00456       ddx1 = zmax-zmin1;
00457       ddx2 = zmax1-zmin;
00458       if (ddx1*ddx2 <= 0.) continue;
00459       otmp[novlp++] = ib;
00460    }
00461    if (!novlp) {
00462       delete [] otmp;
00463       node->SetOverlaps(ovlps, 0);
00464       return;
00465    }
00466    ovlps = new Int_t[novlp];
00467    memcpy(ovlps, otmp, novlp*sizeof(Int_t));
00468    delete [] otmp;
00469    node->SetOverlaps(ovlps, novlp);
00470 }
00471 
00472 //_____________________________________________________________________________
00473 Bool_t TGeoVoxelFinder::GetIndices(Double_t *point)
00474 {
00475 // Getindices for current slices on x, y, z
00476    fSlices[0] = -2; // -2 means 'all daughters in slice'
00477    fSlices[1] = -2;
00478    fSlices[2] = -2;
00479    Bool_t flag=kTRUE;
00480    if (fPriority[0]) {
00481       fSlices[0] = TMath::BinarySearch(fIbx, fXb, point[0]);
00482       if ((fSlices[0]<0) || (fSlices[0]>=fIbx-1)) {
00483          // outside slices
00484          flag=kFALSE;
00485       } else {   
00486          if (fPriority[0]==2) {
00487             // nothing in current slice 
00488             if (!fNsliceX[fSlices[0]]) flag = kFALSE;
00489          }   
00490       }
00491    }   
00492    if (fPriority[1]) {
00493       fSlices[1] = TMath::BinarySearch(fIby, fYb, point[1]);
00494       if ((fSlices[1]<0) || (fSlices[1]>=fIby-1)) {
00495          // outside slices
00496          flag=kFALSE;
00497       } else {   
00498          if (fPriority[1]==2) {
00499             // nothing in current slice 
00500             if (!fNsliceY[fSlices[1]]) flag = kFALSE;
00501          }
00502       }
00503    }   
00504    if (fPriority[2]) {
00505       fSlices[2] = TMath::BinarySearch(fIbz, fZb, point[2]);
00506       if ((fSlices[2]<0) || (fSlices[2]>=fIbz-1)) return kFALSE;
00507       if (fPriority[2]==2) {
00508          // nothing in current slice 
00509          if (!fNsliceZ[fSlices[2]]) return kFALSE;
00510       }
00511    }       
00512    return flag;
00513 }
00514 
00515 //_____________________________________________________________________________
00516 Int_t *TGeoVoxelFinder::GetExtraX(Int_t islice, Bool_t left, Int_t &nextra) const
00517 {
00518 //--- Return the list of extra candidates in a given X slice compared to
00519 // another (left or right)
00520    Int_t *list = 0;
00521    nextra = 0;
00522    if (fPriority[0]!=2) return list;
00523    if (left) {
00524       nextra = fExtraX[fOEx[islice]];
00525       list = &fExtraX[fOEx[islice]+2];
00526    } else {
00527       nextra = fExtraX[fOEx[islice]+1];
00528       list = &fExtraX[fOEx[islice]+2+fExtraX[fOEx[islice]]];
00529    }
00530    return list;   
00531 }
00532          
00533 //_____________________________________________________________________________
00534 Int_t *TGeoVoxelFinder::GetExtraY(Int_t islice, Bool_t left, Int_t &nextra) const
00535 {
00536 //--- Return the list of extra candidates in a given Y slice compared to
00537 // another (left or right)
00538    Int_t *list = 0;
00539    nextra = 0;
00540    if (fPriority[1]!=2) return list;
00541    if (left) {
00542       nextra = fExtraY[fOEy[islice]];
00543       list = &fExtraY[fOEy[islice]+2];
00544    } else {
00545       nextra = fExtraY[fOEy[islice]+1];
00546       list = &fExtraY[fOEy[islice]+2+fExtraY[fOEy[islice]]];
00547    }
00548    return list;   
00549 }
00550          
00551 //_____________________________________________________________________________
00552 Int_t *TGeoVoxelFinder::GetExtraZ(Int_t islice, Bool_t left, Int_t &nextra) const
00553 {
00554 //--- Return the list of extra candidates in a given Z slice compared to
00555 // another (left or right)
00556    Int_t *list = 0;
00557    nextra = 0;
00558    if (fPriority[2]!=2) return list;
00559    if (left) {
00560       nextra = fExtraZ[fOEz[islice]];
00561       list = &fExtraZ[fOEz[islice]+2];
00562    } else {
00563       nextra = fExtraZ[fOEz[islice]+1];
00564       list = &fExtraZ[fOEz[islice]+2+fExtraZ[fOEz[islice]]];
00565    }
00566    return list;   
00567 }
00568 
00569 //_____________________________________________________________________________
00570 Int_t *TGeoVoxelFinder::GetValidExtra(Int_t *list, Int_t &ncheck)
00571 {
00572 // Get extra candidates that are not contained in current check list
00573 //   UChar_t *bits = gGeoManager->GetBits();
00574    fNcandidates = 0;
00575    Int_t icand;
00576    UInt_t bitnumber, loc;
00577    UChar_t bit, byte;
00578    for (icand=0; icand<ncheck; icand++) {
00579       bitnumber = (UInt_t)list[icand];
00580       loc = bitnumber>>3;
00581       bit = bitnumber%8;
00582       byte = (~fBits1[loc]) & (1<<bit);
00583       if (byte) fCheckList[fNcandidates++]=list[icand];
00584    }
00585    ncheck = fNcandidates;
00586    return fCheckList;        
00587 }      
00588 
00589 //_____________________________________________________________________________
00590 Int_t *TGeoVoxelFinder::GetValidExtra(Int_t /*n1*/, UChar_t *array1, Int_t *list, Int_t &ncheck)
00591 {
00592 // Get extra candidates that are contained in array1 but not in current check list
00593 //   UChar_t *bits = gGeoManager->GetBits();
00594    fNcandidates = 0;
00595    Int_t icand;
00596    UInt_t bitnumber, loc;
00597    UChar_t bit, byte;
00598    for (icand=0; icand<ncheck; icand++) {
00599       bitnumber = (UInt_t)list[icand];
00600       loc = bitnumber>>3;
00601       bit = bitnumber%8;
00602       byte = (~fBits1[loc]) & array1[loc] & (1<<bit);
00603       if (byte) fCheckList[fNcandidates++]=list[icand];
00604    }
00605    ncheck = fNcandidates;
00606    return fCheckList;        
00607 }      
00608 
00609 //_____________________________________________________________________________
00610 Int_t *TGeoVoxelFinder::GetValidExtra(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2, Int_t *list, Int_t &ncheck)
00611 {
00612 // Get extra candidates that are contained in array1 but not in current check list
00613 //   UChar_t *bits = gGeoManager->GetBits();
00614    fNcandidates = 0;
00615    Int_t icand;
00616    UInt_t bitnumber, loc;
00617    UChar_t bit, byte;
00618    for (icand=0; icand<ncheck; icand++) {
00619       bitnumber = (UInt_t)list[icand];
00620       loc = bitnumber>>3;
00621       bit = bitnumber%8;
00622       byte = (~fBits1[loc]) & array1[loc] & array2[loc] & (1<<bit);
00623       if (byte) fCheckList[fNcandidates++]=list[icand];
00624    }
00625    ncheck = fNcandidates;
00626    return fCheckList;        
00627 }      
00628 
00629 
00630 //_____________________________________________________________________________
00631 Int_t *TGeoVoxelFinder::GetNextCandidates(Double_t *point, Int_t &ncheck)
00632 {
00633 // Returns list of new candidates in next voxel. If NULL, nowhere to
00634 // go next. 
00635    if (NeedRebuild()) {
00636       Voxelize();
00637       fVolume->FindOverlaps();
00638    }   
00639    ncheck = 0;
00640    if (fLimits[0]<0) return 0;
00641    if (fLimits[1]<0) return 0;
00642    if (fLimits[2]<0) return 0;
00643    Int_t dind[3]; // new slices
00644    //---> start from old slices
00645    memcpy(&dind[0], &fSlices[0], 3*sizeof(Int_t));
00646    Double_t dmin[3]; // distances to get to next X,Y, Z slices.
00647    dmin[0] = dmin[1] = dmin[2] = TGeoShape::Big();
00648    //---> max. possible step to be considered
00649    Double_t maxstep = TMath::Min(gGeoManager->GetStep(), fLimits[TMath::LocMin(3, fLimits)]);
00650 //   printf("1- maxstep=%g\n", maxstep);
00651    Bool_t isXlimit=kFALSE, isYlimit=kFALSE, isZlimit=kFALSE;
00652    Bool_t isForcedX=kFALSE, isForcedY=kFALSE, isForcedZ=kFALSE;
00653    Double_t dforced[3];
00654    dforced[0] = dforced[1] = dforced[2] = TGeoShape::Big();
00655    Int_t iforced = 0;
00656    //
00657    //---> work on X
00658    if (fPriority[0] && fInc[0]) {
00659       //---> increment/decrement slice
00660       dind[0] += fInc[0];
00661       if (fInc[0]==1) {
00662          if (dind[0]<0 || dind[0]>fIbx-1) return 0; // outside range
00663          dmin[0] = (fXb[dind[0]]-point[0])*fInvdir[0];
00664       } else {
00665          if (fSlices[0]<0 || fSlices[0]>fIbx-1) return 0; // outside range
00666          dmin[0] = (fXb[fSlices[0]]-point[0])*fInvdir[0];
00667       }
00668       isXlimit = (dmin[0]>maxstep)?kTRUE:kFALSE;
00669 //      printf("---> X : priority=%i, slice=%i/%i inc=%i\n",
00670 //             fPriority[0], fSlices[0], fIbx-2, fInc[0]);
00671 //      printf("2- step to next X (%i) = %g\n", (Int_t)isXlimit, dmin[0]);
00672       //---> check if propagation to next slice on this axis is forced
00673       if ((fSlices[0]==-1) || (fSlices[0]==fIbx-1)) {
00674          isForcedX = kTRUE;
00675          dforced[0] = dmin[0];
00676          iforced++;
00677 //         printf("   FORCED 1\n");
00678          if (isXlimit) return 0;
00679       } else {
00680          if (fPriority[0]==2) {
00681             // if no candidates in current slice, force next slice
00682             if (fNsliceX[fSlices[0]]==0) {
00683                isForcedX = kTRUE;
00684                dforced[0] = dmin[0];
00685                iforced++;
00686 //               printf("   FORCED 2\n");
00687                if (isXlimit) return 0;
00688             }
00689          }
00690       }         
00691    } else {
00692       // no slices on this axis -> bounding box limit
00693 //      printf("   No slice on X\n");
00694       dmin[0] = fLimits[0];
00695       isXlimit = kTRUE;
00696    }   
00697    //---> work on Y
00698    if (fPriority[1] && fInc[1]) {
00699       //---> increment/decrement slice
00700       dind[1] += fInc[1];
00701       if (fInc[1]==1) {
00702          if (dind[1]<0 || dind[1]>fIby-1) return 0; // outside range
00703          dmin[1] = (fYb[dind[1]]-point[1])*fInvdir[1];
00704       } else {
00705          if (fSlices[1]<0 || fSlices[1]>fIby-1) return 0; // outside range
00706          dmin[1] = (fYb[fSlices[1]]-point[1])*fInvdir[1];
00707       }
00708       isYlimit = (dmin[1]>maxstep)?kTRUE:kFALSE;
00709 //      printf("---> Y : priority=%i, slice=%i/%i inc=%i\n",
00710 //             fPriority[1], fSlices[1], fIby-2, fInc[1]);
00711 //      printf("3- step to next Y (%i) = %g\n", (Int_t)isYlimit, dmin[1]);
00712       
00713       //---> check if propagation to next slice on this axis is forced
00714       if ((fSlices[1]==-1) || (fSlices[1]==fIby-1)) {
00715          isForcedY = kTRUE;
00716          dforced[1] = dmin[1];
00717          iforced++;
00718 //         printf("   FORCED 1\n");
00719          if (isYlimit) return 0;
00720       } else {
00721          if (fPriority[1]==2) {
00722             // if no candidates in current slice, force next slice
00723             if (fNsliceY[fSlices[1]]==0) {
00724                isForcedY = kTRUE;
00725                dforced[1] = dmin[1];
00726                iforced++;
00727 //               printf("   FORCED 2\n");
00728                if (isYlimit) return 0;
00729             }
00730          }
00731       }   
00732    } else {
00733       // no slices on this axis -> bounding box limit
00734 //      printf("   No slice on Y\n");
00735       dmin[1] = fLimits[1];
00736       isYlimit = kTRUE;
00737    }   
00738    //---> work on Z
00739    if (fPriority[2] && fInc[2]) {
00740       //---> increment/decrement slice
00741       dind[2] += fInc[2];
00742       if (fInc[2]==1) {
00743          if (dind[2]<0 || dind[2]>fIbz-1) return 0; // outside range
00744          dmin[2] = (fZb[dind[2]]-point[2])*fInvdir[2];
00745       } else {
00746          if (fSlices[2]<0 || fSlices[2]>fIbz-1) return 0; // outside range
00747          dmin[2] = (fZb[fSlices[2]]-point[2])*fInvdir[2];
00748       }
00749       isZlimit = (dmin[2]>maxstep)?kTRUE:kFALSE;
00750 //      printf("---> Z : priority=%i, slice=%i/%i inc=%i\n",
00751 //             fPriority[2], fSlices[2], fIbz-2, fInc[2]);
00752 //      printf("4- step to next Z (%i) = %g\n", (Int_t)isZlimit, dmin[2]);
00753       
00754       //---> check if propagation to next slice on this axis is forced
00755       if ((fSlices[2]==-1) || (fSlices[2]==fIbz-1)) {
00756          isForcedZ = kTRUE;
00757          dforced[2] = dmin[2];
00758          iforced++;
00759 //         printf("   FORCED 1\n");
00760          if (isZlimit) return 0;
00761       } else {
00762          if (fPriority[2]==2) {
00763             // if no candidates in current slice, force next slice
00764             if (fNsliceZ[fSlices[2]]==0) {
00765                isForcedZ = kTRUE;
00766                dforced[2] = dmin[2];
00767                iforced++;
00768 //               printf("   FORCED 2\n");
00769                if (isZlimit) return 0;
00770             }
00771          }
00772       }
00773    } else {
00774       // no slices on this axis -> bounding box limit
00775 //      printf("   No slice on Z\n");
00776       dmin[2] = fLimits[2];
00777       isZlimit = kTRUE;
00778    }   
00779    //---> We are done with checking. See which is the closest slice.
00780    // First check if some slice is forced
00781    
00782    Double_t dslice = 0;
00783    Int_t islice = 0;
00784    if (iforced) {
00785    // some slice is forced
00786       if (isForcedX) {
00787       // X forced
00788          dslice = dforced[0];
00789          islice = 0;
00790          if (isForcedY) {
00791          // X+Y forced
00792             if (dforced[1]>dslice) {
00793                dslice = dforced[1];
00794                islice = 1;
00795             }
00796             if (isForcedZ) {
00797             // X+Y+Z forced
00798                if (dforced[2]>dslice) {
00799                   dslice = dforced[2];
00800                   islice = 2;
00801                }
00802             }
00803          } else {
00804          // X forced
00805             if (isForcedZ) {
00806             // X+Z forced
00807                if (dforced[2]>dslice) {
00808                   dslice = dforced[2];
00809                   islice = 2;
00810                }
00811             }
00812          }   
00813       } else {
00814          if (isForcedY) {
00815          // Y forced
00816             dslice = dforced[1];
00817             islice = 1;
00818             if (isForcedZ) {
00819             // Y+Z forced
00820                if (dforced[2]>dslice) {
00821                   dslice = dforced[2];
00822                   islice = 2;
00823                }
00824             }
00825          } else {
00826          // Z forced
00827             dslice = dforced[2];
00828             islice = 2;
00829          }   
00830       }                     
00831    } else {
00832    // Nothing forced -> get minimum distance
00833       islice = TMath::LocMin(3, dmin);
00834       dslice = dmin[islice];
00835       if (dslice>=maxstep) {
00836 //         printf("DSLICE > MAXSTEP -> EXIT\n");      
00837          return 0;
00838       }   
00839    }
00840 //   printf("5- islicenext=%i  DSLICE=%g\n", islice, dslice);
00841    Double_t xptnew;
00842    Int_t *new_list; // list of new candidates
00843    UChar_t *slice1 = 0;
00844    UChar_t *slice2 = 0;
00845    Int_t ndd[2] = {0,0};
00846    Int_t islices = 0;
00847    Bool_t left;
00848    switch (islice) {
00849       case 0:
00850          if (isXlimit) return 0;
00851          // increment/decrement X slice
00852          fSlices[0]=dind[0];
00853          if (iforced) {
00854          // we have to recompute Y and Z slices
00855             if (dslice>fLimits[1]) return 0;
00856             if (dslice>fLimits[2]) return 0;
00857             if ((dslice>dmin[1]) && fInc[1]) {
00858                xptnew = point[1]+dslice/fInvdir[1];
00859 //               printf("   recomputing Y slice, pos=%g\n", xptnew);
00860                while (1) {
00861                   fSlices[1] += fInc[1];
00862                   if (fInc[1]==1) {
00863                      if (fSlices[1]<-1 || fSlices[1]>fIby-2) break; // outside range
00864                      if (fYb[fSlices[1]+1]>=xptnew) break;
00865                   } else {
00866                      if (fSlices[1]<0 || fSlices[1]>fIby-1) break; // outside range
00867                      if (fYb[fSlices[1]]<= xptnew) break;
00868                   }
00869                }
00870 //               printf("   %i/%i\n", fSlices[1], fIby-2);
00871             }
00872             if ((dslice>dmin[2]) && fInc[2]) {             
00873                xptnew = point[2]+dslice/fInvdir[2];
00874 //               printf("   recomputing Z slice, pos=%g\n", xptnew);
00875                while (1) {
00876                   fSlices[2] += fInc[2];
00877                   if (fInc[2]==1) {
00878                      if (fSlices[2]<-1 || fSlices[2]>fIbz-2) break; // outside range
00879                      if (fZb[fSlices[2]+1]>=xptnew) break;
00880                   } else {
00881                      if (fSlices[2]<0 || fSlices[2]>fIbz-1) break; // outside range
00882                      if (fZb[fSlices[2]]<= xptnew) break;
00883                   }
00884                }          
00885 //               printf("   %i/%i\n", fSlices[2], fIbz-2);
00886             }
00887          }
00888          // new indices are set -> Get new candidates   
00889          if (fPriority[0]==1) {
00890          // we are entering the unique slice on this axis
00891          //---> intersect and store Y and Z
00892             if (fPriority[1]==2) {
00893                if (fSlices[1]<0 || fSlices[1]>=fIby-1) return fCheckList; // outside range
00894                ndd[0] = fNsliceY[fSlices[1]];
00895                if (!ndd[0]) return fCheckList;
00896                slice1 = &fIndcY[fOBy[fSlices[1]]];
00897                islices++;
00898             }
00899             if (fPriority[2]==2) {
00900                if (fSlices[2]<0 || fSlices[2]>=fIbz-1) return fCheckList; // outside range
00901                ndd[1] = fNsliceZ[fSlices[2]];
00902                if (!ndd[1]) return fCheckList;
00903                islices++;
00904                if (slice1) {
00905                   slice2 = &fIndcZ[fOBz[fSlices[2]]];
00906                } else {
00907                   slice1 = &fIndcZ[fOBz[fSlices[2]]];
00908                   ndd[0] = ndd[1];
00909                }
00910             }
00911             if (islices==1) {
00912                IntersectAndStore(ndd[0], slice1);
00913             } else {
00914                IntersectAndStore(ndd[0], slice1, ndd[1], slice2);
00915             }
00916             ncheck = fNcandidates;
00917             return fCheckList;   
00918          }
00919          // We got into a new slice -> Get only new candidates
00920          left = (fInc[0]>0)?kTRUE:kFALSE;
00921          new_list = GetExtraX(fSlices[0], left, ncheck);
00922 //         printf("   New list on X : %i new candidates\n", ncheck);
00923          if (!ncheck) return fCheckList;
00924          if (fPriority[1]==2) {
00925             if (fSlices[1]<0 || fSlices[1]>=fIby-1) {
00926                ncheck = 0;
00927                return fCheckList; // outside range
00928             }
00929             ndd[0] = fNsliceY[fSlices[1]];
00930             if (!ndd[0]) {
00931                ncheck = 0;
00932                return fCheckList;
00933             }   
00934             slice1 = &fIndcY[fOBy[fSlices[1]]];
00935             islices++;
00936          }
00937          if (fPriority[2]==2) {
00938             if (fSlices[2]<0 || fSlices[2]>=fIbz-1) {
00939                ncheck = 0;
00940                return fCheckList; // outside range
00941             }
00942             ndd[1] = fNsliceZ[fSlices[2]];
00943             if (!ndd[1]) {
00944                ncheck = 0;
00945                return fCheckList;
00946             }   
00947             islices++;
00948             if (slice1) {
00949                slice2 = &fIndcZ[fOBz[fSlices[2]]];
00950             } else {
00951                slice1 = &fIndcZ[fOBz[fSlices[2]]];
00952                ndd[0] = ndd[1];
00953             }
00954          }
00955          if (!islices) return GetValidExtra(new_list, ncheck);
00956          if (islices==1) {
00957             return GetValidExtra(ndd[0], slice1, new_list, ncheck);
00958          } else {
00959             return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck);
00960          }
00961       case 1:
00962          if (isYlimit) return 0;
00963          // increment/decrement Y slice
00964          fSlices[1]=dind[1];
00965          if (iforced) {
00966          // we have to recompute X and Z slices
00967             if (dslice>fLimits[0]) return 0;
00968             if (dslice>fLimits[2]) return 0;
00969             if ((dslice>dmin[0]) && fInc[0]) {
00970                xptnew = point[0]+dslice/fInvdir[0];
00971 //               printf("   recomputing X slice, pos=%g\n", xptnew);
00972                while (1) {
00973                   fSlices[0] += fInc[0];
00974                   if (fInc[0]==1) {
00975                      if (fSlices[0]<-1 || fSlices[0]>fIbx-2) break; // outside range
00976                      if (fXb[fSlices[0]+1]>=xptnew) break;
00977                   } else {
00978                      if (fSlices[0]<0 || fSlices[0]>fIbx-1) break; // outside range
00979                      if (fXb[fSlices[0]]<= xptnew) break;
00980                   }
00981                }
00982 //               printf("   %i/%i\n", fSlices[0], fIbx-2);
00983             }
00984             if ((dslice>dmin[2]) && fInc[2]) {             
00985                xptnew = point[2]+dslice/fInvdir[2];
00986 //               printf("   recomputing Z slice, pos=%g\n", xptnew);
00987                while (1) {
00988                   fSlices[2] += fInc[2];
00989                   if (fInc[2]==1) {
00990                      if (fSlices[2]<-1 || fSlices[2]>fIbz-2) break; // outside range
00991                      if (fZb[fSlices[2]+1]>=xptnew) break;
00992                   } else {
00993                      if (fSlices[2]<0 || fSlices[2]>fIbz-1) break; // outside range
00994                      if (fZb[fSlices[2]]<= xptnew) break;
00995                   }
00996                }          
00997 //               printf("   %i/%i\n", fSlices[2], fIbz-2);
00998             }
00999          }
01000          // new indices are set -> Get new candidates   
01001          if (fPriority[1]==1) {
01002          // we are entering the unique slice on this axis
01003          //---> intersect and store X and Z
01004             if (fPriority[0]==2) {
01005                if (fSlices[0]<0 || fSlices[0]>=fIbx-1) return fCheckList; // outside range
01006                ndd[0] = fNsliceX[fSlices[0]];
01007                if (!ndd[0]) return fCheckList;
01008                slice1 = &fIndcX[fOBx[fSlices[0]]];
01009                islices++;
01010             }
01011             if (fPriority[2]==2) {
01012                if (fSlices[2]<0 || fSlices[2]>=fIbz-1) return fCheckList; // outside range
01013                ndd[1] = fNsliceZ[fSlices[2]];
01014                if (!ndd[1]) return fCheckList;
01015                islices++;
01016                if (slice1) {
01017                   slice2 = &fIndcZ[fOBz[fSlices[2]]];
01018                } else {
01019                   slice1 = &fIndcZ[fOBz[fSlices[2]]];
01020                   ndd[0] = ndd[1];
01021                }
01022             }
01023             if (islices==1) {
01024                IntersectAndStore(ndd[0], slice1);
01025             } else {
01026                IntersectAndStore(ndd[0], slice1, ndd[1], slice2);
01027             }
01028             ncheck = fNcandidates;
01029             return fCheckList;   
01030          }
01031          // We got into a new slice -> Get only new candidates
01032          left = (fInc[1]>0)?kTRUE:kFALSE;
01033          new_list = GetExtraY(fSlices[1], left, ncheck);
01034 //         printf("   New list on Y : %i new candidates\n", ncheck);
01035          if (!ncheck) return fCheckList;
01036          if (fPriority[0]==2) {
01037             if (fSlices[0]<0 || fSlices[0]>=fIbx-1) {
01038                ncheck = 0;
01039                return fCheckList; // outside range
01040             }
01041             ndd[0] = fNsliceX[fSlices[0]];
01042             if (!ndd[0]) {
01043                ncheck = 0;
01044                return fCheckList;
01045             }   
01046             slice1 = &fIndcX[fOBx[fSlices[0]]];
01047             islices++;
01048          }
01049          if (fPriority[2]==2) {
01050             if (fSlices[2]<0 || fSlices[2]>=fIbz-1) {
01051                ncheck = 0;
01052                return fCheckList; // outside range
01053             }
01054             ndd[1] = fNsliceZ[fSlices[2]];
01055             if (!ndd[1]) {
01056                ncheck = 0;
01057                return fCheckList;
01058             }   
01059             islices++;
01060             if (slice1) {
01061                slice2 = &fIndcZ[fOBz[fSlices[2]]];
01062             } else {
01063                slice1 = &fIndcZ[fOBz[fSlices[2]]];
01064                ndd[0] = ndd[1];
01065             }
01066          }
01067          if (!islices) return GetValidExtra(new_list, ncheck);
01068          if (islices==1) {
01069             return GetValidExtra(ndd[0], slice1, new_list, ncheck);
01070          } else {
01071             return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck);
01072          }
01073       case 2:
01074          if (isZlimit) return 0;
01075          // increment/decrement Z slice
01076          fSlices[2]=dind[2];
01077          if (iforced) {
01078          // we have to recompute Y and X slices
01079             if (dslice>fLimits[1]) return 0;
01080             if (dslice>fLimits[0]) return 0;
01081             if ((dslice>dmin[1]) && fInc[1]) {
01082                xptnew = point[1]+dslice/fInvdir[1];
01083 //               printf("   recomputing Y slice, pos=%g\n", xptnew);
01084                while (1) {
01085                   fSlices[1] += fInc[1];
01086                   if (fInc[1]==1) {
01087                      if (fSlices[1]<-1 || fSlices[1]>fIby-2) break; // outside range
01088                      if (fYb[fSlices[1]+1]>=xptnew) break;
01089                   } else {
01090                      if (fSlices[1]<0 || fSlices[1]>fIby-1) break; // outside range
01091                      if (fYb[fSlices[1]]<= xptnew) break;
01092                   }
01093                }
01094 //               printf("   %i/%i\n", fSlices[1], fIby-2);
01095             }
01096             if ((dslice>dmin[0]) && fInc[0]) {             
01097                xptnew = point[0]+dslice/fInvdir[0];
01098 //               printf("   recomputing X slice, pos=%g\n", xptnew);
01099                while (1) {
01100                   fSlices[0] += fInc[0];
01101                   if (fInc[0]==1) {
01102                      if (fSlices[0]<-1 || fSlices[0]>fIbx-2) break; // outside range
01103                      if (fXb[fSlices[0]+1]>=xptnew) break;
01104                   } else {
01105                      if (fSlices[0]<0 || fSlices[0]>fIbx-1) break; // outside range
01106                      if (fXb[fSlices[0]]<= xptnew) break;
01107                   }
01108                }          
01109 //               printf("   %i/%i\n", fSlices[0], fIbx-2);
01110             }
01111          }
01112          // new indices are set -> Get new candidates   
01113          if (fPriority[2]==1) {
01114          // we are entering the unique slice on this axis
01115          //---> intersect and store Y and X
01116             if (fPriority[1]==2) {
01117                if (fSlices[1]<0 || fSlices[1]>=fIby-1) return fCheckList; // outside range
01118                ndd[0] = fNsliceY[fSlices[1]];
01119                if (!ndd[0]) return fCheckList;
01120                slice1 = &fIndcY[fOBy[fSlices[1]]];
01121                islices++;
01122             }
01123             if (fPriority[0]==2) {
01124                if (fSlices[0]<0 || fSlices[0]>=fIbx-1) return fCheckList; // outside range
01125                ndd[1] = fNsliceX[fSlices[0]];
01126                if (!ndd[1]) return fCheckList;
01127                islices++;
01128                if (slice1) {
01129                   slice2 = &fIndcX[fOBx[fSlices[0]]];
01130                } else {
01131                   slice1 = &fIndcX[fOBx[fSlices[0]]];
01132                   ndd[0] = ndd[1];
01133                }
01134             }
01135             if (islices==1) {
01136                IntersectAndStore(ndd[0], slice1);
01137             } else {
01138                IntersectAndStore(ndd[0], slice1, ndd[1], slice2);
01139             }
01140             ncheck = fNcandidates;
01141             return fCheckList;   
01142          }
01143          // We got into a new slice -> Get only new candidates
01144          left = (fInc[2]>0)?kTRUE:kFALSE;
01145          new_list = GetExtraZ(fSlices[2], left, ncheck);
01146 //         printf("   New list on Z : %i new candidates\n", ncheck);
01147          if (!ncheck) return fCheckList;
01148          if (fPriority[1]==2) {
01149             if (fSlices[1]<0 || fSlices[1]>=fIby-1) {
01150                ncheck = 0;
01151                return fCheckList; // outside range
01152             }
01153             ndd[0] = fNsliceY[fSlices[1]];
01154             if (!ndd[0]) {
01155                ncheck = 0;
01156                return fCheckList;
01157             }   
01158             slice1 = &fIndcY[fOBy[fSlices[1]]];
01159             islices++;
01160          }
01161          if (fPriority[0]==2) {
01162             if (fSlices[0]<0 || fSlices[0]>=fIbx-1) {
01163                ncheck = 0;
01164                return fCheckList; // outside range
01165             }
01166             ndd[1] = fNsliceX[fSlices[0]];
01167             if (!ndd[1]) {
01168                ncheck = 0;
01169                return fCheckList;
01170             }   
01171             islices++;
01172             if (slice1) {
01173                slice2 = &fIndcX[fOBx[fSlices[0]]];
01174             } else {
01175                slice1 = &fIndcX[fOBx[fSlices[0]]];
01176                ndd[0] = ndd[1];
01177             }
01178          }
01179          if (!islices) return GetValidExtra(new_list, ncheck);
01180          if (islices==1) {
01181             return GetValidExtra(ndd[0], slice1, new_list, ncheck);
01182          } else {
01183             return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck);
01184          }
01185       default:
01186          Error("GetNextCandidates", "Invalid islice=%i inside %s", islice, fVolume->GetName());
01187    }      
01188    return 0;            
01189 }
01190 
01191 //_____________________________________________________________________________
01192 void TGeoVoxelFinder::SortCrossedVoxels(Double_t *point, Double_t *dir)
01193 {
01194 // get the list in the next voxel crossed by a ray
01195    if (NeedRebuild()) {
01196       TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
01197       vox->Voxelize();
01198       fVolume->FindOverlaps();
01199    }   
01200    fCurrentVoxel = 0;
01201 //   printf("###Sort crossed voxels for %s\n", fVolume->GetName());
01202    fNcandidates = 0;
01203    Int_t  loc = 1+((fVolume->GetNdaughters()-1)>>3);
01204 //   printf("   LOC=%i\n", loc*sizeof(UChar_t));
01205 //   UChar_t *bits = gGeoManager->GetBits();
01206    memset(fBits1, 0, loc);
01207    memset(fInc, 0, 3*sizeof(Int_t));
01208    for (Int_t i=0; i<3; i++) {
01209       fInvdir[i] = TGeoShape::Big();
01210       if (TMath::Abs(dir[i])<1E-10) continue;
01211       fInc[i] = (dir[i]>0)?1:-1;
01212       fInvdir[i] = 1./dir[i];
01213    }
01214    Bool_t flag = GetIndices(point);
01215    TGeoBBox *box = (TGeoBBox*)(fVolume->GetShape());
01216    const Double_t *box_orig = box->GetOrigin();
01217    if (fInc[0]==0) {
01218       fLimits[0] = TGeoShape::Big();
01219    } else {   
01220       if (fSlices[0]==-2) {
01221          // no slice on this axis -> get limit to bounding box limit
01222          fLimits[0] = (box_orig[0]-point[0]+fInc[0]*box->GetDX())*fInvdir[0];
01223       } else {
01224          if (fInc[0]==1) {
01225             fLimits[0] = (fXb[fIbx-1]-point[0])*fInvdir[0];
01226          } else {
01227             fLimits[0] = (fXb[0]-point[0])*fInvdir[0];
01228          }
01229       }
01230    }                
01231    if (fInc[1]==0) {
01232       fLimits[1] = TGeoShape::Big();
01233    } else {   
01234       if (fSlices[1]==-2) {
01235          // no slice on this axis -> get limit to bounding box limit
01236          fLimits[1] = (box_orig[1]-point[1]+fInc[1]*box->GetDY())*fInvdir[1];
01237       } else {
01238          if (fInc[1]==1) {
01239             fLimits[1] = (fYb[fIby-1]-point[1])*fInvdir[1];
01240          } else {
01241             fLimits[1] = (fYb[0]-point[1])*fInvdir[1];
01242          }
01243       }
01244    }                
01245    if (fInc[2]==0) {
01246       fLimits[2] = TGeoShape::Big();
01247    } else {   
01248       if (fSlices[2]==-2) {
01249          // no slice on this axis -> get limit to bounding box limit
01250          fLimits[2] = (box_orig[2]-point[2]+fInc[2]*box->GetDZ())*fInvdir[2];
01251       } else {
01252          if (fInc[2]==1) {
01253             fLimits[2] = (fZb[fIbz-1]-point[2])*fInvdir[2];
01254          } else {
01255             fLimits[2] = (fZb[0]-point[2])*fInvdir[2];
01256          }
01257       }
01258    }                
01259    
01260    if (!flag) {
01261 //      printf("   NO candidates in first voxel\n");
01262 //      printf("   bits[0]=%i\n", bits[0]);
01263       return;
01264    }
01265 //   printf("   current slices : %i   %i  %i\n", fSlices[0], fSlices[1], fSlices[2]);
01266    Int_t nd[3];
01267    Int_t islices = 0;
01268    memset(&nd[0], 0, 3*sizeof(Int_t));
01269    UChar_t *slicex = 0;
01270    if (fPriority[0]==2) {
01271       nd[0] = fNsliceX[fSlices[0]];
01272       slicex=&fIndcX[fOBx[fSlices[0]]];
01273       islices++;
01274    }   
01275    UChar_t *slicey = 0;
01276    if (fPriority[1]==2) {
01277       nd[1] = fNsliceY[fSlices[1]];
01278       islices++;
01279       if (slicex) {
01280          slicey=&fIndcY[fOBy[fSlices[1]]];
01281       } else {
01282          slicex=&fIndcY[fOBy[fSlices[1]]];
01283          nd[0] = nd[1];
01284       } 
01285    }   
01286    UChar_t *slicez = 0;
01287    if (fPriority[2]==2) {
01288       nd[2] = fNsliceZ[fSlices[2]];
01289       islices++;
01290       if (slicex && slicey) {
01291          slicez=&fIndcZ[fOBz[fSlices[2]]];
01292       } else {
01293          if (slicex) {
01294             slicey=&fIndcZ[fOBz[fSlices[2]]];
01295             nd[1] = nd[2];   
01296          } else {
01297             slicex=&fIndcZ[fOBz[fSlices[2]]];
01298             nd[0] = nd[2];
01299          }
01300       }         
01301    } 
01302 //   printf("Ndaughters in first voxel : %i %i %i\n", nd[0], nd[1], nd[2]);
01303    switch (islices) {
01304       case 0:
01305          Error("SortCrossedVoxels", "no slices for %s", fVolume->GetName());
01306 //         printf("Slices :(%i,%i,%i) Priority:(%i,%i,%i)\n", fSlices[0], fSlices[1], fSlices[2], fPriority[0], fPriority[1], fPriority[2]);
01307          return;
01308       case 1:
01309          IntersectAndStore(nd[0], slicex);
01310          break;
01311       case 2:
01312          IntersectAndStore(nd[0], slicex, nd[1], slicey);
01313          break;
01314       default:
01315          IntersectAndStore(nd[0], slicex, nd[1], slicey, nd[2], slicez);    
01316    }      
01317 //   printf("   bits[0]=%i  END\n", bits[0]);
01318 //   if (fNcandidates) {
01319 //      printf("   candidates for first voxel :\n");
01320 //      for (Int_t i=0; i<fNcandidates; i++) printf("    %i\n", fCheckList[i]);
01321 //   }   
01322 }   
01323 //_____________________________________________________________________________
01324 Int_t *TGeoVoxelFinder::GetCheckList(Double_t *point, Int_t &nelem)
01325 {
01326 // get the list of daughter indices for which point is inside their bbox
01327    if (NeedRebuild()) {
01328       Voxelize();
01329       fVolume->FindOverlaps();
01330    }   
01331    if (fVolume->GetNdaughters() == 1) {
01332       if (fXb) {
01333          if (point[0]<fXb[0] || point[0]>fXb[1]) return 0;
01334       }
01335       if (fYb) {
01336          if (point[1]<fYb[0] || point[1]>fYb[1]) return 0;
01337       }   
01338 
01339       if (fZb) {
01340          if (point[2]<fZb[0] || point[2]>fZb[1]) return 0;
01341       }   
01342       fCheckList[0] = 0;
01343       nelem = 1;
01344       return fCheckList;
01345    }
01346    Int_t nslices = 0;
01347    UChar_t *slice1 = 0;
01348    UChar_t *slice2 = 0; 
01349    UChar_t *slice3 = 0;
01350    Int_t nd[3] = {0,0,0};
01351    Int_t im;
01352    if (fPriority[0]) {
01353       im = TMath::BinarySearch(fIbx, fXb, point[0]);
01354       if ((im==-1) || (im==fIbx-1)) return 0;
01355       if (fPriority[0]==2) {
01356          nd[0] = fNsliceX[im];
01357          if (!nd[0]) return 0;
01358          nslices++;
01359          slice1 = &fIndcX[fOBx[im]];
01360       }   
01361    }
01362 
01363    if (fPriority[1]) {
01364       im = TMath::BinarySearch(fIby, fYb, point[1]);
01365       if ((im==-1) || (im==fIby-1)) return 0;
01366       if (fPriority[1]==2) {
01367          nd[1] = fNsliceY[im];
01368          if (!nd[1]) return 0;
01369          nslices++;
01370          if (slice1) {
01371             slice2 = &fIndcY[fOBy[im]];
01372          } else {
01373             slice1 = &fIndcY[fOBy[im]];
01374             nd[0] = nd[1];
01375          }   
01376       }   
01377    }
01378 
01379    if (fPriority[2]) {
01380       im = TMath::BinarySearch(fIbz, fZb, point[2]);
01381       if ((im==-1) || (im==fIbz-1)) return 0;
01382       if (fPriority[2]==2) {
01383          nd[2] = fNsliceZ[im];
01384          if (!nd[2]) return 0;
01385          nslices++;
01386          if (slice1 && slice2) {
01387             slice3 = &fIndcZ[fOBz[im]];
01388          } else {
01389             if (slice1) {
01390                slice2 = &fIndcZ[fOBz[im]];
01391                nd[1] = nd[2];
01392             } else {
01393                slice1 = &fIndcZ[fOBz[im]];
01394                nd[0] = nd[2];
01395             }   
01396          }      
01397       }   
01398    }
01399    nelem = 0;
01400 //   Int_t i = 0;
01401    Bool_t intersect = kFALSE;
01402    switch (nslices) {
01403       case 0:
01404          Error("GetCheckList", "No slices for %s", fVolume->GetName());
01405          return 0;
01406       case 1:
01407          intersect = Intersect(nd[0], slice1, nelem, fCheckList);
01408          break;
01409       case 2:
01410          intersect = Intersect(nd[0], slice1, nd[1], slice2, nelem, fCheckList);
01411          break;
01412       default:         
01413          intersect = Intersect(nd[0], slice1, nd[1], slice2, nd[2], slice3, nelem, fCheckList);
01414    }      
01415    if (intersect) return fCheckList;
01416    return 0;   
01417 }
01418 
01419 //_____________________________________________________________________________
01420 Int_t *TGeoVoxelFinder::GetVoxelCandidates(Int_t i, Int_t j, Int_t k, Int_t &ncheck)
01421 {
01422 // get the list of candidates in voxel (i,j,k) - no check
01423    UChar_t *slice1 = 0;
01424    UChar_t *slice2 = 0; 
01425    UChar_t *slice3 = 0;
01426    Int_t nd[3] = {0,0,0};
01427    Int_t nslices = 0;
01428    if (fPriority[0]==2) {   
01429       nd[0] = fNsliceX[i];
01430       if (!nd[0]) return 0;
01431       nslices++;
01432       slice1 = &fIndcX[fOBx[i]];
01433    }   
01434 
01435    if (fPriority[1]==2) {   
01436       nd[1] = fNsliceY[j];
01437       if (!nd[1]) return 0;
01438       nslices++;
01439       if (slice1) {
01440          slice2 = &fIndcY[fOBy[j]];
01441       } else {
01442          slice1 = &fIndcY[fOBy[j]];
01443          nd[0] = nd[1];
01444       }   
01445    }   
01446 
01447    if (fPriority[2]==2) {
01448       nd[2] = fNsliceZ[k];
01449       if (!nd[2]) return 0;
01450       nslices++;
01451       if (slice1 && slice2) {
01452          slice3 = &fIndcZ[fOBz[k]];
01453       } else {
01454          if (slice1) {
01455             slice2 = &fIndcZ[fOBz[k]];
01456             nd[1] = nd[2];
01457          } else {
01458             slice1 = &fIndcZ[fOBz[k]];
01459             nd[0] = nd[2];
01460          }   
01461       }      
01462    }   
01463    Bool_t intersect = kFALSE;
01464    switch (nslices) {
01465       case 0:
01466          Error("GetCheckList", "No slices for %s", fVolume->GetName());
01467          return 0;
01468       case 1:
01469          intersect = Intersect(nd[0], slice1, ncheck, fCheckList);
01470          break;
01471       case 2:
01472          intersect = Intersect(nd[0], slice1, nd[1], slice2, ncheck, fCheckList);
01473          break;
01474       default:         
01475          intersect = Intersect(nd[0], slice1, nd[1], slice2, nd[2], slice3, ncheck, fCheckList);
01476    }      
01477    if (intersect) return fCheckList;
01478    return 0; 
01479 }     
01480 
01481 //_____________________________________________________________________________
01482 Int_t *TGeoVoxelFinder::GetNextVoxel(Double_t *point, Double_t * /*dir*/, Int_t &ncheck)
01483 {
01484 // get the list of new candidates for the next voxel crossed by current ray
01485 //   printf("### GetNextVoxel\n");
01486    if (NeedRebuild()) {
01487       Voxelize();
01488       fVolume->FindOverlaps();
01489    }   
01490    if (fCurrentVoxel==0) {
01491 //      printf(">>> first voxel, %i candidates\n", ncheck);
01492 //      printf("   bits[0]=%i\n", gGeoManager->GetBits()[0]);
01493       fCurrentVoxel++;
01494       ncheck = fNcandidates;
01495       return fCheckList;
01496    }
01497    fCurrentVoxel++;
01498 //   printf(">>> voxel %i\n", fCurrentVoxel);
01499    // Get slices for next voxel
01500 //   printf("before - fSlices : %i %i %i\n", fSlices[0], fSlices[1], fSlices[2]);
01501    return GetNextCandidates(point, ncheck);
01502 } 
01503 
01504 //_____________________________________________________________________________
01505 Bool_t TGeoVoxelFinder::Intersect(Int_t n1, UChar_t *array1, Int_t &nf, Int_t *result)
01506 {
01507 // return the list of nodes corresponding to one array of bits
01508    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01509    nf = 0;
01510    Int_t nbytes = 1+((nd-1)>>3);
01511    Int_t current_byte;
01512    Int_t current_bit;
01513    UChar_t byte;
01514    Bool_t ibreak = kFALSE;
01515    for (current_byte=0; current_byte<nbytes; current_byte++) {
01516       byte = array1[current_byte];
01517       if (!byte) continue;
01518       for (current_bit=0; current_bit<8; current_bit++) {
01519          if (byte & (1<<current_bit)) {
01520             result[nf++] = (current_byte<<3)+current_bit;
01521             if (nf==n1) {
01522                ibreak = kTRUE;
01523                break;
01524             }   
01525          }
01526       }
01527       if (ibreak) return kTRUE;
01528    }
01529    return kTRUE;        
01530 }      
01531 
01532 //_____________________________________________________________________________
01533 Bool_t TGeoVoxelFinder::IntersectAndStore(Int_t n1, UChar_t *array1)
01534 {
01535 // return the list of nodes corresponding to one array of bits
01536    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01537 //   UChar_t *bits = gGeoManager->GetBits();
01538    fNcandidates = 0;
01539    Int_t nbytes = 1+((nd-1)>>3);
01540    memcpy(fBits1, array1, nbytes*sizeof(UChar_t)); 
01541    Int_t current_byte;
01542    Int_t current_bit;
01543    UChar_t byte;
01544    Bool_t ibreak = kFALSE;
01545    Int_t icand;
01546    for (current_byte=0; current_byte<nbytes; current_byte++) {
01547       byte = array1[current_byte];
01548       icand = current_byte<<3;
01549       if (!byte) continue;
01550       for (current_bit=0; current_bit<8; current_bit++) {
01551          if (byte & (1<<current_bit)) {
01552             fCheckList[fNcandidates++] = icand+current_bit;
01553             if (fNcandidates==n1) {
01554                ibreak = kTRUE;
01555                break;
01556             }   
01557          }
01558       }
01559       if (ibreak) return kTRUE;
01560    }
01561    return kTRUE;        
01562 }      
01563 
01564 //_____________________________________________________________________________
01565 Bool_t TGeoVoxelFinder::Union(Int_t n1, UChar_t *array1)
01566 {
01567 // make union of older bits with new array
01568 //   printf("Union - one slice\n");
01569    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01570 //   UChar_t *bits = gGeoManager->GetBits();
01571    fNcandidates = 0;
01572    Int_t nbytes = 1+((nd-1)>>3);
01573    Int_t current_byte;
01574    Int_t current_bit;
01575    UChar_t byte;
01576    Bool_t ibreak = kFALSE;
01577    for (current_byte=0; current_byte<nbytes; current_byte++) {
01578 //      printf("   byte %i : bits=%i array=%i\n", current_byte, bits[current_byte], array1[current_byte]);
01579       byte = (~fBits1[current_byte]) & array1[current_byte];
01580       if (!byte) continue;
01581       for (current_bit=0; current_bit<8; current_bit++) {
01582          if (byte & (1<<current_bit)) {
01583             fCheckList[fNcandidates++] = (current_byte<<3)+current_bit;
01584             if (fNcandidates==n1) {
01585                ibreak = kTRUE;
01586                break;
01587             }   
01588          }
01589       }
01590       fBits1[current_byte] |= byte;
01591       if (ibreak) return kTRUE;
01592    }
01593    return (fNcandidates>0);        
01594 }      
01595 
01596 //_____________________________________________________________________________
01597 Bool_t TGeoVoxelFinder::Union(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2)
01598 {
01599 // make union of older bits with new array
01600 //   printf("Union - two slices\n");
01601    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01602 //   UChar_t *bits = gGeoManager->GetBits();
01603    fNcandidates = 0;
01604    Int_t nbytes = 1+((nd-1)>>3);
01605    Int_t current_byte;
01606    Int_t current_bit;
01607    UChar_t byte;
01608    for (current_byte=0; current_byte<nbytes; current_byte++) {
01609       byte = (~fBits1[current_byte]) & (array1[current_byte] & array2[current_byte]);
01610       if (!byte) continue;
01611       for (current_bit=0; current_bit<8; current_bit++) {
01612          if (byte & (1<<current_bit)) {
01613             fCheckList[fNcandidates++] = (current_byte<<3)+current_bit;
01614          }
01615       }
01616       fBits1[current_byte] |= byte;
01617    }
01618    return (fNcandidates>0);        
01619 }      
01620 
01621 //_____________________________________________________________________________
01622 Bool_t TGeoVoxelFinder::Union(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2, Int_t /*n3*/, UChar_t *array3)
01623 {
01624 // make union of older bits with new array
01625 //   printf("Union - three slices\n");
01626 //   printf("n1=%i n2=%i n3=%i\n", n1,n2,n3);
01627    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01628 //   UChar_t *bits = gGeoManager->GetBits();
01629    fNcandidates = 0;
01630    Int_t nbytes = 1+((nd-1)>>3);
01631    Int_t current_byte;
01632    Int_t current_bit;
01633    UChar_t byte;
01634    for (current_byte=0; current_byte<nbytes; current_byte++) {
01635       byte = (~fBits1[current_byte]) & (array1[current_byte] & array2[current_byte] & array3[current_byte]);
01636       if (!byte) continue;
01637       for (current_bit=0; current_bit<8; current_bit++) {
01638          if (byte & (1<<current_bit)) {
01639             fCheckList[fNcandidates++] = (current_byte<<3)+current_bit;
01640          }
01641       }
01642       fBits1[current_byte] |= byte;
01643    }
01644    return (fNcandidates>0);        
01645 }      
01646 
01647 //_____________________________________________________________________________
01648 Bool_t TGeoVoxelFinder::Intersect(Int_t n1, UChar_t *array1, Int_t n2, UChar_t *array2, Int_t &nf, Int_t *result)
01649 {
01650 // return the list of nodes corresponding to the intersection of two arrays of bits
01651    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01652    nf = 0;
01653    Int_t nbytes = 1+((nd-1)>>3);
01654    Int_t current_byte;
01655    Int_t current_bit;
01656    UChar_t byte;
01657    Bool_t ibreak = kFALSE;
01658    for (current_byte=0; current_byte<nbytes; current_byte++) {
01659       byte = array1[current_byte] & array2[current_byte];
01660       if (!byte) continue;
01661       for (current_bit=0; current_bit<8; current_bit++) {
01662          if (byte & (1<<current_bit)) {
01663             result[nf++] = (current_byte<<3)+current_bit;
01664             if ((nf==n1) || (nf==n2)) {
01665                ibreak = kTRUE;
01666                break;
01667             }   
01668          }
01669       }
01670       if (ibreak) return kTRUE;
01671    }
01672    return (nf>0);
01673 }
01674 
01675 //_____________________________________________________________________________
01676 Bool_t TGeoVoxelFinder::IntersectAndStore(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2)
01677 {
01678 // return the list of nodes corresponding to the intersection of two arrays of bits
01679    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01680 //   UChar_t *bits = gGeoManager->GetBits();
01681    fNcandidates = 0;
01682    Int_t nbytes = 1+((nd-1)>>3);
01683 //   memset(bits, 0, nbytes*sizeof(UChar_t));
01684    Int_t current_byte;
01685    Int_t current_bit;
01686    Int_t icand;
01687    UChar_t byte;
01688    for (current_byte=0; current_byte<nbytes; current_byte++) {
01689       byte = array1[current_byte] & array2[current_byte];
01690       icand = current_byte<<3;
01691       fBits1[current_byte] = byte;
01692       if (!byte) continue;
01693       for (current_bit=0; current_bit<8; current_bit++) {
01694          if (byte & (1<<current_bit)) {
01695             fCheckList[fNcandidates++] = icand+current_bit;
01696          }
01697       }
01698    }
01699    return (fNcandidates>0);
01700 }
01701 
01702 //_____________________________________________________________________________
01703 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)
01704 {
01705 // return the list of nodes corresponding to the intersection of three arrays of bits
01706    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01707    nf = 0;
01708    Int_t nbytes = 1+((nd-1)>>3);
01709    Int_t current_byte;
01710    Int_t current_bit;
01711    UChar_t byte;
01712    Bool_t ibreak = kFALSE;
01713    for (current_byte=0; current_byte<nbytes; current_byte++) {
01714       byte = array1[current_byte] & array2[current_byte] & array3[current_byte];
01715       if (!byte) continue;
01716       for (current_bit=0; current_bit<8; current_bit++) {
01717          if (byte & (1<<current_bit)) {
01718             result[nf++] = (current_byte<<3)+current_bit;
01719             if ((nf==n1) || (nf==n2) || (nf==n3)) {
01720                ibreak = kTRUE;
01721                break;
01722             }   
01723          }
01724       }
01725       if (ibreak) return kTRUE;
01726    }
01727    return (nf>0);
01728 }
01729 
01730 //_____________________________________________________________________________
01731 Bool_t TGeoVoxelFinder::IntersectAndStore(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2, Int_t /*n3*/, UChar_t *array3)
01732 {
01733 // return the list of nodes corresponding to the intersection of three arrays of bits
01734    Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
01735 //   UChar_t *bits = gGeoManager->GetBits();
01736    fNcandidates = 0;
01737    Int_t nbytes = 1+((nd-1)>>3);
01738 //   memset(bits, 0, nbytes*sizeof(UChar_t));
01739    Int_t current_byte;
01740    Int_t current_bit;
01741    Int_t icand;
01742    UChar_t byte;
01743    for (current_byte=0; current_byte<nbytes; current_byte++) {
01744       byte = array1[current_byte] & array2[current_byte] & array3[current_byte];
01745       icand = current_byte<<3;
01746       fBits1[current_byte] = byte;
01747       if (!byte) continue;
01748       for (current_bit=0; current_bit<8; current_bit++) {
01749          if (byte & (1<<current_bit)) {
01750             fCheckList[fNcandidates++] = icand+current_bit;
01751          }
01752       }
01753    }
01754    return (fNcandidates>0);
01755 }
01756 //_____________________________________________________________________________
01757 void TGeoVoxelFinder::SortAll(Option_t *)
01758 {
01759 // order bounding boxes along x, y, z
01760    Int_t nd = fVolume->GetNdaughters();
01761    Int_t nperslice  = 1+(nd-1)/(8*sizeof(UChar_t)); /*Nbytes per slice*/
01762    Int_t nmaxslices = 2*nd+1; // max number of slices on each axis
01763    Double_t xmin, xmax, ymin, ymax, zmin, zmax;
01764    TGeoBBox *box = (TGeoBBox*)fVolume->GetShape(); // bounding box for volume
01765    // compute range on X, Y, Z according to volume bounding box
01766    xmin = (box->GetOrigin())[0] - box->GetDX();
01767    xmax = (box->GetOrigin())[0] + box->GetDX();
01768    ymin = (box->GetOrigin())[1] - box->GetDY();
01769    ymax = (box->GetOrigin())[1] + box->GetDY();
01770    zmin = (box->GetOrigin())[2] - box->GetDZ();
01771    zmax = (box->GetOrigin())[2] + box->GetDZ();
01772    if ((xmin>=xmax) || (ymin>=ymax) || (zmin>=zmax)) {
01773       Error("SortAll", "Wrong bounding box for volume %s", fVolume->GetName());
01774       return;
01775    }   
01776    Int_t id;
01777    // compute boundaries coordinates on X,Y,Z
01778    Double_t *boundaries = new Double_t[6*nd]; // list of different boundaries
01779    for (id=0; id<nd; id++) {
01780       // x boundaries
01781       boundaries[2*id] = fBoxes[6*id+3]-fBoxes[6*id];
01782       boundaries[2*id+1] = fBoxes[6*id+3]+fBoxes[6*id];
01783       // y boundaries
01784       boundaries[2*id+2*nd] = fBoxes[6*id+4]-fBoxes[6*id+1];
01785       boundaries[2*id+2*nd+1] = fBoxes[6*id+4]+fBoxes[6*id+1];
01786       // z boundaries
01787       boundaries[2*id+4*nd] = fBoxes[6*id+5]-fBoxes[6*id+2];
01788       boundaries[2*id+4*nd+1] = fBoxes[6*id+5]+fBoxes[6*id+2];
01789    }
01790    Int_t *index = new Int_t[2*nd]; // indexes for sorted boundaries on one axis
01791    UChar_t *ind = new UChar_t[nmaxslices*nperslice]; // ind[fOBx[i]] = ndghts in slice fInd[i]--fInd[i+1]
01792    Int_t *extra = new Int_t[nmaxslices*4]; 
01793    // extra[fOEx[i]]   = nextra_to_left (i/i-1)
01794    // extra[fOEx[i]+1] = nextra_to_right (i/i+1)
01795    // Int_t *extra_to_left  = extra[fOEx[i]+2]
01796    // Int_t *extra_to_right = extra[fOEx[i]+2+nextra_to_left]
01797    Double_t *temp = new Double_t[2*nd]; // temporary array to store sorted boundary positions
01798    Int_t current  = 0;
01799    Int_t indextra = 0;
01800    Int_t nleft, nright;
01801    Int_t *extra_left  = new Int_t[nd];
01802    Int_t *extra_right = new Int_t[nd];
01803    Double_t xxmin, xxmax, xbmin, xbmax, ddx1, ddx2;
01804    UChar_t *bits;
01805    UInt_t loc, bitnumber;
01806    UChar_t bit;
01807 
01808    // sort x boundaries
01809    Int_t ib = 0; // total number of DIFFERENT boundaries
01810    TMath::Sort(2*nd, &boundaries[0], &index[0], kFALSE);
01811    // compact common boundaries
01812    for (id=0; id<2*nd; id++) {
01813       if (!ib) {temp[ib++] = boundaries[index[id]]; continue;}
01814       if (TMath::Abs(temp[ib-1]-boundaries[index[id]])>1E-10)
01815          temp[ib++] = boundaries[index[id]];
01816    }
01817    // now find priority
01818    if (ib < 2) {
01819       Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on X", fVolume->GetName());
01820       delete [] boundaries;
01821       delete [] index;
01822       delete [] ind;
01823       delete [] temp;
01824       delete [] extra;
01825       delete [] extra_left;
01826       delete [] extra_right;
01827       SetInvalid();
01828       return;
01829    }   
01830    if (ib == 2) {
01831    // check range
01832       if (((temp[0]-xmin)<1E-10) && ((temp[1]-xmax)>-1E-10)) {
01833       // ordering on this axis makes no sense. Clear all arrays.
01834          fPriority[0] = 0;  // always skip this axis
01835          if (fIndcX) delete [] fIndcX; 
01836          fIndcX = 0;
01837          fNx = 0;
01838          if (fXb) delete [] fXb;   
01839          fXb = 0;
01840          fIbx = 0;
01841          if (fOBx) delete [] fOBx;  
01842          fOBx = 0;
01843          fNox = 0;
01844       } else {
01845          fPriority[0] = 1; // all in one slice
01846       }
01847    } else {
01848       fPriority[0] = 2;    // check all
01849    }
01850    // store compacted boundaries
01851    if (fPriority[0]) {
01852       if (fXb) delete [] fXb;
01853       fXb = new Double_t[ib];
01854       memcpy(fXb, &temp[0], ib*sizeof(Double_t));
01855       fIbx = ib;
01856    }   
01857    
01858    //--- now build the lists of nodes in each slice of X axis
01859    if (fPriority[0]==2) {
01860       memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
01861       if (fOBx) delete [] fOBx;
01862       fNox = fIbx-1; // number of different slices
01863       fOBx = new Int_t[fNox]; // offsets in ind
01864       if (fOEx) delete [] fOEx;
01865       fOEx = new Int_t[fNox]; // offsets in extra
01866       if (fNsliceX) delete [] fNsliceX;
01867       fNsliceX = new Int_t[fNox];
01868       current  = 0;
01869       indextra = 0;
01870       //--- now loop all slices
01871       for (id=0; id<fNox; id++) {
01872          fOBx[id] = current; // offset in dght list for this slice
01873          fOEx[id] = indextra; // offset in exta list for this slice
01874          fNsliceX[id] = 0; // ndght in this slice
01875          extra[indextra] = extra[indextra+1] = 0; // no extra left/right
01876          nleft = nright = 0;
01877          bits = &ind[current]; // adress of bits for this slice
01878          xxmin = fXb[id];
01879          xxmax = fXb[id+1];
01880          for (Int_t ic=0; ic<nd; ic++) {
01881             xbmin = fBoxes[6*ic+3]-fBoxes[6*ic];   
01882             xbmax = fBoxes[6*ic+3]+fBoxes[6*ic];
01883             ddx1 = xbmin-xxmax;
01884             if (ddx1>-1E-10) continue;
01885             ddx2 = xbmax-xxmin;
01886             if (ddx2<1E-10) continue;
01887             // daughter ic in interval
01888             //---> set the bit
01889             fNsliceX[id]++;
01890             bitnumber = (UInt_t)ic;
01891             loc = bitnumber/8;
01892             bit = bitnumber%8;
01893             bits[loc] |= 1<<bit;
01894             //---> chech if it is extra to left/right
01895             //--- left
01896             ddx1 = xbmin-xxmin;
01897             ddx2 = xbmax-xxmax;
01898             if ((id==0) || (ddx1>-1E-10)) {
01899                extra_left[nleft++] = ic;
01900             }   
01901             //---right
01902             if ((id==(fNoz-1)) || (ddx2<1E-10)) {
01903                extra_right[nright++] = ic;
01904             }   
01905          }
01906          //--- compute offset of next slice
01907          if (fNsliceX[id]>0) current += nperslice;
01908          //--- copy extra candidates
01909          extra[indextra] = nleft;
01910          extra[indextra+1] = nright;
01911          if (nleft)  memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
01912          if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));  
01913          indextra += 2+nleft+nright;
01914       }
01915       if (fIndcX) delete [] fIndcX;
01916       fNx = current;
01917       fIndcX = new UChar_t[current];
01918       memcpy(fIndcX, ind, current*sizeof(UChar_t));
01919       if (fExtraX) delete [] fExtraX;
01920       fNex = indextra;
01921       if (indextra>nmaxslices*4) printf("Woops!!!\n");
01922       fExtraX = new Int_t[indextra];
01923       memcpy(fExtraX, extra, indextra*sizeof(Int_t));
01924    }   
01925 
01926    // sort y boundaries
01927    ib = 0;
01928    TMath::Sort(2*nd, &boundaries[2*nd], &index[0], kFALSE);
01929    // compact common boundaries
01930    for (id=0; id<2*nd; id++) {
01931       if (!ib) {temp[ib++] = boundaries[2*nd+index[id]]; continue;}
01932       if (TMath::Abs(temp[ib-1]-boundaries[2*nd+index[id]])>1E-10) 
01933          temp[ib++]=boundaries[2*nd+index[id]];
01934    }
01935    // now find priority on Y
01936    if (ib < 2) {
01937       Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on Y", fVolume->GetName());
01938       delete [] boundaries;
01939       delete [] index;
01940       delete [] ind;
01941       delete [] temp;
01942       delete [] extra;
01943       delete [] extra_left;
01944       delete [] extra_right;
01945       SetInvalid();
01946       return;
01947    }   
01948    if (ib == 2) {
01949    // check range
01950       if (((temp[0]-ymin)<1E-10) && ((temp[1]-ymax)>-1E-10)) {
01951       // ordering on this axis makes no sense. Clear all arrays.
01952          fPriority[1] = 0; // always skip this axis
01953          if (fIndcY) delete [] fIndcY; 
01954          fIndcY = 0;
01955          fNy = 0;
01956          if (fYb) delete [] fYb;   
01957          fYb = 0;
01958          fIby = 0;
01959          if (fOBy) delete [] fOBy;  
01960          fOBy = 0;
01961          fNoy = 0;
01962       } else {
01963          fPriority[1] = 1; // all in one slice
01964       }
01965    } else {
01966       fPriority[1] = 2;    // check all
01967    }
01968 
01969    // store compacted boundaries
01970    if (fPriority[1]) {
01971       if (fYb) delete [] fYb;
01972       fYb = new Double_t[ib];
01973       memcpy(fYb, &temp[0], ib*sizeof(Double_t));
01974       fIby = ib;   
01975    }   
01976 
01977 
01978    if (fPriority[1]==2) {
01979    //--- now build the lists of nodes in each slice of Y axis
01980       memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
01981       if (fOBy) delete [] fOBy;
01982       fNoy = fIby-1; // number of different slices
01983       fOBy = new Int_t[fNoy]; // offsets in ind
01984       if (fOEy) delete [] fOEy;
01985       fOEy = new Int_t[fNoy]; // offsets in extra
01986       if (fNsliceY) delete [] fNsliceY;
01987       fNsliceY = new Int_t[fNoy];
01988       current = 0;
01989       indextra = 0;
01990       //--- now loop all slices
01991       for (id=0; id<fNoy; id++) {
01992          fOBy[id] = current; // offset of dght list
01993          fOEy[id] = indextra; // offset in exta list for this slice
01994          fNsliceY[id] = 0; // ndght in this slice
01995          extra[indextra] = extra[indextra+1] = 0; // no extra left/right
01996          nleft = nright = 0;
01997          bits = &ind[current]; // adress of bits for this slice
01998          xxmin = fYb[id];
01999          xxmax = fYb[id+1];
02000          for (Int_t ic=0; ic<nd; ic++) {
02001             xbmin = fBoxes[6*ic+4]-fBoxes[6*ic+1];   
02002             xbmax = fBoxes[6*ic+4]+fBoxes[6*ic+1];   
02003             ddx1 = xbmin-xxmax;
02004             if (ddx1>-1E-10) continue;
02005             ddx2 = xbmax-xxmin;
02006             if (ddx2<1E-10) continue;
02007             // daughter ic in interval
02008             //---> set the bit
02009             fNsliceY[id]++;
02010             bitnumber = (UInt_t)ic;
02011             loc = bitnumber/8;
02012             bit = bitnumber%8;
02013             bits[loc] |= 1<<bit;
02014             //---> chech if it is extra to left/right
02015             //--- left
02016             ddx1 = xbmin-xxmin;
02017             ddx2 = xbmax-xxmax;
02018             if ((id==0) || (ddx1>-1E-10)) {
02019                extra_left[nleft++] = ic;
02020             }   
02021             //---right
02022             if ((id==(fNoz-1)) || (ddx2<1E-10)) {
02023                extra_right[nright++] = ic;
02024             }   
02025          }
02026          //--- compute offset of next slice
02027          if (fNsliceY[id]>0) current += nperslice;
02028          //--- copy extra candidates
02029          extra[indextra] = nleft;
02030          extra[indextra+1] = nright;
02031          if (nleft)  memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
02032          if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));  
02033          indextra += 2+nleft+nright;
02034       }
02035       if (fIndcY) delete [] fIndcY;
02036       fNy = current;
02037       fIndcY = new UChar_t[current];
02038       memcpy(fIndcY, &ind[0], current*sizeof(UChar_t));
02039       if (fExtraY) delete [] fExtraY;
02040       fNey = indextra;
02041       if (indextra>nmaxslices*4) printf("Woops!!!\n");
02042       fExtraY = new Int_t[indextra];
02043       memcpy(fExtraY, extra, indextra*sizeof(Int_t));
02044    }
02045    
02046    // sort z boundaries
02047    ib = 0;
02048    TMath::Sort(2*nd, &boundaries[4*nd], &index[0], kFALSE);
02049    // compact common boundaries
02050    for (id=0; id<2*nd; id++) {
02051       if (!ib) {temp[ib++] = boundaries[4*nd+index[id]]; continue;}
02052       if ((TMath::Abs(temp[ib-1]-boundaries[4*nd+index[id]]))>1E-10) 
02053          temp[ib++]=boundaries[4*nd+index[id]];
02054    }      
02055    // now find priority on Z
02056    if (ib < 2) {
02057       Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on Z", fVolume->GetName());
02058       delete [] boundaries;
02059       delete [] index;
02060       delete [] ind;
02061       delete [] temp;
02062       delete [] extra;
02063       delete [] extra_left;
02064       delete [] extra_right;
02065       SetInvalid();
02066       return;
02067    }   
02068    if (ib == 2) {
02069    // check range
02070       if (((temp[0]-zmin)<1E-10) && ((temp[1]-zmax)>-1E-10)) {
02071       // ordering on this axis makes no sense. Clear all arrays.
02072          fPriority[2] = 0;
02073          if (fIndcZ) delete [] fIndcZ; 
02074          fIndcZ = 0;
02075          fNz = 0;
02076          if (fZb) delete [] fZb;   
02077          fZb = 0;
02078          fIbz = 0;
02079          if (fOBz) delete [] fOBz;  
02080          fOBz = 0;
02081          fNoz = 0;
02082       } else {
02083          fPriority[2] = 1; // all in one slice
02084       }
02085    } else {
02086       fPriority[2] = 2;    // check all
02087    }
02088 
02089    // store compacted boundaries
02090    if (fPriority[2]) {
02091       if (fZb) delete [] fZb;
02092       fZb = new Double_t[ib];
02093       memcpy(fZb, &temp[0], ib*sizeof(Double_t));
02094       fIbz = ib;   
02095    }   
02096 
02097 
02098    if (fPriority[2]==2) {
02099    //--- now build the lists of nodes in each slice of Y axis
02100       memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
02101       if (fOBz) delete [] fOBz;
02102       fNoz = fIbz-1; // number of different slices
02103       fOBz = new Int_t[fNoz]; // offsets in ind
02104       if (fOEz) delete [] fOEz;
02105       fOEz = new Int_t[fNoz]; // offsets in extra
02106       if (fNsliceZ) delete [] fNsliceZ;
02107       fNsliceZ = new Int_t[fNoz];
02108       current = 0;
02109       indextra = 0;
02110       //--- now loop all slices
02111       for (id=0; id<fNoz; id++) {
02112          fOBz[id] = current; // offset of dght list
02113          fOEz[id] = indextra; // offset in exta list for this slice
02114          fNsliceZ[id] = 0; // ndght in this slice
02115          extra[indextra] = extra[indextra+1] = 0; // no extra left/right
02116          nleft = nright = 0;
02117          bits = &ind[current]; // adress of bits for this slice
02118          xxmin = fZb[id];
02119          xxmax = fZb[id+1];
02120          for (Int_t ic=0; ic<nd; ic++) {
02121             xbmin = fBoxes[6*ic+5]-fBoxes[6*ic+2];   
02122             xbmax = fBoxes[6*ic+5]+fBoxes[6*ic+2];   
02123             ddx1 = xbmin-xxmax;
02124             if (ddx1>-1E-10) continue;
02125             ddx2 = xbmax-xxmin;
02126             if (ddx2<1E-10) continue;
02127             // daughter ic in interval
02128             //---> set the bit
02129             fNsliceZ[id]++;
02130             bitnumber = (UInt_t)ic;
02131             loc = bitnumber/8;
02132             bit = bitnumber%8;
02133             bits[loc] |= 1<<bit;
02134             //---> chech if it is extra to left/right
02135             //--- left
02136             ddx1 = xbmin-xxmin;
02137             ddx2 = xbmax-xxmax;
02138             if ((id==0) || (ddx1>-1E-10)) {
02139                extra_left[nleft++] = ic;
02140             }   
02141             //---right
02142             if ((id==(fNoz-1)) || (ddx2<1E-10)) {
02143                extra_right[nright++] = ic;
02144             }   
02145          }
02146          //--- compute offset of next slice
02147          if (fNsliceZ[id]>0) current += nperslice;
02148          //--- copy extra candidates
02149          extra[indextra] = nleft;
02150          extra[indextra+1] = nright;
02151          if (nleft)  memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
02152          if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));  
02153          indextra += 2+nleft+nright;
02154       }
02155       if (fIndcZ) delete [] fIndcZ;
02156       fNz = current;
02157       fIndcZ = new UChar_t[current];
02158       memcpy(fIndcZ, &ind[0], current*sizeof(UChar_t));
02159       if (fExtraZ) delete [] fExtraZ;
02160       fNez = indextra;
02161       if (indextra>nmaxslices*4) printf("Woops!!!\n");
02162       fExtraZ = new Int_t[indextra];
02163       memcpy(fExtraZ, extra, indextra*sizeof(Int_t));
02164    }   
02165    delete [] boundaries;   
02166    delete [] index;
02167    delete [] temp;
02168    delete [] ind;
02169    delete [] extra;
02170    delete [] extra_left;
02171    delete [] extra_right;
02172 
02173    if ((!fPriority[0]) && (!fPriority[1]) && (!fPriority[2])) {
02174       SetInvalid();
02175       if (nd>1) Error("SortAll", "Volume %s: Cannot make slices on any axis", fVolume->GetName());
02176    } 
02177 }
02178 
02179 //_____________________________________________________________________________
02180 void TGeoVoxelFinder::Print(Option_t *) const
02181 {
02182 // Print the voxels.
02183    if (NeedRebuild()) {
02184       TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
02185       vox->Voxelize();
02186       fVolume->FindOverlaps();
02187    }   
02188    Int_t id, i;
02189    Int_t nd = fVolume->GetNdaughters();
02190    printf("Voxels for volume %s (nd=%i)\n", fVolume->GetName(), fVolume->GetNdaughters());
02191    printf("priority : x=%i y=%i z=%i\n", fPriority[0], fPriority[1], fPriority[2]);
02192 //   return;
02193    Int_t nextra;
02194    Int_t nbytes = 1+((fVolume->GetNdaughters()-1)>>3);
02195    UChar_t byte, bit;
02196    UChar_t *slice;
02197    printf("XXX\n");
02198    if (fPriority[0]==2) {
02199       for (id=0; id<fIbx; id++) {
02200          printf("%15.10f\n",fXb[id]);
02201          if (id == (fIbx-1)) break;
02202          printf("slice %i : %i\n", id, fNsliceX[id]);
02203          if (fNsliceX[id]) {
02204             slice = &fIndcX[fOBx[id]];
02205             for (i=0; i<nbytes; i++) {
02206                byte = slice[i];
02207                for (bit=0; bit<8; bit++) {
02208                   if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
02209                }
02210             }
02211             printf("\n");
02212          }         
02213          GetExtraX(id,kTRUE,nextra);
02214          printf("   extra_about_left  = %i\n", nextra); 
02215          GetExtraX(id,kFALSE,nextra);
02216          printf("   extra_about_right = %i\n", nextra); 
02217       }
02218    } else if (fPriority[0]==1) {
02219       printf("%15.10f\n",fXb[0]);
02220       for (id=0; id<nd; id++) printf(" %i ",id);
02221       printf("\n");
02222       printf("%15.10f\n",fXb[1]);
02223    }
02224    printf("YYY\n"); 
02225    if (fPriority[1]==2) { 
02226       for (id=0; id<fIby; id++) {
02227          printf("%15.10f\n", fYb[id]);
02228          if (id == (fIby-1)) break;
02229          printf("slice %i : %i\n", id, fNsliceY[id]);
02230          if (fNsliceY[id]) {
02231             slice = &fIndcY[fOBy[id]];
02232             for (i=0; i<nbytes; i++) {
02233                byte = slice[i];
02234                for (bit=0; bit<8; bit++) {
02235                   if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
02236                }
02237             }
02238          }         
02239          GetExtraY(id,kTRUE,nextra);
02240          printf("   extra_about_left  = %i\n", nextra); 
02241          GetExtraY(id,kFALSE,nextra);
02242          printf("   extra_about_right = %i\n", nextra); 
02243       }
02244    } else if (fPriority[1]==1) {
02245       printf("%15.10f\n",fYb[0]);
02246       for (id=0; id<nd; id++) printf(" %i ",id);
02247       printf("\n");
02248       printf("%15.10f\n",fYb[1]);
02249    }
02250 
02251    printf("ZZZ\n"); 
02252    if (fPriority[2]==2) { 
02253       for (id=0; id<fIbz; id++) {
02254          printf("%15.10f\n", fZb[id]);
02255          if (id == (fIbz-1)) break;
02256          printf("slice %i : %i\n", id, fNsliceZ[id]);
02257          if (fNsliceZ[id]) {
02258             slice = &fIndcZ[fOBz[id]];
02259             for (i=0; i<nbytes; i++) {
02260                byte = slice[i];
02261                for (bit=0; bit<8; bit++) {
02262                   if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
02263                }
02264             }
02265             printf("\n");
02266          }         
02267          GetExtraZ(id,kTRUE,nextra);
02268          printf("   extra_about_left  = %i\n", nextra); 
02269          GetExtraZ(id,kFALSE,nextra);
02270          printf("   extra_about_right = %i\n", nextra); 
02271       }
02272    } else if (fPriority[2]==1) {
02273       printf("%15.10f\n",fZb[0]);
02274       for (id=0; id<nd; id++) printf(" %i ",id);
02275       printf("\n");
02276       printf("%15.10f\n",fZb[1]);
02277    }
02278 }
02279 
02280 //_____________________________________________________________________________
02281 void TGeoVoxelFinder::PrintVoxelLimits(Double_t *point) const
02282 {
02283 // print the voxel containing point
02284    if (NeedRebuild()) {
02285       TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
02286       vox->Voxelize();
02287       fVolume->FindOverlaps();
02288    }   
02289    Int_t im=0;
02290    if (fPriority[0]) {
02291       im = TMath::BinarySearch(fIbx, fXb, point[0]);
02292       if ((im==-1) || (im==fIbx-1)) {
02293          printf("Voxel X limits: OUT\n");
02294       } else {
02295          printf("Voxel X limits: %g  %g\n", fXb[im], fXb[im+1]);
02296       }
02297    }
02298    if (fPriority[1]) {
02299       im = TMath::BinarySearch(fIby, fYb, point[1]);
02300       if ((im==-1) || (im==fIby-1)) {
02301          printf("Voxel Y limits: OUT\n");
02302       } else {
02303          printf("Voxel Y limits: %g  %g\n", fYb[im], fYb[im+1]);
02304       }
02305    }
02306    if (fPriority[2]) {
02307       im = TMath::BinarySearch(fIbz, fZb, point[2]);
02308       if ((im==-1) || (im==fIbz-1)) {
02309          printf("Voxel Z limits: OUT\n");
02310       } else {
02311          printf("Voxel Z limits: %g  %g\n", fZb[im], fZb[im+1]);
02312       }
02313    }
02314 }
02315 //_____________________________________________________________________________
02316 void TGeoVoxelFinder::Voxelize(Option_t * /*option*/)
02317 {
02318 // Voxelize attached volume according to option
02319    // If the volume is an assembly, make sure the bbox is computed.
02320    if (fVolume->IsAssembly()) fVolume->GetShape()->ComputeBBox();
02321    Int_t nd = fVolume->GetNdaughters();
02322    TGeoVolume *vd;
02323    for (Int_t i=0; i<nd; i++) {
02324       vd = fVolume->GetNode(i)->GetVolume();
02325       if (vd->IsAssembly()) vd->GetShape()->ComputeBBox();
02326    }   
02327    BuildVoxelLimits();
02328    SortAll();
02329    SetNeedRebuild(kFALSE);
02330 }
02331 //_____________________________________________________________________________
02332 void TGeoVoxelFinder::Streamer(TBuffer &R__b)
02333 {
02334    // Stream an object of class TGeoVoxelFinder.
02335    if (R__b.IsReading()) {
02336       UInt_t R__s, R__c;
02337       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
02338       if (R__v > 2) {
02339          R__b.ReadClassBuffer(TGeoVoxelFinder::Class(), this, R__v, R__s, R__c);
02340          return;
02341       }
02342       // Process old versions of the voxel finder. Just read the data
02343       // from the buffer in a temp variable then mark voxels as garbage.
02344       UChar_t *dummy = new UChar_t[R__c-2];
02345       R__b.ReadFastArray(dummy, R__c-2);
02346       delete [] dummy;
02347       SetInvalid(kTRUE);
02348    } else {
02349       R__b.WriteClassBuffer(TGeoVoxelFinder::Class(), this);
02350    }
02351 }

Generated on Tue Jul 5 14:12:58 2011 for ROOT_528-00b_version by  doxygen 1.5.1