56 : fBoundingBox(
"VoxBBox", 1, 1, 1)
58 fCountOfVoxels = fNPerSlice = fTotalCandidates = 0;
73void G4Voxelizer::BuildEmpty()
78 std::vector<G4int> xyz(3), max(3), candidates(fTotalCandidates);
79 const std::vector<G4int> empty(0);
81 for (
auto i = 0; i <= 2; ++i) max[i] = (
G4int)fBoundaries[i].size();
82 unsigned int size = max[0] * max[1] * max[2];
88 for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])
90 for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1])
92 for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[0])
103 std::vector<G4int> &c = (fCandidates[index] = empty);
104 c.reserve(candidates.size());
105 c.assign(candidates.begin(), candidates.end());
111 G4cout <<
"Non-empty voxels count: " << fCandidates.size() <<
G4endl;
116void G4Voxelizer::BuildVoxelLimits(std::vector<G4VSolid*>& solids,
117 std::vector<G4Transform3D>& transforms)
124 if (std::size_t numNodes = solids.size())
126 fBoxes.resize(numNodes);
127 fNPerSlice =
G4int(1 + (fBoxes.size() - 1) / (8 *
sizeof(
unsigned int)));
132 G4ThreeVector toleranceVector(fTolerance,fTolerance,fTolerance);
134 for (std::size_t i = 0; i < numNodes; ++i)
146 orbToleranceVector.
set(tolerance,tolerance,tolerance);
147 min -= orbToleranceVector;
148 max += orbToleranceVector;
152 min -= toleranceVector;
153 max += toleranceVector;
155 TransformLimits(min, max, transform);
156 fBoxes[i].hlen = (
max -
min) / 2.;
157 fBoxes[i].pos = (
max +
min) / 2.;
159 fTotalCandidates = (
G4int)fBoxes.size();
164void G4Voxelizer::BuildVoxelLimits(std::vector<G4VFacet*>& facets)
171 if (std::size_t numNodes = facets.size())
173 fBoxes.resize(numNodes);
174 fNPerSlice =
G4int(1+(fBoxes.size()-1)/(8*
sizeof(
unsigned int)));
176 G4ThreeVector toleranceVector(10*fTolerance, 10*fTolerance, 10*fTolerance);
178 for (std::size_t i = 0; i < numNodes; ++i)
186 min -= toleranceVector;
187 max += toleranceVector;
189 fBoxes[i].hlen = hlen;
190 fBoxes[i].pos =
min + hlen;
192 fTotalCandidates = (
G4int)fBoxes.size();
201 std::size_t numNodes = fBoxes.size();
203 for(std::size_t i = 0; i < numNodes; ++i)
205 G4cout << setw(10) << setiosflags(ios::fixed) <<
206 " -> Node " << i+1 <<
":\n" <<
207 "\t * [x,y,z] = " << fBoxes[i].hlen <<
208 "\t * [x,y,z] = " << fBoxes[i].pos <<
"\n";
210 G4cout.precision(oldprec);
214void G4Voxelizer::CreateSortedBoundary(std::vector<G4double>& boundary,
221 std::size_t numNodes = fBoxes.size();
225 for(std::size_t i = 0 ; i < numNodes; ++i)
230 G4double p = fBoxes[i].pos[axis], d = fBoxes[i].hlen[axis];
235 G4cout <<
"Boundary " << p - d <<
" - " << p + d <<
G4endl;
237 boundary[2*i] = p - d;
238 boundary[2*i+1] = p + d;
240 std::sort(boundary.begin(), boundary.end());
244void G4Voxelizer::BuildBoundaries()
256 if (std::size_t numNodes = fBoxes.size())
258 const G4double tolerance = fTolerance / 100.0;
261 std::vector<G4double> sortedBoundary(2*numNodes);
263 for (
auto j = 0; j <= 2; ++j)
265 CreateSortedBoundary(sortedBoundary, j);
266 std::vector<G4double> &boundary = fBoundaries[j];
269 for(std::size_t i = 0 ; i < 2*numNodes; ++i)
271 G4double newBoundary = sortedBoundary[i];
273 if (j == 0)
G4cout <<
"Examining " << newBoundary <<
"..." <<
G4endl;
276 if(!size || std::abs(boundary[size-1] - newBoundary) > tolerance)
280 if (j == 0)
G4cout <<
"Adding boundary " << newBoundary <<
"..."
283 boundary.push_back(newBoundary);
297 std::vector<G4double> reduced;
298 for (
G4int i = 0; i <
n; ++i)
302 if (i % skip == 0 || i == 0 || i == size - 1)
309 reduced.push_back(boundary[i]);
321 char axis[3] = {
'X',
'Y',
'Z'};
322 for (
auto i = 0; i <= 2; ++i)
324 G4cout <<
" * " << axis[i] <<
" axis:" <<
G4endl <<
" | ";
334 std::size_t count = boundaries.size();
336 for(std::size_t i = 0; i < count; ++i)
338 G4cout << setw(10) << setiosflags(ios::fixed) << boundaries[i];
339 if(i != count-1)
G4cout <<
"-> ";
342 G4cout.precision(oldprec);
346void G4Voxelizer::BuildBitmasks(std::vector<G4double> boundaries[],
352 std::size_t numNodes = fBoxes.size();
355 for (
auto k = 0; k < 3; ++k)
357 std::vector<G4double>& boundary = boundaries[k];
358 G4int voxelsCount = (
G4int)boundary.size() - 1;
367 bitmask.
SetBitNumber(voxelsCount*bitsPerSlice-1,
false);
371 std::vector<G4int>& candidatesCount = fCandidatesCounts[k];
372 candidatesCount.resize(voxelsCount);
374 for(
G4int i = 0 ; i < voxelsCount; ++i) { candidatesCount[i] = 0; }
378 for(std::size_t j = 0 ; j < numNodes; ++j)
383 G4double p = fBoxes[j].pos[k], d = fBoxes[j].hlen[k];
389 if (i < 0) { i = 0; }
397 candidatesCount[i]++;
400 while (max > boundary[i] && i < voxelsCount);
416 for(
auto i=0; i<numNodes; ++i)
428 char axis[3] = {
'X',
'Y',
'Z'};
432 for (
auto j = 0; j <= 2; ++j)
436 for(
G4int i=0; i < count-1; ++i)
438 G4cout <<
" Slice #" << i+1 <<
": [" << fBoundaries[j][i]
439 <<
" ; " << fBoundaries[j][i+1] <<
"] -> ";
440 bits.
set(size,(
const char *)fBitmasks[j].
fAllBits+i
441 *fNPerSlice*
sizeof(
G4int));
442 G4String result = GetCandidatesAsString(bits);
449void G4Voxelizer::BuildBoundingBox()
452 fBoundaries[1].front(),
453 fBoundaries[2].front());
455 fBoundaries[1].back(),
456 fBoundaries[2].back());
457 BuildBoundingBox(min, max);
465 for (
auto i = 0; i <= 2; ++i)
469 fBoundingBoxSize[i] = (
max -
min) / 2 + tolerance * 0.5;
470 fBoundingBoxCenter[i] =
min + fBoundingBoxSize[i];
492void G4Voxelizer::SetReductionRatio(
G4int maxVoxels,
496 * fCandidatesCounts[1].size() * fCandidatesCounts[2].size();
498 if (maxVoxels > 0 && maxVoxels < maxTotal)
501 ratio = std::pow(ratio, 1./3.);
502 if (ratio > 1) { ratio = 1; }
503 reductionRatio.
set(ratio,ratio,ratio);
508void G4Voxelizer::BuildReduceVoxels(std::vector<G4double> boundaries[],
511 for (
auto k = 0; k <= 2; ++k)
513 std::vector<G4int> &candidatesCount = fCandidatesCounts[k];
515 std::vector<G4VoxelInfo> voxels(max);
516 G4VoxelComparator comp(voxels);
517 std::set<G4int, G4VoxelComparator> voxelSet(comp);
518 std::vector<G4int> mergings;
523 voxel.
count = candidatesCount[j];
529 for (
G4int j = 0; j <
max - 1; ++j) { voxelSet.insert(j); }
532 G4double reduction = reductionRatio[k];
535 G4int count = 0, currentCount;
536 while ((currentCount = (
G4int)voxelSet.size()) > 2)
539 if ((currentRatio <= reduction) && (currentCount <= 1000))
541 const G4int pos = *voxelSet.begin();
542 mergings.push_back(pos + 1);
547 if (voxelSet.erase(pos) != 1)
551 if (voxel.
next != max - 1)
552 if (voxelSet.erase(voxel.
next) != 1)
557 if (voxelSet.erase(voxel.
previous) != 1)
565 if (voxel.
next != max - 1)
566 voxelSet.insert(voxel.
next);
579 std::sort(mergings.begin(), mergings.end());
581 const std::vector<G4double>& boundary = boundaries[k];
583 vector<G4double> reducedBoundary;
584 G4int skip = mergings[0], i = 0;
590 reducedBoundary.push_back(boundary[j]);
592 else if (++i < mergingsSize)
597 boundaries[k] = reducedBoundary;
663void G4Voxelizer::BuildReduceVoxels2(std::vector<G4double> boundaries[],
666 for (
auto k = 0; k <= 2; ++k)
668 std::vector<G4int> &candidatesCount = fCandidatesCounts[k];
671 for (
G4int i = 0; i <
max; ++i) total += candidatesCount[i];
673 G4double reduction = reductionRatio[k];
677 G4int destination = (
G4int) (reduction * max) + 1;
678 if (destination > 1000) destination = 1000;
679 if (destination < 2) destination = 2;
682 std::vector<G4int> mergings;
684 std::vector<G4double> &boundary = boundaries[k];
685 std::vector<G4double> reducedBoundary(destination);
687 G4int sum = 0, cur = 0;
690 sum += candidatesCount[i];
691 if (sum > average * (cur + 1) || i == 0)
694 reducedBoundary[cur] = val;
696 if (cur == destination)
700 reducedBoundary[destination-1] = boundary[
max];
701 boundaries[k] = reducedBoundary;
707 std::vector<G4Transform3D>& transforms)
709 BuildVoxelLimits(solids, transforms);
711 BuildBitmasks(fBoundaries, fBitmasks);
717 for (
auto i = 0; i < 3; ++i)
719 fCandidatesCounts[i].resize(0);
724void G4Voxelizer::CreateMiniVoxels(std::vector<G4double> boundaries[],
727 std::vector<G4int> voxel(3), maxVoxels(3);
728 for (
auto i = 0; i <= 2; ++i) maxVoxels[i] = (
G4int)boundaries[i].size();
731 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
733 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
735 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
737 std::vector<G4int> candidates;
742 for (
auto i = 0; i <= 2; ++i)
744 G4int index = voxel[i];
745 const std::vector<G4double> &boundary = boundaries[i];
746 G4double hlen = 0.5 * (boundary[index+1] - boundary[index]);
748 box.
pos[i] = boundary[index] + hlen;
750 fVoxelBoxes.push_back(box);
751 std::vector<G4int>(candidates).swap(candidates);
752 fVoxelBoxesCandidates.push_back(candidates);
762 G4int maxVoxels = fMaxVoxels;
765 std::size_t size = facets.size();
768 for (std::size_t i = 0; i < facets.size(); ++i)
770 if (facets[i]->GetNumberOfVertices() > 3) ++size;
774 if ((size >= 10 || maxVoxels > 0) && maxVoxels != 0 && maxVoxels != 1)
780 BuildVoxelLimits(facets);
792 BuildBitmasks(fBoundaries, 0,
true);
796 maxVoxels = fTotalCandidates;
797 if (fTotalCandidates > 1000000) maxVoxels = 1000000;
800 SetReductionRatio(maxVoxels, reductionRatio);
805 G4cout <<
"Total number of voxels: " << fCountOfVoxels <<
G4endl;
808 BuildReduceVoxels2(fBoundaries, reductionRatio);
813 G4cout <<
"Total number of voxels after reduction: "
814 << fCountOfVoxels <<
G4endl;
821 BuildBitmasks(fBoundaries, fBitmasks);
829 std::vector<G4double> miniBoundaries[3];
831 for (
auto i = 0; i <= 2; ++i) { miniBoundaries[i] = fBoundaries[i]; }
833 G4int voxelsCountMini = (fCountOfVoxels >= 1000)
834 ? 100 :
G4int(fCountOfVoxels / 10);
836 SetReductionRatio(voxelsCountMini, reductionRatioMini);
842 BuildReduceVoxels(miniBoundaries, reductionRatioMini);
846 G4cout <<
"Total number of mini voxels: " << total <<
G4endl;
853 BuildBitmasks(miniBoundaries, bitmasksMini);
859 CreateMiniVoxels(miniBoundaries, bitmasksMini);
874 G4cout <<
"Deallocating unnecessary fields during runtime..." <<
G4endl;
879 for (
auto i = 0; i < 3; ++i)
881 fCandidatesCounts[i].resize(0);
882 fBitmasks[i].
Clear();
894 G4cout <<
" Candidates in voxel [" << voxels[0] <<
" ; " << voxels[1]
895 <<
" ; " << voxels[2] <<
"]: ";
896 std::vector<G4int> candidates;
899 for (
G4int i = 0; i < count; ++i)
G4cout << candidates[i];
904void G4Voxelizer::FindComponentsFastest(
unsigned int mask,
905 std::vector<G4int>& list,
G4int i)
907 for (
G4int byte = 0;
byte < (
G4int) (
sizeof(
unsigned int)); ++byte)
909 if (
G4int maskByte = mask & 0xFF)
911 for (
G4int bit = 0; bit < 8; ++bit)
914 { list.push_back(8*(
sizeof(
unsigned int)*i+
byte) + bit); }
915 if (!(maskByte >>= 1))
break;
942 min.set(kInfinity,kInfinity,kInfinity);
943 max.set(-kInfinity,-kInfinity,-kInfinity);
947 for (
G4int i = 0 ; i < limit; ++i)
951 G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
954 if (current.
x() >
max.x())
max.setX(current.
x());
955 if (current.
x() <
min.x())
min.setX(current.
x());
957 if (current.
y() >
max.y())
max.setY(current.
y());
958 if (current.
y() <
min.y())
min.setY(current.
y());
960 if (current.
z() >
max.z())
max.setZ(current.
z());
961 if (current.
z() <
min.z())
min.setZ(current.
z());
967 std::vector<G4int> &list,
G4SurfBits *crossed)
const
973 for (
auto i = 0; i <= 2; ++i)
975 if(point[i] < fBoundaries[i].front() || point[i] >= fBoundaries[i].back())
979 if (fTotalCandidates == 1)
988 unsigned int mask = 0xFFffFFff;
990 if (fBoundaries[0].size() > 2)
993 if (!(mask = ((
unsigned int*) fBitmasks[0].fAllBits)[slice]))
996 if (fBoundaries[1].size() > 2)
999 if (!(mask &= ((
unsigned int*) fBitmasks[1].fAllBits)[slice]))
1002 if (fBoundaries[2].size() > 2)
1005 if (!(mask &= ((
unsigned int*) fBitmasks[2].fAllBits)[slice]))
1008 if (crossed && (!(mask &= ~((
unsigned int*)crossed->
fAllBits)[0])))
1011 FindComponentsFastest(mask, list, 0);
1015 unsigned int* masks[3], mask;
1016 for (
auto i = 0; i <= 2; ++i)
1019 masks[i] = ((
unsigned int*) fBitmasks[i].fAllBits)
1020 + slice * fNPerSlice;
1022 unsigned int* maskCrossed = crossed
1023 ? (
unsigned int*)crossed->
fAllBits : 0;
1025 for (
G4int i = 0 ; i < fNPerSlice; ++i)
1030 if (!(mask = masks[0][i]))
continue;
1031 if (!(mask &= masks[1][i]))
continue;
1032 if (!(mask &= masks[2][i]))
continue;
1033 if (maskCrossed && !(mask &= ~maskCrossed[i]))
continue;
1035 FindComponentsFastest(mask, list, i);
1082 return (
G4int)list.size();
1089 std::vector<G4int>& list,
1094 if (fTotalCandidates == 1)
1101 if (fNPerSlice == 1)
1104 if (!(mask = ((
unsigned int *) bitmasks[0].fAllBits)[voxels[0]]))
1106 if (!(mask &= ((
unsigned int *) bitmasks[1].fAllBits)[voxels[1]]))
1108 if (!(mask &= ((
unsigned int *) bitmasks[2].fAllBits)[voxels[2]]))
1110 if (crossed && (!(mask &= ~((
unsigned int *)crossed->
fAllBits)[0])))
1113 FindComponentsFastest(mask, list, 0);
1117 unsigned int *masks[3], mask;
1118 for (
auto i = 0; i <= 2; ++i)
1120 masks[i] = ((
unsigned int *) bitmasks[i].fAllBits)
1121 + voxels[i]*fNPerSlice;
1123 unsigned int *maskCrossed = crossed !=
nullptr
1124 ? (
unsigned int *)crossed->
fAllBits : 0;
1126 for (
G4int i = 0 ; i < fNPerSlice; ++i)
1131 if (!(mask = masks[0][i]))
continue;
1132 if (!(mask &= masks[1][i]))
continue;
1133 if (!(mask &= masks[2][i]))
continue;
1134 if (maskCrossed && !(mask &= ~maskCrossed[i]))
continue;
1136 FindComponentsFastest(mask, list, i);
1140 return (
G4int)list.size();
1146 std::vector<G4int>& list,
G4SurfBits* crossed)
const
1156 for (
auto i = 0; i < 3; ++i)
1158 if (point[i] < fBoundaries[i].front() || point[i] > fBoundaries[i].back())
1193 safe = safx = -f.
x() + std::abs(aPoint.
x());
1194 safy = -f.
y() + std::abs(aPoint.
y());
1195 if ( safy > safe ) safe = safy;
1196 safz = -f.
z() + std::abs(aPoint.
z());
1197 if ( safz > safe ) safe = safz;
1198 if (safe < 0.0)
return 0.0;
1202 if ( safx > 0 ) { safsq += safx*safx; ++count; }
1203 if ( safy > 0 ) { safsq += safy*safy; ++count; }
1204 if ( safz > 0 ) { safsq += safz*safz; ++count; }
1205 if (count == 1)
return safe;
1206 return std::sqrt(safsq);
1213 std::vector<G4int>& curVoxel)
const
1218 for (
G4int i = 0; i <= 2; ++i)
1222 const std::vector<G4double>& boundary = fBoundaries[i];
1223 G4int index = curVoxel[i];
1224 if (direction[i] >= 1e-10)
1230 if (direction[i] > -1e-10)
1233 G4double dif = boundary[index] - point[i];
1234 G4double distance = dif / direction[i];
1236 if (shift > distance)
1243 if (shift != kInfinity)
1248 if (direction[cur] > 0)
1250 if (++curVoxel[cur] >= (
G4int) fBoundaries[cur].size() - 1)
1255 if (--curVoxel[cur] < 0)
1298 std::vector<G4int>& curVoxel)
const
1300 for (
auto i = 0; i <= 2; ++i)
1302 G4int index = curVoxel[i];
1303 const std::vector<G4double> &boundary = fBoundaries[i];
1305 if (direction[i] > 0)
1307 if (point[i] >= boundary[++index])
1308 if (++curVoxel[i] >= (
G4int) boundary.size() - 1)
1313 if (point[i] < boundary[index])
1314 if (--curVoxel[i] < 0)
1319 if (curVoxel[i] != indexOK)
1320 curVoxel[i] = indexOK;
1330 fReductionRatio.
set(0,0,0);
1337 fReductionRatio = ratioOfReduction;
1343 fDefaultVoxelsCount = count;
1349 return fDefaultVoxelsCount;
1356 size += fBoxes.capacity() *
sizeof(
G4VoxelBox);
1357 size +=
sizeof(
G4double) * (fBoundaries[0].capacity()
1358 + fBoundaries[1].capacity() + fBoundaries[2].capacity());
1359 size +=
sizeof(
G4int) * (fCandidatesCounts[0].capacity()
1360 + fCandidatesCounts[1].capacity() + fCandidatesCounts[2].capacity());
1365 for (
G4int i = 0; i < csize; ++i)
1367 size +=
sizeof(vector<G4int>) + fCandidates[i].capacity() *
sizeof(
G4int);
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
void set(double x, double y, double z)
void SetZHalfLength(G4double dz)
void SetYHalfLength(G4double dy)
void SetXHalfLength(G4double dx)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetRadialTolerance() const
static void DeRegister(G4VSolid *pSolid)
static G4SolidStore * GetInstance()
unsigned int GetNbytes() const
void ResetAllBits(G4bool value=false)
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
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)
static G4int GetDefaultVoxelsCount()
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