33 fCountOfVoxels = fNPerSlice = fTotalCandidates = 0;
50 void UVoxelizer::BuildEmpty()
54 vector<int> xyz(3), candidates(fTotalCandidates);
55 const vector<int> empty(0);
58 for (
int i = 0; i <= 2; ++i) max[i] = fBoundaries[i].size();
59 unsigned int size = max[0] * max[1] * max[2];
65 for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])
67 for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1])
69 for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[0])
78 vector<int>&
c = (fCandidates[
index] = empty);
79 c.reserve(candidates.size());
80 c.assign(candidates.begin(), candidates.end());
86 cout <<
"Non-empty voxels count: " << fCandidates.size() << endl;
92 void UVoxelizer::BuildVoxelLimits(vector<VUSolid*>& solids, vector<UTransform3D*>& transforms)
98 if (
int numNodes = solids.size())
100 fBoxes.resize(numNodes);
101 fNPerSlice = 1 + (fBoxes.size() - 1) / (8 *
sizeof(
unsigned int));
107 toleranceVector.
Set(fTolerance);
109 for (
int i = 0; i < numNodes; ++i)
120 orbToleranceVector.
Set(tolerance);
121 min -= orbToleranceVector;
122 max += orbToleranceVector;
126 min -= toleranceVector;
127 max += toleranceVector;
131 fBoxes[i].hlen = (max -
min) / 2;
132 fBoxes[i].pos = transform.
fTr;
134 fTotalCandidates = fBoxes.size();
137 #endif // USOLIDSONLY
139 void UVoxelizer::BuildVoxelLimits(vector<VUFacet*>& facets)
145 if (
int numNodes = facets.size())
147 fBoxes.resize(numNodes);
148 fNPerSlice = 1 + (fBoxes.size() - 1) / (8 *
sizeof(
unsigned int));
151 toleranceVector.
Set(10 * fTolerance);
153 for (
int i = 0; i < numNodes; ++i)
161 min -= toleranceVector;
162 max += toleranceVector;
164 fBoxes[i].hlen = hlen;
165 fBoxes[i].pos = min + hlen;
167 fTotalCandidates = fBoxes.size();
176 int numNodes = fBoxes.size();
177 int oldprc = cout.precision();
178 for (
int i = 0; i < numNodes; ++i)
180 cout << setw(10) << setiosflags(ios::fixed) << setprecision(16) <<
181 " -> Node " << i + 1 <<
":\n" <<
182 "\t * [x,y,z] = " << fBoxes[i].hlen <<
183 "\t * [x,y,z] = " << fBoxes[i].pos <<
"\n";
185 cout.precision(oldprc) ;
189 void UVoxelizer::CreateSortedBoundary(vector<double>& boundary,
int axis)
193 int numNodes = fBoxes.size();
195 for (
int i = 0 ; i < numNodes; ++i)
199 double p = fBoxes[i].pos[axis],
d = fBoxes[i].hlen[axis];
201 boundary[2 * i] = p -
d;
202 boundary[2 * i + 1] = p +
d;
204 sort(boundary.begin(), boundary.end());
207 void UVoxelizer::BuildBoundaries()
218 if (
int numNodes = fBoxes.size())
220 const double tolerance = fTolerance / 100.0;
221 vector<double> sortedBoundary(2 * numNodes);
225 for (
int j = 0; j <= 2; ++j)
227 CreateSortedBoundary(sortedBoundary, j);
228 vector<double>& boundary = fBoundaries[j];
233 for (
int i = 0 ; i < 2 * numNodes; ++i)
235 double newBoundary = sortedBoundary[i];
236 int size = boundary.size();
237 if (!size || abs(boundary[size - 1] - newBoundary) > tolerance)
241 boundary.push_back(newBoundary);
251 int n = boundary.size();
255 int skip = n / (max / 2);
256 vector<double> reduced;
257 for (
int i = 0; i <
n; ++i)
260 int size = boundary.size();
261 if (i % skip == 0 || i == 0 || i == size - 1)
262 reduced.push_back(boundary[i]);
272 char axis[3] = {
'X',
'Y',
'Z'};
273 for (
int i = 0; i <= 2; ++i)
275 cout <<
" * " << axis[i] <<
" axis:" << endl <<
" | ";
285 int count = boundaries.size();
286 int oldprc = cout.precision();
287 for (
int i = 0; i < count; ++i)
289 cout << setw(10) << setiosflags(ios::fixed) << setprecision(16) << boundaries[i];
292 if (i != count - 1) cout <<
"-> ";
294 cout <<
"|" << endl <<
"Number of boundaries: " << count << endl;
295 cout.precision(oldprc) ;
298 void UVoxelizer::BuildBitmasks(std::vector<double> boundaries[],
UBits bitmasks[])
302 int numNodes = fBoxes.size();
305 for (
int k = 0; k < 3; k++)
308 vector<double>& boundary = boundaries[k];
309 int voxelsCount = boundary.size() - 1;
310 UBits& bitmask = bitmasks[k];
312 if (bitmasks != NULL)
315 bitmask.
SetBitNumber(voxelsCount * bitsPerSlice - 1,
false);
317 vector<int>& candidatesCount = fCandidatesCounts[k];
318 candidatesCount.resize(voxelsCount);
320 for (
int i = 0 ; i < voxelsCount; ++i) candidatesCount[i] = 0;
323 for (
int j = 0 ; j < numNodes; j++)
327 double p = fBoxes[j].pos[k],
d = fBoxes[j].hlen[k];
337 if (bitmasks != NULL)
340 candidatesCount[i]++;
344 while (max > boundary[i] && i < voxelsCount);
384 cout <<
"Build list nodes completed" << endl;
389 string UVoxelizer::GetCandidatesAsString(
const UBits& bits)
393 int numNodes = fBoxes.size();
395 for (
int i = 0; i < numNodes; ++i)
397 const string&
result = ss.str();
405 char axis[3] = {
'X',
'Y',
'Z'};
407 int size = 8 *
sizeof(
int) * fNPerSlice;
410 for (
int j = 0; j <= 2; ++j)
412 cout <<
" * " << axis[j] <<
" axis:" << endl;
413 int count = fBoundaries[j].size();
414 for (
int i = 0; i < count - 1; ++i)
416 cout <<
" Slice #" << i + 1 <<
": [" << fBoundaries[j][i] <<
" ; " << fBoundaries[j][i + 1] <<
"] -> ";
417 bits.
Set(size, (
const char*)fBitmasks[j].fAllBits + i * fNPerSlice *
sizeof(
int));
418 string result = GetCandidatesAsString(bits);
419 cout <<
"[ " << result.c_str() <<
"] " << endl;
426 UVector3 min(fBoundaries[0].front(), fBoundaries[1].front(), fBoundaries[2].front());
427 UVector3 max(fBoundaries[0].back(), fBoundaries[1].back(), fBoundaries[2].back());
433 for (
int i = 0; i <= 2; ++i)
435 double min = amin[i];
436 double max = amax[i];
437 fBoundingBoxSize[i] = (max -
min) / 2 + tolerance * 0.5;
438 fBoundingBoxCenter[i] = min + fBoundingBoxSize[i];
440 fBoundingBox =
UBox(
"", fBoundingBoxSize.
x, fBoundingBoxSize.
y, fBoundingBoxSize.
z);
473 return (left == right) ? l < r : left <
right;
477 void UVoxelizer::SetReductionRatio(
int maxVoxels,
UVector3& reductionRatio)
479 double maxTotal = (double) fCandidatesCounts[0].size() * fCandidatesCounts[1].size() * fCandidatesCounts[2].size();
481 if (maxVoxels > 0 && maxVoxels < maxTotal)
483 double ratio = (double) maxVoxels / maxTotal;
484 ratio = pow(ratio, 1. / 3.);
485 if (ratio > 1) ratio = 1;
486 reductionRatio.
Set(ratio);
490 void UVoxelizer::BuildReduceVoxels(vector<double> boundaries[],
UVector3 reductionRatio)
492 for (
int k = 0; k <= 2; ++k)
494 vector<int>& candidatesCount = fCandidatesCounts[k];
495 int max = candidatesCount.size();
496 vector<UVoxelInfo> voxels(max);
498 set<int, UVoxelComparator> voxelSet(comp);
499 vector<int> mergings;
501 for (
int j = 0; j <
max; ++j)
504 voxel.
count = candidatesCount[j];
511 for (
int j = 0; j < max - 1; ++j) voxelSet.insert(j);
513 double reduction = reductionRatio[k];
516 int count = 0, currentCount;
517 while ((currentCount = voxelSet.size()) > 2)
519 double currentRatio = 1 - (double) count / max;
520 if (currentRatio <= reduction && currentCount <= 1000)
522 const int pos = *voxelSet.begin();
523 mergings.push_back(pos + 1);
528 if (voxelSet.erase(pos) != 1)
532 if (voxel.
next != max - 1)
533 if (voxelSet.erase(voxel.
next) != 1)
538 if (voxelSet.erase(voxel.
previous) != 1)
546 if (voxel.
next != max - 1)
547 voxelSet.insert(voxel.
next);
562 sort(mergings.begin(), mergings.end());
564 const vector<double>& boundary = boundaries[k];
565 int mergingsSize = mergings.size();
566 vector<double> reducedBoundary;
567 int skip = mergings[0], i = 0;
568 max = boundary.size();
569 for (
int j = 0; j <
max; ++j)
572 reducedBoundary.push_back(boundary[j]);
573 else if (++i < mergingsSize)
578 boundaries[k] = reducedBoundary;
584 void UVoxelizer::BuildReduceVoxels2(vector<double> boundaries[],
UVector3 reductionRatio)
586 for (
int k = 0; k <= 2; ++k)
588 vector<int>& candidatesCount = fCandidatesCounts[k];
589 int max = candidatesCount.size();
591 for (
int i = 0; i <
max; ++i) total += candidatesCount[i];
593 double reduction = reductionRatio[k];
597 int destination = (
int)(reduction * max) + 1;
598 if (destination > 1000) destination = 1000;
599 if (destination < 2) destination = 2;
600 double average = ((double)total / max) / reduction;
602 vector<int> mergings;
604 vector<double>& boundary = boundaries[k];
605 vector<double> reducedBoundary(destination);
607 int sum = 0, cur = 0;
608 for (
int i = 0; i <
max; ++i)
611 sum += candidatesCount[i];
612 if (sum > average * (cur + 1) || i == 0)
614 double val = boundary[i];
615 reducedBoundary[cur] = val;
617 if (cur == destination)
621 reducedBoundary[destination - 1] = boundary[
max];
622 boundaries[k] = reducedBoundary;
630 BuildVoxelLimits(solids, transforms);
634 BuildBitmasks(fBoundaries, fBitmasks);
642 for (
int i = 0; i < 3; ++i) fCandidatesCounts[i].resize(0);
644 #endif // USOLIDSONLY
646 void UVoxelizer::CreateMiniVoxels(std::vector<double> boundaries[],
UBits bitmasks[])
648 vector<int> voxel(3), maxVoxels(3);
649 for (
int i = 0; i <= 2; ++i) maxVoxels[i] = boundaries[i].size();
652 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
654 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
656 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
658 vector<int> candidates;
663 for (
int i = 0; i <= 2; ++i)
665 int index = voxel[i];
666 const vector<double>& boundary = boundaries[i];
667 double hlen = 0.5 * (boundary[index + 1] - boundary[
index]);
669 box.
pos[i] = boundary[
index] + hlen;
671 fVoxelBoxes.push_back(box);
672 vector<int>(candidates).
swap(candidates);
673 fVoxelBoxesCandidates.push_back(candidates);
682 int maxVoxels = fMaxVoxels;
683 UVector3 reductionRatio = fReductionRatio;
685 int size = facets.size();
687 for (
int i = 0; i < (
int) facets.size(); ++i)
688 if (facets[i]->GetNumberOfVertices() > 3) size++;
690 if ((size >= 10 || maxVoxels > 0) && maxVoxels != 0 && maxVoxels != 1)
692 BuildVoxelLimits(facets);
696 BuildBitmasks(fBoundaries, NULL);
698 if (maxVoxels < 0 && reductionRatio ==
UVector3())
711 maxVoxels = fTotalCandidates;
712 if (fTotalCandidates > 1000000) maxVoxels = 1000000;
715 SetReductionRatio(maxVoxels, reductionRatio);
720 cout <<
"Total number of voxels: " << fCountOfVoxels << endl;
723 BuildReduceVoxels2(fBoundaries, reductionRatio);
728 cout <<
"Total number of voxels after reduction: " << fCountOfVoxels << endl;
731 BuildBitmasks(fBoundaries, fBitmasks);
735 UBits bitmasksMini[3];
738 std::vector<double> miniBoundaries[3];
740 for (
int i = 0; i <= 2; ++i) miniBoundaries[i] = fBoundaries[i];
742 int voxelsCountMini = (fCountOfVoxels >= 1000) ? 100 : fCountOfVoxels / 10;
747 SetReductionRatio(voxelsCountMini, reductionRatioMini);
749 BuildReduceVoxels(miniBoundaries, reductionRatioMini);
753 cout <<
"Total number of mini voxels: " << total << endl;
756 BuildBitmasks(miniBoundaries, bitmasksMini);
758 CreateMiniVoxels(miniBoundaries, bitmasksMini);
765 for (
int i = 0; i < 3; ++i)
767 fCandidatesCounts[i].resize(0);
768 fBitmasks[i].
Clear();
779 cout <<
" Candidates in voxel [" << voxels[0] <<
" ; " << voxels[1] <<
" ; " << voxels[2] <<
"]: ";
780 vector<int> candidates;
783 for (
int i = 0; i < count; ++i) cout << candidates[i];
784 cout <<
"] " << endl;
789 inline void findComponents2(
unsigned int mask, vector<int>& list,
int i)
791 for (
int bit = 0; bit < (
int)(8 *
sizeof(
unsigned int)); bit++)
794 list.push_back(8 *
sizeof(
unsigned int)*i + bit);
795 if (!(mask >>= 1))
break;
799 inline void findComponents3(
unsigned int mask, vector<int>& list,
int i)
809 for (
int byte = 0; byte < (
int)(
sizeof(
unsigned int)); byte++)
811 if (
int maskByte = mask & 0xFF)
815 static const int firstBits[256] =
817 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
818 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
819 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
820 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
821 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
822 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
823 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
824 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
825 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
826 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
827 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
828 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
829 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
830 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
831 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
832 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
835 int bit = firstBits[maskByte];
836 list.push_back(8 * (
sizeof(
unsigned int)*i + byte) + bit);
837 maskByte -= 1 << bit;
845 #endif // USOLIDSONLY
849 for (
int byte = 0; byte < (
int)(
sizeof(
unsigned int)); byte++)
851 if (
int maskByte = mask & 0xFF)
853 for (
int bit = 0; bit < 8; bit++)
856 list.push_back(8 * (
sizeof(
unsigned int)*i + byte) + bit);
857 if (!(maskByte >>= 1))
break;
871 for (
int i = 0; i <= 2; ++i)
872 if (point[i] < fBoundaries[i].front() || point[i] >= fBoundaries[i].back())
875 if (fTotalCandidates == 1)
884 unsigned int mask = 0xFFffFFff;
886 if (fBoundaries[0].size() > 2)
889 if (!(mask = ((
unsigned int*) fBitmasks[0].fAllBits)[slice]))
return 0;
891 if (fBoundaries[1].size() > 2)
894 if (!(mask &= ((
unsigned int*) fBitmasks[1].fAllBits)[slice]
897 if (fBoundaries[2].size() > 2)
900 if (!(mask &= ((
unsigned int*) fBitmasks[2].fAllBits)[slice]
903 if (crossed && (!(mask &= ~((
unsigned int*)crossed->
fAllBits)[0])))
return 0;
909 unsigned int* masks[3], mask;
910 for (
int i = 0; i <= 2; ++i)
914 masks[i] = ((
unsigned int*) fBitmasks[i].fAllBits) + slice * fNPerSlice;
916 unsigned int* maskCrossed = crossed ? (
unsigned int*)crossed->
fAllBits : NULL;
918 for (
int i = 0 ; i < fNPerSlice; ++i)
922 if (!(mask = masks[0][i]))
continue;
923 if (!(mask &= masks[1][i]))
continue;
924 if (!(mask &= masks[2][i]))
continue;
925 if (maskCrossed && !(mask &= ~maskCrossed[i]))
continue;
942 if (fTotalCandidates == 1)
952 if (!(mask = ((
unsigned int*) bitmasks[0].fAllBits)[voxels[0]]
954 if (!(mask &= ((
unsigned int*) bitmasks[1].fAllBits)[voxels[1]]
956 if (!(mask &= ((
unsigned int*) bitmasks[2].fAllBits)[voxels[2]]
958 if (crossed && (!(mask &= ~((
unsigned int*)crossed->
fAllBits)[0])))
return 0;
964 unsigned int* masks[3], mask;
965 for (
int i = 0; i <= 2; ++i)
966 masks[i] = ((
unsigned int*) bitmasks[i].fAllBits) + voxels[i] * fNPerSlice;
968 unsigned int* maskCrossed = crossed ? (
unsigned int*)crossed->
fAllBits : NULL;
970 for (
int i = 0 ; i < fNPerSlice; ++i)
974 if (!(mask = masks[0][i]))
continue;
975 if (!(mask &= masks[1][i]))
continue;
976 if (!(mask &= masks[2][i]))
continue;
977 if (maskCrossed && !(mask &= ~maskCrossed[i]))
continue;
999 for (
int i = 0; i < 3; ++i)
1000 if (point[i] < fBoundaries[i].front() || point[i] > fBoundaries[i].back())
1009 UVector3 pointShifted = point - fBoundingBoxCenter;
1010 double shift = fBoundingBox.
DistanceToIn(pointShifted, direction);
1016 UVector3 pointShifted = point - fBoundingBoxCenter;
1026 double safe, safx, safy, safz;
1027 safe = safx = -f.
x + std::abs(aPoint.
x);
1028 safy = -f.
y + std::abs(aPoint.
y);
1029 if (safy > safe) safe = safy;
1030 safz = -f.
z + std::abs(aPoint.
z);
1031 if (safz > safe) safe = safz;
1032 if (safe < 0.0)
return 0.0;
1038 safsq += safx * safx;
1043 safsq += safy * safy;
1048 safsq += safz * safz;
1051 if (count == 1)
return safe;
1052 return std::sqrt(safsq);
1058 double shift = UUtils::kInfinity;
1061 for (
int i = 0; i <= 2; ++i)
1064 const vector<double>& boundary = fBoundaries[i];
1065 int index = curVoxel[i];
1066 if (direction[i] >= 1e-10)
1081 if (direction[i] <= -1e-10)
1093 double dif = boundary[
index] - point[i];
1094 double distance = dif / direction[i];
1096 if (shift > distance)
1103 if (shift != UUtils::kInfinity)
1106 if (direction[cur] > 0)
1108 if (++curVoxel[cur] >= (
int) fBoundaries[cur].size() - 1)
1109 shift = UUtils::kInfinity;
1113 if (--curVoxel[cur] < 0)
1114 shift = UUtils::kInfinity;
1127 fReductionRatio.
Set(0);
1133 fReductionRatio = ratioOfReduction;
1139 size += fBoxes.capacity() *
sizeof(
UVoxelBox);
1140 size +=
sizeof(double) * (fBoundaries[0].capacity() + fBoundaries[1].capacity() + fBoundaries[2].capacity());
1141 size +=
sizeof(
int) * (fCandidatesCounts[0].capacity() + fCandidatesCounts[1].capacity() + fCandidatesCounts[2].capacity());
1144 int csize = fCandidates.size();
1145 for (
int i = 0; i < csize; ++i)
1146 size +=
sizeof(vector<int>) + fCandidates[i].capacity() *
sizeof(
int);
1153 fDefaultVoxelsCount = count;
1158 return fDefaultVoxelsCount;
1161 int UVoxelizer::fDefaultVoxelsCount = -1;
1260 #endif // USOLIDSONLY
virtual UGeometryType GetEntityType() const =0
int GetVoxelsIndex(int x, int y, int z) const
double DistanceToNext(const UVector3 &point, const UVector3 &direction, std::vector< int > &curVoxel) const
static void DeRegister(G4VSolid *pSolid)
vector< UVoxelInfo > & fVoxels
unsigned int GetNbytes() const
typedef int(XMLCALL *XML_NotStandaloneHandler)(void *userData)
for(Int_t i=0;i< nentries;i++)
void findComponentsFastest(unsigned int mask, vector< int > &list, int i)
virtual double Extent(const UVector3)=0
void SetMaxVoxels(int max)
G4double G4NeutronHPJENDLHEData::G4double result
bool operator()(int l, int r)
void ResetAllBits(bool value=false)
static double Tolerance()
bool Contains(const UVector3 &point) const
double DistanceToFirst(const UVector3 &point, const UVector3 &direction) const
static int BinarySearch(const std::vector< T > &vec, T value)
static double MinDistanceToBox(const UVector3 &aPoint, const UVector3 &f)
static G4SolidStore * GetInstance()
void swap(shared_ptr< P > &, shared_ptr< P > &)
int GetCandidatesVoxelArray(const UVector3 &point, std::vector< int > &list, UBits *crossed=NULL) const
void Set(unsigned int nbits, const char *array)
long long CountVoxels(std::vector< double > boundaries[]) const
void SetBitNumber(unsigned int bitnumber, bool value=true)
double DistanceToIn(const UVector3 &aPoint, const UVector3 &aDirection, double aPstep=UUtils::kInfinity) const
G4double total(Particle const *const p1, Particle const *const p2)
void Set(double xx, double yy, double zz)
double GetRadialTolerance()
T max(const T t1, const T t2)
brief Return the largest of the two arguments
bool TestBitNumber(unsigned int bitnumber) const
void GetCandidatesVoxel(std::vector< int > &voxels)
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
static int GetDefaultVoxelsCount()
int SaveVectorToExternalFile(const std::vector< double > &vector, const std::string &filename)
int GetBitsPerSlice() const
UVoxelComparator(vector< UVoxelInfo > &voxels)
void DisplayVoxelLimits()
virtual void Extent(UVector3 &aMin, UVector3 &aMax) const =0
std::string ToString(int number)
double SafetyToBoundingBox(const UVector3 &point) const
void ResetBitNumber(unsigned int bitnumber)
static void SetDefaultVoxelsCount(int count)
void Voxelize(std::vector< VUSolid * > &solids, std::vector< UTransform3D * > &transforms)
void TransformLimits(UVector3 &min, UVector3 &max, const UTransform3D &transformation)