55 : fBoundingBox(
"VoxBBox", 1, 1, 1)
57 fCountOfVoxels = fNPerSlice = fTotalCandidates = 0;
70void G4Voxelizer::BuildEmpty()
75 std::vector<G4int> xyz(3), max(3), candidates(fTotalCandidates);
76 const std::vector<G4int> empty(0);
78 for (
auto i = 0; i <= 2; ++i) max[i] = (
G4int)fBoundaries[i].size();
79 unsigned int size = max[0] * max[1] * max[2];
85 for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])
87 for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1])
89 for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[0])
100 std::vector<G4int> &c = (fCandidates[index] = empty);
101 c.reserve(candidates.size());
102 c.assign(candidates.begin(), candidates.end());
108 G4cout <<
"Non-empty voxels count: " << fCandidates.size() <<
G4endl;
113void G4Voxelizer::BuildVoxelLimits(std::vector<G4VSolid*>& solids,
114 std::vector<G4Transform3D>& transforms)
121 if (std::size_t numNodes = solids.size())
123 fBoxes.resize(numNodes);
124 fNPerSlice =
G4int(1 + (fBoxes.size() - 1) / (8 *
sizeof(
unsigned int)));
129 G4ThreeVector toleranceVector(fTolerance,fTolerance,fTolerance);
131 for (std::size_t i = 0; i < numNodes; ++i)
143 orbToleranceVector.
set(tolerance,tolerance,tolerance);
144 min -= orbToleranceVector;
145 max += orbToleranceVector;
149 min -= toleranceVector;
150 max += toleranceVector;
152 TransformLimits(min, max, transform);
153 fBoxes[i].hlen = (
max -
min) / 2.;
154 fBoxes[i].pos = (
max +
min) / 2.;
156 fTotalCandidates = (
G4int)fBoxes.size();
161void G4Voxelizer::BuildVoxelLimits(std::vector<G4VFacet*>& facets)
168 if (std::size_t numNodes = facets.size())
170 fBoxes.resize(numNodes);
171 fNPerSlice =
G4int(1+(fBoxes.size()-1)/(8*
sizeof(
unsigned int)));
173 G4ThreeVector toleranceVector(10*fTolerance, 10*fTolerance, 10*fTolerance);
175 for (std::size_t i = 0; i < numNodes; ++i)
183 min -= toleranceVector;
184 max += toleranceVector;
186 fBoxes[i].hlen = hlen;
187 fBoxes[i].pos =
min + hlen;
189 fTotalCandidates = (
G4int)fBoxes.size();
198 std::size_t numNodes = fBoxes.size();
200 for(std::size_t i = 0; i < numNodes; ++i)
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";
207 G4cout.precision(oldprec);
211void G4Voxelizer::CreateSortedBoundary(std::vector<G4double>& boundary,
218 std::size_t numNodes = fBoxes.size();
222 for(std::size_t i = 0 ; i < numNodes; ++i)
227 G4double p = fBoxes[i].pos[axis], d = fBoxes[i].hlen[axis];
232 G4cout <<
"Boundary " << p - d <<
" - " << p + d <<
G4endl;
234 boundary[2*i] = p - d;
235 boundary[2*i+1] = p + d;
237 std::sort(boundary.begin(), boundary.end());
241void G4Voxelizer::BuildBoundaries()
253 if (std::size_t numNodes = fBoxes.size())
255 const G4double tolerance = fTolerance / 100.0;
258 std::vector<G4double> sortedBoundary(2*numNodes);
260 for (
auto j = 0; j <= 2; ++j)
262 CreateSortedBoundary(sortedBoundary, j);
263 std::vector<G4double> &boundary = fBoundaries[j];
266 for(std::size_t i = 0 ; i < 2*numNodes; ++i)
268 G4double newBoundary = sortedBoundary[i];
270 if (j == 0)
G4cout <<
"Examining " << newBoundary <<
"..." <<
G4endl;
272 auto size = (
G4int)boundary.size();
273 if((size == 0) || std::abs(boundary[size-1] - newBoundary) > tolerance)
277 if (j == 0)
G4cout <<
"Adding boundary " << newBoundary <<
"..."
280 boundary.push_back(newBoundary);
288 auto n = (
G4int)boundary.size();
294 std::vector<G4double> reduced;
295 for (
G4int i = 0; i <
n; ++i)
298 auto size = (
G4int)boundary.size();
299 if (i % skip == 0 || i == 0 || i == size - 1)
306 reduced.push_back(boundary[i]);
318 char axis[3] = {
'X',
'Y',
'Z'};
319 for (
auto i = 0; i <= 2; ++i)
321 G4cout <<
" * " << axis[i] <<
" axis:" <<
G4endl <<
" | ";
331 std::size_t count = boundaries.size();
333 for(std::size_t i = 0; i < count; ++i)
335 G4cout << setw(10) << setiosflags(ios::fixed) << boundaries[i];
336 if(i != count-1)
G4cout <<
"-> ";
339 G4cout.precision(oldprec);
343void G4Voxelizer::BuildBitmasks(std::vector<G4double> boundaries[],
349 std::size_t numNodes = fBoxes.size();
352 for (
auto k = 0; k < 3; ++k)
354 std::vector<G4double>& boundary = boundaries[k];
355 G4int voxelsCount = (
G4int)boundary.size() - 1;
364 bitmask.
SetBitNumber(voxelsCount*bitsPerSlice-1,
false);
368 std::vector<G4int>& candidatesCount = fCandidatesCounts[k];
369 candidatesCount.resize(voxelsCount);
371 for(
G4int i = 0 ; i < voxelsCount; ++i) { candidatesCount[i] = 0; }
375 for(std::size_t j = 0 ; j < numNodes; ++j)
380 G4double p = fBoxes[j].pos[k], d = fBoxes[j].hlen[k];
386 if (i < 0) { i = 0; }
394 candidatesCount[i]++;
397 while (max > boundary[i] && i < voxelsCount);
411 auto numNodes = (
G4int)fBoxes.size();
413 for(
auto i=0; i<numNodes; ++i)
425 char axis[3] = {
'X',
'Y',
'Z'};
429 for (
auto j = 0; j <= 2; ++j)
432 auto count = (
G4int)fBoundaries[j].size();
433 for(
G4int i=0; i < count-1; ++i)
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);
446void G4Voxelizer::BuildBoundingBox()
449 fBoundaries[1].front(),
450 fBoundaries[2].front());
452 fBoundaries[1].back(),
453 fBoundaries[2].back());
454 BuildBoundingBox(min, max);
462 for (
auto i = 0; i <= 2; ++i)
466 fBoundingBoxSize[i] = (
max -
min) / 2 + tolerance * 0.5;
467 fBoundingBoxCenter[i] =
min + fBoundingBoxSize[i];
489void G4Voxelizer::SetReductionRatio(
G4int maxVoxels,
493 * fCandidatesCounts[1].size() * fCandidatesCounts[2].size();
495 if (maxVoxels > 0 && maxVoxels < maxTotal)
498 ratio = std::pow(ratio, 1./3.);
499 if (ratio > 1) { ratio = 1; }
500 reductionRatio.
set(ratio,ratio,ratio);
505void G4Voxelizer::BuildReduceVoxels(std::vector<G4double> boundaries[],
508 for (
auto k = 0; k <= 2; ++k)
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;
520 voxel.
count = candidatesCount[j];
526 for (
G4int j = 0; j <
max - 1; ++j) { voxelSet.insert(j); }
529 G4double reduction = reductionRatio[k];
532 G4int count = 0, currentCount;
533 while ((currentCount = (
G4int)voxelSet.size()) > 2)
536 if ((currentRatio <= reduction) && (currentCount <= 1000))
538 const G4int pos = *voxelSet.begin();
539 mergings.push_back(pos + 1);
544 if (voxelSet.erase(pos) != 1)
548 if (voxel.
next != max - 1)
549 if (voxelSet.erase(voxel.
next) != 1)
554 if (voxelSet.erase(voxel.
previous) != 1)
562 if (voxel.
next != max - 1)
563 voxelSet.insert(voxel.
next);
574 if (!mergings.empty())
576 std::sort(mergings.begin(), mergings.end());
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;
587 reducedBoundary.push_back(boundary[j]);
589 else if (++i < mergingsSize)
594 boundaries[k] = reducedBoundary;
660void G4Voxelizer::BuildReduceVoxels2(std::vector<G4double> boundaries[],
663 for (
auto k = 0; k <= 2; ++k)
665 std::vector<G4int> &candidatesCount = fCandidatesCounts[k];
666 auto max = (
G4int)candidatesCount.size();
668 for (
G4int i = 0; i <
max; ++i) total += candidatesCount[i];
670 G4double reduction = reductionRatio[k];
674 G4int destination = (
G4int) (reduction * max) + 1;
675 if (destination > 1000) destination = 1000;
676 if (destination < 2) destination = 2;
679 std::vector<G4int> mergings;
681 std::vector<G4double> &boundary = boundaries[k];
682 std::vector<G4double> reducedBoundary(destination);
684 G4int sum = 0, cur = 0;
687 sum += candidatesCount[i];
688 if (sum > average * (cur + 1) || i == 0)
691 reducedBoundary[cur] = val;
693 if (cur == destination)
697 reducedBoundary[destination-1] = boundary[
max];
698 boundaries[k] = reducedBoundary;
704 std::vector<G4Transform3D>& transforms)
706 BuildVoxelLimits(solids, transforms);
708 BuildBitmasks(fBoundaries, fBitmasks);
714 for (
auto & fCandidatesCount : fCandidatesCounts)
716 fCandidatesCount.resize(0);
721void G4Voxelizer::CreateMiniVoxels(std::vector<G4double> boundaries[],
724 std::vector<G4int> voxel(3), maxVoxels(3);
725 for (
auto i = 0; i <= 2; ++i) maxVoxels[i] = (
G4int)boundaries[i].size();
728 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
730 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
732 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
734 std::vector<G4int> candidates;
739 for (
auto i = 0; i <= 2; ++i)
741 G4int index = voxel[i];
742 const std::vector<G4double> &boundary = boundaries[i];
743 G4double hlen = 0.5 * (boundary[index+1] - boundary[index]);
745 box.
pos[i] = boundary[index] + hlen;
747 fVoxelBoxes.push_back(box);
748 std::vector<G4int>(candidates).swap(candidates);
749 fVoxelBoxesCandidates.push_back(candidates);
759 G4int maxVoxels = fMaxVoxels;
762 std::size_t size = facets.size();
765 for (
const auto & facet : facets)
767 if (facet->GetNumberOfVertices() > 3) ++size;
771 if ((size >= 10 || maxVoxels > 0) && maxVoxels != 0 && maxVoxels != 1)
777 BuildVoxelLimits(facets);
789 BuildBitmasks(fBoundaries,
nullptr,
true);
793 maxVoxels = fTotalCandidates;
794 if (fTotalCandidates > 1000000) maxVoxels = 1000000;
797 SetReductionRatio(maxVoxels, reductionRatio);
802 G4cout <<
"Total number of voxels: " << fCountOfVoxels <<
G4endl;
805 BuildReduceVoxels2(fBoundaries, reductionRatio);
810 G4cout <<
"Total number of voxels after reduction: "
811 << fCountOfVoxels <<
G4endl;
818 BuildBitmasks(fBoundaries, fBitmasks);
826 std::vector<G4double> miniBoundaries[3];
828 for (
auto i = 0; i <= 2; ++i) { miniBoundaries[i] = fBoundaries[i]; }
830 G4int voxelsCountMini = (fCountOfVoxels >= 1000)
831 ? 100 :
G4int(fCountOfVoxels / 10);
833 SetReductionRatio(voxelsCountMini, reductionRatioMini);
839 BuildReduceVoxels(miniBoundaries, reductionRatioMini);
843 G4cout <<
"Total number of mini voxels: " << total <<
G4endl;
850 BuildBitmasks(miniBoundaries, bitmasksMini);
856 CreateMiniVoxels(miniBoundaries, bitmasksMini);
871 G4cout <<
"Deallocating unnecessary fields during runtime..." <<
G4endl;
876 for (
auto i = 0; i < 3; ++i)
878 fCandidatesCounts[i].resize(0);
879 fBitmasks[i].
Clear();
891 G4cout <<
" Candidates in voxel [" << voxels[0] <<
" ; " << voxels[1]
892 <<
" ; " << voxels[2] <<
"]: ";
893 std::vector<G4int> candidates;
896 for (
G4int i = 0; i < count; ++i)
G4cout << candidates[i];
901void G4Voxelizer::FindComponentsFastest(
unsigned int mask,
902 std::vector<G4int>& list,
G4int i)
904 for (
G4int byte = 0;
byte < (
G4int) (
sizeof(
unsigned int)); ++byte)
906 if (
G4int maskByte = mask & 0xFF)
908 for (
G4int bit = 0; bit < 8; ++bit)
910 if ((maskByte & 1) != 0)
911 { list.push_back(8*(
sizeof(
unsigned int)*i+
byte) + bit); }
912 if ((maskByte >>= 1) == 0)
break;
939 min.set(kInfinity,kInfinity,kInfinity);
940 max.set(-kInfinity,-kInfinity,-kInfinity);
944 for (
G4int i = 0 ; i < limit; ++i)
948 G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
951 if (current.
x() >
max.x())
max.setX(current.
x());
952 if (current.
x() <
min.x())
min.setX(current.
x());
954 if (current.
y() >
max.y())
max.setY(current.
y());
955 if (current.
y() <
min.y())
min.setY(current.
y());
957 if (current.
z() >
max.z())
max.setZ(current.
z());
958 if (current.
z() <
min.z())
min.setZ(current.
z());
964 std::vector<G4int> &list,
G4SurfBits *crossed)
const
970 for (
auto i = 0; i <= 2; ++i)
972 if(point[i] < fBoundaries[i].front() || point[i] >= fBoundaries[i].back())
976 if (fTotalCandidates == 1)
985 unsigned int mask = 0xFFffFFff;
987 if (fBoundaries[0].size() > 2)
990 if ((mask = ((
unsigned int*) fBitmasks[0].fAllBits)[slice]) == 0u)
993 if (fBoundaries[1].size() > 2)
996 if ((mask &= ((
unsigned int*) fBitmasks[1].fAllBits)[slice]) == 0u)
999 if (fBoundaries[2].size() > 2)
1002 if ((mask &= ((
unsigned int*) fBitmasks[2].fAllBits)[slice]) == 0u)
1005 if ((crossed !=
nullptr) && ((mask &= ~((
unsigned int*)crossed->
fAllBits)[0]) == 0u))
1008 FindComponentsFastest(mask, list, 0);
1012 unsigned int* masks[3], mask;
1013 for (
auto i = 0; i <= 2; ++i)
1016 masks[i] = ((
unsigned int*) fBitmasks[i].fAllBits)
1017 + slice * fNPerSlice;
1019 unsigned int* maskCrossed = crossed !=
nullptr
1020 ? (
unsigned int*)crossed->
fAllBits :
nullptr;
1022 for (
G4int i = 0 ; i < fNPerSlice; ++i)
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;
1032 FindComponentsFastest(mask, list, i);
1079 return (
G4int)list.size();
1086 std::vector<G4int>& list,
1091 if (fTotalCandidates == 1)
1098 if (fNPerSlice == 1)
1101 if ((mask = ((
unsigned int *) bitmasks[0].fAllBits)[voxels[0]]) == 0u)
1103 if ((mask &= ((
unsigned int *) bitmasks[1].fAllBits)[voxels[1]]) == 0u)
1105 if ((mask &= ((
unsigned int *) bitmasks[2].fAllBits)[voxels[2]]) == 0u)
1107 if ((crossed !=
nullptr) && ((mask &= ~((
unsigned int *)crossed->
fAllBits)[0]) == 0u))
1110 FindComponentsFastest(mask, list, 0);
1114 unsigned int *masks[3], mask;
1115 for (
auto i = 0; i <= 2; ++i)
1117 masks[i] = ((
unsigned int *) bitmasks[i].fAllBits)
1118 + voxels[i]*fNPerSlice;
1120 unsigned int *maskCrossed = crossed !=
nullptr
1121 ? (
unsigned int *)crossed->
fAllBits :
nullptr;
1123 for (
G4int i = 0 ; i < fNPerSlice; ++i)
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;
1133 FindComponentsFastest(mask, list, i);
1137 return (
G4int)list.size();
1143 std::vector<G4int>& list,
G4SurfBits* crossed)
const
1153 for (
auto i = 0; i < 3; ++i)
1155 if (point[i] < fBoundaries[i].front() || point[i] > fBoundaries[i].back())
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;
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);
1210 std::vector<G4int>& curVoxel)
const
1215 for (
G4int i = 0; i <= 2; ++i)
1219 const std::vector<G4double>& boundary = fBoundaries[i];
1220 G4int index = curVoxel[i];
1221 if (direction[i] >= 1e-10)
1227 if (direction[i] > -1e-10)
1230 G4double dif = boundary[index] - point[i];
1231 G4double distance = dif / direction[i];
1233 if (shift > distance)
1240 if (shift != kInfinity)
1245 if (direction[cur] > 0)
1247 if (++curVoxel[cur] >= (
G4int) fBoundaries[cur].size() - 1)
1252 if (--curVoxel[cur] < 0)
1295 std::vector<G4int>& curVoxel)
const
1297 for (
auto i = 0; i <= 2; ++i)
1299 G4int index = curVoxel[i];
1300 const std::vector<G4double> &boundary = fBoundaries[i];
1302 if (direction[i] > 0)
1304 if (point[i] >= boundary[++index])
1305 if (++curVoxel[i] >= (
G4int) boundary.size() - 1)
1310 if (point[i] < boundary[index])
1311 if (--curVoxel[i] < 0)
1316 if (curVoxel[i] != indexOK)
1317 curVoxel[i] = indexOK;
1327 fReductionRatio.
set(0,0,0);
1334 fReductionRatio = ratioOfReduction;
1340 fDefaultVoxelsCount = count;
1346 return fDefaultVoxelsCount;
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());
1361 auto csize = (
G4int)fCandidates.size();
1362 for (
G4int i = 0; i < csize; ++i)
1364 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)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
void SetZHalfLength(G4double dz)
void SetYHalfLength(G4double dy)
void SetXHalfLength(G4double dx)
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