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