Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4SurfaceVoxelizer.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// $Id:$
27// GEANT4 tag $Name: not supported by cvs2svn $
28//
29// --------------------------------------------------------------------
30// GEANT 4 class header file
31//
32// G4SurfaceVoxelizer implementation
33//
34// History:
35// 19.10.12 Marek Gayer, created
36// --------------------------------------------------------------------
37
38#include <iostream>
39#include <iomanip>
40#include <sstream>
41#include <algorithm>
42#include <set>
43
44#include "G4VSolid.hh"
45
46#include "G4Orb.hh"
47#include "G4SurfaceVoxelizer.hh"
48#include "G4SolidStore.hh"
49#include "Randomize.hh"
52#include "G4CSGSolid.hh"
53#include "G4Types.hh"
54#include "geomdefs.hh"
55
56using namespace std;
57
58G4int G4SurfaceVoxelizer::fDefaultVoxelsCount = -1;
59
60//______________________________________________________________________________
62 : fBoundingBox("TessBBox", 1, 1, 1)
63{
64 fCountOfVoxels = fNPerSlice = fTotalCandidates = 0;
65
67
68 SetMaxVoxels(fDefaultVoxelsCount);
69
70 G4SolidStore::GetInstance()->DeRegister(&fBoundingBox);
71}
72
73//______________________________________________________________________________
75{
76}
77
78//______________________________________________________________________________
79void G4SurfaceVoxelizer::BuildEmpty()
80{
81 // by reserving the size of candidates, we would avoid reallocation of
82 // the vector which could cause fragmentation
83 //
84 vector<G4int> xyz(3), max(3), candidates(fTotalCandidates);
85 const vector<G4int> empty(0);
86
87 for (G4int i = 0; i <= 2; i++) max[i] = fBoundaries[i].size();
88 unsigned int size = max[0] * max[1] * max[2];
89
90 fEmpty.Clear();
91 fEmpty.ResetBitNumber(size-1);
92 fEmpty.ResetAllBits(true);
93
94 for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])
95 {
96 for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1])
97 {
98 for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[0])
99 {
100 G4int index = GetVoxelsIndex(xyz);
101 if (GetCandidatesVoxelArray(xyz, candidates))
102 {
103 fEmpty.SetBitNumber(index, false);
104
105 // rather than assigning directly with:
106 // "fCandidates[index] = candidates;", in an effort to ensure that
107 // capacity would be just exact, we rather use following 3 lines
108 //
109 vector<G4int> &c = (fCandidates[index] = empty);
110 c.reserve(candidates.size());
111 c.assign(candidates.begin(), candidates.end());
112 }
113 }
114 }
115 }
116#ifdef G4SPECSDEBUG
117 G4cout << "Non-empty voxels count: " << fCandidates.size() << endl;
118#endif
119}
120
121//______________________________________________________________________________
122void G4SurfaceVoxelizer::BuildVoxelLimits(std::vector<G4VFacet *> &facets)
123{
124 // "BuildVoxelLimits"'s aim is to store the coordinates of the origin as well
125 // as the half lengths related to the bounding box of each node.
126 // These quantities are stored in the array "fBoxes" (6 different values per
127 // node.
128
129 if (G4int numNodes = facets.size()) // Number of nodes
130 {
131 fBoxes.resize(numNodes); // Array which will store the half lengths
132 fNPerSlice = 1+(fBoxes.size()-1)/(8*sizeof(unsigned int));
133
134 G4ThreeVector toleranceVector;
135 toleranceVector.set(10 * fTolerance,10 * fTolerance,10 * fTolerance);
136
137 for (G4int i = 0; i < numNodes; ++i)
138 {
139 G4VFacet &facet = *facets[i];
140 G4ThreeVector min, max;
141 G4ThreeVector x(1,0,0), y(0,1,0), z(0,0,1);
142 G4ThreeVector extent;
143 max.set (facet.Extent(x), facet.Extent(y), facet.Extent(z));
144 min.set (-facet.Extent(-x), -facet.Extent(-y), -facet.Extent(-z));
145 min -= toleranceVector; max += toleranceVector;
146 G4ThreeVector hlen = (max - min) / 2;
147 fBoxes[i].hlen = hlen;
148 fBoxes[i].pos = min + hlen;
149 }
150 fTotalCandidates = fBoxes.size();
151 }
152}
153
154//______________________________________________________________________________
156{
157 // "DisplayVoxelLimits" displays the dX, dY, dZ, pX, pY and pZ for each node
158
159 G4int numNodes = fBoxes.size();
160 G4int oldprec = G4cout.precision(16);
161 for(G4int i = 0; i < numNodes; ++i)
162 {
163 G4cout << setw(10) << setiosflags(ios::fixed) <<
164 " -> Node " << i+1 << ":\n" <<
165 "\t * [x,y,z] = " << fBoxes[i].hlen <<
166 "\t * [x,y,z] = " << fBoxes[i].pos << "\n";
167 }
168 G4cout.precision(oldprec);
169}
170
171//______________________________________________________________________________
172void G4SurfaceVoxelizer::CreateSortedBoundary(std::vector<G4double> &boundary,
173 G4int axis)
174{
175 // "CreateBoundaries"'s aim is to determine the slices induced by the
176 // bounding fBoxes, along each axis. The created boundaries are stored
177 // in the array "boundariesRaw"
178
179 G4int numNodes = fBoxes.size(); // Number of nodes in structure
180
181 // Determination of the boundaries along x, y and z axis
182 //
183 for(G4int i = 0 ; i < numNodes; ++i)
184 {
185 // For each node, the boundaries are created by using the array "fBoxes"
186 // built in method "BuildVoxelLimits"
187 //
188 G4double p = fBoxes[i].pos[axis], d = fBoxes[i].hlen[axis];
189
190 // x boundaries
191 //
192 boundary[2*i] = p - d;
193 boundary[2*i+1] = p + d;
194 }
195 sort(boundary.begin(), boundary.end());
196}
197
198//______________________________________________________________________________
199void G4SurfaceVoxelizer::BuildBoundaries()
200{
201 // "SortBoundaries" orders the boundaries along each axis (increasing order)
202 // and also does not take into account redundant boundaries, i.e. if two
203 // boundaries are separated by a distance strictly inferior to "tolerance".
204 // The sorted boundaries are respectively stored in:
205 // * boundaries[0..2]
206
207 // In addition, the number of elements contained in the three latter arrays
208 // are precise thanks to variables: boundariesCountX, boundariesCountY and
209 // boundariesCountZ.
210
211 if (G4int numNodes = fBoxes.size())
212 {
213 const G4double tolerance = fTolerance / 100.0;
214 // Minimal distance to discriminate two boundaries.
215
216 vector<G4double> sortedBoundary(2*numNodes);
217
218 G4int considered;
219
220 for (G4int j = 0; j <= 2; ++j)
221 {
222 CreateSortedBoundary(sortedBoundary, j);
223 vector<G4double> &boundary = fBoundaries[j];
224 boundary.clear();
225
226 considered = 0;
227
228 for(G4int i = 0 ; i < 2*numNodes; ++i)
229 {
230 G4double newBoundary = sortedBoundary[i];
231 G4int size = boundary.size();
232 if(!size || abs(boundary[size-1] - newBoundary) > tolerance)
233 {
234 considered++;
235 {
236 boundary.push_back(newBoundary);
237 continue;
238 }
239 }
240 // If two successive boundaries are too close from each other,
241 // only the first one is considered
242 }
243
244 G4int n = boundary.size();
245 G4int max = 100000;
246 if (n > max/2)
247 {
248 G4int skip = n / (max /2); // n has to be 2x bigger then 50.000.
249 // therefore only from 100.000 reduced
250 vector<G4double> reduced;
251 for (G4int i = 0; i < n; i++)
252 {
253 // 50 ok for 2k, 1000, 2000
254 G4int size = boundary.size();
255 if (i % skip == 0 || i == 0 || i == size - 1)
256 {
257 // this condition of merging boundaries was wrong,
258 // it did not count with right part, which can be
259 // completely ommited and not included in final consideration.
260 // Now should be OK
261 //
262 reduced.push_back(boundary[i]);
263 }
264 }
265 boundary = reduced;
266 }
267 }
268 }
269}
270
271//______________________________________________________________________________
273{
274 char axis[3] = {'X', 'Y', 'Z'};
275 for (G4int i = 0; i <= 2; ++i)
276 {
277 G4cout << " * " << axis[i] << " axis:" << endl << " | ";
278 DisplayBoundaries(fBoundaries[i]);
279 }
280}
281
282//______________________________________________________________________________
283void G4SurfaceVoxelizer::DisplayBoundaries(std::vector<G4double> &boundaries)
284{
285 // Prints the positions of the boundaries of the slices on the three axes
286
287 G4int count = boundaries.size();
288 G4int oldprec = G4cout.precision(16);
289 for(G4int i = 0; i < count; ++i)
290 {
291 G4cout << setw(10) << setiosflags(ios::fixed) << boundaries[i];
292 if(i != count-1) G4cout << "-> ";
293 }
294 G4cout << "|" << endl << "Number of boundaries: " << count << endl;
295 G4cout.precision(oldprec);
296}
297
298//______________________________________________________________________________
299void G4SurfaceVoxelizer::BuildBitmasks(std::vector<G4double> boundaries[],
300 G4SurfBits bitmasks[], G4bool countsOnly)
301{
302 // "BuildListNodes" stores in the bitmasks solids present in each slice
303 // along an axis.
304
305 G4int numNodes = fBoxes.size();
306 G4int bitsPerSlice = GetBitsPerSlice();
307
308 for (G4int k = 0; k < 3; k++)
309 {
310 G4int total = 0;
311 vector<G4double> &boundary = boundaries[k];
312 G4int voxelsCount = boundary.size() - 1;
313 G4SurfBits &bitmask = bitmasks[k];
314
315 if (!countsOnly)
316 {
317 bitmask.Clear();
318 bitmask.SetBitNumber(voxelsCount*bitsPerSlice-1, false);
319 // it is here so we can set the maximum number of bits. this line
320 // will rellocate the memory and set all to zero
321 }
322 vector<G4int> &candidatesCount = fCandidatesCounts[k];
323 candidatesCount.resize(voxelsCount);
324
325 for(G4int i = 0 ; i < voxelsCount; ++i) { candidatesCount[i] = 0; }
326
327 // Loop on the nodes, number of slices per axis
328 //
329 for(G4int j = 0 ; j < numNodes; j++)
330 {
331 // Determination of the minimum and maximum position along x
332 // of the bounding boxe of each node
333 //
334 G4double p = fBoxes[j].pos[k], d = fBoxes[j].hlen[k];
335
336 G4double min = p - d; // - localTolerance;
337 G4double max = p + d; // + localTolerance;
338
339 G4int i = BinarySearch(boundary, min);
340
341 do
342 {
343 if (!countsOnly)
344 bitmask.SetBitNumber(i*bitsPerSlice+j);
345
346 candidatesCount[i]++;
347 total++;
348 i++;
349 }
350 while (max > boundary[i] && i < voxelsCount);
351 }
352 }
353#ifdef G4SPECSDEBUG
354 G4cout << "Build list nodes completed" << endl;
355#endif
356}
357
358//______________________________________________________________________________
359G4String G4SurfaceVoxelizer::GetCandidatesAsString(const G4SurfBits &bits)
360{
361 // Decodes the candidates in mask as G4String.
362
363 stringstream ss;
364 G4int numNodes = fBoxes.size();
365
366 for(G4int i=0; i<numNodes; ++i)
367 {
368 if (bits.TestBitNumber(i)) { ss << i+1 << " "; }
369 }
370 return ss.str();
371}
372
373//______________________________________________________________________________
375{
376 // Prints which solids are present in the slices previously elaborated.
377
378 char axis[3] = {'X', 'Y', 'Z'};
379 G4int size=8*sizeof(G4int)*fNPerSlice;
380 G4SurfBits bits(size);
381
382 for (G4int j = 0; j <= 2; ++j)
383 {
384 G4cout << " * " << axis[j] << " axis:" << endl;
385 G4int count = fBoundaries[j].size();
386 for(G4int i=0; i < count-1; ++i)
387 {
388 G4cout << " Slice #" << i+1 << ": [" << fBoundaries[j][i]
389 << " ; " << fBoundaries[j][i+1] << "] -> ";
390 bits.set(size,(const char *)fBitmasks[j].fAllBits+i
391 *fNPerSlice*sizeof(G4int));
392 G4String result = GetCandidatesAsString(bits);
393 G4cout << "[ " << result.c_str() << "] " << endl;
394 }
395 }
396}
397
398//______________________________________________________________________________
399void G4SurfaceVoxelizer::BuildBoundingBox()
400{
401 G4ThreeVector toleranceVector;
402 toleranceVector.set(fTolerance/100,fTolerance/100,fTolerance/100);
403 for (G4int i = 0; i <= 2; ++i)
404 {
405 G4double min = fBoundaries[i].front();
406 G4double max = fBoundaries[i].back();
407 fBoundingBoxSize[i] = (max-min)/2;
408 fBoundingBoxCenter[i] = min + fBoundingBoxSize[i];
409 }
410 // sizes -= toleranceVector;
411 fBoundingBox = G4Box("TessBBox", fBoundingBoxSize.x(),
412 fBoundingBoxSize.y(), fBoundingBoxSize.z());
413}
414
415// algorithm -
416
417// in order to get balanced voxels, merge should always unite those regions,
418// where the number of voxels is least the number.
419// We will keep sorted list (std::set) with all voxels. there will be
420// comparator function between two voxels, which will tell if voxel is less
421// by looking at his right neighbor.
422// First, we will add all the voxels into the tree.
423// We will be pick the first item in the tree, merging it, adding the right
424// merged voxel into the a list for future reduction (fBitmasks will be
425// rebuilded later, therefore they need not to be updated).
426// The merged voxel need to be added to the tree again, so it's position
427// would be updated.
428
429//______________________________________________________________________________
430void G4SurfaceVoxelizer::SetReductionRatio(G4int maxVoxels,
431 G4ThreeVector &reductionRatio)
432{
433 G4double maxTotal = (G4double) fCandidatesCounts[0].size()
434 * fCandidatesCounts[1].size() * fCandidatesCounts[2].size();
435
436 if (maxVoxels > 0 && maxVoxels < maxTotal)
437 {
438 G4double ratio = (G4double) maxVoxels / maxTotal;
439 ratio = pow(ratio, 1./3.);
440 if (ratio > 1) { ratio = 1; }
441 reductionRatio.set(ratio,ratio,ratio);
442 }
443}
444
445//______________________________________________________________________________
446void G4SurfaceVoxelizer::BuildReduceVoxels(std::vector<G4double> boundaries[],
447 G4ThreeVector reductionRatio)
448{
449 for (G4int k = 0; k <= 2; ++k)
450 {
451 vector<G4int> &candidatesCount = fCandidatesCounts[k];
452 G4int max = candidatesCount.size();
453 vector<G4VoxelInfo> voxels(max);
454 G4VoxelComparator comp(voxels);
455 set<G4int, G4VoxelComparator> voxelSet(comp);
456 vector<G4int> mergings;
457
458 for (G4int j = 0; j < max; ++j)
459 {
460 G4VoxelInfo &voxel = voxels[j];
461 voxel.count = candidatesCount[j];
462 voxel.previous = j - 1;
463 voxel.next = j + 1;
464 voxels[j] = voxel;
465 }
466
467 for (G4int j = 0; j < max - 1; ++j) { voxelSet.insert(j); }
468 // we go to size-1 to make sure we will not merge the last element
469
470 G4int count = 0;
471 while (true)
472 {
473 G4double reduction = reductionRatio[k];
474 if (reduction == 0)
475 break;
476 G4int currentCount = voxelSet.size();
477 if (currentCount <= 2)
478 break;
479 G4double currentRatio = 1 - (G4double) count / max;
480 if (currentRatio <= reduction && currentCount <= 1000)
481 break;
482 const G4int pos = *voxelSet.begin();
483 mergings.push_back(pos);
484
485 G4VoxelInfo &voxel = voxels[pos];
486 G4VoxelInfo &nextVoxel = voxels[voxel.next];
487
488 voxelSet.erase(pos);
489 if (voxel.next != max - 1) { voxelSet.erase(voxel.next); }
490 if (voxel.previous != -1) { voxelSet.erase(voxel.previous); }
491
492 nextVoxel.count += voxel.count;
493 voxel.count = 0;
494 nextVoxel.previous = voxel.previous;
495
496 if (voxel.next != max - 1)
497 voxelSet.insert(voxel.next);
498
499 if (voxel.previous != -1)
500 {
501 voxels[voxel.previous].next = voxel.next;
502 voxelSet.insert(voxel.previous);
503 }
504 count++;
505 }
506
507 if (mergings.size())
508 {
509 sort(mergings.begin(), mergings.end());
510
511 vector<G4double> &boundary = boundaries[k];
512 vector<G4double> reducedBoundary(boundary.size() - mergings.size());
513 G4int skip = mergings[0] + 1, cur = 0, i = 0;
514 max = boundary.size();
515 for (G4int j = 0; j < max; ++j)
516 {
517 if (j != skip)
518 {
519 reducedBoundary[cur++] = boundary[j];
520 }
521 else
522 {
523 if (++i < (G4int)mergings.size()) { skip = mergings[i] + 1; }
524 }
525 }
526 boundaries[k] = reducedBoundary;
527 }
528 }
529}
530
531//______________________________________________________________________________
532void G4SurfaceVoxelizer::BuildReduceVoxels2(std::vector<G4double> boundaries[],
533 G4ThreeVector reductionRatio)
534{
535 for (G4int k = 0; k <= 2; ++k)
536 {
537 vector<G4int> &candidatesCount = fCandidatesCounts[k];
538 G4int max = candidatesCount.size();
539 G4int total = 0;
540 for (G4int i = 0; i < max; i++) total += candidatesCount[i];
541
542 G4double reduction = reductionRatio[k];
543 if (reduction == 0)
544 break;
545
546 G4int destination = (G4int) (reduction * max) + 1;
547 if (destination > 1000) destination = 1000;
548 if (destination < 2) destination = 2;
549 G4double average = ((G4double)total / max) / reduction;
550
551 vector<G4int> mergings;
552
553 vector<G4double> &boundary = boundaries[k];
554 vector<G4double> reducedBoundary(destination);
555
556 G4int sum = 0, cur = 0;
557 for (G4int i = 0; i < max; i++)
558 {
559 sum += candidatesCount[i];
560 if (sum > average * (cur + 1) || i == 0)
561 {
562 G4double val = boundary[i];
563 reducedBoundary[cur] = val;
564 cur++;
565 if (cur == destination)
566 break;
567 }
568 }
569 reducedBoundary[destination-1] = boundary[max];
570 boundaries[k] = reducedBoundary;
571 }
572}
573
574//______________________________________________________________________________
575void G4SurfaceVoxelizer::CreateMiniVoxels(std::vector<G4double> boundaries[],
576 G4SurfBits bitmasks[])
577{
578 vector<G4int> voxel(3), maxVoxels(3);
579 for (G4int i = 0; i <= 2; ++i) maxVoxels[i] = boundaries[i].size();
580
581 G4ThreeVector point;
582 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
583 {
584 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
585 {
586 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
587 {
588 vector<G4int> candidates;
589 if (GetCandidatesVoxelArray(voxel, bitmasks, candidates, 0))
590 {
591 // find a box for corresponding non-empty voxel
592 G4VoxelBox box;
593 for (G4int i = 0; i <= 2; ++i)
594 {
595 G4int index = voxel[i];
596 const vector<G4double> &boundary = boundaries[i];
597 G4double hlen = 0.5 * (boundary[index+1] - boundary[index]);
598 box.hlen[i] = hlen;
599 box.pos[i] = boundary[index] + hlen;
600 }
601 fVoxelBoxes.push_back(box);
602 vector<G4int>(candidates).swap(candidates);
603 fVoxelBoxesCandidates.push_back(candidates);
604 }
605 }
606 }
607 }
608}
609
610//______________________________________________________________________________
611void G4SurfaceVoxelizer::Voxelize(std::vector<G4VFacet *> &facets)
612{
613 G4int maxVoxels = fMaxVoxels;
614 G4ThreeVector reductionRatio = fReductionRatio;
615
616 G4int size = facets.size();
617 if (size < 10)
618 {
619 for (G4int i = 0; i < (G4int) facets.size(); i++)
620 {
621 if (facets[i]->GetNumberOfVertices() > 3) size++;
622 }
623 }
624
625 if ((size >= 10 || maxVoxels > 0) && maxVoxels != 0 && maxVoxels != 1)
626 {
627 BuildVoxelLimits(facets);
628
629 BuildBoundaries();
630
631 BuildBitmasks(fBoundaries, 0, true);
632
633 if (maxVoxels < 0 && reductionRatio == G4ThreeVector())
634 {
635 maxVoxels = fTotalCandidates;
636 if (fTotalCandidates > 1000000) maxVoxels = 1000000;
637 }
638
639 SetReductionRatio(maxVoxels, reductionRatio);
640
641 fCountOfVoxels = CountVoxels(fBoundaries);
642
643#ifdef G4SPECSDEBUG
644 G4cout << "Total number of voxels: " << fCountOfVoxels << endl;
645#endif
646
647 BuildReduceVoxels2(fBoundaries, reductionRatio);
648
649 fCountOfVoxels = CountVoxels(fBoundaries);
650
651#ifdef G4SPECSDEBUG
652 G4cout << "Total number of voxels after reduction: "
653 << fCountOfVoxels << endl;
654#endif
655
656 BuildBitmasks(fBoundaries, fBitmasks);
657
658 G4ThreeVector reductionRatioMini;
659
660 G4SurfBits bitmasksMini[3];
661
662 // section for building mini voxels
663
664 vector<G4double> miniBoundaries[3];
665
666 for (G4int i = 0; i <= 2; ++i) { miniBoundaries[i] = fBoundaries[i]; }
667
668 G4int voxelsCountMini = (fCountOfVoxels >= 1000)
669 ? 100 : fCountOfVoxels / 10;
670
671 // if (voxelCountMini < 8) voxelCountMini = 8;
672 // voxelsCountMini = 1;
673
674 SetReductionRatio(voxelsCountMini, reductionRatioMini);
675
676 BuildReduceVoxels(miniBoundaries, reductionRatioMini);
677
678#ifdef G4SPECSDEBUG
679 G4int total = CountVoxels(miniBoundaries);
680 G4cout << "Total number of mini voxels: " << total << endl;
681#endif
682
683 BuildBitmasks(miniBoundaries, bitmasksMini);
684
685 CreateMiniVoxels(miniBoundaries, bitmasksMini);
686
687 BuildBoundingBox();
688
689 BuildEmpty();
690
691 // deallocate fields unnecessary during runtime
692 //
693 fBoxes.resize(0);
694 for (G4int i = 0; i < 3; i++)
695 {
696 fCandidatesCounts[i].resize(0);
697 fBitmasks[i].Clear();
698 }
699 }
700}
701
702
703//______________________________________________________________________________
704void G4SurfaceVoxelizer::GetCandidatesVoxel(std::vector<G4int> &voxels)
705{
706 // "GetCandidates" should compute which solids are possibly contained in
707 // the voxel defined by the three slices characterized by the passed indexes.
708
709 G4cout << " Candidates in voxel [" << voxels[0] << " ; " << voxels[1]
710 << " ; " << voxels[2] << "]: ";
711 vector<G4int> candidates;
712 G4int count = GetCandidatesVoxelArray(voxels, candidates);
713 G4cout << "[ ";
714 for (G4int i = 0; i < count; ++i) G4cout << candidates[i];
715 G4cout << "] " << endl;
716}
717
718//______________________________________________________________________________
719void G4SurfaceVoxelizer::FindComponentsFastest(unsigned int mask,
720 std::vector<G4int> &list, G4int i)
721{
722 for (G4int byte = 0; byte < (G4int) (sizeof(unsigned int)); byte++)
723 {
724 if (G4int maskByte = mask & 0xFF)
725 {
726 for (G4int bit = 0; bit < 8; bit++)
727 {
728 if (maskByte & 1)
729 { list.push_back(8*(sizeof(unsigned int)*i+ byte) + bit); }
730 if (!(maskByte >>= 1)) break;
731 }
732 }
733 mask >>= 8;
734 }
735}
736
737//______________________________________________________________________________
739 std::vector<G4int> &list, G4SurfBits *crossed) const
740{
741 // Method returning the candidates corresponding to the passed point
742
743 list.clear();
744
745 for (G4int i = 0; i <= 2; ++i)
746 {
747 if(point[i] < fBoundaries[i].front() || point[i] >= fBoundaries[i].back())
748 return 0;
749 }
750
751 if (fTotalCandidates == 1)
752 {
753 list.push_back(0);
754 return 1;
755 }
756 else
757 {
758 if (fNPerSlice == 1)
759 {
760 unsigned int mask;
761 G4int slice = BinarySearch(fBoundaries[0], point.x());
762 if (!(mask = ((unsigned int *) fBitmasks[0].fAllBits)[slice]
763 )) return 0;
764 slice = BinarySearch(fBoundaries[1], point.y());
765 if (!(mask &= ((unsigned int *) fBitmasks[1].fAllBits)[slice]
766 )) return 0;
767 slice = BinarySearch(fBoundaries[2], point.z());
768 if (!(mask &= ((unsigned int *) fBitmasks[2].fAllBits)[slice]
769 )) return 0;
770 if (crossed && (!(mask &= ~((unsigned int *)crossed->fAllBits)[0])))
771 return 0;
772
773 FindComponentsFastest(mask, list, 0);
774 }
775 else
776 {
777 unsigned int *masks[3], mask; // masks for X,Y,Z axis
778 for (G4int i = 0; i <= 2; ++i)
779 {
780 G4int slice = BinarySearch(fBoundaries[i], point[i]);
781 masks[i] = ((unsigned int *) fBitmasks[i].fAllBits) + slice*fNPerSlice;
782 }
783 unsigned int *maskCrossed =
784 crossed ? (unsigned int *)crossed->fAllBits : 0;
785
786 for (G4int i = 0 ; i < fNPerSlice; ++i)
787 {
788 // Logic "and" of the masks along the 3 axes x, y, z:
789 // removing "if (!" and ") continue" => slightly slower
790 //
791 if (!(mask = masks[0][i])) continue;
792 if (!(mask &= masks[1][i])) continue;
793 if (!(mask &= masks[2][i])) continue;
794 if (maskCrossed && !(mask &= ~maskCrossed[i])) continue;
795
796 FindComponentsFastest(mask, list, i);
797 }
798 }
799 }
800 return list.size();
801}
802
803//______________________________________________________________________________
804G4int
805G4SurfaceVoxelizer::GetCandidatesVoxelArray(const std::vector<G4int> &voxels,
806 const G4SurfBits bitmasks[],
807 std::vector<G4int> &list,
808 G4SurfBits *crossed) const
809{
810 list.clear();
811
812 if (fTotalCandidates == 1)
813 {
814 list.push_back(0);
815 return 1;
816 }
817 else
818 {
819 if (fNPerSlice == 1)
820 {
821 unsigned int mask;
822 if (!(mask = ((unsigned int *) bitmasks[0].fAllBits)[voxels[0]]
823 )) return 0;
824 if (!(mask &= ((unsigned int *) bitmasks[1].fAllBits)[voxels[1]]
825 )) return 0;
826 if (!(mask &= ((unsigned int *) bitmasks[2].fAllBits)[voxels[2]]
827 )) return 0;
828 if (crossed && (!(mask &= ~((unsigned int *)crossed->fAllBits)[0])))
829 return 0;
830
831 FindComponentsFastest(mask, list, 0);
832 }
833 else
834 {
835 unsigned int *masks[3], mask; // masks for X,Y,Z axis
836 for (G4int i = 0; i <= 2; ++i)
837 {
838 masks[i] = ((unsigned int *) bitmasks[i].fAllBits)
839 + voxels[i]*fNPerSlice;
840 }
841 unsigned int *maskCrossed =
842 crossed ? (unsigned int *)crossed->fAllBits : 0;
843
844 for (G4int i = 0 ; i < fNPerSlice; ++i)
845 {
846 // Logic "and" of the masks along the 3 axes x, y, z:
847 // removing "if (!" and ") continue" => slightly slower
848 //
849 if (!(mask = masks[0][i])) continue;
850 if (!(mask &= masks[1][i])) continue;
851 if (!(mask &= masks[2][i])) continue;
852 if (maskCrossed && !(mask &= ~maskCrossed[i])) continue;
853
854 FindComponentsFastest(mask, list, i);
855 }
856 }
857 }
858 return list.size();
859}
860
861//______________________________________________________________________________
862G4int
863G4SurfaceVoxelizer::GetCandidatesVoxelArray(const std::vector<G4int> &voxels,
864 std::vector<G4int> &list, G4SurfBits *crossed) const
865{
866 // Method returning the candidates corresponding to the passed point
867
868 return GetCandidatesVoxelArray(voxels, fBitmasks, list, crossed);
869}
870
871//______________________________________________________________________________
873{
874 for (G4int i = 0; i < 3; ++i)
875 {
876 if (point[i] < fBoundaries[i].front() || point[i] > fBoundaries[i].back())
877 return false;
878 }
879 return true;
880}
881
882//______________________________________________________________________________
885 const G4ThreeVector &direction) const
886{
887 G4ThreeVector pointShifted = point - fBoundingBoxCenter;
888 G4double shift = fBoundingBox.DistanceToIn(pointShifted, direction);
889 return shift;
890}
891
892//______________________________________________________________________________
895{
896 G4ThreeVector pointShifted = point - fBoundingBoxCenter;
897 G4double shift = MinDistanceToBox(pointShifted, fBoundingBoxSize);
898 return shift;
899}
900
901//______________________________________________________________________________
904 const G4ThreeVector &f)
905{
906 // Estimates the isotropic safety from a point outside the current solid to
907 // any of its surfaces. The algorithm may be accurate or should provide a
908 // fast underestimate.
909
910 G4double safe, safx, safy, safz;
911 safe = safx = -f.x() + std::abs(aPoint.x());
912 safy = -f.y() + std::abs(aPoint.y());
913 if ( safy > safe ) safe = safy;
914 safz = -f.z() + std::abs(aPoint.z());
915 if ( safz > safe ) safe = safz;
916 if (safe < 0.0) return 0.0; // point is inside
917 // if (!aAccurate) return safe;
918 G4double safsq = 0.0;
919 G4int count = 0;
920 if ( safx > 0 ) { safsq += safx*safx; count++; }
921 if ( safy > 0 ) { safsq += safy*safy; count++; }
922 if ( safz > 0 ) { safsq += safz*safz; count++; }
923 if (count == 1) return safe;
924 return std::sqrt(safsq);
925}
926
927//______________________________________________________________________________
930 const G4ThreeVector &direction,
931 const std::vector<G4int> &curVoxel) const
932{
933 G4double shift = kInfinity;
934
935 for (G4int i = 0; i <= 2; ++i)
936 {
937 // Looking for the next voxels on the considered direction X,Y,Z axis
938 //
939 const vector<G4double> &boundary = fBoundaries[i];
940 G4int cur = curVoxel[i];
941 if(direction[i] >= 1e-10)
942 {
943 if (boundary[cur] - point[i] < fTolerance) // make sure shift would
944 if (++cur >= (G4int) boundary.size()) // be non-zero
945 continue;
946 }
947 else
948 {
949 if(direction[i] <= -1e-10)
950 {
951 if (point[i] - boundary[cur] < fTolerance) // make sure shift would
952 if (--cur < 0) // be non-zero
953 continue;
954 }
955 else
956 continue;
957 }
958 G4double dif = boundary[cur] - point[i];
959 G4double distance = dif / direction[i];
960
961 if (shift > distance)
962 shift = distance;
963 }
964
965 return shift;
966}
967
968//______________________________________________________________________________
969G4bool
971 const G4ThreeVector &direction,
972 std::vector<G4int> &curVoxel) const
973{
974 for (G4int i = 0; i <= 2; ++i)
975 {
976 G4int index = curVoxel[i];
977 const vector<G4double> &boundary = fBoundaries[i];
978
979 if (direction[i] > 0)
980 {
981 if (point[i] >= boundary[++index])
982 if (++curVoxel[i] >= (G4int) boundary.size() - 1)
983 return false;
984 }
985 else
986 {
987 if (point[i] < boundary[index])
988 if (--curVoxel[i] < 0)
989 return false;
990 }
991#ifdef G4SPECSDEBUG
992 G4int indexOK = BinarySearch(boundary, point[i]);
993 if (curVoxel[i] != indexOK)
994 curVoxel[i] = indexOK; // put breakpoint here
995#endif
996 }
997 return true;
998}
999
1000//______________________________________________________________________________
1002{
1003 fMaxVoxels = max;
1004 fReductionRatio.set(0,0,0);
1005}
1006
1007//______________________________________________________________________________
1009{
1010 fMaxVoxels = -1;
1011 fReductionRatio = ratioOfReduction;
1012}
1013
1014//______________________________________________________________________________
1016{
1017 G4int res = fDefaultVoxelsCount;
1018 fDefaultVoxelsCount = count;
1019 return res;
1020}
1021
1022//______________________________________________________________________________
1024{
1025 return fDefaultVoxelsCount;
1026}
1027
1028//______________________________________________________________________________
1030{
1031 G4int size = fEmpty.GetNbytes();
1032 size += fBoxes.capacity() * sizeof(G4VoxelBox);
1033 size += sizeof(G4double) * (fBoundaries[0].capacity()
1034 + fBoundaries[1].capacity() + fBoundaries[2].capacity());
1035 size += sizeof(G4int) * (fCandidatesCounts[0].capacity()
1036 + fCandidatesCounts[1].capacity() + fCandidatesCounts[2].capacity());
1037 size += fBitmasks[0].GetNbytes() + fBitmasks[1].GetNbytes()
1038 + fBitmasks[2].GetNbytes();
1039
1040 G4int csize = fCandidates.size();
1041 for (G4int i = 0; i < csize; i++)
1042 {
1043 size += sizeof(vector<G4int>) + fCandidates[i].capacity() * sizeof(G4int);
1044 }
1045
1046 return size;
1047}
1048
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
G4DLLIMPORT std::ostream G4cout
double z() const
double x() const
double y() const
void set(double x, double y, double z)
Definition: G4Box.hh:55
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
Definition: G4Box.cc:556
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
static void DeRegister(G4VSolid *pSolid)
static G4SolidStore * GetInstance()
unsigned int GetNbytes() const
Definition: G4SurfBits.hh:102
unsigned char * fAllBits
Definition: G4SurfBits.hh:113
void ResetAllBits(G4bool value=false)
Definition: G4SurfBits.cc:154
void Clear()
Definition: G4SurfBits.cc:92
void ResetBitNumber(unsigned int bitnumber)
Definition: G4SurfBits.hh:161
void SetBitNumber(unsigned int bitnumber, G4bool value=true)
Definition: G4SurfBits.hh:123
void set(unsigned int nbits, const char *array)
Definition: G4SurfBits.cc:174
G4bool TestBitNumber(unsigned int bitnumber) const
Definition: G4SurfBits.hh:148
G4bool Contains(const G4ThreeVector &point) const
G4bool UpdateCurrentVoxel(const G4ThreeVector &point, const G4ThreeVector &direction, std::vector< G4int > &curVoxel) const
G4double DistanceToBoundingBox(const G4ThreeVector &point) const
void SetMaxVoxels(G4int max)
G4double DistanceToNext(const G4ThreeVector &point, const G4ThreeVector &direction, const std::vector< G4int > &curVoxel) const
G4int GetCandidatesVoxelArray(const G4ThreeVector &point, std::vector< G4int > &list, G4SurfBits *crossed=0) const
G4int GetVoxelsIndex(G4int x, G4int y, G4int z) const
static G4double MinDistanceToBox(const G4ThreeVector &aPoint, const G4ThreeVector &f)
G4double DistanceToFirst(const G4ThreeVector &point, const G4ThreeVector &direction) const
static G4int SetDefaultVoxelsCount(G4int count)
void Voxelize(std::vector< G4VFacet * > &facets)
G4int GetBitsPerSlice() const
long long CountVoxels(std::vector< G4double > boundaries[]) const
static G4int BinarySearch(const std::vector< T > &vec, T value)
void GetCandidatesVoxel(std::vector< G4int > &voxels)
static G4int GetDefaultVoxelsCount()
virtual G4double Extent(const G4ThreeVector)=0
G4ThreeVector hlen
G4ThreeVector pos