Geant4  10.00.p02
UVoxelizer.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * This Software is part of the AIDA Unified Solids Library package *
4 // * See: https://aidasoft.web.cern.ch/USolids *
5 // ********************************************************************
6 //
7 // $Id:$
8 //
9 // --------------------------------------------------------------------
10 //
11 // UVoxelizer
12 //
13 // 19.10.12 Marek Gayer
14 // Created from original implementation in ROOT
15 // --------------------------------------------------------------------
16 
17 #include <iostream>
18 #include <iomanip>
19 #include <sstream>
20 #include <algorithm>
21 #include <set>
22 
23 #include "VUSolid.hh"
24 #include "UUtils.hh"
25 #include "UOrb.hh"
26 #include "UVoxelizer.hh"
27 
28 using namespace std;
29 
30 //______________________________________________________________________________
31 UVoxelizer::UVoxelizer() : fBoundingBox("TessBBox", 1, 1, 1)
32 {
34 
36 
38 
39 #ifndef USOLIDSONLY
41 #endif // USOLIDSONLY
42 }
43 
44 //______________________________________________________________________________
46 {
47 }
48 
49 
51 {
52  // by reserving the size of candidates, we would avoid reallocation of
53  // the vector which could cause fragmentation
54  vector<int> xyz(3), candidates(fTotalCandidates);
55  const vector<int> empty(0);
56  int max[3];
57 
58  for (int i = 0; i <= 2; ++i) max[i] = fBoundaries[i].size();
59  unsigned int size = max[0] * max[1] * max[2];
60 
61  fEmpty.Clear();
62  fEmpty.ResetBitNumber(size - 1);
63  fEmpty.ResetAllBits(true);
64 
65  for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])
66  {
67  for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1])
68  {
69  for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[0])
70  {
71  if (GetCandidatesVoxelArray(xyz, candidates))
72  {
73  int index = GetVoxelsIndex(xyz);
74  fEmpty.SetBitNumber(index, false);
75  // rather than assigning directly with:
76  // "fCandidates[index] = candidates;", in an effort to ensure that
77  // capacity would be just exact, we rather use following 3 lines:
78  vector<int>& c = (fCandidates[index] = empty);
79  c.reserve(candidates.size());
80  c.assign(candidates.begin(), candidates.end());
81  }
82  }
83  }
84  }
85 #ifdef USPECSDEBUG
86  cout << "Non-empty voxels count: " << fCandidates.size() << endl;
87 #endif
88 }
89 
90 #ifdef USOLIDSONLY
91 //______________________________________________________________________________
92 void UVoxelizer::BuildVoxelLimits(vector<VUSolid*>& solids, vector<UTransform3D*>& transforms)
93 {
94  // "BuildVoxelLimits"'s aim is to store the coordinates of the origin as well as
95  // the half lengths related to the bounding box of each node.
96  // These quantities are stored in the array "fBoxes" (6 different values per
97  // node.
98  if (int numNodes = solids.size()) // Number of nodes in "multiUnion"
99  {
100  fBoxes.resize(numNodes); // Array which will store the half lengths
101  fNPerSlice = 1 + (fBoxes.size() - 1) / (8 * sizeof(unsigned int));
102 
103  // related to a particular node, but also
104  // the coordinates of its origin
105 
106  UVector3 toleranceVector;
107  toleranceVector.Set(fTolerance);
108 
109  for (int i = 0; i < numNodes; ++i)
110  {
111  VUSolid& solid = *solids[i];
112  UTransform3D& transform = *transforms[i];
113  UVector3 min, max;
114  solid.Extent(min, max);
115  if (solid.GetEntityType() == "Orb")
116  {
117  UOrb& orb = *(UOrb*) &solid;
118  UVector3 orbToleranceVector;
119  double tolerance = orb.GetRadialTolerance() / 2.0;
120  orbToleranceVector.Set(tolerance);
121  min -= orbToleranceVector;
122  max += orbToleranceVector;
123  }
124  else
125  {
126  min -= toleranceVector;
127  max += toleranceVector;
128  }
129  UUtils::TransformLimits(min, max, transform);
130 
131  fBoxes[i].hlen = (max - min) / 2;
132  fBoxes[i].pos = transform.fTr;
133  }
134  fTotalCandidates = fBoxes.size();
135  }
136 }
137 #endif // USOLIDSONLY
138 
139 void UVoxelizer::BuildVoxelLimits(vector<VUFacet*>& facets)
140 {
141  // "BuildVoxelLimits"'s aim is to store the coordinates of the origin as well as
142  // the half lengths related to the bounding box of each node.
143  // These quantities are stored in the array "fBoxes" (6 different values per
144  // node.
145  if (int numNodes = facets.size()) // Number of nodes in "multiUnion"
146  {
147  fBoxes.resize(numNodes); // Array which will store the half lengths
148  fNPerSlice = 1 + (fBoxes.size() - 1) / (8 * sizeof(unsigned int));
149 
150  UVector3 toleranceVector;
151  toleranceVector.Set(10 * fTolerance);
152 
153  for (int i = 0; i < numNodes; ++i)
154  {
155  VUFacet& facet = *facets[i];
156  UVector3 min, max;
157  UVector3 x(1, 0, 0), y(0, 1, 0), z(0, 0, 1);
158  UVector3 extent;
159  max.Set(facet.Extent(x), facet.Extent(y), facet.Extent(z));
160  min.Set(-facet.Extent(-x), -facet.Extent(-y), -facet.Extent(-z));
161  min -= toleranceVector;
162  max += toleranceVector;
163  UVector3 hlen = (max - min) / 2;
164  fBoxes[i].hlen = hlen;
165  fBoxes[i].pos = min + hlen;
166  }
167  fTotalCandidates = fBoxes.size();
168  }
169 }
170 
171 
172 //______________________________________________________________________________
174 {
175  // "DisplayVoxelLimits" displays the dX, dY, dZ, pX, pY and pZ for each node
176  int numNodes = fBoxes.size();
177  int oldprc = cout.precision();
178  for (int i = 0; i < numNodes; ++i)
179  {
180  cout << setw(10) << setiosflags(ios::fixed) << setprecision(16) <<
181  " -> Node " << i + 1 << ":\n" <<
182  "\t * [x,y,z] = " << fBoxes[i].hlen <<
183  "\t * [x,y,z] = " << fBoxes[i].pos << "\n";
184  }
185  cout.precision(oldprc) ;
186 }
187 
188 //______________________________________________________________________________
189 void UVoxelizer::CreateSortedBoundary(vector<double>& boundary, int axis)
190 {
191  // "CreateBoundaries"'s aim is to determine the slices induced by the bounding fBoxes,
192  // along each axis. The created boundaries are stored in the array "boundariesRaw"
193  int numNodes = fBoxes.size(); // Number of nodes in structure of "UMultiUnion" type
194  // Determination of the boundaries along x, y and z axis:
195  for (int i = 0 ; i < numNodes; ++i)
196  {
197  // For each node, the boundaries are created by using the array "fBoxes"
198  // built in method "BuildVoxelLimits":
199  double p = fBoxes[i].pos[axis], d = fBoxes[i].hlen[axis];
200  // x boundaries
201  boundary[2 * i] = p - d;
202  boundary[2 * i + 1] = p + d;
203  }
204  sort(boundary.begin(), boundary.end());
205 }
206 
208 {
209  // "SortBoundaries" orders the boundaries along each axis (increasing order)
210  // and also does not take into account redundant boundaries, ie if two boundaries
211  // are separated by a distance strictly inferior to "tolerance".
212  // The sorted boundaries are respectively stored in:
213  // * boundaries[0..2]
214 
215  // In addition, the number of elements contained in the three latter arrays are
216  // precise thanks to variables: boundariesCountX, boundariesCountY and boundariesCountZ.
217 
218  if (int numNodes = fBoxes.size())
219  {
220  const double tolerance = fTolerance / 100.0; // Minimal distance to discriminate two boundaries.
221  vector<double> sortedBoundary(2 * numNodes);
222 
223  int considered;
224 
225  for (int j = 0; j <= 2; ++j)
226  {
227  CreateSortedBoundary(sortedBoundary, j);
228  vector<double>& boundary = fBoundaries[j];
229  boundary.clear();
230 
231  considered = 0;
232 
233  for (int i = 0 ; i < 2 * numNodes; ++i)
234  {
235  double newBoundary = sortedBoundary[i];
236  int size = boundary.size();
237  if (!size || abs(boundary[size - 1] - newBoundary) > tolerance)
238  {
239  considered++;
240  {
241  boundary.push_back(newBoundary);
242  continue;
243  }
244  }
245  // If two successive boundaries are too close from each other, only the first one is considered
246  {
247  // cout << "Skipping boundary [" << j << "] : " << i << endl;
248  }
249  }
250 
251  int n = boundary.size();
252  int max = 100000;
253  if (n > max / 2)
254  {
255  int skip = n / (max / 2); // n has to be 2x bigger then 50.000. therefore only from 100.000 re
256  vector<double> reduced;
257  for (int i = 0; i < n; ++i)
258  {
259  // 50 ok for 2k, 1000, 2000
260  int size = boundary.size();
261  if (i % skip == 0 || i == 0 || i == size - 1) // this condition of merging boundaries was wrong, it did not count with right part, which can be completely ommited and not included in final consideration. Now should be OK
262  reduced.push_back(boundary[i]);
263  }
264  boundary = reduced;
265  }
266  }
267  }
268 }
269 
271 {
272  char axis[3] = {'X', 'Y', 'Z'};
273  for (int i = 0; i <= 2; ++i)
274  {
275  cout << " * " << axis[i] << " axis:" << endl << " | ";
277  }
278 }
279 
280 //______________________________________________________________________________
281 void UVoxelizer::DisplayBoundaries(vector<double>& boundaries)
282 {
283  // Prints the positions of the boundaries of the slices on the three axis:
284 
285  int count = boundaries.size();
286  int oldprc = cout.precision();
287  for (int i = 0; i < count; ++i)
288  {
289  cout << setw(10) << setiosflags(ios::fixed) << setprecision(16) << boundaries[i];
290  // printf("%19.15f ", boundaries[0][i]);
291  // cout << boundaries[0][i] << " ";
292  if (i != count - 1) cout << "-> ";
293  }
294  cout << "|" << endl << "Number of boundaries: " << count << endl;
295  cout.precision(oldprc) ;
296 }
297 
298 void UVoxelizer::BuildBitmasks(std::vector<double> boundaries[], UBits bitmasks[])
299 {
300  // "BuildListNodes" stores in the bitmasks solids present in each slice along an axis.
301  // const double localTolerance = 0;
302  int numNodes = fBoxes.size();
303  int bitsPerSlice = GetBitsPerSlice();
304 
305  for (int k = 0; k < 3; k++)
306  {
307  int total = 0;
308  vector<double>& boundary = boundaries[k];
309  int voxelsCount = boundary.size() - 1;
310  UBits& bitmask = bitmasks[k];
311 
312  if (bitmasks != NULL)
313  {
314  bitmask.Clear();
315  bitmask.SetBitNumber(voxelsCount * bitsPerSlice - 1, false); // it is here so we can set the maximum number of bits. this line will rellocate the memory and set all to zero
316  }
317  vector<int>& candidatesCount = fCandidatesCounts[k];
318  candidatesCount.resize(voxelsCount);
319 
320  for (int i = 0 ; i < voxelsCount; ++i) candidatesCount[i] = 0;
321 
322  // Loop on the nodes, number of slices per axis
323  for (int j = 0 ; j < numNodes; j++)
324  {
325  // Determination of the minimum and maximum position along x
326  // of the bounding boxe of each node:
327  double p = fBoxes[j].pos[k], d = fBoxes[j].hlen[k];
328 
329  double min = p - d; // - localTolerance;
330  double max = p + d; // + localTolerance;
331 
332  int i = BinarySearch(boundary, min);
333  if (i < 0) i = 0;
334 
335  do
336  {
337  if (bitmasks != NULL)
338  bitmask.SetBitNumber(i * bitsPerSlice + j);
339 
340  candidatesCount[i]++;
341  total++;
342  i++;
343  }
344  while (max > boundary[i] && i < voxelsCount);
345  }
346 
347 #ifdef DEBUG
348  string fileName = "reduced" + UUtils::ToString(k);
349  UUtils::SaveVectorToExternalFile(candidatesCount, fileName);
350 #endif
351 
352  /*
353  if (voxelsCount < 20000)
354  {
355  int total2 = 0;
356  for(int i = 0 ; i < voxelsCount; ++i)
357  {
358  candidatesCount[i] = 0;
359  // Loop on the nodes, number of slices per axis
360  for(int j = 0 ; j < numNodes; j++)
361  {
362  // Determination of the minimum and maximum position along x
363  // of the bounding boxe of each node:
364  double p = fBoxes[j].pos[k], d = fBoxes[j].hlen[k];
365  double leftBoundary = boundary[i];
366  double rightBoundary = boundary[i+1];
367  double min = p - d; // - localTolerance;
368  double max = p + d; // + localTolerance;
369  if (min < rightBoundary && max > leftBoundary)
370  {
371  // Storage of the number of the node in the array:
372  bitmask.SetBitNumber(i*bitsPerSlice+j);
373  candidatesCount[i]++;
374  total2++;
375  }
376  }
377  }
378  if (total2 != total)
379  total2 = total;
380  }
381  */
382  }
383 #ifdef USPECSDEBUG
384  cout << "Build list nodes completed" << endl;
385 #endif
386 }
387 
388 //______________________________________________________________________________
390 {
391  // Decodes the candidates in mask as string.
392  stringstream ss;
393  int numNodes = fBoxes.size();
394 
395  for (int i = 0; i < numNodes; ++i)
396  if (bits.TestBitNumber(i)) ss << i + 1 << " ";
397  const string& result = ss.str();
398  return result;
399 }
400 
401 
402 //______________________________________________________________________________
404 {
405  char axis[3] = {'X', 'Y', 'Z'};
406  // Prints which solids are present in the slices previously elaborated.
407  int size = 8 * sizeof(int) * fNPerSlice;
408  UBits bits(size);
409 
410  for (int j = 0; j <= 2; ++j)
411  {
412  cout << " * " << axis[j] << " axis:" << endl;
413  int count = fBoundaries[j].size();
414  for (int i = 0; i < count - 1; ++i)
415  {
416  cout << " Slice #" << i + 1 << ": [" << fBoundaries[j][i] << " ; " << fBoundaries[j][i + 1] << "] -> ";
417  bits.Set(size, (const char*)fBitmasks[j].fAllBits + i * fNPerSlice * sizeof(int));
418  string result = GetCandidatesAsString(bits);
419  cout << "[ " << result.c_str() << "] " << endl;
420  }
421  }
422 }
423 
425 {
426  UVector3 min(fBoundaries[0].front(), fBoundaries[1].front(), fBoundaries[2].front());
427  UVector3 max(fBoundaries[0].back(), fBoundaries[1].back(), fBoundaries[2].back());
428  BuildBoundingBox(min, max);
429 }
430 
431 void UVoxelizer::BuildBoundingBox(UVector3& amin, UVector3& amax, double tolerance)
432 {
433  for (int i = 0; i <= 2; ++i)
434  {
435  double min = amin[i];
436  double max = amax[i];
437  fBoundingBoxSize[i] = (max - min) / 2 + tolerance * 0.5;
438  fBoundingBoxCenter[i] = min + fBoundingBoxSize[i];
439  }
441 }
442 
443 
444 // algorithm -
445 
446 // in order to get balanced voxels, merge should always unite those regions, where the number of voxels is least
447 // the number
448 
449 // we will keep sorted list (std::set) with all voxels. there will be comparator function between two voxels,
450 // which will tell if voxel is less by looking at his right neighbor.
451 // first, we will add all the voxels into the tree.
452 // we will be pick the first item in the tree, merging it, adding the right merged voxel into the a list for
453 // future reduction (fBitmasks will be rebuilded later, therefore they need not to be updated).
454 // the merged voxel need to be added to the tree again, so it's position would be updated
455 
456 
458 {
459  public:
460 
461  vector<UVoxelInfo>& fVoxels;
462 
463  UVoxelComparator(vector<UVoxelInfo>& voxels) : fVoxels(voxels)
464  {
465 
466  }
467 
468  bool operator()(int l, int r)
469  {
470  UVoxelInfo& lv = fVoxels[l], &rv = fVoxels[r];
471  int left = lv.count + fVoxels[lv.next].count;
472  int right = rv.count + fVoxels[rv.next].count;;
473  return (left == right) ? l < r : left < right;
474  }
475 };
476 
477 void UVoxelizer::SetReductionRatio(int maxVoxels, UVector3& reductionRatio)
478 {
479  double maxTotal = (double) fCandidatesCounts[0].size() * fCandidatesCounts[1].size() * fCandidatesCounts[2].size();
480 
481  if (maxVoxels > 0 && maxVoxels < maxTotal)
482  {
483  double ratio = (double) maxVoxels / maxTotal;
484  ratio = pow(ratio, 1. / 3.);
485  if (ratio > 1) ratio = 1;
486  reductionRatio.Set(ratio);
487  }
488 }
489 
490 void UVoxelizer::BuildReduceVoxels(vector<double> boundaries[], UVector3 reductionRatio)
491 {
492  for (int k = 0; k <= 2; ++k)
493  {
494  vector<int>& candidatesCount = fCandidatesCounts[k];
495  int max = candidatesCount.size();
496  vector<UVoxelInfo> voxels(max);
497  UVoxelComparator comp(voxels);
498  set<int, UVoxelComparator> voxelSet(comp);
499  vector<int> mergings;
500 
501  for (int j = 0; j < max; ++j)
502  {
503  UVoxelInfo& voxel = voxels[j];
504  voxel.count = candidatesCount[j];
505  voxel.previous = j - 1;
506  voxel.next = j + 1;
507  voxels[j] = voxel;
508  }
509  // voxels[max - 1].count = 99999999999;
510 
511  for (int j = 0; j < max - 1; ++j) voxelSet.insert(j); // we go to size-1 to make sure we will not merge the last element
512 
513  double reduction = reductionRatio[k];
514  if (reduction != 0)
515  {
516  int count = 0, currentCount;
517  while ((currentCount = voxelSet.size()) > 2)
518  {
519  double currentRatio = 1 - (double) count / max;
520  if (currentRatio <= reduction && currentCount <= 1000)
521  break;
522  const int pos = *voxelSet.begin();
523  mergings.push_back(pos + 1);
524 
525  UVoxelInfo& voxel = voxels[pos];
526  UVoxelInfo& nextVoxel = voxels[voxel.next];
527 
528  if (voxelSet.erase(pos) != 1)
529  {
530  ;// k = k;
531  }
532  if (voxel.next != max - 1)
533  if (voxelSet.erase(voxel.next) != 1)
534  {
535  // k = k;
536  }
537  if (voxel.previous != -1)
538  if (voxelSet.erase(voxel.previous) != 1)
539  {
540  // k = k;
541  }
542  nextVoxel.count += voxel.count;
543  voxel.count = 0;
544  nextVoxel.previous = voxel.previous;
545 
546  if (voxel.next != max - 1)
547  voxelSet.insert(voxel.next);
548 
549  if (voxel.previous != -1)
550  {
551  voxels[voxel.previous].next = voxel.next;
552  voxelSet.insert(voxel.previous);
553  }
554  count++;
555  }
556  }
557 
558  // for (int i = 0; i < max; ++i) cout << voxels[i].count << ", ";
559 
560  if (mergings.size())
561  {
562  sort(mergings.begin(), mergings.end());
563 
564  const vector<double>& boundary = boundaries[k];
565  int mergingsSize = mergings.size();
566  vector<double> reducedBoundary;
567  int skip = mergings[0], i = 0;
568  max = boundary.size();
569  for (int j = 0; j < max; ++j)
570  {
571  if (j != skip)
572  reducedBoundary.push_back(boundary[j]);
573  else if (++i < mergingsSize)
574  {
575  skip = mergings[i];
576  }
577  }
578  boundaries[k] = reducedBoundary;
579  }
580  }
581 }
582 
583 
584 void UVoxelizer::BuildReduceVoxels2(vector<double> boundaries[], UVector3 reductionRatio)
585 {
586  for (int k = 0; k <= 2; ++k)
587  {
588  vector<int>& candidatesCount = fCandidatesCounts[k];
589  int max = candidatesCount.size();
590  int total = 0;
591  for (int i = 0; i < max; ++i) total += candidatesCount[i];
592 
593  double reduction = reductionRatio[k];
594  if (reduction == 0)
595  break;
596 
597  int destination = (int)(reduction * max) + 1;
598  if (destination > 1000) destination = 1000;
599  if (destination < 2) destination = 2;
600  double average = ((double)total / max) / reduction;
601 
602  vector<int> mergings;
603 
604  vector<double>& boundary = boundaries[k];
605  vector<double> reducedBoundary(destination);
606 
607  int sum = 0, cur = 0;
608  for (int i = 0; i < max; ++i)
609 
610  {
611  sum += candidatesCount[i];
612  if (sum > average * (cur + 1) || i == 0)
613  {
614  double val = boundary[i];
615  reducedBoundary[cur] = val;
616  cur++;
617  if (cur == destination)
618  break;
619  }
620  }
621  reducedBoundary[destination - 1] = boundary[max];
622  boundaries[k] = reducedBoundary;
623  }
624 }
625 
626 #ifdef USOLIDSONLY
627 //______________________________________________________________________________
628 void UVoxelizer::Voxelize(vector<VUSolid*>& solids, vector<UTransform3D*>& transforms)
629 {
630  BuildVoxelLimits(solids, transforms);
631 
632  BuildBoundaries();
633 
635 
637 
638  BuildEmpty(); // these does not work well for multi-union, actually only makes performance slower, these are only pre-calculated but not used by multi-union
639 
640 // fBoxes.resize(0); // for multiunion, fBoxes are actually needed
641 
642  for (int i = 0; i < 3; ++i) fCandidatesCounts[i].resize(0);
643 }
644 #endif // USOLIDSONLY
645 
646 void UVoxelizer::CreateMiniVoxels(std::vector<double> boundaries[], UBits bitmasks[])
647 {
648  vector<int> voxel(3), maxVoxels(3);
649  for (int i = 0; i <= 2; ++i) maxVoxels[i] = boundaries[i].size();
650 
651  UVector3 point;
652  for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
653  {
654  for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
655  {
656  for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
657  {
658  vector<int> candidates;
659  if (GetCandidatesVoxelArray(voxel, bitmasks, candidates, NULL))
660  {
661  // find a box for corresponding non-empty voxel
662  UVoxelBox box;
663  for (int i = 0; i <= 2; ++i)
664  {
665  int index = voxel[i];
666  const vector<double>& boundary = boundaries[i];
667  double hlen = 0.5 * (boundary[index + 1] - boundary[index]);
668  box.hlen[i] = hlen;
669  box.pos[i] = boundary[index] + hlen;
670  }
671  fVoxelBoxes.push_back(box);
672  vector<int>(candidates).swap(candidates);
673  fVoxelBoxesCandidates.push_back(candidates);
674  }
675  }
676  }
677  }
678 }
679 
680 void UVoxelizer::Voxelize(vector<VUFacet*>& facets)
681 {
682  int maxVoxels = fMaxVoxels;
683  UVector3 reductionRatio = fReductionRatio;
684 
685  int size = facets.size();
686  if (size < 10)
687  for (int i = 0; i < (int) facets.size(); ++i)
688  if (facets[i]->GetNumberOfVertices() > 3) size++;
689 
690  if ((size >= 10 || maxVoxels > 0) && maxVoxels != 0 && maxVoxels != 1)
691  {
692  BuildVoxelLimits(facets);
693 
694  BuildBoundaries();
695 
696  BuildBitmasks(fBoundaries, NULL);
697 
698  if (maxVoxels < 0 && reductionRatio == UVector3())
699  {
700  /*
701  if (fTotalCandidates < 1000)
702  maxVoxels = 10 * fTotalCandidates;
703  else
704  {
705  if (fTotalCandidates < 10000) maxVoxels = 10000;
706  else maxVoxels = fTotalCandidates;
707  }
708  if (fTotalCandidates > 1000000) maxVoxels = 1000000;
709  */
710 
711  maxVoxels = fTotalCandidates;
712  if (fTotalCandidates > 1000000) maxVoxels = 1000000;
713  }
714 
715  SetReductionRatio(maxVoxels, reductionRatio);
716 
718 
719 #ifdef USPECSDEBUG
720  cout << "Total number of voxels: " << fCountOfVoxels << endl;
721 #endif
722 
723  BuildReduceVoxels2(fBoundaries, reductionRatio);
724 
726 
727 #ifdef USPECSDEBUG
728  cout << "Total number of voxels after reduction: " << fCountOfVoxels << endl;
729 #endif
730 
732 
733  UVector3 reductionRatioMini;
734 
735  UBits bitmasksMini[3];
736 
737  // section for building mini voxels
738  std::vector<double> miniBoundaries[3];
739 
740  for (int i = 0; i <= 2; ++i) miniBoundaries[i] = fBoundaries[i];
741 
742  int voxelsCountMini = (fCountOfVoxels >= 1000) ? 100 : fCountOfVoxels / 10;
743  // if (voxelCountMini < 8) voxelCountMini = 8;
744 
745 // voxelsCountMini = 1;
746 
747  SetReductionRatio(voxelsCountMini, reductionRatioMini);
748 
749  BuildReduceVoxels(miniBoundaries, reductionRatioMini);
750 
751 #ifdef USPECSDEBUG
752  int total = CountVoxels(miniBoundaries);
753  cout << "Total number of mini voxels: " << total << endl;
754 #endif
755 
756  BuildBitmasks(miniBoundaries, bitmasksMini);
757 
758  CreateMiniVoxels(miniBoundaries, bitmasksMini);
759 
760  BuildEmpty();
761 
762  // deallocate fields unnecessary during runtime
763  fBoxes.resize(0);
764 
765  for (int i = 0; i < 3; ++i)
766  {
767  fCandidatesCounts[i].resize(0);
768  fBitmasks[i].Clear();
769  }
770  }
771 }
772 
773 
774 //______________________________________________________________________________
775 // "GetCandidates" should compute which solids are possibly contained in
776 // the voxel defined by the three slices characterized by the passed indexes.
777 void UVoxelizer::GetCandidatesVoxel(vector<int>& voxels)
778 {
779  cout << " Candidates in voxel [" << voxels[0] << " ; " << voxels[1] << " ; " << voxels[2] << "]: ";
780  vector<int> candidates;
781  int count = GetCandidatesVoxelArray(voxels, candidates);
782  cout << "[ ";
783  for (int i = 0; i < count; ++i) cout << candidates[i];
784  cout << "] " << endl;
785 }
786 
787 #ifdef USOLIDSONLY
788 
789 inline void findComponents2(unsigned int mask, vector<int>& list, int i)
790 {
791  for (int bit = 0; bit < (int)(8 * sizeof(unsigned int)); bit++)
792  {
793  if (mask & 1)
794  list.push_back(8 * sizeof(unsigned int)*i + bit);
795  if (!(mask >>= 1)) break; // new
796  }
797 }
798 
799 inline void findComponents3(unsigned int mask, vector<int>& list, int i)
800 {
801  // nejrychlejsi asi bude: ve for cyclu traversovat pres vsechny byty:
802  // 1. voendovanou hodnotu pres 0xFF, aby zustal jen posledni byte
803  // 2. pokud 0, continue
804  // 3. najit prvni nastaveny bit pres lookup table
805  // 4. pricist 8*j k nalezenemu bitu, ulozit do seznamu
806  // 5. odecist 1 << bit, dokud neni *-*nula pokracovat na 3
807  // 6. posunout hodnotu do prava >> 8, pokracovat na 1
808 
809  for (int byte = 0; byte < (int)(sizeof(unsigned int)); byte++)
810  {
811  if (int maskByte = mask & 0xFF)
812  {
813  do
814  {
815  static const int firstBits[256] =
816  {
817  8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
818  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
819  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
820  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
821  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
822  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
823  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
824  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
825  7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
826  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
827  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
828  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
829  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
830  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
831  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
832  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
833  };
834 
835  int bit = firstBits[maskByte];
836  list.push_back(8 * (sizeof(unsigned int)*i + byte) + bit);
837  maskByte -= 1 << bit;
838  }
839  while (maskByte);
840  }
841  mask >>= 8;
842  }
843 }
844 
845 #endif // USOLIDSONLY
846 
847 void UVoxelizer::FindComponentsFastest(unsigned int mask, vector<int>& list, int i)
848 {
849  for (int byte = 0; byte < (int)(sizeof(unsigned int)); byte++)
850  {
851  if (int maskByte = mask & 0xFF)
852  {
853  for (int bit = 0; bit < 8; bit++)
854  {
855  if (maskByte & 1)
856  list.push_back(8 * (sizeof(unsigned int)*i + byte) + bit);
857  if (!(maskByte >>= 1)) break;
858  }
859  }
860  mask >>= 8;
861  }
862 }
863 
864 
865 //______________________________________________________________________________
866 // Method returning the candidates corresponding to the passed point
867 int UVoxelizer::GetCandidatesVoxelArray(const UVector3& point, vector<int>& list, UBits* crossed) const
868 {
869  list.clear();
870 
871  for (int i = 0; i <= 2; ++i)
872  if (point[i] < fBoundaries[i].front() || point[i] >= fBoundaries[i].back())
873  return 0;
874 
875  if (fTotalCandidates == 1)
876  {
877  list.push_back(0);
878  return 1;
879  }
880  else
881  {
882  if (fNPerSlice == 1)
883  {
884  unsigned int mask = 0xFFffFFff;
885  int slice;
886  if (fBoundaries[0].size() > 2)
887  {
888  slice = BinarySearch(fBoundaries[0], point.x);
889  if (!(mask = ((unsigned int*) fBitmasks[0].fAllBits)[slice])) return 0;
890  }
891  if (fBoundaries[1].size() > 2)
892  {
893  slice = BinarySearch(fBoundaries[1], point.y);
894  if (!(mask &= ((unsigned int*) fBitmasks[1].fAllBits)[slice]
895  )) return 0;
896  }
897  if (fBoundaries[2].size() > 2)
898  {
899  slice = BinarySearch(fBoundaries[2], point.z);
900  if (!(mask &= ((unsigned int*) fBitmasks[2].fAllBits)[slice]
901  )) return 0;
902  }
903  if (crossed && (!(mask &= ~((unsigned int*)crossed->fAllBits)[0]))) return 0;
904 
905  FindComponentsFastest(mask, list, 0);
906  }
907  else
908  {
909  unsigned int* masks[3], mask; // masks for X,Y,Z axis
910  for (int i = 0; i <= 2; ++i)
911  {
912  int slice = BinarySearch(fBoundaries[i], point[i]);
913  // if (slice < 0 || slice == fBoundaries[i].size()-1) return 0; // not neccesary anymore
914  masks[i] = ((unsigned int*) fBitmasks[i].fAllBits) + slice * fNPerSlice;
915  }
916  unsigned int* maskCrossed = crossed ? (unsigned int*)crossed->fAllBits : NULL;
917 
918  for (int i = 0 ; i < fNPerSlice; ++i)
919  {
920  // Logic "and" of the masks along the 3 axes x, y, z:
921  // removing "if (!" and ") continue" => slightly slower
922  if (!(mask = masks[0][i])) continue;
923  if (!(mask &= masks[1][i])) continue;
924  if (!(mask &= masks[2][i])) continue;
925  if (maskCrossed && !(mask &= ~maskCrossed[i])) continue;
926 
927  FindComponentsFastest(mask, list, i);
928  }
929  }
930  }
931  return list.size();
932 }
933 
934 
935 
936 
937 
938 int UVoxelizer::GetCandidatesVoxelArray(const vector<int>& voxels, const UBits bitmasks[], vector<int>& list, UBits* crossed) const
939 {
940  list.clear();
941 
942  if (fTotalCandidates == 1)
943  {
944  list.push_back(0);
945  return 1;
946  }
947  else
948  {
949  if (fNPerSlice == 1)
950  {
951  unsigned int mask;
952  if (!(mask = ((unsigned int*) bitmasks[0].fAllBits)[voxels[0]]
953  )) return 0;
954  if (!(mask &= ((unsigned int*) bitmasks[1].fAllBits)[voxels[1]]
955  )) return 0;
956  if (!(mask &= ((unsigned int*) bitmasks[2].fAllBits)[voxels[2]]
957  )) return 0;
958  if (crossed && (!(mask &= ~((unsigned int*)crossed->fAllBits)[0]))) return 0;
959 
960  FindComponentsFastest(mask, list, 0);
961  }
962  else
963  {
964  unsigned int* masks[3], mask; // masks for X,Y,Z axis
965  for (int i = 0; i <= 2; ++i)
966  masks[i] = ((unsigned int*) bitmasks[i].fAllBits) + voxels[i] * fNPerSlice;
967 
968  unsigned int* maskCrossed = crossed ? (unsigned int*)crossed->fAllBits : NULL;
969 
970  for (int i = 0 ; i < fNPerSlice; ++i)
971  {
972  // Logic "and" of the masks along the 3 axes x, y, z:
973  // removing "if (!" and ") continue" => slightly slower
974  if (!(mask = masks[0][i])) continue;
975  if (!(mask &= masks[1][i])) continue;
976  if (!(mask &= masks[2][i])) continue;
977  if (maskCrossed && !(mask &= ~maskCrossed[i])) continue;
978 
979  FindComponentsFastest(mask, list, i);
980  }
981  }
982  }
983  return list.size();
984 }
985 
986 
987 
988 //______________________________________________________________________________
989 // Method returning the candidates corresponding to the passed point
990 int UVoxelizer::GetCandidatesVoxelArray(const vector<int>& voxels, vector<int>& list, UBits* crossed) const
991 {
992  return GetCandidatesVoxelArray(voxels, fBitmasks, list, crossed);
993 }
994 
995 
996 
997 bool UVoxelizer::Contains(const UVector3& point) const
998 {
999  for (int i = 0; i < 3; ++i)
1000  if (point[i] < fBoundaries[i].front() || point[i] > fBoundaries[i].back())
1001  return false;
1002  return true;
1003 }
1004 
1005 
1006 
1007 double UVoxelizer::DistanceToFirst(const UVector3& point, const UVector3& direction) const
1008 {
1009  UVector3 pointShifted = point - fBoundingBoxCenter;
1010  double shift = fBoundingBox.DistanceToIn(pointShifted, direction);
1011  return shift;
1012 }
1013 
1014 double UVoxelizer::SafetyToBoundingBox(const UVector3& point) const
1015 {
1016  UVector3 pointShifted = point - fBoundingBoxCenter;
1017  double shift = MinDistanceToBox(pointShifted, fBoundingBoxSize);
1018  return shift;
1019 }
1020 
1021 double UVoxelizer::MinDistanceToBox(const UVector3& aPoint, const UVector3& f)
1022 {
1023  // Estimates the isotropic safety from a point outside the current solid to any
1024  // of its surfaces. The algorithm may be accurate or should provide a fast
1025  // underestimate.
1026  double safe, safx, safy, safz;
1027  safe = safx = -f.x + std::abs(aPoint.x);
1028  safy = -f.y + std::abs(aPoint.y);
1029  if (safy > safe) safe = safy;
1030  safz = -f.z + std::abs(aPoint.z);
1031  if (safz > safe) safe = safz;
1032  if (safe < 0.0) return 0.0; // point is inside
1033 // if (!aAccurate) return safe;
1034  double safsq = 0.0;
1035  int count = 0;
1036  if (safx > 0)
1037  {
1038  safsq += safx * safx;
1039  count++;
1040  }
1041  if (safy > 0)
1042  {
1043  safsq += safy * safy;
1044  count++;
1045  }
1046  if (safz > 0)
1047  {
1048  safsq += safz * safz;
1049  count++;
1050  }
1051  if (count == 1) return safe;
1052  return std::sqrt(safsq);
1053 }
1054 
1055 
1056 double UVoxelizer::DistanceToNext(const UVector3& point, const UVector3& direction, vector<int>& curVoxel) const
1057 {
1058  double shift = UUtils::kInfinity;
1059  int cur = 0; // the smallest index, which would be than increased
1060 
1061  for (int i = 0; i <= 2; ++i)
1062  {
1063  // Looking for the next voxels on the considered direction X,Y,Z axis
1064  const vector<double>& boundary = fBoundaries[i];
1065  int index = curVoxel[i];
1066  if (direction[i] >= 1e-10)
1067  {
1068  ++index;
1069 // if (boundary[++index] - point[i] < fTolerance)
1070 
1071 // if (++index >= (int) boundary.size() - 1)
1072 // exit = true;
1073 
1074 // make sure shift would be non-zero => not needed anymore
1075 
1076 // if (++index >= (int) boundary.size()) // the shift is not important, only is important to increase the boundary index, even if it would be zero, than we would in next steps always increase another dimension, so it would continue alright
1077 // continue;
1078  }
1079  else
1080  {
1081  if (direction[i] <= -1e-10)
1082  {
1083 // if (point[i] - boundary[index] < fTolerance) // make sure shift would be non-zero
1084 // if (--index < 0)
1085 // continue;
1086 
1087 // if (--index < 0)
1088 // exit = true;
1089  }
1090  else
1091  continue;
1092  }
1093  double dif = boundary[index] - point[i];
1094  double distance = dif / direction[i];
1095 
1096  if (shift > distance)
1097  {
1098  shift = distance;
1099  cur = i;
1100  }
1101  }
1102 
1103  if (shift != UUtils::kInfinity)
1104  {
1105  // updating current voxel using the index corresponding to the closest voxel boundary on the ray
1106  if (direction[cur] > 0)
1107  {
1108  if (++curVoxel[cur] >= (int) fBoundaries[cur].size() - 1)
1109  shift = UUtils::kInfinity;
1110  }
1111  else
1112  {
1113  if (--curVoxel[cur] < 0)
1114  shift = UUtils::kInfinity;
1115  }
1116  }
1117 
1118  return shift;
1119 }
1120 
1121 
1122 
1123 
1125 {
1126  fMaxVoxels = max;
1127  fReductionRatio.Set(0);
1128 }
1129 
1130 void UVoxelizer::SetMaxVoxels(const UVector3& ratioOfReduction)
1131 {
1132  fMaxVoxels = -1;
1133  fReductionRatio = ratioOfReduction;
1134 }
1135 
1137 {
1138  int size = fEmpty.GetNbytes();
1139  size += fBoxes.capacity() * sizeof(UVoxelBox);
1140  size += sizeof(double) * (fBoundaries[0].capacity() + fBoundaries[1].capacity() + fBoundaries[2].capacity());
1141  size += sizeof(int) * (fCandidatesCounts[0].capacity() + fCandidatesCounts[1].capacity() + fCandidatesCounts[2].capacity());
1142  size += fBitmasks[0].GetNbytes() + fBitmasks[1].GetNbytes() + fBitmasks[2].GetNbytes();
1143 
1144  int csize = fCandidates.size();
1145  for (int i = 0; i < csize; ++i)
1146  size += sizeof(vector<int>) + fCandidates[i].capacity() * sizeof(int);
1147 
1148  return size;
1149 }
1150 
1152 {
1153  fDefaultVoxelsCount = count;
1154 }
1155 
1157 {
1158  return fDefaultVoxelsCount;
1159 }
1160 
1162 
1163 #ifdef USOLIDSONLY
1164 
1165 /*
1166 // THIS METHOD IS NOT NECCESSARY. destructors are called automatically. it is enough to call destructor of
1167 // object which contains the voxel finder
1168 //
1169 inline void DeleteObjects()
1170 {
1171 for (int k = 0; k < 3; k++)
1172 {
1173 std::vector<double> &boundary = fBoundaries[k];
1174 boundary.resize(0);
1175 UBits &bitmask = fBitmasks[k];
1176 bitmask.Clear();
1177 bitmask.SetBitNumber(1, false); // it is here so we can set the maximum
1178 }
1179 }
1180 */
1181 
1182 /*
1183 UVoxelCandidatesIterator::UVoxelCandidatesIterator(const UVoxelizer &f, const UVector3 &point) : curInt(-1), curBit((int) (8*sizeof(unsigned int))), nextAvailable(true)
1184 {
1185  carNodes = f.fBoxes.size();
1186  if (carNodes > 1)
1187  {
1188  n = 1+(carNodes-1)/(8*sizeof(unsigned int));
1189  int sliceX = UVoxelizer::BinarySearch(f.fBoundaries[0], point.x);
1190  int sliceY = UVoxelizer::BinarySearch(f.fBoundaries[1], point.y);
1191  int sliceZ = UVoxelizer::BinarySearch(f.fBoundaries[2], point.z);
1192 
1193  unsigned int *maskX = ((unsigned int *) f.fBitmasks[0].fAllBits) + sliceX*n;
1194  maskXLeft = (sliceX && point.x == f.fBoundaries[0][sliceX]) ? maskX - n : NULL;
1195 
1196  unsigned int *maskY = ((unsigned int *) f.fBitmasks[1].fAllBits) + sliceY*n;
1197  maskYLeft = (sliceY && point.y == f.fBoundaries[1][sliceY]) ? maskY - n : NULL;
1198  unsigned int *maskZ = ((unsigned int *) f.fBitmasks[2].fAllBits) + sliceZ*n;
1199  maskZLeft = (sliceZ && point.z == f.fBoundaries[2][sliceZ]) ? maskZ - n : NULL;
1200 
1201  if (sliceX == -1 || sliceX == f.fBoundaries[0].back()) nextAvailable = false;
1202  if (sliceY == -1 || sliceY == f.fBoundaries[1].back()) nextAvailable = false;
1203  if (sliceZ == -1 || sliceZ == f.fBoundaries[2].back()) nextAvailable = false;
1204  }
1205  else
1206  {
1207  if (point.x < f.fBoundaries[0].front() || point.x > f.fBoundaries[0].back()) nextAvailable = false;
1208  if (point.y < f.fBoundaries[1].front() || point.y > f.fBoundaries[1].back()) nextAvailable = false;
1209  if (point.z < f.fBoundaries[2].front() || point.z > f.fBoundaries[2].back()) nextAvailable = false;
1210  }
1211 }
1212 
1213 int UVoxelCandidatesIterator::Next()
1214 {
1215  if (!nextAvailable) return -1;
1216 
1217  if (carNodes == 1)
1218  {
1219  nextAvailable = false;
1220  return 0;
1221  }
1222  else
1223  {
1224  do
1225  {
1226  while (curBit == (int) (8*sizeof(unsigned int)))
1227  {
1228  if (curInt++ >= n)
1229  {
1230  nextAvailable = false;
1231  return -1;
1232  }
1233  // Logic "and" of the masks along the 3 axes x, y, z:
1234  // removing "if (!" and ") continue" => slightly slower
1235  if (!(mask = maskXLeft ? maskX[curInt] | maskXLeft[curInt] : maskX[curInt]) ||
1236  !(mask &= maskYLeft ? maskY[curInt] | maskYLeft[curInt] : maskY[curInt]) ||
1237  !(mask &= maskZLeft ? maskZ[curInt] | maskZLeft[curInt] : maskZ[curInt]))
1238  {
1239  continue;
1240  }
1241  curBit = 0;
1242  }
1243  int shifted = 1 << curBit; // new
1244  if (mask & shifted)
1245  {
1246  int res = 8*sizeof(unsigned int)*curInt+curBit;
1247  if (!(mask -= shifted))
1248  curBit = (int) (8*sizeof(unsigned int));
1249 
1250  return res;
1251  }
1252  curBit++;
1253  }
1254  while (nextAvailable);
1255  return -1;
1256  }
1257 }
1258 */
1259 
1260 #endif // USOLIDSONLY
static int fDefaultVoxelsCount
Definition: UVoxelizer.hh:241
UVector3 hlen
Definition: UVoxelizer.hh:38
virtual UGeometryType GetEntityType() const =0
void DisplayBoundaries()
Definition: UVoxelizer.cc:270
int GetVoxelsIndex(int x, int y, int z) const
Definition: UVoxelizer.hh:126
double DistanceToNext(const UVector3 &point, const UVector3 &direction, std::vector< int > &curVoxel) const
Definition: UVoxelizer.cc:1056
static void DeRegister(G4VSolid *pSolid)
vector< UVoxelInfo > & fVoxels
Definition: UVoxelizer.cc:461
static void FindComponentsFastest(unsigned int mask, std::vector< int > &list, int i)
Definition: UVoxelizer.cc:847
unsigned int GetNbytes() const
Definition: UBits.hh:124
G4double z
Definition: TRTMaterials.hh:39
void CreateMiniVoxels(std::vector< double > fBoundaries[], UBits bitmasks[])
Definition: UVoxelizer.cc:646
virtual double Extent(const UVector3)=0
void SetMaxVoxels(int max)
Definition: UVoxelizer.cc:1124
void BuildEmpty()
Definition: UVoxelizer.cc:50
bool operator()(int l, int r)
Definition: UVoxelizer.cc:468
int fMaxVoxels
Definition: UVoxelizer.hh:297
void ResetAllBits(bool value=false)
Definition: UBits.cc:386
static double Tolerance()
Definition: VUSolid.hh:127
bool Contains(const UVector3 &point) const
Definition: UVoxelizer.cc:997
double x
Definition: UVector3.hh:136
Definition: UBox.hh:33
std::vector< UVoxelBox > fBoxes
Definition: UVoxelizer.hh:281
int fTotalCandidates
Definition: UVoxelizer.hh:287
void BuildVoxelLimits(std::vector< VUSolid * > &solids, std::vector< UTransform3D * > &transforms)
double DistanceToFirst(const UVector3 &point, const UVector3 &direction) const
Definition: UVoxelizer.cc:1007
std::vector< double > fBoundaries[3]
Definition: UVoxelizer.hh:283
static int BinarySearch(const std::vector< T > &vec, T value)
Definition: UVoxelizer.hh:57
UVector3 fTr
Definition: UTransform3D.hh:29
static const double kInfinity
Definition: UUtils.hh:53
Definition: UOrb.hh:28
unsigned char * fAllBits
Definition: UBits.hh:42
void BuildReduceVoxels2(std::vector< double > fBoundaries[], UVector3 reductionRatio)
Definition: UVoxelizer.cc:584
void BuildBoundaries()
Definition: UVoxelizer.cc:207
static double MinDistanceToBox(const UVector3 &aPoint, const UVector3 &f)
Definition: UVoxelizer.cc:1021
void Clear()
Definition: UBits.cc:72
void BuildBoundingBox()
Definition: UVoxelizer.cc:424
std::vector< std::vector< int > > fVoxelBoxesCandidates
Definition: UVoxelizer.hh:245
UVector3 pos
Definition: UVoxelizer.hh:39
static G4SolidStore * GetInstance()
int GetCandidatesVoxelArray(const UVector3 &point, std::vector< int > &list, UBits *crossed=NULL) const
Definition: UVoxelizer.cc:867
void BuildBitmasks(std::vector< double > fBoundaries[], UBits bitmasks[])
Definition: UVoxelizer.cc:298
const G4int n
void Set(unsigned int nbits, const char *array)
Definition: UBits.cc:407
long long CountVoxels(std::vector< double > boundaries[]) const
Definition: UVoxelizer.hh:189
void SetBitNumber(unsigned int bitnumber, bool value=true)
Definition: UBits.hh:172
double DistanceToIn(const UVector3 &aPoint, const UVector3 &aDirection, double aPstep=UUtils::kInfinity) const
Definition: UBox.cc:117
int previous
Definition: UVoxelizer.hh:45
UVector3 fReductionRatio
Definition: UVoxelizer.hh:295
int fNPerSlice
Definition: UVoxelizer.hh:279
std::string GetCandidatesAsString(const UBits &bits)
Definition: UVoxelizer.cc:389
UBits fBitmasks[3]
Definition: UVoxelizer.hh:289
G4double total(Particle const *const p1, Particle const *const p2)
void Set(double xx, double yy, double zz)
Definition: UVector3.hh:245
double GetRadialTolerance()
Definition: UOrb.hh:74
T max(const T t1, const T t2)
brief Return the largest of the two arguments
UBox fBoundingBox
Definition: UVoxelizer.hh:292
bool TestBitNumber(unsigned int bitnumber) const
Definition: UBits.hh:199
void GetCandidatesVoxel(std::vector< int > &voxels)
Definition: UVoxelizer.cc:777
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
static int GetDefaultVoxelsCount()
Definition: UVoxelizer.cc:1156
std::vector< UVoxelBox > fVoxelBoxes
Definition: UVoxelizer.hh:243
double fTolerance
Definition: UVoxelizer.hh:299
long long fCountOfVoxels
Definition: UVoxelizer.hh:251
int GetBitsPerSlice() const
Definition: UVoxelizer.hh:113
void BuildReduceVoxels(std::vector< double > fBoundaries[], UVector3 reductionRatio)
Definition: UVoxelizer.cc:490
std::vector< int > fCandidatesCounts[3]
Definition: UVoxelizer.hh:285
void CreateSortedBoundary(std::vector< double > &boundaryRaw, int axis)
Definition: UVoxelizer.cc:189
UVoxelComparator(vector< UVoxelInfo > &voxels)
Definition: UVoxelizer.cc:463
void DisplayListNodes()
Definition: UVoxelizer.cc:403
void DisplayVoxelLimits()
Definition: UVoxelizer.cc:173
std::map< int, std::vector< int > > fCandidates
Definition: UVoxelizer.hh:247
virtual void Extent(UVector3 &aMin, UVector3 &aMax) const =0
std::string ToString(int number)
Definition: UUtils.cc:77
double z
Definition: UVector3.hh:138
void SetReductionRatio(int maxVoxels, UVector3 &reductionRatio)
Definition: UVoxelizer.cc:477
double SafetyToBoundingBox(const UVector3 &point) const
Definition: UVoxelizer.cc:1014
int AllocatedMemory()
Definition: UVoxelizer.cc:1136
void ResetBitNumber(unsigned int bitnumber)
Definition: UBits.hh:212
static void SetDefaultVoxelsCount(int count)
Definition: UVoxelizer.cc:1151
void Voxelize(std::vector< VUSolid * > &solids, std::vector< UTransform3D * > &transforms)
UVector3 fBoundingBoxSize
Definition: UVoxelizer.hh:293
double y
Definition: UVector3.hh:137
UBits fEmpty
Definition: UVoxelizer.hh:301
static const G4double pos
Definition: UBits.hh:38
void TransformLimits(UVector3 &min, UVector3 &max, const UTransform3D &transformation)
Definition: UUtils.cc:29
UVector3 fBoundingBoxCenter
Definition: UVoxelizer.hh:291