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