Logo ROOT   6.08/07
Reference Guide
TGeoVoxelFinder.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 04/02/02
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TGeoVoxelFinder
13 \ingroup Geometry_classes
14 
15 Finder class handling voxels.
16 
17 Full description with examples and pictures
18 
19 \image html geom_t_finder.png
20 \image html geom_t_voxelfind.png
21 \image html geom_t_voxtree.png
22 */
23 
24 #include "TGeoVoxelFinder.h"
25 
26 #include "TBuffer.h"
27 #include "TObject.h"
28 #include "TMath.h"
29 #include "TThread.h"
30 #include "TGeoMatrix.h"
31 #include "TGeoBBox.h"
32 #include "TGeoNode.h"
33 #include "TGeoManager.h"
34 #include "TGeoStateInfo.h"
35 
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// Default constructor
40 
42 {
43  fVolume = 0;
44  fNboxes = 0;
45  fIbx = 0;
46  fIby = 0;
47  fIbz = 0;
48  fNox = 0;
49  fNoy = 0;
50  fNoz = 0;
51  fNex = 0;
52  fNey = 0;
53  fNez = 0;
54  fNx = 0;
55  fNy = 0;
56  fNz = 0;
57  fBoxes = 0;
58  fXb = 0;
59  fYb = 0;
60  fZb = 0;
61  fOBx = 0;
62  fOBy = 0;
63  fOBz = 0;
64  fOEx = 0;
65  fOEy = 0;
66  fOEz = 0;
67  fIndcX = 0;
68  fIndcY = 0;
69  fIndcZ = 0;
70  fExtraX = 0;
71  fExtraY = 0;
72  fExtraZ = 0;
73  fNsliceX = 0;
74  fNsliceY = 0;
75  fNsliceZ = 0;
76  memset(fPriority, 0, 3*sizeof(Int_t));
77  SetInvalid(kFALSE);
78 }
79 ////////////////////////////////////////////////////////////////////////////////
80 /// Default constructor
81 
83 {
84  if (!vol) {
85  Fatal("TGeoVoxelFinder", "Null pointer for volume");
86  return; // To make code checkers happy
87  }
88  fVolume = vol;
90  fNboxes = 0;
91  fIbx = 0;
92  fIby = 0;
93  fIbz = 0;
94  fNox = 0;
95  fNoy = 0;
96  fNoz = 0;
97  fNex = 0;
98  fNey = 0;
99  fNez = 0;
100  fNx = 0;
101  fNy = 0;
102  fNz = 0;
103  fBoxes = 0;
104  fXb = 0;
105  fYb = 0;
106  fZb = 0;
107  fOBx = 0;
108  fOBy = 0;
109  fOBz = 0;
110  fOEx = 0;
111  fOEy = 0;
112  fOEz = 0;
113  fIndcX = 0;
114  fIndcY = 0;
115  fIndcZ = 0;
116  fExtraX = 0;
117  fExtraY = 0;
118  fExtraZ = 0;
119  fNsliceX = 0;
120  fNsliceY = 0;
121  fNsliceZ = 0;
122  memset(fPriority, 0, 3*sizeof(Int_t));
123  SetNeedRebuild();
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 ///copy constructor
128 
130  TObject(vf),
131  fVolume(vf.fVolume),
132  fIbx(vf.fIbx),
133  fIby(vf.fIby),
134  fIbz(vf.fIbz),
135  fNboxes(vf.fNboxes),
136  fNox(vf.fNox),
137  fNoy(vf.fNoy),
138  fNoz(vf.fNoz),
139  fNex(vf.fNex),
140  fNey(vf.fNey),
141  fNez(vf.fNez),
142  fNx(vf.fNx),
143  fNy(vf.fNy),
144  fNz(vf.fNz),
145  fBoxes(vf.fBoxes),
146  fXb(vf.fXb),
147  fYb(vf.fYb),
148  fZb(vf.fZb),
149  fOBx(vf.fOBx),
150  fOBy(vf.fOBy),
151  fOBz(vf.fOBz),
152  fOEx(vf.fOEx),
153  fOEy(vf.fOEy),
154  fOEz(vf.fOEz),
155  fExtraX(vf.fExtraX),
156  fExtraY(vf.fExtraY),
157  fExtraZ(vf.fExtraZ),
158  fNsliceX(vf.fNsliceX),
159  fNsliceY(vf.fNsliceY),
160  fNsliceZ(vf.fNsliceZ),
161  fIndcX(vf.fIndcX),
162  fIndcY(vf.fIndcY),
163  fIndcZ(vf.fIndcZ)
164 {
165  for(Int_t i=0; i<3; i++) {
166  fPriority[i]=vf.fPriority[i];
167  }
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 ///assignment operator
172 
174 {
175  if(this!=&vf) {
176  TObject::operator=(vf);
177  fVolume=vf.fVolume;
178  fIbx=vf.fIbx;
179  fIby=vf.fIby;
180  fIbz=vf.fIbz;
181  fNboxes=vf.fNboxes;
182  fNox=vf.fNox;
183  fNoy=vf.fNoy;
184  fNoz=vf.fNoz;
185  fNex=vf.fNex;
186  fNey=vf.fNey;
187  fNez=vf.fNez;
188  fNx=vf.fNx;
189  fNy=vf.fNy;
190  fNz=vf.fNz;
191  for(Int_t i=0; i<3; i++) {
192  fPriority[i]=vf.fPriority[i];
193  }
194  fBoxes=vf.fBoxes;
195  fXb=vf.fXb;
196  fYb=vf.fYb;
197  fZb=vf.fZb;
198  fOBx=vf.fOBx;
199  fOBy=vf.fOBy;
200  fOBz=vf.fOBz;
201  fOEx=vf.fOEx;
202  fOEy=vf.fOEy;
203  fOEz=vf.fOEz;
204  fNsliceX=vf.fNsliceX;
205  fNsliceY=vf.fNsliceY;
206  fNsliceZ=vf.fNsliceZ;
207  fIndcX=vf.fIndcX;
208  fIndcY=vf.fIndcY;
209  fIndcZ=vf.fIndcZ;
210  fExtraX=vf.fExtraX;
211  fExtraY=vf.fExtraY;
212  fExtraZ=vf.fExtraZ;
213  }
214  return *this;
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 /// Destructor
219 
221 {
222  if (fOBx) delete [] fOBx;
223  if (fOBy) delete [] fOBy;
224  if (fOBz) delete [] fOBz;
225  if (fOEx) delete [] fOEx;
226  if (fOEy) delete [] fOEy;
227  if (fOEz) delete [] fOEz;
228 // printf("OBx OBy OBz...\n");
229  if (fBoxes) delete [] fBoxes;
230 // printf("boxes...\n");
231  if (fXb) delete [] fXb;
232  if (fYb) delete [] fYb;
233  if (fZb) delete [] fZb;
234 // printf("Xb Yb Zb...\n");
235  if (fNsliceX) delete [] fNsliceX;
236  if (fNsliceY) delete [] fNsliceY;
237  if (fNsliceZ) delete [] fNsliceZ;
238  if (fIndcX) delete [] fIndcX;
239  if (fIndcY) delete [] fIndcY;
240  if (fIndcZ) delete [] fIndcZ;
241  if (fExtraX) delete [] fExtraX;
242  if (fExtraY) delete [] fExtraY;
243  if (fExtraZ) delete [] fExtraZ;
244 // printf("IndX IndY IndZ...\n");
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 
250 {
251  return td.fVoxNcandidates;
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 
257 {
258  nelem = td.fVoxNcandidates;
259  return td.fVoxCheckList;
260 }
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 /// build the array of bounding boxes of the nodes inside
264 
266 {
267  Int_t nd = fVolume->GetNdaughters();
268  if (!nd) return;
269  Int_t id;
270  TGeoNode *node;
271  if (fBoxes) delete [] fBoxes;
272  fNboxes = 6*nd;
273  fBoxes = new Double_t[fNboxes];
274  Double_t vert[24] = {0};
275  Double_t pt[3] = {0};
276  Double_t xyz[6] = {0};
277 // printf("boundaries for %s :\n", GetName());
278  TGeoBBox *box = 0;
279  for (id=0; id<nd; id++) {
280  node = fVolume->GetNode(id);
281 // if (!strcmp(node->ClassName(), "TGeoNodeOffset") continue;
282  box = (TGeoBBox*)node->GetVolume()->GetShape();
283  box->SetBoxPoints(&vert[0]);
284  for (Int_t point=0; point<8; point++) {
285  DaughterToMother(id, &vert[3*point], &pt[0]);
286  if (!point) {
287  xyz[0] = xyz[1] = pt[0];
288  xyz[2] = xyz[3] = pt[1];
289  xyz[4] = xyz[5] = pt[2];
290  continue;
291  }
292  for (Int_t j=0; j<3; j++) {
293  if (pt[j] < xyz[2*j]) xyz[2*j]=pt[j];
294  if (pt[j] > xyz[2*j+1]) xyz[2*j+1]=pt[j];
295  }
296  }
297  fBoxes[6*id] = 0.5*(xyz[1]-xyz[0]); // dX
298  fBoxes[6*id+1] = 0.5*(xyz[3]-xyz[2]); // dY
299  fBoxes[6*id+2] = 0.5*(xyz[5]-xyz[4]); // dZ
300  fBoxes[6*id+3] = 0.5*(xyz[0]+xyz[1]); // Ox
301  fBoxes[6*id+4] = 0.5*(xyz[2]+xyz[3]); // Oy
302  fBoxes[6*id+5] = 0.5*(xyz[4]+xyz[5]); // Oz
303  }
304 }
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 /// convert a point from the local reference system of node id to reference
308 /// system of mother volume
309 
310 void TGeoVoxelFinder::DaughterToMother(Int_t id, const Double_t *local, Double_t *master) const
311 {
312  TGeoMatrix *mat = fVolume->GetNode(id)->GetMatrix();
313  if (!mat) memcpy(master,local,3*sizeof(Double_t));
314  else mat->LocalToMaster(local, master);
315 }
316 ////////////////////////////////////////////////////////////////////////////////
317 /// Computes squared distance from POINT to the voxel(s) containing node INODE. Returns 0
318 /// if POINT inside voxel(s).
319 
320 Bool_t TGeoVoxelFinder::IsSafeVoxel(const Double_t *point, Int_t inode, Double_t minsafe) const
321 {
322  if (NeedRebuild()) {
323  TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
324  vox->Voxelize();
326  }
327  Double_t dxyz, minsafe2=minsafe*minsafe;
328  Int_t ist = 6*inode;
329  Int_t i;
330  Double_t rsq = 0;
331  for (i=0; i<3; i++) {
332  dxyz = TMath::Abs(point[i]-fBoxes[ist+i+3])-fBoxes[ist+i];
333  if (dxyz>-1E-6) rsq+=dxyz*dxyz;
334  if (rsq > minsafe2*(1.+TGeoShape::Tolerance())) return kTRUE;
335  }
336  return kFALSE;
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// Compute voxelization efficiency.
341 
343 {
344  printf("Voxelization efficiency for %s\n", fVolume->GetName());
345  if (NeedRebuild()) {
346  Voxelize();
348  }
350  Double_t eff = 0;
351  Double_t effslice = 0;
352  Int_t id;
353  if (fPriority[0]) {
354  for (id=0; id<fIbx-1; id++) { // loop on boundaries
355  effslice += fNsliceX[id];
356  }
357  if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
358  else printf("Woops : slice X\n");
359  }
360  printf("X efficiency : %g\n", effslice);
361  eff += effslice;
362  effslice = 0;
363  if (fPriority[1]) {
364  for (id=0; id<fIby-1; id++) { // loop on boundaries
365  effslice += fNsliceY[id];
366  }
367  if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
368  else printf("Woops : slice X\n");
369  }
370  printf("Y efficiency : %g\n", effslice);
371  eff += effslice;
372  effslice = 0;
373  if (fPriority[2]) {
374  for (id=0; id<fIbz-1; id++) { // loop on boundaries
375  effslice += fNsliceZ[id];
376  }
377  if (!TGeoShape::IsSameWithinTolerance(effslice,0)) effslice = nd/effslice;
378  else printf("Woops : slice X\n");
379  }
380  printf("Z efficiency : %g\n", effslice);
381  eff += effslice;
382  eff /= 3.;
383  printf("Total efficiency : %g\n", eff);
384  return eff;
385 }
386 ////////////////////////////////////////////////////////////////////////////////
387 /// create the list of nodes for which the bboxes overlap with inode's bbox
388 
390 {
391  if (!fBoxes) return;
392  Double_t xmin, xmax, ymin, ymax, zmin, zmax;
393  Double_t xmin1, xmax1, ymin1, ymax1, zmin1, zmax1;
394  Double_t ddx1, ddx2;
395  Int_t nd = fVolume->GetNdaughters();
396  Int_t *ovlps = 0;
397  Int_t *otmp = new Int_t[nd-1];
398  Int_t novlp = 0;
399  TGeoNode *node = fVolume->GetNode(inode);
400  xmin = fBoxes[6*inode+3] - fBoxes[6*inode];
401  xmax = fBoxes[6*inode+3] + fBoxes[6*inode];
402  ymin = fBoxes[6*inode+4] - fBoxes[6*inode+1];
403  ymax = fBoxes[6*inode+4] + fBoxes[6*inode+1];
404  zmin = fBoxes[6*inode+5] - fBoxes[6*inode+2];
405  zmax = fBoxes[6*inode+5] + fBoxes[6*inode+2];
406  // loop on brothers
407  for (Int_t ib=0; ib<nd; ib++) {
408  if (ib == inode) continue; // everyone overlaps with itself
409  xmin1 = fBoxes[6*ib+3] - fBoxes[6*ib];
410  xmax1 = fBoxes[6*ib+3] + fBoxes[6*ib];
411  ymin1 = fBoxes[6*ib+4] - fBoxes[6*ib+1];
412  ymax1 = fBoxes[6*ib+4] + fBoxes[6*ib+1];
413  zmin1 = fBoxes[6*ib+5] - fBoxes[6*ib+2];
414  zmax1 = fBoxes[6*ib+5] + fBoxes[6*ib+2];
415 
416  ddx1 = xmax-xmin1;
417  ddx2 = xmax1-xmin;
418  if (ddx1*ddx2 <= 0.) continue;
419  ddx1 = ymax-ymin1;
420  ddx2 = ymax1-ymin;
421  if (ddx1*ddx2 <= 0.) continue;
422  ddx1 = zmax-zmin1;
423  ddx2 = zmax1-zmin;
424  if (ddx1*ddx2 <= 0.) continue;
425  otmp[novlp++] = ib;
426  }
427  if (!novlp) {
428  delete [] otmp;
429  node->SetOverlaps(ovlps, 0);
430  return;
431  }
432  ovlps = new Int_t[novlp];
433  memcpy(ovlps, otmp, novlp*sizeof(Int_t));
434  delete [] otmp;
435  node->SetOverlaps(ovlps, novlp);
436 }
437 
438 ////////////////////////////////////////////////////////////////////////////////
439 /// Get indices for current slices on x, y, z
440 
442 {
443  td.fVoxSlices[0] = -2; // -2 means 'all daughters in slice'
444  td.fVoxSlices[1] = -2;
445  td.fVoxSlices[2] = -2;
446  Bool_t flag=kTRUE;
447  if (fPriority[0]) {
448  td.fVoxSlices[0] = TMath::BinarySearch(fIbx, fXb, point[0]);
449  if ((td.fVoxSlices[0]<0) || (td.fVoxSlices[0]>=fIbx-1)) {
450  // outside slices
451  flag=kFALSE;
452  } else {
453  if (fPriority[0]==2) {
454  // nothing in current slice
455  if (!fNsliceX[td.fVoxSlices[0]]) flag = kFALSE;
456  }
457  }
458  }
459  if (fPriority[1]) {
460  td.fVoxSlices[1] = TMath::BinarySearch(fIby, fYb, point[1]);
461  if ((td.fVoxSlices[1]<0) || (td.fVoxSlices[1]>=fIby-1)) {
462  // outside slices
463  flag=kFALSE;
464  } else {
465  if (fPriority[1]==2) {
466  // nothing in current slice
467  if (!fNsliceY[td.fVoxSlices[1]]) flag = kFALSE;
468  }
469  }
470  }
471  if (fPriority[2]) {
472  td.fVoxSlices[2] = TMath::BinarySearch(fIbz, fZb, point[2]);
473  if ((td.fVoxSlices[2]<0) || (td.fVoxSlices[2]>=fIbz-1)) return kFALSE;
474  if (fPriority[2]==2) {
475  // nothing in current slice
476  if (!fNsliceZ[td.fVoxSlices[2]]) return kFALSE;
477  }
478  }
479  return flag;
480 }
481 
482 ////////////////////////////////////////////////////////////////////////////////
483 /// Return the list of extra candidates in a given X slice compared to
484 /// another (left or right)
485 
486 Int_t *TGeoVoxelFinder::GetExtraX(Int_t islice, Bool_t left, Int_t &nextra) const
487 {
488  Int_t *list = 0;
489  nextra = 0;
490  if (fPriority[0]!=2) return list;
491  if (left) {
492  nextra = fExtraX[fOEx[islice]];
493  list = &fExtraX[fOEx[islice]+2];
494  } else {
495  nextra = fExtraX[fOEx[islice]+1];
496  list = &fExtraX[fOEx[islice]+2+fExtraX[fOEx[islice]]];
497  }
498  return list;
499 }
500 
501 ////////////////////////////////////////////////////////////////////////////////
502 /// Return the list of extra candidates in a given Y slice compared to
503 /// another (left or right)
504 
505 Int_t *TGeoVoxelFinder::GetExtraY(Int_t islice, Bool_t left, Int_t &nextra) const
506 {
507  Int_t *list = 0;
508  nextra = 0;
509  if (fPriority[1]!=2) return list;
510  if (left) {
511  nextra = fExtraY[fOEy[islice]];
512  list = &fExtraY[fOEy[islice]+2];
513  } else {
514  nextra = fExtraY[fOEy[islice]+1];
515  list = &fExtraY[fOEy[islice]+2+fExtraY[fOEy[islice]]];
516  }
517  return list;
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// Return the list of extra candidates in a given Z slice compared to
522 /// another (left or right)
523 
524 Int_t *TGeoVoxelFinder::GetExtraZ(Int_t islice, Bool_t left, Int_t &nextra) const
525 {
526  Int_t *list = 0;
527  nextra = 0;
528  if (fPriority[2]!=2) return list;
529  if (left) {
530  nextra = fExtraZ[fOEz[islice]];
531  list = &fExtraZ[fOEz[islice]+2];
532  } else {
533  nextra = fExtraZ[fOEz[islice]+1];
534  list = &fExtraZ[fOEz[islice]+2+fExtraZ[fOEz[islice]]];
535  }
536  return list;
537 }
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 /// Get extra candidates that are not contained in current check list
541 
543 {
544  td.fVoxNcandidates = 0;
545  Int_t icand;
546  UInt_t bitnumber, loc;
547  UChar_t bit, byte;
548  for (icand=0; icand<ncheck; icand++) {
549  bitnumber = (UInt_t)list[icand];
550  loc = bitnumber>>3;
551  bit = bitnumber%8;
552  byte = (~td.fVoxBits1[loc]) & (1<<bit);
553  if (byte) td.fVoxCheckList[td.fVoxNcandidates++]=list[icand];
554  }
555  ncheck = td.fVoxNcandidates;
556  return td.fVoxCheckList;
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// Get extra candidates that are contained in array1 but not in current check list
561 
563 {
564  td.fVoxNcandidates = 0;
565  Int_t icand;
566  UInt_t bitnumber, loc;
567  UChar_t bit, byte;
568  for (icand=0; icand<ncheck; icand++) {
569  bitnumber = (UInt_t)list[icand];
570  loc = bitnumber>>3;
571  bit = bitnumber%8;
572  byte = (~td.fVoxBits1[loc]) & array1[loc] & (1<<bit);
573  if (byte) td.fVoxCheckList[td.fVoxNcandidates++]=list[icand];
574  }
575  ncheck = td.fVoxNcandidates;
576  return td.fVoxCheckList;
577 }
578 
579 ////////////////////////////////////////////////////////////////////////////////
580 /// Get extra candidates that are contained in array1 but not in current check list
581 
582 Int_t *TGeoVoxelFinder::GetValidExtra(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2, Int_t *list, Int_t &ncheck, TGeoStateInfo &td)
583 {
584  td.fVoxNcandidates = 0;
585  Int_t icand;
586  UInt_t bitnumber, loc;
587  UChar_t bit, byte;
588  for (icand=0; icand<ncheck; icand++) {
589  bitnumber = (UInt_t)list[icand];
590  loc = bitnumber>>3;
591  bit = bitnumber%8;
592  byte = (~td.fVoxBits1[loc]) & array1[loc] & array2[loc] & (1<<bit);
593  if (byte) td.fVoxCheckList[td.fVoxNcandidates++]=list[icand];
594  }
595  ncheck = td.fVoxNcandidates;
596  return td.fVoxCheckList;
597 }
598 
599 ////////////////////////////////////////////////////////////////////////////////
600 /// Returns list of new candidates in next voxel. If NULL, nowhere to
601 /// go next.
602 
604 {
605  if (NeedRebuild()) {
606  Voxelize();
608  }
609  ncheck = 0;
610  if (td.fVoxLimits[0]<0) return 0;
611  if (td.fVoxLimits[1]<0) return 0;
612  if (td.fVoxLimits[2]<0) return 0;
613  Int_t dind[3]; // new slices
614  //---> start from old slices
615  memcpy(&dind[0], &td.fVoxSlices[0], 3*sizeof(Int_t));
616  Double_t dmin[3]; // distances to get to next X,Y, Z slices.
617  dmin[0] = dmin[1] = dmin[2] = TGeoShape::Big();
618  //---> max. possible step to be considered
620 // printf("1- maxstep=%g\n", maxstep);
621  Bool_t isXlimit=kFALSE, isYlimit=kFALSE, isZlimit=kFALSE;
622  Bool_t isForcedX=kFALSE, isForcedY=kFALSE, isForcedZ=kFALSE;
623  Double_t dforced[3];
624  dforced[0] = dforced[1] = dforced[2] = TGeoShape::Big();
625  Int_t iforced = 0;
626  //
627  //---> work on X
628  if (fPriority[0] && td.fVoxInc[0]) {
629  //---> increment/decrement slice
630  dind[0] += td.fVoxInc[0];
631  if (td.fVoxInc[0]==1) {
632  if (dind[0]<0 || dind[0]>fIbx-1) return 0; // outside range
633  dmin[0] = (fXb[dind[0]]-point[0])*td.fVoxInvdir[0];
634  } else {
635  if (td.fVoxSlices[0]<0 || td.fVoxSlices[0]>fIbx-1) return 0; // outside range
636  dmin[0] = (fXb[td.fVoxSlices[0]]-point[0])*td.fVoxInvdir[0];
637  }
638  isXlimit = (dmin[0]>maxstep)?kTRUE:kFALSE;
639 // printf("---> X : priority=%i, slice=%i/%i inc=%i\n",
640 // fPriority[0], td.fVoxSlices[0], fIbx-2, td.fVoxInc[0]);
641 // printf("2- step to next X (%i) = %g\n", (Int_t)isXlimit, dmin[0]);
642  //---> check if propagation to next slice on this axis is forced
643  if ((td.fVoxSlices[0]==-1) || (td.fVoxSlices[0]==fIbx-1)) {
644  isForcedX = kTRUE;
645  dforced[0] = dmin[0];
646  iforced++;
647 // printf(" FORCED 1\n");
648  if (isXlimit) return 0;
649  } else {
650  if (fPriority[0]==2) {
651  // if no candidates in current slice, force next slice
652  if (fNsliceX[td.fVoxSlices[0]]==0) {
653  isForcedX = kTRUE;
654  dforced[0] = dmin[0];
655  iforced++;
656 // printf(" FORCED 2\n");
657  if (isXlimit) return 0;
658  }
659  }
660  }
661  } else {
662  // no slices on this axis -> bounding box limit
663 // printf(" No slice on X\n");
664  dmin[0] = td.fVoxLimits[0];
665  isXlimit = kTRUE;
666  }
667  //---> work on Y
668  if (fPriority[1] && td.fVoxInc[1]) {
669  //---> increment/decrement slice
670  dind[1] += td.fVoxInc[1];
671  if (td.fVoxInc[1]==1) {
672  if (dind[1]<0 || dind[1]>fIby-1) return 0; // outside range
673  dmin[1] = (fYb[dind[1]]-point[1])*td.fVoxInvdir[1];
674  } else {
675  if (td.fVoxSlices[1]<0 || td.fVoxSlices[1]>fIby-1) return 0; // outside range
676  dmin[1] = (fYb[td.fVoxSlices[1]]-point[1])*td.fVoxInvdir[1];
677  }
678  isYlimit = (dmin[1]>maxstep)?kTRUE:kFALSE;
679 // printf("---> Y : priority=%i, slice=%i/%i inc=%i\n",
680 // fPriority[1], td.fVoxSlices[1], fIby-2, td.fVoxInc[1]);
681 // printf("3- step to next Y (%i) = %g\n", (Int_t)isYlimit, dmin[1]);
682 
683  //---> check if propagation to next slice on this axis is forced
684  if ((td.fVoxSlices[1]==-1) || (td.fVoxSlices[1]==fIby-1)) {
685  isForcedY = kTRUE;
686  dforced[1] = dmin[1];
687  iforced++;
688 // printf(" FORCED 1\n");
689  if (isYlimit) return 0;
690  } else {
691  if (fPriority[1]==2) {
692  // if no candidates in current slice, force next slice
693  if (fNsliceY[td.fVoxSlices[1]]==0) {
694  isForcedY = kTRUE;
695  dforced[1] = dmin[1];
696  iforced++;
697 // printf(" FORCED 2\n");
698  if (isYlimit) return 0;
699  }
700  }
701  }
702  } else {
703  // no slices on this axis -> bounding box limit
704 // printf(" No slice on Y\n");
705  dmin[1] = td.fVoxLimits[1];
706  isYlimit = kTRUE;
707  }
708  //---> work on Z
709  if (fPriority[2] && td.fVoxInc[2]) {
710  //---> increment/decrement slice
711  dind[2] += td.fVoxInc[2];
712  if (td.fVoxInc[2]==1) {
713  if (dind[2]<0 || dind[2]>fIbz-1) return 0; // outside range
714  dmin[2] = (fZb[dind[2]]-point[2])*td.fVoxInvdir[2];
715  } else {
716  if (td.fVoxSlices[2]<0 || td.fVoxSlices[2]>fIbz-1) return 0; // outside range
717  dmin[2] = (fZb[td.fVoxSlices[2]]-point[2])*td.fVoxInvdir[2];
718  }
719  isZlimit = (dmin[2]>maxstep)?kTRUE:kFALSE;
720 // printf("---> Z : priority=%i, slice=%i/%i inc=%i\n",
721 // fPriority[2], td.fVoxSlices[2], fIbz-2, td.fVoxInc[2]);
722 // printf("4- step to next Z (%i) = %g\n", (Int_t)isZlimit, dmin[2]);
723 
724  //---> check if propagation to next slice on this axis is forced
725  if ((td.fVoxSlices[2]==-1) || (td.fVoxSlices[2]==fIbz-1)) {
726  isForcedZ = kTRUE;
727  dforced[2] = dmin[2];
728  iforced++;
729 // printf(" FORCED 1\n");
730  if (isZlimit) return 0;
731  } else {
732  if (fPriority[2]==2) {
733  // if no candidates in current slice, force next slice
734  if (fNsliceZ[td.fVoxSlices[2]]==0) {
735  isForcedZ = kTRUE;
736  dforced[2] = dmin[2];
737  iforced++;
738 // printf(" FORCED 2\n");
739  if (isZlimit) return 0;
740  }
741  }
742  }
743  } else {
744  // no slices on this axis -> bounding box limit
745 // printf(" No slice on Z\n");
746  dmin[2] = td.fVoxLimits[2];
747  isZlimit = kTRUE;
748  }
749  //---> We are done with checking. See which is the closest slice.
750  // First check if some slice is forced
751 
752  Double_t dslice = 0;
753  Int_t islice = 0;
754  if (iforced) {
755  // some slice is forced
756  if (isForcedX) {
757  // X forced
758  dslice = dforced[0];
759  islice = 0;
760  if (isForcedY) {
761  // X+Y forced
762  if (dforced[1]>dslice) {
763  dslice = dforced[1];
764  islice = 1;
765  }
766  if (isForcedZ) {
767  // X+Y+Z forced
768  if (dforced[2]>dslice) {
769  dslice = dforced[2];
770  islice = 2;
771  }
772  }
773  } else {
774  // X forced
775  if (isForcedZ) {
776  // X+Z forced
777  if (dforced[2]>dslice) {
778  dslice = dforced[2];
779  islice = 2;
780  }
781  }
782  }
783  } else {
784  if (isForcedY) {
785  // Y forced
786  dslice = dforced[1];
787  islice = 1;
788  if (isForcedZ) {
789  // Y+Z forced
790  if (dforced[2]>dslice) {
791  dslice = dforced[2];
792  islice = 2;
793  }
794  }
795  } else {
796  // Z forced
797  dslice = dforced[2];
798  islice = 2;
799  }
800  }
801  } else {
802  // Nothing forced -> get minimum distance
803  islice = TMath::LocMin(3, dmin);
804  dslice = dmin[islice];
805  if (dslice>=maxstep) {
806 // printf("DSLICE > MAXSTEP -> EXIT\n");
807  return 0;
808  }
809  }
810 // printf("5- islicenext=%i DSLICE=%g\n", islice, dslice);
811  Double_t xptnew;
812  Int_t *new_list; // list of new candidates
813  UChar_t *slice1 = 0;
814  UChar_t *slice2 = 0;
815  Int_t ndd[2] = {0,0};
816  Int_t islices = 0;
817  Bool_t left;
818  switch (islice) {
819  case 0:
820  if (isXlimit) return 0;
821  // increment/decrement X slice
822  td.fVoxSlices[0]=dind[0];
823  if (iforced) {
824  // we have to recompute Y and Z slices
825  if (dslice>td.fVoxLimits[1]) return 0;
826  if (dslice>td.fVoxLimits[2]) return 0;
827  if ((dslice>dmin[1]) && td.fVoxInc[1]) {
828  xptnew = point[1]+dslice/td.fVoxInvdir[1];
829  // printf(" recomputing Y slice, pos=%g\n", xptnew);
830  while (1) {
831  td.fVoxSlices[1] += td.fVoxInc[1];
832  if (td.fVoxInc[1]==1) {
833  if (td.fVoxSlices[1]<-1 || td.fVoxSlices[1]>fIby-2) break; // outside range
834  if (fYb[td.fVoxSlices[1]+1]>=xptnew) break;
835  } else {
836  if (td.fVoxSlices[1]<0 || td.fVoxSlices[1]>fIby-1) break; // outside range
837  if (fYb[td.fVoxSlices[1]]<= xptnew) break;
838  }
839  }
840  // printf(" %i/%i\n", td.fVoxSlices[1], fIby-2);
841  }
842  if ((dslice>dmin[2]) && td.fVoxInc[2]) {
843  xptnew = point[2]+dslice/td.fVoxInvdir[2];
844  // printf(" recomputing Z slice, pos=%g\n", xptnew);
845  while (1) {
846  td.fVoxSlices[2] += td.fVoxInc[2];
847  if (td.fVoxInc[2]==1) {
848  if (td.fVoxSlices[2]<-1 || td.fVoxSlices[2]>fIbz-2) break; // outside range
849  if (fZb[td.fVoxSlices[2]+1]>=xptnew) break;
850  } else {
851  if (td.fVoxSlices[2]<0 || td.fVoxSlices[2]>fIbz-1) break; // outside range
852  if (fZb[td.fVoxSlices[2]]<= xptnew) break;
853  }
854  }
855  // printf(" %i/%i\n", td.fVoxSlices[2], fIbz-2);
856  }
857  }
858  // new indices are set -> Get new candidates
859  if (fPriority[0]==1) {
860  // we are entering the unique slice on this axis
861  //---> intersect and store Y and Z
862  if (fPriority[1]==2) {
863  if (td.fVoxSlices[1]<0 || td.fVoxSlices[1]>=fIby-1) return td.fVoxCheckList; // outside range
864  ndd[0] = fNsliceY[td.fVoxSlices[1]];
865  if (!ndd[0]) return td.fVoxCheckList;
866  slice1 = &fIndcY[fOBy[td.fVoxSlices[1]]];
867  islices++;
868  }
869  if (fPriority[2]==2) {
870  if (td.fVoxSlices[2]<0 || td.fVoxSlices[2]>=fIbz-1) return td.fVoxCheckList; // outside range
871  ndd[1] = fNsliceZ[td.fVoxSlices[2]];
872  if (!ndd[1]) return td.fVoxCheckList;
873  islices++;
874  if (slice1) {
875  slice2 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
876  } else {
877  slice1 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
878  ndd[0] = ndd[1];
879  }
880  }
881  if (islices<=1) {
882  IntersectAndStore(ndd[0], slice1, td);
883  } else {
884  IntersectAndStore(ndd[0], slice1, ndd[1], slice2, td);
885  }
886  ncheck = td.fVoxNcandidates;
887  return td.fVoxCheckList;
888  }
889  // We got into a new slice -> Get only new candidates
890  left = (td.fVoxInc[0]>0)?kTRUE:kFALSE;
891  new_list = GetExtraX(td.fVoxSlices[0], left, ncheck);
892 // printf(" New list on X : %i new candidates\n", ncheck);
893  if (!ncheck) return td.fVoxCheckList;
894  if (fPriority[1]==2) {
895  if (td.fVoxSlices[1]<0 || td.fVoxSlices[1]>=fIby-1) {
896  ncheck = 0;
897  return td.fVoxCheckList; // outside range
898  }
899  ndd[0] = fNsliceY[td.fVoxSlices[1]];
900  if (!ndd[0]) {
901  ncheck = 0;
902  return td.fVoxCheckList;
903  }
904  slice1 = &fIndcY[fOBy[td.fVoxSlices[1]]];
905  islices++;
906  }
907  if (fPriority[2]==2) {
908  if (td.fVoxSlices[2]<0 || td.fVoxSlices[2]>=fIbz-1) {
909  ncheck = 0;
910  return td.fVoxCheckList; // outside range
911  }
912  ndd[1] = fNsliceZ[td.fVoxSlices[2]];
913  if (!ndd[1]) {
914  ncheck = 0;
915  return td.fVoxCheckList;
916  }
917  islices++;
918  if (slice1) {
919  slice2 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
920  } else {
921  slice1 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
922  ndd[0] = ndd[1];
923  }
924  }
925  if (!islices) return GetValidExtra(new_list, ncheck, td);
926  if (islices==1) {
927  return GetValidExtra(ndd[0], slice1, new_list, ncheck,td);
928  } else {
929  return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck, td);
930  }
931  case 1:
932  if (isYlimit) return 0;
933  // increment/decrement Y slice
934  td.fVoxSlices[1]=dind[1];
935  if (iforced) {
936  // we have to recompute X and Z slices
937  if (dslice>td.fVoxLimits[0]) return 0;
938  if (dslice>td.fVoxLimits[2]) return 0;
939  if ((dslice>dmin[0]) && td.fVoxInc[0]) {
940  xptnew = point[0]+dslice/td.fVoxInvdir[0];
941 // printf(" recomputing X slice, pos=%g\n", xptnew);
942  while (1) {
943  td.fVoxSlices[0] += td.fVoxInc[0];
944  if (td.fVoxInc[0]==1) {
945  if (td.fVoxSlices[0]<-1 || td.fVoxSlices[0]>fIbx-2) break; // outside range
946  if (fXb[td.fVoxSlices[0]+1]>=xptnew) break;
947  } else {
948  if (td.fVoxSlices[0]<0 || td.fVoxSlices[0]>fIbx-1) break; // outside range
949  if (fXb[td.fVoxSlices[0]]<= xptnew) break;
950  }
951  }
952 // printf(" %i/%i\n", td.fVoxSlices[0], fIbx-2);
953  }
954  if ((dslice>dmin[2]) && td.fVoxInc[2]) {
955  xptnew = point[2]+dslice/td.fVoxInvdir[2];
956 // printf(" recomputing Z slice, pos=%g\n", xptnew);
957  while (1) {
958  td.fVoxSlices[2] += td.fVoxInc[2];
959  if (td.fVoxInc[2]==1) {
960  if (td.fVoxSlices[2]<-1 || td.fVoxSlices[2]>fIbz-2) break; // outside range
961  if (fZb[td.fVoxSlices[2]+1]>=xptnew) break;
962  } else {
963  if (td.fVoxSlices[2]<0 || td.fVoxSlices[2]>fIbz-1) break; // outside range
964  if (fZb[td.fVoxSlices[2]]<= xptnew) break;
965  }
966  }
967 // printf(" %i/%i\n", td.fVoxSlices[2], fIbz-2);
968  }
969  }
970  // new indices are set -> Get new candidates
971  if (fPriority[1]==1) {
972  // we are entering the unique slice on this axis
973  //---> intersect and store X and Z
974  if (fPriority[0]==2) {
975  if (td.fVoxSlices[0]<0 || td.fVoxSlices[0]>=fIbx-1) return td.fVoxCheckList; // outside range
976  ndd[0] = fNsliceX[td.fVoxSlices[0]];
977  if (!ndd[0]) return td.fVoxCheckList;
978  slice1 = &fIndcX[fOBx[td.fVoxSlices[0]]];
979  islices++;
980  }
981  if (fPriority[2]==2) {
982  if (td.fVoxSlices[2]<0 || td.fVoxSlices[2]>=fIbz-1) return td.fVoxCheckList; // outside range
983  ndd[1] = fNsliceZ[td.fVoxSlices[2]];
984  if (!ndd[1]) return td.fVoxCheckList;
985  islices++;
986  if (slice1) {
987  slice2 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
988  } else {
989  slice1 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
990  ndd[0] = ndd[1];
991  }
992  }
993  if (islices<=1) {
994  IntersectAndStore(ndd[0], slice1, td);
995  } else {
996  IntersectAndStore(ndd[0], slice1, ndd[1], slice2, td);
997  }
998  ncheck = td.fVoxNcandidates;
999  return td.fVoxCheckList;
1000  }
1001  // We got into a new slice -> Get only new candidates
1002  left = (td.fVoxInc[1]>0)?kTRUE:kFALSE;
1003  new_list = GetExtraY(td.fVoxSlices[1], left, ncheck);
1004 // printf(" New list on Y : %i new candidates\n", ncheck);
1005  if (!ncheck) return td.fVoxCheckList;
1006  if (fPriority[0]==2) {
1007  if (td.fVoxSlices[0]<0 || td.fVoxSlices[0]>=fIbx-1) {
1008  ncheck = 0;
1009  return td.fVoxCheckList; // outside range
1010  }
1011  ndd[0] = fNsliceX[td.fVoxSlices[0]];
1012  if (!ndd[0]) {
1013  ncheck = 0;
1014  return td.fVoxCheckList;
1015  }
1016  slice1 = &fIndcX[fOBx[td.fVoxSlices[0]]];
1017  islices++;
1018  }
1019  if (fPriority[2]==2) {
1020  if (td.fVoxSlices[2]<0 || td.fVoxSlices[2]>=fIbz-1) {
1021  ncheck = 0;
1022  return td.fVoxCheckList; // outside range
1023  }
1024  ndd[1] = fNsliceZ[td.fVoxSlices[2]];
1025  if (!ndd[1]) {
1026  ncheck = 0;
1027  return td.fVoxCheckList;
1028  }
1029  islices++;
1030  if (slice1) {
1031  slice2 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
1032  } else {
1033  slice1 = &fIndcZ[fOBz[td.fVoxSlices[2]]];
1034  ndd[0] = ndd[1];
1035  }
1036  }
1037  if (!islices) return GetValidExtra(new_list, ncheck, td);
1038  if (islices==1) {
1039  return GetValidExtra(ndd[0], slice1, new_list, ncheck, td);
1040  } else {
1041  return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck, td);
1042  }
1043  case 2:
1044  if (isZlimit) return 0;
1045  // increment/decrement Z slice
1046  td.fVoxSlices[2]=dind[2];
1047  if (iforced) {
1048  // we have to recompute Y and X slices
1049  if (dslice>td.fVoxLimits[1]) return 0;
1050  if (dslice>td.fVoxLimits[0]) return 0;
1051  if ((dslice>dmin[1]) && td.fVoxInc[1]) {
1052  xptnew = point[1]+dslice/td.fVoxInvdir[1];
1053  // printf(" recomputing Y slice, pos=%g\n", xptnew);
1054  while (1) {
1055  td.fVoxSlices[1] += td.fVoxInc[1];
1056  if (td.fVoxInc[1]==1) {
1057  if (td.fVoxSlices[1]<-1 || td.fVoxSlices[1]>fIby-2) break; // outside range
1058  if (fYb[td.fVoxSlices[1]+1]>=xptnew) break;
1059  } else {
1060  if (td.fVoxSlices[1]<0 || td.fVoxSlices[1]>fIby-1) break; // outside range
1061  if (fYb[td.fVoxSlices[1]]<= xptnew) break;
1062  }
1063  }
1064  // printf(" %i/%i\n", td.fVoxSlices[1], fIby-2);
1065  }
1066  if ((dslice>dmin[0]) && td.fVoxInc[0]) {
1067  xptnew = point[0]+dslice/td.fVoxInvdir[0];
1068  // printf(" recomputing X slice, pos=%g\n", xptnew);
1069  while (1) {
1070  td.fVoxSlices[0] += td.fVoxInc[0];
1071  if (td.fVoxInc[0]==1) {
1072  if (td.fVoxSlices[0]<-1 || td.fVoxSlices[0]>fIbx-2) break; // outside range
1073  if (fXb[td.fVoxSlices[0]+1]>=xptnew) break;
1074  } else {
1075  if (td.fVoxSlices[0]<0 || td.fVoxSlices[0]>fIbx-1) break; // outside range
1076  if (fXb[td.fVoxSlices[0]]<= xptnew) break;
1077  }
1078  }
1079 // printf(" %i/%i\n", td.fVoxSlices[0], fIbx-2);
1080  }
1081  }
1082  // new indices are set -> Get new candidates
1083  if (fPriority[2]==1) {
1084  // we are entering the unique slice on this axis
1085  //---> intersect and store Y and X
1086  if (fPriority[1]==2) {
1087  if (td.fVoxSlices[1]<0 || td.fVoxSlices[1]>=fIby-1) return td.fVoxCheckList; // outside range
1088  ndd[0] = fNsliceY[td.fVoxSlices[1]];
1089  if (!ndd[0]) return td.fVoxCheckList;
1090  slice1 = &fIndcY[fOBy[td.fVoxSlices[1]]];
1091  islices++;
1092  }
1093  if (fPriority[0]==2) {
1094  if (td.fVoxSlices[0]<0 || td.fVoxSlices[0]>=fIbx-1) return td.fVoxCheckList; // outside range
1095  ndd[1] = fNsliceX[td.fVoxSlices[0]];
1096  if (!ndd[1]) return td.fVoxCheckList;
1097  islices++;
1098  if (slice1) {
1099  slice2 = &fIndcX[fOBx[td.fVoxSlices[0]]];
1100  } else {
1101  slice1 = &fIndcX[fOBx[td.fVoxSlices[0]]];
1102  ndd[0] = ndd[1];
1103  }
1104  }
1105  if (islices<=1) {
1106  IntersectAndStore(ndd[0], slice1, td);
1107  } else {
1108  IntersectAndStore(ndd[0], slice1, ndd[1], slice2, td);
1109  }
1110  ncheck = td.fVoxNcandidates;
1111  return td.fVoxCheckList;
1112  }
1113  // We got into a new slice -> Get only new candidates
1114  left = (td.fVoxInc[2]>0)?kTRUE:kFALSE;
1115  new_list = GetExtraZ(td.fVoxSlices[2], left, ncheck);
1116 // printf(" New list on Z : %i new candidates\n", ncheck);
1117  if (!ncheck) return td.fVoxCheckList;
1118  if (fPriority[1]==2) {
1119  if (td.fVoxSlices[1]<0 || td.fVoxSlices[1]>=fIby-1) {
1120  ncheck = 0;
1121  return td.fVoxCheckList; // outside range
1122  }
1123  ndd[0] = fNsliceY[td.fVoxSlices[1]];
1124  if (!ndd[0]) {
1125  ncheck = 0;
1126  return td.fVoxCheckList;
1127  }
1128  slice1 = &fIndcY[fOBy[td.fVoxSlices[1]]];
1129  islices++;
1130  }
1131  if (fPriority[0]==2) {
1132  if (td.fVoxSlices[0]<0 || td.fVoxSlices[0]>=fIbx-1) {
1133  ncheck = 0;
1134  return td.fVoxCheckList; // outside range
1135  }
1136  ndd[1] = fNsliceX[td.fVoxSlices[0]];
1137  if (!ndd[1]) {
1138  ncheck = 0;
1139  return td.fVoxCheckList;
1140  }
1141  islices++;
1142  if (slice1) {
1143  slice2 = &fIndcX[fOBx[td.fVoxSlices[0]]];
1144  } else {
1145  slice1 = &fIndcX[fOBx[td.fVoxSlices[0]]];
1146  ndd[0] = ndd[1];
1147  }
1148  }
1149  if (!islices) return GetValidExtra(new_list, ncheck, td);
1150  if (islices==1) {
1151  return GetValidExtra(ndd[0], slice1, new_list, ncheck, td);
1152  } else {
1153  return GetValidExtra(ndd[0], slice1, ndd[1], slice2, new_list, ncheck, td);
1154  }
1155  default:
1156  Error("GetNextCandidates", "Invalid islice=%i inside %s", islice, fVolume->GetName());
1157  }
1158  return 0;
1159 }
1160 
1161 ////////////////////////////////////////////////////////////////////////////////
1162 /// get the list in the next voxel crossed by a ray
1163 
1165 {
1166  if (NeedRebuild()) {
1167  TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
1168  vox->Voxelize();
1169  fVolume->FindOverlaps();
1170  }
1171  td.fVoxCurrent = 0;
1172 // printf("###Sort crossed voxels for %s\n", fVolume->GetName());
1173  td.fVoxNcandidates = 0;
1174  Int_t loc = 1+((fVolume->GetNdaughters()-1)>>3);
1175 // printf(" LOC=%i\n", loc*sizeof(UChar_t));
1176 // UChar_t *bits = gGeoManager->GetBits();
1177  memset(td.fVoxBits1, 0, loc);
1178  memset(td.fVoxInc, 0, 3*sizeof(Int_t));
1179  for (Int_t i=0; i<3; i++) {
1180  td.fVoxInvdir[i] = TGeoShape::Big();
1181  if (TMath::Abs(dir[i])<1E-10) continue;
1182  td.fVoxInc[i] = (dir[i]>0)?1:-1;
1183  td.fVoxInvdir[i] = 1./dir[i];
1184  }
1185  Bool_t flag = GetIndices(point, td);
1186  TGeoBBox *box = (TGeoBBox*)(fVolume->GetShape());
1187  const Double_t *box_orig = box->GetOrigin();
1188  if (td.fVoxInc[0]==0) {
1189  td.fVoxLimits[0] = TGeoShape::Big();
1190  } else {
1191  if (td.fVoxSlices[0]==-2) {
1192  // no slice on this axis -> get limit to bounding box limit
1193  td.fVoxLimits[0] = (box_orig[0]-point[0]+td.fVoxInc[0]*box->GetDX())*td.fVoxInvdir[0];
1194  } else {
1195  if (td.fVoxInc[0]==1) {
1196  td.fVoxLimits[0] = (fXb[fIbx-1]-point[0])*td.fVoxInvdir[0];
1197  } else {
1198  td.fVoxLimits[0] = (fXb[0]-point[0])*td.fVoxInvdir[0];
1199  }
1200  }
1201  }
1202  if (td.fVoxInc[1]==0) {
1203  td.fVoxLimits[1] = TGeoShape::Big();
1204  } else {
1205  if (td.fVoxSlices[1]==-2) {
1206  // no slice on this axis -> get limit to bounding box limit
1207  td.fVoxLimits[1] = (box_orig[1]-point[1]+td.fVoxInc[1]*box->GetDY())*td.fVoxInvdir[1];
1208  } else {
1209  if (td.fVoxInc[1]==1) {
1210  td.fVoxLimits[1] = (fYb[fIby-1]-point[1])*td.fVoxInvdir[1];
1211  } else {
1212  td.fVoxLimits[1] = (fYb[0]-point[1])*td.fVoxInvdir[1];
1213  }
1214  }
1215  }
1216  if (td.fVoxInc[2]==0) {
1217  td.fVoxLimits[2] = TGeoShape::Big();
1218  } else {
1219  if (td.fVoxSlices[2]==-2) {
1220  // no slice on this axis -> get limit to bounding box limit
1221  td.fVoxLimits[2] = (box_orig[2]-point[2]+td.fVoxInc[2]*box->GetDZ())*td.fVoxInvdir[2];
1222  } else {
1223  if (td.fVoxInc[2]==1) {
1224  td.fVoxLimits[2] = (fZb[fIbz-1]-point[2])*td.fVoxInvdir[2];
1225  } else {
1226  td.fVoxLimits[2] = (fZb[0]-point[2])*td.fVoxInvdir[2];
1227  }
1228  }
1229  }
1230 
1231  if (!flag) {
1232 // printf(" NO candidates in first voxel\n");
1233 // printf(" bits[0]=%i\n", bits[0]);
1234  return;
1235  }
1236 // printf(" current slices : %i %i %i\n", td.fVoxSlices[0], td.fVoxSlices[1], td.fVoxSlices[2]);
1237  Int_t nd[3];
1238  Int_t islices = 0;
1239  memset(&nd[0], 0, 3*sizeof(Int_t));
1240  UChar_t *slicex = 0;
1241  if (fPriority[0]==2) {
1242  nd[0] = fNsliceX[td.fVoxSlices[0]];
1243  slicex=&fIndcX[fOBx[td.fVoxSlices[0]]];
1244  islices++;
1245  }
1246  UChar_t *slicey = 0;
1247  if (fPriority[1]==2) {
1248  nd[1] = fNsliceY[td.fVoxSlices[1]];
1249  islices++;
1250  if (slicex) {
1251  slicey=&fIndcY[fOBy[td.fVoxSlices[1]]];
1252  } else {
1253  slicex=&fIndcY[fOBy[td.fVoxSlices[1]]];
1254  nd[0] = nd[1];
1255  }
1256  }
1257  UChar_t *slicez = 0;
1258  if (fPriority[2]==2) {
1259  nd[2] = fNsliceZ[td.fVoxSlices[2]];
1260  islices++;
1261  if (slicex && slicey) {
1262  slicez=&fIndcZ[fOBz[td.fVoxSlices[2]]];
1263  } else {
1264  if (slicex) {
1265  slicey=&fIndcZ[fOBz[td.fVoxSlices[2]]];
1266  nd[1] = nd[2];
1267  } else {
1268  slicex=&fIndcZ[fOBz[td.fVoxSlices[2]]];
1269  nd[0] = nd[2];
1270  }
1271  }
1272  }
1273 // printf("Ndaughters in first voxel : %i %i %i\n", nd[0], nd[1], nd[2]);
1274  switch (islices) {
1275  case 0:
1276  Error("SortCrossedVoxels", "no slices for %s", fVolume->GetName());
1277 // printf("Slices :(%i,%i,%i) Priority:(%i,%i,%i)\n", td.fVoxSlices[0], td.fVoxSlices[1], td.fVoxSlices[2], fPriority[0], fPriority[1], fPriority[2]);
1278  return;
1279  case 1:
1280  IntersectAndStore(nd[0], slicex, td);
1281  break;
1282  case 2:
1283  IntersectAndStore(nd[0], slicex, nd[1], slicey, td);
1284  break;
1285  default:
1286  IntersectAndStore(nd[0], slicex, nd[1], slicey, nd[2], slicez, td);
1287  }
1288 // printf(" bits[0]=%i END\n", bits[0]);
1289 // if (td.fVoxNcandidates) {
1290 // printf(" candidates for first voxel :\n");
1291 // for (Int_t i=0; i<td.fVoxNcandidates; i++) printf(" %i\n", td.fVoxCheckList[i]);
1292 // }
1293 }
1294 
1295 ////////////////////////////////////////////////////////////////////////////////
1296 /// get the list of daughter indices for which point is inside their bbox
1297 
1299 {
1300  if (NeedRebuild()) {
1301  Voxelize();
1302  fVolume->FindOverlaps();
1303  }
1304  if (fVolume->GetNdaughters() == 1) {
1305  if (fXb) {
1306  if (point[0]<fXb[0] || point[0]>fXb[1]) return 0;
1307  }
1308  if (fYb) {
1309  if (point[1]<fYb[0] || point[1]>fYb[1]) return 0;
1310  }
1311 
1312  if (fZb) {
1313  if (point[2]<fZb[0] || point[2]>fZb[1]) return 0;
1314  }
1315  td.fVoxCheckList[0] = 0;
1316  nelem = 1;
1317  return td.fVoxCheckList;
1318  }
1319  Int_t nslices = 0;
1320  UChar_t *slice1 = 0;
1321  UChar_t *slice2 = 0;
1322  UChar_t *slice3 = 0;
1323  Int_t nd[3] = {0,0,0};
1324  Int_t im;
1325  if (fPriority[0]) {
1326  im = TMath::BinarySearch(fIbx, fXb, point[0]);
1327  if ((im==-1) || (im==fIbx-1)) return 0;
1328  if (fPriority[0]==2) {
1329  nd[0] = fNsliceX[im];
1330  if (!nd[0]) return 0;
1331  nslices++;
1332  slice1 = &fIndcX[fOBx[im]];
1333  }
1334  }
1335 
1336  if (fPriority[1]) {
1337  im = TMath::BinarySearch(fIby, fYb, point[1]);
1338  if ((im==-1) || (im==fIby-1)) return 0;
1339  if (fPriority[1]==2) {
1340  nd[1] = fNsliceY[im];
1341  if (!nd[1]) return 0;
1342  nslices++;
1343  if (slice1) {
1344  slice2 = &fIndcY[fOBy[im]];
1345  } else {
1346  slice1 = &fIndcY[fOBy[im]];
1347  nd[0] = nd[1];
1348  }
1349  }
1350  }
1351 
1352  if (fPriority[2]) {
1353  im = TMath::BinarySearch(fIbz, fZb, point[2]);
1354  if ((im==-1) || (im==fIbz-1)) return 0;
1355  if (fPriority[2]==2) {
1356  nd[2] = fNsliceZ[im];
1357  if (!nd[2]) return 0;
1358  nslices++;
1359  if (slice1 && slice2) {
1360  slice3 = &fIndcZ[fOBz[im]];
1361  } else {
1362  if (slice1) {
1363  slice2 = &fIndcZ[fOBz[im]];
1364  nd[1] = nd[2];
1365  } else {
1366  slice1 = &fIndcZ[fOBz[im]];
1367  nd[0] = nd[2];
1368  }
1369  }
1370  }
1371  }
1372  nelem = 0;
1373 // Int_t i = 0;
1374  Bool_t intersect = kFALSE;
1375  switch (nslices) {
1376  case 0:
1377  Error("GetCheckList", "No slices for %s", fVolume->GetName());
1378  return 0;
1379  case 1:
1380  intersect = Intersect(nd[0], slice1, nelem, td.fVoxCheckList);
1381  break;
1382  case 2:
1383  intersect = Intersect(nd[0], slice1, nd[1], slice2, nelem, td.fVoxCheckList);
1384  break;
1385  default:
1386  intersect = Intersect(nd[0], slice1, nd[1], slice2, nd[2], slice3, nelem, td.fVoxCheckList);
1387  }
1388  if (intersect) return td.fVoxCheckList;
1389  return 0;
1390 }
1391 
1392 ////////////////////////////////////////////////////////////////////////////////
1393 /// get the list of candidates in voxel (i,j,k) - no check
1394 
1396 {
1397  UChar_t *slice1 = 0;
1398  UChar_t *slice2 = 0;
1399  UChar_t *slice3 = 0;
1400  Int_t nd[3] = {0,0,0};
1401  Int_t nslices = 0;
1402  if (fPriority[0]==2) {
1403  nd[0] = fNsliceX[i];
1404  if (!nd[0]) return 0;
1405  nslices++;
1406  slice1 = &fIndcX[fOBx[i]];
1407  }
1408 
1409  if (fPriority[1]==2) {
1410  nd[1] = fNsliceY[j];
1411  if (!nd[1]) return 0;
1412  nslices++;
1413  if (slice1) {
1414  slice2 = &fIndcY[fOBy[j]];
1415  } else {
1416  slice1 = &fIndcY[fOBy[j]];
1417  nd[0] = nd[1];
1418  }
1419  }
1420 
1421  if (fPriority[2]==2) {
1422  nd[2] = fNsliceZ[k];
1423  if (!nd[2]) return 0;
1424  nslices++;
1425  if (slice1 && slice2) {
1426  slice3 = &fIndcZ[fOBz[k]];
1427  } else {
1428  if (slice1) {
1429  slice2 = &fIndcZ[fOBz[k]];
1430  nd[1] = nd[2];
1431  } else {
1432  slice1 = &fIndcZ[fOBz[k]];
1433  nd[0] = nd[2];
1434  }
1435  }
1436  }
1437  Bool_t intersect = kFALSE;
1438  switch (nslices) {
1439  case 0:
1440  Error("GetCheckList", "No slices for %s", fVolume->GetName());
1441  return 0;
1442  case 1:
1443  intersect = Intersect(nd[0], slice1, ncheck, td.fVoxCheckList);
1444  break;
1445  case 2:
1446  intersect = Intersect(nd[0], slice1, nd[1], slice2, ncheck, td.fVoxCheckList);
1447  break;
1448  default:
1449  intersect = Intersect(nd[0], slice1, nd[1], slice2, nd[2], slice3, ncheck, td.fVoxCheckList);
1450  }
1451  if (intersect) return td.fVoxCheckList;
1452  return 0;
1453 }
1454 
1455 ////////////////////////////////////////////////////////////////////////////////
1456 /// get the list of new candidates for the next voxel crossed by current ray
1457 /// printf("### GetNextVoxel\n");
1458 
1459 Int_t *TGeoVoxelFinder::GetNextVoxel(const Double_t *point, const Double_t * /*dir*/, Int_t &ncheck, TGeoStateInfo &td)
1460 {
1461  if (NeedRebuild()) {
1462  Voxelize();
1463  fVolume->FindOverlaps();
1464  }
1465  if (td.fVoxCurrent==0) {
1466 // printf(">>> first voxel, %i candidates\n", ncheck);
1467 // printf(" bits[0]=%i\n", gGeoManager->GetBits()[0]);
1468  td.fVoxCurrent++;
1469  ncheck = td.fVoxNcandidates;
1470  return td.fVoxCheckList;
1471  }
1472  td.fVoxCurrent++;
1473 // printf(">>> voxel %i\n", td.fCurrentVoxel);
1474  // Get slices for next voxel
1475 // printf("before - td.fSlices : %i %i %i\n", td.fSlices[0], td.fSlices[1], td.fSlices[2]);
1476  return GetNextCandidates(point, ncheck, td);
1477 }
1478 
1479 ////////////////////////////////////////////////////////////////////////////////
1480 /// return the list of nodes corresponding to one array of bits
1481 
1483 {
1484  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1485  nf = 0;
1486  Int_t nbytes = 1+((nd-1)>>3);
1487  Int_t current_byte;
1488  Int_t current_bit;
1489  UChar_t byte;
1490  Bool_t ibreak = kFALSE;
1491  for (current_byte=0; current_byte<nbytes; current_byte++) {
1492  byte = array1[current_byte];
1493  if (!byte) continue;
1494  for (current_bit=0; current_bit<8; current_bit++) {
1495  if (byte & (1<<current_bit)) {
1496  result[nf++] = (current_byte<<3)+current_bit;
1497  if (nf==n1) {
1498  ibreak = kTRUE;
1499  break;
1500  }
1501  }
1502  }
1503  if (ibreak) return kTRUE;
1504  }
1505  return kTRUE;
1506 }
1507 
1508 ////////////////////////////////////////////////////////////////////////////////
1509 /// return the list of nodes corresponding to one array of bits
1510 
1512 {
1513  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1514 // UChar_t *bits = gGeoManager->GetBits();
1515  td.fVoxNcandidates = 0;
1516  Int_t nbytes = 1+((nd-1)>>3);
1517  if (!array1) {
1518  memset(td.fVoxBits1, 0xFF, nbytes*sizeof(UChar_t));
1519  while (td.fVoxNcandidates<nd) {
1521  ++td.fVoxNcandidates;
1522  }
1523  return kTRUE;
1524  }
1525  memcpy(td.fVoxBits1, array1, nbytes*sizeof(UChar_t));
1526  Int_t current_byte;
1527  Int_t current_bit;
1528  UChar_t byte;
1529  Bool_t ibreak = kFALSE;
1530  Int_t icand;
1531  for (current_byte=0; current_byte<nbytes; current_byte++) {
1532  byte = array1[current_byte];
1533  icand = current_byte<<3;
1534  if (!byte) continue;
1535  for (current_bit=0; current_bit<8; current_bit++) {
1536  if (byte & (1<<current_bit)) {
1537  td.fVoxCheckList[td.fVoxNcandidates++] = icand+current_bit;
1538  if (td.fVoxNcandidates==n1) {
1539  ibreak = kTRUE;
1540  break;
1541  }
1542  }
1543  }
1544  if (ibreak) return kTRUE;
1545  }
1546  return kTRUE;
1547 }
1548 
1549 ////////////////////////////////////////////////////////////////////////////////
1550 /// make union of older bits with new array
1551 /// printf("Union - one slice\n");
1552 
1554 {
1555  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1556 // UChar_t *bits = gGeoManager->GetBits();
1557  td.fVoxNcandidates = 0;
1558  Int_t nbytes = 1+((nd-1)>>3);
1559  Int_t current_byte;
1560  Int_t current_bit;
1561  UChar_t byte;
1562  Bool_t ibreak = kFALSE;
1563  for (current_byte=0; current_byte<nbytes; current_byte++) {
1564 // printf(" byte %i : bits=%i array=%i\n", current_byte, bits[current_byte], array1[current_byte]);
1565  byte = (~td.fVoxBits1[current_byte]) & array1[current_byte];
1566  if (!byte) continue;
1567  for (current_bit=0; current_bit<8; current_bit++) {
1568  if (byte & (1<<current_bit)) {
1569  td.fVoxCheckList[td.fVoxNcandidates++] = (current_byte<<3)+current_bit;
1570  if (td.fVoxNcandidates==n1) {
1571  ibreak = kTRUE;
1572  break;
1573  }
1574  }
1575  }
1576  td.fVoxBits1[current_byte] |= byte;
1577  if (ibreak) return kTRUE;
1578  }
1579  return (td.fVoxNcandidates>0);
1580 }
1581 
1582 ////////////////////////////////////////////////////////////////////////////////
1583 /// make union of older bits with new array
1584 /// printf("Union - two slices\n");
1585 
1586 Bool_t TGeoVoxelFinder::Union(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2, TGeoStateInfo &td)
1587 {
1588  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1589 // UChar_t *bits = gGeoManager->GetBits();
1590  td.fVoxNcandidates = 0;
1591  Int_t nbytes = 1+((nd-1)>>3);
1592  Int_t current_byte;
1593  Int_t current_bit;
1594  UChar_t byte;
1595  for (current_byte=0; current_byte<nbytes; current_byte++) {
1596  byte = (~td.fVoxBits1[current_byte]) & (array1[current_byte] & array2[current_byte]);
1597  if (!byte) continue;
1598  for (current_bit=0; current_bit<8; current_bit++) {
1599  if (byte & (1<<current_bit)) {
1600  td.fVoxCheckList[td.fVoxNcandidates++] = (current_byte<<3)+current_bit;
1601  }
1602  }
1603  td.fVoxBits1[current_byte] |= byte;
1604  }
1605  return (td.fVoxNcandidates>0);
1606 }
1607 
1608 ////////////////////////////////////////////////////////////////////////////////
1609 /// make union of older bits with new array
1610 /// printf("Union - three slices\n");
1611 /// printf("n1=%i n2=%i n3=%i\n", n1,n2,n3);
1612 
1613 Bool_t TGeoVoxelFinder::Union(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2, Int_t /*n3*/, UChar_t *array3, TGeoStateInfo &td)
1614 {
1615  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1616 // UChar_t *bits = gGeoManager->GetBits();
1617  td.fVoxNcandidates = 0;
1618  Int_t nbytes = 1+((nd-1)>>3);
1619  Int_t current_byte;
1620  Int_t current_bit;
1621  UChar_t byte;
1622  for (current_byte=0; current_byte<nbytes; current_byte++) {
1623  byte = (~td.fVoxBits1[current_byte]) & (array1[current_byte] & array2[current_byte] & array3[current_byte]);
1624  if (!byte) continue;
1625  for (current_bit=0; current_bit<8; current_bit++) {
1626  if (byte & (1<<current_bit)) {
1627  td.fVoxCheckList[td.fVoxNcandidates++] = (current_byte<<3)+current_bit;
1628  }
1629  }
1630  td.fVoxBits1[current_byte] |= byte;
1631  }
1632  return (td.fVoxNcandidates>0);
1633 }
1634 
1635 ////////////////////////////////////////////////////////////////////////////////
1636 /// return the list of nodes corresponding to the intersection of two arrays of bits
1637 
1639 {
1640  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1641  nf = 0;
1642  Int_t nbytes = 1+((nd-1)>>3);
1643  Int_t current_byte;
1644  Int_t current_bit;
1645  UChar_t byte;
1646  Bool_t ibreak = kFALSE;
1647  for (current_byte=0; current_byte<nbytes; current_byte++) {
1648  byte = array1[current_byte] & array2[current_byte];
1649  if (!byte) continue;
1650  for (current_bit=0; current_bit<8; current_bit++) {
1651  if (byte & (1<<current_bit)) {
1652  result[nf++] = (current_byte<<3)+current_bit;
1653  if ((nf==n1) || (nf==n2)) {
1654  ibreak = kTRUE;
1655  break;
1656  }
1657  }
1658  }
1659  if (ibreak) return kTRUE;
1660  }
1661  return (nf>0);
1662 }
1663 
1664 ////////////////////////////////////////////////////////////////////////////////
1665 /// return the list of nodes corresponding to the intersection of two arrays of bits
1666 
1668 {
1669  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1670 // UChar_t *bits = gGeoManager->GetBits();
1671  td.fVoxNcandidates = 0;
1672  Int_t nbytes = 1+((nd-1)>>3);
1673 // memset(bits, 0, nbytes*sizeof(UChar_t));
1674  Int_t current_byte;
1675  Int_t current_bit;
1676  Int_t icand;
1677  UChar_t byte;
1678  for (current_byte=0; current_byte<nbytes; current_byte++) {
1679  byte = array1[current_byte] & array2[current_byte];
1680  icand = current_byte<<3;
1681  td.fVoxBits1[current_byte] = byte;
1682  if (!byte) continue;
1683  for (current_bit=0; current_bit<8; current_bit++) {
1684  if (byte & (1<<current_bit)) {
1685  td.fVoxCheckList[td.fVoxNcandidates++] = icand+current_bit;
1686  }
1687  }
1688  }
1689  return (td.fVoxNcandidates>0);
1690 }
1691 
1692 ////////////////////////////////////////////////////////////////////////////////
1693 /// return the list of nodes corresponding to the intersection of three arrays of bits
1694 
1696 {
1697  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1698  nf = 0;
1699  Int_t nbytes = 1+((nd-1)>>3);
1700  Int_t current_byte;
1701  Int_t current_bit;
1702  UChar_t byte;
1703  Bool_t ibreak = kFALSE;
1704  for (current_byte=0; current_byte<nbytes; current_byte++) {
1705  byte = array1[current_byte] & array2[current_byte] & array3[current_byte];
1706  if (!byte) continue;
1707  for (current_bit=0; current_bit<8; current_bit++) {
1708  if (byte & (1<<current_bit)) {
1709  result[nf++] = (current_byte<<3)+current_bit;
1710  if ((nf==n1) || (nf==n2) || (nf==n3)) {
1711  ibreak = kTRUE;
1712  break;
1713  }
1714  }
1715  }
1716  if (ibreak) return kTRUE;
1717  }
1718  return (nf>0);
1719 }
1720 
1721 ////////////////////////////////////////////////////////////////////////////////
1722 /// return the list of nodes corresponding to the intersection of three arrays of bits
1723 
1724 Bool_t TGeoVoxelFinder::IntersectAndStore(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*/, UChar_t *array2, Int_t /*n3*/, UChar_t *array3, TGeoStateInfo &td)
1725 {
1726  Int_t nd = fVolume->GetNdaughters(); // also number of bits to scan
1727 // UChar_t *bits = gGeoManager->GetBits();
1728  td.fVoxNcandidates = 0;
1729  Int_t nbytes = 1+((nd-1)>>3);
1730 // memset(bits, 0, nbytes*sizeof(UChar_t));
1731  Int_t current_byte;
1732  Int_t current_bit;
1733  Int_t icand;
1734  UChar_t byte;
1735  for (current_byte=0; current_byte<nbytes; current_byte++) {
1736  byte = array1[current_byte] & array2[current_byte] & array3[current_byte];
1737  icand = current_byte<<3;
1738  td.fVoxBits1[current_byte] = byte;
1739  if (!byte) continue;
1740  for (current_bit=0; current_bit<8; current_bit++) {
1741  if (byte & (1<<current_bit)) {
1742  td.fVoxCheckList[td.fVoxNcandidates++] = icand+current_bit;
1743  }
1744  }
1745  }
1746  return (td.fVoxNcandidates>0);
1747 }
1748 ////////////////////////////////////////////////////////////////////////////////
1749 /// order bounding boxes along x, y, z
1750 
1752 {
1753  Int_t nd = fVolume->GetNdaughters();
1754  Int_t nperslice = 1+(nd-1)/(8*sizeof(UChar_t)); /*Nbytes per slice*/
1755  Int_t nmaxslices = 2*nd+1; // max number of slices on each axis
1756  Double_t xmin, xmax, ymin, ymax, zmin, zmax;
1757  TGeoBBox *box = (TGeoBBox*)fVolume->GetShape(); // bounding box for volume
1758  // compute range on X, Y, Z according to volume bounding box
1759  xmin = (box->GetOrigin())[0] - box->GetDX();
1760  xmax = (box->GetOrigin())[0] + box->GetDX();
1761  ymin = (box->GetOrigin())[1] - box->GetDY();
1762  ymax = (box->GetOrigin())[1] + box->GetDY();
1763  zmin = (box->GetOrigin())[2] - box->GetDZ();
1764  zmax = (box->GetOrigin())[2] + box->GetDZ();
1765  if ((xmin>=xmax) || (ymin>=ymax) || (zmin>=zmax)) {
1766  Error("SortAll", "Wrong bounding box for volume %s", fVolume->GetName());
1767  return;
1768  }
1769  Int_t id;
1770  // compute boundaries coordinates on X,Y,Z
1771  Double_t *boundaries = new Double_t[6*nd]; // list of different boundaries
1772  for (id=0; id<nd; id++) {
1773  // x boundaries
1774  boundaries[2*id] = fBoxes[6*id+3]-fBoxes[6*id];
1775  boundaries[2*id+1] = fBoxes[6*id+3]+fBoxes[6*id];
1776  // y boundaries
1777  boundaries[2*id+2*nd] = fBoxes[6*id+4]-fBoxes[6*id+1];
1778  boundaries[2*id+2*nd+1] = fBoxes[6*id+4]+fBoxes[6*id+1];
1779  // z boundaries
1780  boundaries[2*id+4*nd] = fBoxes[6*id+5]-fBoxes[6*id+2];
1781  boundaries[2*id+4*nd+1] = fBoxes[6*id+5]+fBoxes[6*id+2];
1782  }
1783  Int_t *index = new Int_t[2*nd]; // indexes for sorted boundaries on one axis
1784  UChar_t *ind = new UChar_t[nmaxslices*nperslice]; // ind[fOBx[i]] = ndghts in slice fInd[i]--fInd[i+1]
1785  Int_t *extra = new Int_t[nmaxslices*4];
1786  // extra[fOEx[i]] = nextra_to_left (i/i-1)
1787  // extra[fOEx[i]+1] = nextra_to_right (i/i+1)
1788  // Int_t *extra_to_left = extra[fOEx[i]+2]
1789  // Int_t *extra_to_right = extra[fOEx[i]+2+nextra_to_left]
1790  Double_t *temp = new Double_t[2*nd]; // temporary array to store sorted boundary positions
1791  Int_t current = 0;
1792  Int_t indextra = 0;
1793  Int_t nleft, nright;
1794  Int_t *extra_left = new Int_t[nd];
1795  Int_t *extra_right = new Int_t[nd];
1796  Double_t xxmin, xxmax, xbmin, xbmax, ddx1, ddx2;
1797  UChar_t *bits;
1798  UInt_t loc, bitnumber;
1799  UChar_t bit;
1800 
1801  // sort x boundaries
1802  Int_t ib = 0; // total number of DIFFERENT boundaries
1803  TMath::Sort(2*nd, &boundaries[0], &index[0], kFALSE);
1804  // compact common boundaries
1805  for (id=0; id<2*nd; id++) {
1806  if (!ib) {temp[ib++] = boundaries[index[id]]; continue;}
1807  if (TMath::Abs(temp[ib-1]-boundaries[index[id]])>1E-10)
1808  temp[ib++] = boundaries[index[id]];
1809  }
1810  // now find priority
1811  if (ib < 2) {
1812  Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on X", fVolume->GetName());
1813  delete [] boundaries;
1814  delete [] index;
1815  delete [] ind;
1816  delete [] temp;
1817  delete [] extra;
1818  delete [] extra_left;
1819  delete [] extra_right;
1820  SetInvalid();
1821  return;
1822  }
1823  if (ib == 2) {
1824  // check range
1825  if (((temp[0]-xmin)<1E-10) && ((temp[1]-xmax)>-1E-10)) {
1826  // ordering on this axis makes no sense. Clear all arrays.
1827  fPriority[0] = 0; // always skip this axis
1828  if (fIndcX) delete [] fIndcX;
1829  fIndcX = 0;
1830  fNx = 0;
1831  if (fXb) delete [] fXb;
1832  fXb = 0;
1833  fIbx = 0;
1834  if (fOBx) delete [] fOBx;
1835  fOBx = 0;
1836  fNox = 0;
1837  } else {
1838  fPriority[0] = 1; // all in one slice
1839  }
1840  } else {
1841  fPriority[0] = 2; // check all
1842  }
1843  // store compacted boundaries
1844  if (fPriority[0]) {
1845  if (fXb) delete [] fXb;
1846  fXb = new Double_t[ib];
1847  memcpy(fXb, &temp[0], ib*sizeof(Double_t));
1848  fIbx = ib;
1849  }
1850 
1851  //--- now build the lists of nodes in each slice of X axis
1852  if (fPriority[0]==2) {
1853  memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
1854  if (fOBx) delete [] fOBx;
1855  fNox = fIbx-1; // number of different slices
1856  fOBx = new Int_t[fNox]; // offsets in ind
1857  if (fOEx) delete [] fOEx;
1858  fOEx = new Int_t[fNox]; // offsets in extra
1859  if (fNsliceX) delete [] fNsliceX;
1860  fNsliceX = new Int_t[fNox];
1861  current = 0;
1862  indextra = 0;
1863  //--- now loop all slices
1864  for (id=0; id<fNox; id++) {
1865  fOBx[id] = current; // offset in dght list for this slice
1866  fOEx[id] = indextra; // offset in exta list for this slice
1867  fNsliceX[id] = 0; // ndght in this slice
1868  extra[indextra] = extra[indextra+1] = 0; // no extra left/right
1869  nleft = nright = 0;
1870  bits = &ind[current]; // adress of bits for this slice
1871  xxmin = fXb[id];
1872  xxmax = fXb[id+1];
1873  for (Int_t ic=0; ic<nd; ic++) {
1874  xbmin = fBoxes[6*ic+3]-fBoxes[6*ic];
1875  xbmax = fBoxes[6*ic+3]+fBoxes[6*ic];
1876  ddx1 = xbmin-xxmax;
1877  if (ddx1>-1E-10) continue;
1878  ddx2 = xbmax-xxmin;
1879  if (ddx2<1E-10) continue;
1880  // daughter ic in interval
1881  //---> set the bit
1882  fNsliceX[id]++;
1883  bitnumber = (UInt_t)ic;
1884  loc = bitnumber/8;
1885  bit = bitnumber%8;
1886  bits[loc] |= 1<<bit;
1887  //---> chech if it is extra to left/right
1888  //--- left
1889  ddx1 = xbmin-xxmin;
1890  ddx2 = xbmax-xxmax;
1891  if ((id==0) || (ddx1>-1E-10)) {
1892  extra_left[nleft++] = ic;
1893  }
1894  //---right
1895  if ((id==(fNoz-1)) || (ddx2<1E-10)) {
1896  extra_right[nright++] = ic;
1897  }
1898  }
1899  //--- compute offset of next slice
1900  if (fNsliceX[id]>0) current += nperslice;
1901  //--- copy extra candidates
1902  extra[indextra] = nleft;
1903  extra[indextra+1] = nright;
1904  if (nleft) memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
1905  if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));
1906  indextra += 2+nleft+nright;
1907  }
1908  if (fIndcX) delete [] fIndcX;
1909  fNx = current;
1910  fIndcX = new UChar_t[current];
1911  memcpy(fIndcX, ind, current*sizeof(UChar_t));
1912  if (fExtraX) delete [] fExtraX;
1913  fNex = indextra;
1914  if (indextra>nmaxslices*4) printf("Woops!!!\n");
1915  fExtraX = new Int_t[indextra];
1916  memcpy(fExtraX, extra, indextra*sizeof(Int_t));
1917  }
1918 
1919  // sort y boundaries
1920  ib = 0;
1921  TMath::Sort(2*nd, &boundaries[2*nd], &index[0], kFALSE);
1922  // compact common boundaries
1923  for (id=0; id<2*nd; id++) {
1924  if (!ib) {temp[ib++] = boundaries[2*nd+index[id]]; continue;}
1925  if (TMath::Abs(temp[ib-1]-boundaries[2*nd+index[id]])>1E-10)
1926  temp[ib++]=boundaries[2*nd+index[id]];
1927  }
1928  // now find priority on Y
1929  if (ib < 2) {
1930  Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on Y", fVolume->GetName());
1931  delete [] boundaries;
1932  delete [] index;
1933  delete [] ind;
1934  delete [] temp;
1935  delete [] extra;
1936  delete [] extra_left;
1937  delete [] extra_right;
1938  SetInvalid();
1939  return;
1940  }
1941  if (ib == 2) {
1942  // check range
1943  if (((temp[0]-ymin)<1E-10) && ((temp[1]-ymax)>-1E-10)) {
1944  // ordering on this axis makes no sense. Clear all arrays.
1945  fPriority[1] = 0; // always skip this axis
1946  if (fIndcY) delete [] fIndcY;
1947  fIndcY = 0;
1948  fNy = 0;
1949  if (fYb) delete [] fYb;
1950  fYb = 0;
1951  fIby = 0;
1952  if (fOBy) delete [] fOBy;
1953  fOBy = 0;
1954  fNoy = 0;
1955  } else {
1956  fPriority[1] = 1; // all in one slice
1957  }
1958  } else {
1959  fPriority[1] = 2; // check all
1960  }
1961 
1962  // store compacted boundaries
1963  if (fPriority[1]) {
1964  if (fYb) delete [] fYb;
1965  fYb = new Double_t[ib];
1966  memcpy(fYb, &temp[0], ib*sizeof(Double_t));
1967  fIby = ib;
1968  }
1969 
1970 
1971  if (fPriority[1]==2) {
1972  //--- now build the lists of nodes in each slice of Y axis
1973  memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
1974  if (fOBy) delete [] fOBy;
1975  fNoy = fIby-1; // number of different slices
1976  fOBy = new Int_t[fNoy]; // offsets in ind
1977  if (fOEy) delete [] fOEy;
1978  fOEy = new Int_t[fNoy]; // offsets in extra
1979  if (fNsliceY) delete [] fNsliceY;
1980  fNsliceY = new Int_t[fNoy];
1981  current = 0;
1982  indextra = 0;
1983  //--- now loop all slices
1984  for (id=0; id<fNoy; id++) {
1985  fOBy[id] = current; // offset of dght list
1986  fOEy[id] = indextra; // offset in exta list for this slice
1987  fNsliceY[id] = 0; // ndght in this slice
1988  extra[indextra] = extra[indextra+1] = 0; // no extra left/right
1989  nleft = nright = 0;
1990  bits = &ind[current]; // adress of bits for this slice
1991  xxmin = fYb[id];
1992  xxmax = fYb[id+1];
1993  for (Int_t ic=0; ic<nd; ic++) {
1994  xbmin = fBoxes[6*ic+4]-fBoxes[6*ic+1];
1995  xbmax = fBoxes[6*ic+4]+fBoxes[6*ic+1];
1996  ddx1 = xbmin-xxmax;
1997  if (ddx1>-1E-10) continue;
1998  ddx2 = xbmax-xxmin;
1999  if (ddx2<1E-10) continue;
2000  // daughter ic in interval
2001  //---> set the bit
2002  fNsliceY[id]++;
2003  bitnumber = (UInt_t)ic;
2004  loc = bitnumber/8;
2005  bit = bitnumber%8;
2006  bits[loc] |= 1<<bit;
2007  //---> check if it is extra to left/right
2008  //--- left
2009  ddx1 = xbmin-xxmin;
2010  ddx2 = xbmax-xxmax;
2011  if ((id==0) || (ddx1>-1E-10)) {
2012  extra_left[nleft++] = ic;
2013  }
2014  //---right
2015  if ((id==(fNoz-1)) || (ddx2<1E-10)) {
2016  extra_right[nright++] = ic;
2017  }
2018  }
2019  //--- compute offset of next slice
2020  if (fNsliceY[id]>0) current += nperslice;
2021  //--- copy extra candidates
2022  extra[indextra] = nleft;
2023  extra[indextra+1] = nright;
2024  if (nleft) memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
2025  if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));
2026  indextra += 2+nleft+nright;
2027  }
2028  if (fIndcY) delete [] fIndcY;
2029  fNy = current;
2030  fIndcY = new UChar_t[current];
2031  memcpy(fIndcY, &ind[0], current*sizeof(UChar_t));
2032  if (fExtraY) delete [] fExtraY;
2033  fNey = indextra;
2034  if (indextra>nmaxslices*4) printf("Woops!!!\n");
2035  fExtraY = new Int_t[indextra];
2036  memcpy(fExtraY, extra, indextra*sizeof(Int_t));
2037  }
2038 
2039  // sort z boundaries
2040  ib = 0;
2041  TMath::Sort(2*nd, &boundaries[4*nd], &index[0], kFALSE);
2042  // compact common boundaries
2043  for (id=0; id<2*nd; id++) {
2044  if (!ib) {temp[ib++] = boundaries[4*nd+index[id]]; continue;}
2045  if ((TMath::Abs(temp[ib-1]-boundaries[4*nd+index[id]]))>1E-10)
2046  temp[ib++]=boundaries[4*nd+index[id]];
2047  }
2048  // now find priority on Z
2049  if (ib < 2) {
2050  Error("SortAll", "Cannot voxelize %s :less than 2 boundaries on Z", fVolume->GetName());
2051  delete [] boundaries;
2052  delete [] index;
2053  delete [] ind;
2054  delete [] temp;
2055  delete [] extra;
2056  delete [] extra_left;
2057  delete [] extra_right;
2058  SetInvalid();
2059  return;
2060  }
2061  if (ib == 2) {
2062  // check range
2063  if (((temp[0]-zmin)<1E-10) && ((temp[1]-zmax)>-1E-10)) {
2064  // ordering on this axis makes no sense. Clear all arrays.
2065  fPriority[2] = 0;
2066  if (fIndcZ) delete [] fIndcZ;
2067  fIndcZ = 0;
2068  fNz = 0;
2069  if (fZb) delete [] fZb;
2070  fZb = 0;
2071  fIbz = 0;
2072  if (fOBz) delete [] fOBz;
2073  fOBz = 0;
2074  fNoz = 0;
2075  } else {
2076  fPriority[2] = 1; // all in one slice
2077  }
2078  } else {
2079  fPriority[2] = 2; // check all
2080  }
2081 
2082  // store compacted boundaries
2083  if (fPriority[2]) {
2084  if (fZb) delete [] fZb;
2085  fZb = new Double_t[ib];
2086  memcpy(fZb, &temp[0], ib*sizeof(Double_t));
2087  fIbz = ib;
2088  }
2089 
2090 
2091  if (fPriority[2]==2) {
2092  //--- now build the lists of nodes in each slice of Y axis
2093  memset(ind, 0, (nmaxslices*nperslice)*sizeof(UChar_t));
2094  if (fOBz) delete [] fOBz;
2095  fNoz = fIbz-1; // number of different slices
2096  fOBz = new Int_t[fNoz]; // offsets in ind
2097  if (fOEz) delete [] fOEz;
2098  fOEz = new Int_t[fNoz]; // offsets in extra
2099  if (fNsliceZ) delete [] fNsliceZ;
2100  fNsliceZ = new Int_t[fNoz];
2101  current = 0;
2102  indextra = 0;
2103  //--- now loop all slices
2104  for (id=0; id<fNoz; id++) {
2105  fOBz[id] = current; // offset of dght list
2106  fOEz[id] = indextra; // offset in exta list for this slice
2107  fNsliceZ[id] = 0; // ndght in this slice
2108  extra[indextra] = extra[indextra+1] = 0; // no extra left/right
2109  nleft = nright = 0;
2110  bits = &ind[current]; // adress of bits for this slice
2111  xxmin = fZb[id];
2112  xxmax = fZb[id+1];
2113  for (Int_t ic=0; ic<nd; ic++) {
2114  xbmin = fBoxes[6*ic+5]-fBoxes[6*ic+2];
2115  xbmax = fBoxes[6*ic+5]+fBoxes[6*ic+2];
2116  ddx1 = xbmin-xxmax;
2117  if (ddx1>-1E-10) continue;
2118  ddx2 = xbmax-xxmin;
2119  if (ddx2<1E-10) continue;
2120  // daughter ic in interval
2121  //---> set the bit
2122  fNsliceZ[id]++;
2123  bitnumber = (UInt_t)ic;
2124  loc = bitnumber/8;
2125  bit = bitnumber%8;
2126  bits[loc] |= 1<<bit;
2127  //---> check if it is extra to left/right
2128  //--- left
2129  ddx1 = xbmin-xxmin;
2130  ddx2 = xbmax-xxmax;
2131  if ((id==0) || (ddx1>-1E-10)) {
2132  extra_left[nleft++] = ic;
2133  }
2134  //---right
2135  if ((id==(fNoz-1)) || (ddx2<1E-10)) {
2136  extra_right[nright++] = ic;
2137  }
2138  }
2139  //--- compute offset of next slice
2140  if (fNsliceZ[id]>0) current += nperslice;
2141  //--- copy extra candidates
2142  extra[indextra] = nleft;
2143  extra[indextra+1] = nright;
2144  if (nleft) memcpy(&extra[indextra+2], extra_left, nleft*sizeof(Int_t));
2145  if (nright) memcpy(&extra[indextra+2+nleft], extra_right, nright*sizeof(Int_t));
2146  indextra += 2+nleft+nright;
2147  }
2148  if (fIndcZ) delete [] fIndcZ;
2149  fNz = current;
2150  fIndcZ = new UChar_t[current];
2151  memcpy(fIndcZ, &ind[0], current*sizeof(UChar_t));
2152  if (fExtraZ) delete [] fExtraZ;
2153  fNez = indextra;
2154  if (indextra>nmaxslices*4) printf("Woops!!!\n");
2155  fExtraZ = new Int_t[indextra];
2156  memcpy(fExtraZ, extra, indextra*sizeof(Int_t));
2157  }
2158  delete [] boundaries;
2159  delete [] index;
2160  delete [] temp;
2161  delete [] ind;
2162  delete [] extra;
2163  delete [] extra_left;
2164  delete [] extra_right;
2165 
2166  if ((!fPriority[0]) && (!fPriority[1]) && (!fPriority[2])) {
2167  SetInvalid();
2168  if (nd>1) Error("SortAll", "Volume %s: Cannot make slices on any axis", fVolume->GetName());
2169  }
2170 }
2171 
2172 ////////////////////////////////////////////////////////////////////////////////
2173 /// Print the voxels.
2174 
2176 {
2177  if (NeedRebuild()) {
2178  TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
2179  vox->Voxelize();
2180  fVolume->FindOverlaps();
2181  }
2182  Int_t id, i;
2183  Int_t nd = fVolume->GetNdaughters();
2184  printf("Voxels for volume %s (nd=%i)\n", fVolume->GetName(), fVolume->GetNdaughters());
2185  printf("priority : x=%i y=%i z=%i\n", fPriority[0], fPriority[1], fPriority[2]);
2186 // return;
2187  Int_t nextra;
2188  Int_t nbytes = 1+((fVolume->GetNdaughters()-1)>>3);
2189  UChar_t byte, bit;
2190  UChar_t *slice;
2191  printf("XXX\n");
2192  if (fPriority[0]==2) {
2193  for (id=0; id<fIbx; id++) {
2194  printf("%15.10f\n",fXb[id]);
2195  if (id == (fIbx-1)) break;
2196  printf("slice %i : %i\n", id, fNsliceX[id]);
2197  if (fNsliceX[id]) {
2198  slice = &fIndcX[fOBx[id]];
2199  for (i=0; i<nbytes; i++) {
2200  byte = slice[i];
2201  for (bit=0; bit<8; bit++) {
2202  if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
2203  }
2204  }
2205  printf("\n");
2206  }
2207  GetExtraX(id,kTRUE,nextra);
2208  printf(" extra_about_left = %i\n", nextra);
2209  GetExtraX(id,kFALSE,nextra);
2210  printf(" extra_about_right = %i\n", nextra);
2211  }
2212  } else if (fPriority[0]==1) {
2213  printf("%15.10f\n",fXb[0]);
2214  for (id=0; id<nd; id++) printf(" %i ",id);
2215  printf("\n");
2216  printf("%15.10f\n",fXb[1]);
2217  }
2218  printf("YYY\n");
2219  if (fPriority[1]==2) {
2220  for (id=0; id<fIby; id++) {
2221  printf("%15.10f\n", fYb[id]);
2222  if (id == (fIby-1)) break;
2223  printf("slice %i : %i\n", id, fNsliceY[id]);
2224  if (fNsliceY[id]) {
2225  slice = &fIndcY[fOBy[id]];
2226  for (i=0; i<nbytes; i++) {
2227  byte = slice[i];
2228  for (bit=0; bit<8; bit++) {
2229  if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
2230  }
2231  }
2232  }
2233  GetExtraY(id,kTRUE,nextra);
2234  printf(" extra_about_left = %i\n", nextra);
2235  GetExtraY(id,kFALSE,nextra);
2236  printf(" extra_about_right = %i\n", nextra);
2237  }
2238  } else if (fPriority[1]==1) {
2239  printf("%15.10f\n",fYb[0]);
2240  for (id=0; id<nd; id++) printf(" %i ",id);
2241  printf("\n");
2242  printf("%15.10f\n",fYb[1]);
2243  }
2244 
2245  printf("ZZZ\n");
2246  if (fPriority[2]==2) {
2247  for (id=0; id<fIbz; id++) {
2248  printf("%15.10f\n", fZb[id]);
2249  if (id == (fIbz-1)) break;
2250  printf("slice %i : %i\n", id, fNsliceZ[id]);
2251  if (fNsliceZ[id]) {
2252  slice = &fIndcZ[fOBz[id]];
2253  for (i=0; i<nbytes; i++) {
2254  byte = slice[i];
2255  for (bit=0; bit<8; bit++) {
2256  if (byte & (1<<bit)) printf(" %i ", 8*i+bit);
2257  }
2258  }
2259  printf("\n");
2260  }
2261  GetExtraZ(id,kTRUE,nextra);
2262  printf(" extra_about_left = %i\n", nextra);
2263  GetExtraZ(id,kFALSE,nextra);
2264  printf(" extra_about_right = %i\n", nextra);
2265  }
2266  } else if (fPriority[2]==1) {
2267  printf("%15.10f\n",fZb[0]);
2268  for (id=0; id<nd; id++) printf(" %i ",id);
2269  printf("\n");
2270  printf("%15.10f\n",fZb[1]);
2271  }
2272 }
2273 
2274 ////////////////////////////////////////////////////////////////////////////////
2275 /// print the voxel containing point
2276 
2278 {
2279  if (NeedRebuild()) {
2280  TGeoVoxelFinder *vox = (TGeoVoxelFinder*)this;
2281  vox->Voxelize();
2282  fVolume->FindOverlaps();
2283  }
2284  Int_t im=0;
2285  if (fPriority[0]) {
2286  im = TMath::BinarySearch(fIbx, fXb, point[0]);
2287  if ((im==-1) || (im==fIbx-1)) {
2288  printf("Voxel X limits: OUT\n");
2289  } else {
2290  printf("Voxel X limits: %g %g\n", fXb[im], fXb[im+1]);
2291  }
2292  }
2293  if (fPriority[1]) {
2294  im = TMath::BinarySearch(fIby, fYb, point[1]);
2295  if ((im==-1) || (im==fIby-1)) {
2296  printf("Voxel Y limits: OUT\n");
2297  } else {
2298  printf("Voxel Y limits: %g %g\n", fYb[im], fYb[im+1]);
2299  }
2300  }
2301  if (fPriority[2]) {
2302  im = TMath::BinarySearch(fIbz, fZb, point[2]);
2303  if ((im==-1) || (im==fIbz-1)) {
2304  printf("Voxel Z limits: OUT\n");
2305  } else {
2306  printf("Voxel Z limits: %g %g\n", fZb[im], fZb[im+1]);
2307  }
2308  }
2309 }
2310 ////////////////////////////////////////////////////////////////////////////////
2311 /// Voxelize attached volume according to option
2312 /// If the volume is an assembly, make sure the bbox is computed.
2313 
2315 {
2317  Int_t nd = fVolume->GetNdaughters();
2318  TGeoVolume *vd;
2319  for (Int_t i=0; i<nd; i++) {
2320  vd = fVolume->GetNode(i)->GetVolume();
2321  if (vd->IsAssembly()) vd->GetShape()->ComputeBBox();
2322  }
2323  BuildVoxelLimits();
2324  SortAll();
2326 }
2327 ////////////////////////////////////////////////////////////////////////////////
2328 /// Stream an object of class TGeoVoxelFinder.
2329 
2330 void TGeoVoxelFinder::Streamer(TBuffer &R__b)
2331 {
2332  if (R__b.IsReading()) {
2333  UInt_t R__s, R__c;
2334  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2335  if (R__v > 2) {
2336  R__b.ReadClassBuffer(TGeoVoxelFinder::Class(), this, R__v, R__s, R__c);
2337  return;
2338  }
2339  // Process old versions of the voxel finder. Just read the data
2340  // from the buffer in a temp variable then mark voxels as garbage.
2341  UChar_t *dummy = new UChar_t[R__c-2];
2342  R__b.ReadFastArray(dummy, R__c-2);
2343  delete [] dummy;
2344  SetInvalid(kTRUE);
2345  } else {
2347  }
2348 }
Statefull info for the current geometry level.
Definition: TGeoStateInfo.h:23
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
Bool_t IsReading() const
Definition: TBuffer.h:83
float xmin
Definition: THbookFile.cxx:93
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
Bool_t Union(Int_t n1, UChar_t *array1, TGeoStateInfo &td)
make union of older bits with new array printf("Union - one slice\n");
Box class.
Definition: TGeoBBox.h:19
Int_t fVoxSlices[3]
Definition: TGeoStateInfo.h:39
virtual void Voxelize(Option_t *option="")
Voxelize attached volume according to option If the volume is an assembly, make sure the bbox is comp...
short Version_t
Definition: RtypesCore.h:61
virtual Double_t GetDX() const
Definition: TGeoBBox.h:72
void SetCylVoxels(Bool_t flag=kTRUE)
Definition: TGeoVolume.h:229
const char Option_t
Definition: RtypesCore.h:62
Geometrical transformation package.
Definition: TGeoMatrix.h:40
float ymin
Definition: THbookFile.cxx:93
virtual Int_t * GetCheckList(const Double_t *point, Int_t &nelem, TGeoStateInfo &td)
get the list of daughter indices for which point is inside their bbox
TGeoNode * GetNode(const char *name) const
get the pointer to a daughter node
Int_t * GetExtraZ(Int_t islice, Bool_t left, Int_t &nextra) const
Return the list of extra candidates in a given Z slice compared to another (left or right) ...
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition: TGeoVolume.h:61
Bool_t Intersect(Int_t n1, UChar_t *array1, Int_t &nf, Int_t *result)
return the list of nodes corresponding to one array of bits
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
Int_t * GetExtraX(Int_t islice, Bool_t left, Int_t &nextra) const
Return the list of extra candidates in a given X slice compared to another (left or right) ...
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
UChar_t * fVoxBits1
Definition: TGeoStateInfo.h:38
Double_t GetStep() const
Definition: TGeoManager.h:382
TGeoVoxelFinder & operator=(const TGeoVoxelFinder &)
assignment operator
const char * Class
Definition: TXMLSetup.cxx:64
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
virtual void SortCrossedVoxels(const Double_t *point, const Double_t *dir, TGeoStateInfo &td)
get the list in the next voxel crossed by a ray
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
static Bool_t IsSameWithinTolerance(Double_t a, Double_t b)
Check if two numbers differ with less than a tolerance.
Definition: TGeoShape.cxx:328
Bool_t NeedRebuild() const
virtual Int_t * GetNextVoxel(const Double_t *point, const Double_t *dir, Int_t &ncheck, TGeoStateInfo &td)
get the list of new candidates for the next voxel crossed by current ray printf("### GetNextVoxel\n")...
static Double_t Tolerance()
Definition: TGeoShape.h:93
Int_t GetNdaughters() const
Definition: TGeoVolume.h:362
void SetInvalid(Bool_t flag=kTRUE)
void PrintVoxelLimits(const Double_t *point) const
print the voxel containing point
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMath.h:989
virtual TGeoMatrix * GetMatrix() const =0
TObject & operator=(const TObject &rhs)
TObject assignment operator.
Definition: TObject.cxx:103
virtual void Print(Option_t *option="") const
Print the voxels.
Int_t * GetExtraY(Int_t islice, Bool_t left, Int_t &nextra) const
Return the list of extra candidates in a given Y slice compared to another (left or right) ...
XFontStruct * id
Definition: TGX11.cxx:108
void SetBoxPoints(Double_t *points) const
Fill box vertices to an array.
Definition: TGeoBBox.cxx:940
Double_t * fBoxes
unsigned char byte
Definition: gifdecode.c:10
void SortAll(Option_t *option="")
order bounding boxes along x, y, z
Int_t * GetVoxelCandidates(Int_t i, Int_t j, Int_t k, Int_t &ncheck, TGeoStateInfo &td)
get the list of candidates in voxel (i,j,k) - no check
void SetNeedRebuild(Bool_t flag=kTRUE)
float ymax
Definition: THbookFile.cxx:93
TPaveText * pt
virtual void FindOverlaps(Int_t inode) const
create the list of nodes for which the bboxes overlap with inode&#39;s bbox
Double_t fVoxLimits[3]
Definition: TGeoStateInfo.h:42
Double_t fVoxInvdir[3]
Definition: TGeoStateInfo.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
TGeoVoxelFinder()
Default constructor.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
virtual const Double_t * GetOrigin() const
Definition: TGeoBBox.h:75
Double_t E()
Definition: TMath.h:54
float xmax
Definition: THbookFile.cxx:93
Bool_t GetIndices(const Double_t *point, TGeoStateInfo &td)
Get indices for current slices on x, y, z.
virtual Double_t GetDY() const
Definition: TGeoBBox.h:73
Bool_t IsSafeVoxel(const Double_t *point, Int_t inode, Double_t minsafe) const
Computes squared distance from POINT to the voxel(s) containing node INODE.
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void LocalToMaster(const Double_t *local, Double_t *master) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
Definition: TGeoMatrix.cxx:389
virtual Double_t Efficiency()
Compute voxelization efficiency.
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
Int_t fVoxInc[3]
Definition: TGeoStateInfo.h:40
TGeoVolume * fVolume
#define ClassImp(name)
Definition: Rtypes.h:279
Int_t * GetValidExtra(Int_t *list, Int_t &ncheck, TGeoStateInfo &td)
Get extra candidates that are not contained in current check list.
R__EXTERN TGeoManager * gGeoManager
Definition: TGeoManager.h:554
double Double_t
Definition: RtypesCore.h:55
virtual Int_t * GetNextCandidates(const Double_t *point, Int_t &ncheck, TGeoStateInfo &td)
Returns list of new candidates in next voxel.
void DaughterToMother(Int_t id, const Double_t *local, Double_t *master) const
convert a point from the local reference system of node id to reference system of mother volume ...
static RooMathCoreReg dummy
Int_t * fVoxCheckList
Definition: TGeoStateInfo.h:37
Finder class handling voxels.
virtual void ComputeBBox()=0
static Double_t Big()
Definition: TGeoShape.h:90
Mother of all ROOT objects.
Definition: TObject.h:37
void BuildVoxelLimits()
build the array of bounding boxes of the nodes inside
Bool_t IntersectAndStore(Int_t n1, UChar_t *array1, TGeoStateInfo &td)
return the list of nodes corresponding to one array of bits
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition: TGeoNode.h:51
virtual ~TGeoVoxelFinder()
Destructor.
Int_t GetNcandidates(TGeoStateInfo &td) const
double result[121]
unsigned char UChar_t
Definition: RtypesCore.h:34
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
void FindOverlaps() const
loop all nodes marked as overlaps and find overlapping brothers
Int_t fVoxNcandidates
Definition: TGeoStateInfo.h:35
TGeoShape * GetShape() const
Definition: TGeoVolume.h:204
Long64_t LocMin(Long64_t n, const T *a)
Definition: TMath.h:682
const Bool_t kTRUE
Definition: Rtypes.h:91
TGeoVolume * GetVolume() const
Definition: TGeoNode.h:106
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMath.h:931
void SetOverlaps(Int_t *ovlp, Int_t novlp)
set the list of overlaps for this node (ovlp must be created with operator new)
Definition: TGeoNode.cxx:675
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual Double_t GetDZ() const
Definition: TGeoBBox.h:74
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.