58G4int G4SurfaceVoxelizer::fDefaultVoxelsCount = -1;
62 : fBoundingBox(
"TessBBox", 1, 1, 1)
64 fCountOfVoxels = fNPerSlice = fTotalCandidates = 0;
79void G4SurfaceVoxelizer::BuildEmpty()
84 vector<G4int> xyz(3), max(3), candidates(fTotalCandidates);
85 const vector<G4int> empty(0);
87 for (
G4int i = 0; i <= 2; i++) max[i] = fBoundaries[i].size();
88 unsigned int size = max[0] * max[1] * max[2];
94 for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])
96 for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1])
98 for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[0])
109 vector<G4int> &c = (fCandidates[index] = empty);
110 c.reserve(candidates.size());
111 c.assign(candidates.begin(), candidates.end());
117 G4cout <<
"Non-empty voxels count: " << fCandidates.size() << endl;
122void G4SurfaceVoxelizer::BuildVoxelLimits(std::vector<G4VFacet *> &facets)
129 if (
G4int numNodes = facets.size())
131 fBoxes.resize(numNodes);
132 fNPerSlice = 1+(fBoxes.size()-1)/(8*
sizeof(
unsigned int));
135 toleranceVector.
set(10 * fTolerance,10 * fTolerance,10 * fTolerance);
137 for (
G4int i = 0; i < numNodes; ++i)
145 min -= toleranceVector; max += toleranceVector;
147 fBoxes[i].hlen = hlen;
148 fBoxes[i].pos = min + hlen;
150 fTotalCandidates = fBoxes.size();
159 G4int numNodes = fBoxes.size();
161 for(
G4int i = 0; i < numNodes; ++i)
163 G4cout << setw(10) << setiosflags(ios::fixed) <<
164 " -> Node " << i+1 <<
":\n" <<
165 "\t * [x,y,z] = " << fBoxes[i].hlen <<
166 "\t * [x,y,z] = " << fBoxes[i].pos <<
"\n";
168 G4cout.precision(oldprec);
172void G4SurfaceVoxelizer::CreateSortedBoundary(std::vector<G4double> &boundary,
179 G4int numNodes = fBoxes.size();
183 for(
G4int i = 0 ; i < numNodes; ++i)
188 G4double p = fBoxes[i].pos[axis], d = fBoxes[i].hlen[axis];
192 boundary[2*i] = p - d;
193 boundary[2*i+1] = p + d;
195 sort(boundary.begin(), boundary.end());
199void G4SurfaceVoxelizer::BuildBoundaries()
211 if (
G4int numNodes = fBoxes.size())
213 const G4double tolerance = fTolerance / 100.0;
216 vector<G4double> sortedBoundary(2*numNodes);
220 for (
G4int j = 0; j <= 2; ++j)
222 CreateSortedBoundary(sortedBoundary, j);
223 vector<G4double> &boundary = fBoundaries[j];
228 for(
G4int i = 0 ; i < 2*numNodes; ++i)
230 G4double newBoundary = sortedBoundary[i];
231 G4int size = boundary.size();
232 if(!size || abs(boundary[size-1] - newBoundary) > tolerance)
236 boundary.push_back(newBoundary);
244 G4int n = boundary.size();
248 G4int skip =
n / (max /2);
250 vector<G4double> reduced;
251 for (
G4int i = 0; i <
n; i++)
254 G4int size = boundary.size();
255 if (i % skip == 0 || i == 0 || i == size - 1)
262 reduced.push_back(boundary[i]);
274 char axis[3] = {
'X',
'Y',
'Z'};
275 for (
G4int i = 0; i <= 2; ++i)
277 G4cout <<
" * " << axis[i] <<
" axis:" << endl <<
" | ";
287 G4int count = boundaries.size();
289 for(
G4int i = 0; i < count; ++i)
291 G4cout << setw(10) << setiosflags(ios::fixed) << boundaries[i];
292 if(i != count-1)
G4cout <<
"-> ";
294 G4cout <<
"|" << endl <<
"Number of boundaries: " << count << endl;
295 G4cout.precision(oldprec);
299void G4SurfaceVoxelizer::BuildBitmasks(std::vector<G4double> boundaries[],
305 G4int numNodes = fBoxes.size();
308 for (
G4int k = 0; k < 3; k++)
311 vector<G4double> &boundary = boundaries[k];
312 G4int voxelsCount = boundary.size() - 1;
318 bitmask.
SetBitNumber(voxelsCount*bitsPerSlice-1,
false);
322 vector<G4int> &candidatesCount = fCandidatesCounts[k];
323 candidatesCount.resize(voxelsCount);
325 for(
G4int i = 0 ; i < voxelsCount; ++i) { candidatesCount[i] = 0; }
329 for(
G4int j = 0 ; j < numNodes; j++)
334 G4double p = fBoxes[j].pos[k], d = fBoxes[j].hlen[k];
346 candidatesCount[i]++;
350 while (max > boundary[i] && i < voxelsCount);
354 G4cout <<
"Build list nodes completed" << endl;
364 G4int numNodes = fBoxes.size();
366 for(
G4int i=0; i<numNodes; ++i)
378 char axis[3] = {
'X',
'Y',
'Z'};
382 for (
G4int j = 0; j <= 2; ++j)
384 G4cout <<
" * " << axis[j] <<
" axis:" << endl;
385 G4int count = fBoundaries[j].size();
386 for(
G4int i=0; i < count-1; ++i)
388 G4cout <<
" Slice #" << i+1 <<
": [" << fBoundaries[j][i]
389 <<
" ; " << fBoundaries[j][i+1] <<
"] -> ";
390 bits.
set(size,(
const char *)fBitmasks[j].fAllBits+i
391 *fNPerSlice*
sizeof(
G4int));
392 G4String result = GetCandidatesAsString(bits);
393 G4cout <<
"[ " << result.c_str() <<
"] " << endl;
399void G4SurfaceVoxelizer::BuildBoundingBox()
402 toleranceVector.
set(fTolerance/100,fTolerance/100,fTolerance/100);
403 for (
G4int i = 0; i <= 2; ++i)
405 G4double min = fBoundaries[i].front();
406 G4double max = fBoundaries[i].back();
407 fBoundingBoxSize[i] = (max-min)/2;
408 fBoundingBoxCenter[i] = min + fBoundingBoxSize[i];
411 fBoundingBox =
G4Box(
"TessBBox", fBoundingBoxSize.
x(),
412 fBoundingBoxSize.
y(), fBoundingBoxSize.
z());
430void G4SurfaceVoxelizer::SetReductionRatio(
G4int maxVoxels,
434 * fCandidatesCounts[1].size() * fCandidatesCounts[2].size();
436 if (maxVoxels > 0 && maxVoxels < maxTotal)
439 ratio = pow(ratio, 1./3.);
440 if (ratio > 1) { ratio = 1; }
441 reductionRatio.
set(ratio,ratio,ratio);
446void G4SurfaceVoxelizer::BuildReduceVoxels(std::vector<G4double> boundaries[],
449 for (
G4int k = 0; k <= 2; ++k)
451 vector<G4int> &candidatesCount = fCandidatesCounts[k];
452 G4int max = candidatesCount.size();
453 vector<G4VoxelInfo> voxels(max);
454 G4VoxelComparator comp(voxels);
455 set<G4int, G4VoxelComparator> voxelSet(comp);
456 vector<G4int> mergings;
458 for (
G4int j = 0; j < max; ++j)
461 voxel.
count = candidatesCount[j];
467 for (
G4int j = 0; j < max - 1; ++j) { voxelSet.insert(j); }
473 G4double reduction = reductionRatio[k];
476 G4int currentCount = voxelSet.size();
477 if (currentCount <= 2)
480 if (currentRatio <= reduction && currentCount <= 1000)
482 const G4int pos = *voxelSet.begin();
483 mergings.push_back(pos);
489 if (voxel.
next != max - 1) { voxelSet.erase(voxel.
next); }
496 if (voxel.
next != max - 1)
497 voxelSet.insert(voxel.
next);
509 sort(mergings.begin(), mergings.end());
511 vector<G4double> &boundary = boundaries[k];
512 vector<G4double> reducedBoundary(boundary.size() - mergings.size());
513 G4int skip = mergings[0] + 1, cur = 0, i = 0;
514 max = boundary.size();
515 for (
G4int j = 0; j < max; ++j)
519 reducedBoundary[cur++] = boundary[j];
523 if (++i < (
G4int)mergings.size()) { skip = mergings[i] + 1; }
526 boundaries[k] = reducedBoundary;
532void G4SurfaceVoxelizer::BuildReduceVoxels2(std::vector<G4double> boundaries[],
535 for (
G4int k = 0; k <= 2; ++k)
537 vector<G4int> &candidatesCount = fCandidatesCounts[k];
538 G4int max = candidatesCount.size();
540 for (
G4int i = 0; i < max; i++) total += candidatesCount[i];
542 G4double reduction = reductionRatio[k];
546 G4int destination = (
G4int) (reduction * max) + 1;
547 if (destination > 1000) destination = 1000;
548 if (destination < 2) destination = 2;
551 vector<G4int> mergings;
553 vector<G4double> &boundary = boundaries[k];
554 vector<G4double> reducedBoundary(destination);
556 G4int sum = 0, cur = 0;
557 for (
G4int i = 0; i < max; i++)
559 sum += candidatesCount[i];
560 if (sum > average * (cur + 1) || i == 0)
563 reducedBoundary[cur] = val;
565 if (cur == destination)
569 reducedBoundary[destination-1] = boundary[max];
570 boundaries[k] = reducedBoundary;
575void G4SurfaceVoxelizer::CreateMiniVoxels(std::vector<G4double> boundaries[],
578 vector<G4int> voxel(3), maxVoxels(3);
579 for (
G4int i = 0; i <= 2; ++i) maxVoxels[i] = boundaries[i].size();
582 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
584 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
586 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
588 vector<G4int> candidates;
593 for (
G4int i = 0; i <= 2; ++i)
595 G4int index = voxel[i];
596 const vector<G4double> &boundary = boundaries[i];
597 G4double hlen = 0.5 * (boundary[index+1] - boundary[index]);
599 box.
pos[i] = boundary[index] + hlen;
601 fVoxelBoxes.push_back(box);
602 vector<G4int>(candidates).swap(candidates);
603 fVoxelBoxesCandidates.push_back(candidates);
613 G4int maxVoxels = fMaxVoxels;
616 G4int size = facets.size();
619 for (
G4int i = 0; i < (
G4int) facets.size(); i++)
621 if (facets[i]->GetNumberOfVertices() > 3) size++;
625 if ((size >= 10 || maxVoxels > 0) && maxVoxels != 0 && maxVoxels != 1)
627 BuildVoxelLimits(facets);
631 BuildBitmasks(fBoundaries, 0,
true);
635 maxVoxels = fTotalCandidates;
636 if (fTotalCandidates > 1000000) maxVoxels = 1000000;
639 SetReductionRatio(maxVoxels, reductionRatio);
644 G4cout <<
"Total number of voxels: " << fCountOfVoxels << endl;
647 BuildReduceVoxels2(fBoundaries, reductionRatio);
652 G4cout <<
"Total number of voxels after reduction: "
653 << fCountOfVoxels << endl;
656 BuildBitmasks(fBoundaries, fBitmasks);
664 vector<G4double> miniBoundaries[3];
666 for (
G4int i = 0; i <= 2; ++i) { miniBoundaries[i] = fBoundaries[i]; }
668 G4int voxelsCountMini = (fCountOfVoxels >= 1000)
669 ? 100 : fCountOfVoxels / 10;
674 SetReductionRatio(voxelsCountMini, reductionRatioMini);
676 BuildReduceVoxels(miniBoundaries, reductionRatioMini);
680 G4cout <<
"Total number of mini voxels: " << total << endl;
683 BuildBitmasks(miniBoundaries, bitmasksMini);
685 CreateMiniVoxels(miniBoundaries, bitmasksMini);
694 for (
G4int i = 0; i < 3; i++)
696 fCandidatesCounts[i].resize(0);
697 fBitmasks[i].
Clear();
709 G4cout <<
" Candidates in voxel [" << voxels[0] <<
" ; " << voxels[1]
710 <<
" ; " << voxels[2] <<
"]: ";
711 vector<G4int> candidates;
714 for (
G4int i = 0; i < count; ++i)
G4cout << candidates[i];
719void G4SurfaceVoxelizer::FindComponentsFastest(
unsigned int mask,
720 std::vector<G4int> &list,
G4int i)
722 for (
G4int byte = 0;
byte < (
G4int) (
sizeof(
unsigned int));
byte++)
724 if (
G4int maskByte = mask & 0xFF)
726 for (
G4int bit = 0; bit < 8; bit++)
729 { list.push_back(8*(
sizeof(
unsigned int)*i+
byte) + bit); }
730 if (!(maskByte >>= 1))
break;
739 std::vector<G4int> &list,
G4SurfBits *crossed)
const
745 for (
G4int i = 0; i <= 2; ++i)
747 if(point[i] < fBoundaries[i].front() || point[i] >= fBoundaries[i].back())
751 if (fTotalCandidates == 1)
762 if (!(mask = ((
unsigned int *) fBitmasks[0].fAllBits)[slice]
765 if (!(mask &= ((
unsigned int *) fBitmasks[1].fAllBits)[slice]
768 if (!(mask &= ((
unsigned int *) fBitmasks[2].fAllBits)[slice]
770 if (crossed && (!(mask &= ~((
unsigned int *)crossed->
fAllBits)[0])))
773 FindComponentsFastest(mask, list, 0);
777 unsigned int *masks[3], mask;
778 for (
G4int i = 0; i <= 2; ++i)
781 masks[i] = ((
unsigned int *) fBitmasks[i].fAllBits) + slice*fNPerSlice;
783 unsigned int *maskCrossed =
784 crossed ? (
unsigned int *)crossed->
fAllBits : 0;
786 for (
G4int i = 0 ; i < fNPerSlice; ++i)
791 if (!(mask = masks[0][i]))
continue;
792 if (!(mask &= masks[1][i]))
continue;
793 if (!(mask &= masks[2][i]))
continue;
794 if (maskCrossed && !(mask &= ~maskCrossed[i]))
continue;
796 FindComponentsFastest(mask, list, i);
807 std::vector<G4int> &list,
812 if (fTotalCandidates == 1)
822 if (!(mask = ((
unsigned int *) bitmasks[0].fAllBits)[voxels[0]]
824 if (!(mask &= ((
unsigned int *) bitmasks[1].fAllBits)[voxels[1]]
826 if (!(mask &= ((
unsigned int *) bitmasks[2].fAllBits)[voxels[2]]
828 if (crossed && (!(mask &= ~((
unsigned int *)crossed->
fAllBits)[0])))
831 FindComponentsFastest(mask, list, 0);
835 unsigned int *masks[3], mask;
836 for (
G4int i = 0; i <= 2; ++i)
838 masks[i] = ((
unsigned int *) bitmasks[i].fAllBits)
839 + voxels[i]*fNPerSlice;
841 unsigned int *maskCrossed =
842 crossed ? (
unsigned int *)crossed->
fAllBits : 0;
844 for (
G4int i = 0 ; i < fNPerSlice; ++i)
849 if (!(mask = masks[0][i]))
continue;
850 if (!(mask &= masks[1][i]))
continue;
851 if (!(mask &= masks[2][i]))
continue;
852 if (maskCrossed && !(mask &= ~maskCrossed[i]))
continue;
854 FindComponentsFastest(mask, list, i);
864 std::vector<G4int> &list,
G4SurfBits *crossed)
const
874 for (
G4int i = 0; i < 3; ++i)
876 if (point[i] < fBoundaries[i].front() || point[i] > fBoundaries[i].back())
911 safe = safx = -f.
x() + std::abs(aPoint.
x());
912 safy = -f.
y() + std::abs(aPoint.
y());
913 if ( safy > safe ) safe = safy;
914 safz = -f.
z() + std::abs(aPoint.
z());
915 if ( safz > safe ) safe = safz;
916 if (safe < 0.0)
return 0.0;
920 if ( safx > 0 ) { safsq += safx*safx; count++; }
921 if ( safy > 0 ) { safsq += safy*safy; count++; }
922 if ( safz > 0 ) { safsq += safz*safz; count++; }
923 if (count == 1)
return safe;
924 return std::sqrt(safsq);
931 const std::vector<G4int> &curVoxel)
const
935 for (
G4int i = 0; i <= 2; ++i)
939 const vector<G4double> &boundary = fBoundaries[i];
940 G4int cur = curVoxel[i];
941 if(direction[i] >= 1e-10)
943 if (boundary[cur] - point[i] < fTolerance)
944 if (++cur >= (
G4int) boundary.size())
949 if(direction[i] <= -1e-10)
951 if (point[i] - boundary[cur] < fTolerance)
958 G4double dif = boundary[cur] - point[i];
959 G4double distance = dif / direction[i];
961 if (shift > distance)
972 std::vector<G4int> &curVoxel)
const
974 for (
G4int i = 0; i <= 2; ++i)
976 G4int index = curVoxel[i];
977 const vector<G4double> &boundary = fBoundaries[i];
979 if (direction[i] > 0)
981 if (point[i] >= boundary[++index])
982 if (++curVoxel[i] >= (
G4int) boundary.size() - 1)
987 if (point[i] < boundary[index])
988 if (--curVoxel[i] < 0)
993 if (curVoxel[i] != indexOK)
994 curVoxel[i] = indexOK;
1004 fReductionRatio.
set(0,0,0);
1011 fReductionRatio = ratioOfReduction;
1017 G4int res = fDefaultVoxelsCount;
1018 fDefaultVoxelsCount = count;
1025 return fDefaultVoxelsCount;
1032 size += fBoxes.capacity() *
sizeof(
G4VoxelBox);
1033 size +=
sizeof(
G4double) * (fBoundaries[0].capacity()
1034 + fBoundaries[1].capacity() + fBoundaries[2].capacity());
1035 size +=
sizeof(
G4int) * (fCandidatesCounts[0].capacity()
1036 + fCandidatesCounts[1].capacity() + fCandidatesCounts[2].capacity());
1040 G4int csize = fCandidates.size();
1041 for (
G4int i = 0; i < csize; i++)
1043 size +=
sizeof(vector<G4int>) + fCandidates[i].capacity() *
sizeof(
G4int);
CLHEP::Hep3Vector G4ThreeVector
G4DLLIMPORT std::ostream G4cout
void set(double x, double y, double z)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
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
G4bool Contains(const G4ThreeVector &point) const
G4bool UpdateCurrentVoxel(const G4ThreeVector &point, const G4ThreeVector &direction, std::vector< G4int > &curVoxel) const
void DisplayVoxelLimits()
G4double DistanceToBoundingBox(const G4ThreeVector &point) const
void SetMaxVoxels(G4int max)
G4double DistanceToNext(const G4ThreeVector &point, const G4ThreeVector &direction, const std::vector< G4int > &curVoxel) const
G4int GetCandidatesVoxelArray(const G4ThreeVector &point, std::vector< G4int > &list, G4SurfBits *crossed=0) const
G4int GetVoxelsIndex(G4int x, G4int y, G4int z) const
static G4double MinDistanceToBox(const G4ThreeVector &aPoint, const G4ThreeVector &f)
G4double DistanceToFirst(const G4ThreeVector &point, const G4ThreeVector &direction) const
static G4int SetDefaultVoxelsCount(G4int count)
void Voxelize(std::vector< G4VFacet * > &facets)
G4int GetBitsPerSlice() const
long long CountVoxels(std::vector< G4double > boundaries[]) const
static G4int BinarySearch(const std::vector< T > &vec, T value)
void GetCandidatesVoxel(std::vector< G4int > &voxels)
static G4int GetDefaultVoxelsCount()
virtual G4double Extent(const G4ThreeVector)=0