50#if !defined(G4GEOM_USE_UTESSELLATEDSOLID)
110 fMinExtent.set(0,0,0);
111 fMaxExtent.set(0,0,0);
140 if (&ts ==
this) {
return *
this; }
156void G4TessellatedSolid::Initialize()
160 fRebuildPolyhedron =
false; fpPolyhedron =
nullptr;
161 fCubicVolume = 0.; fSurfaceArea = 0.;
163 fGeometryType =
"G4TessellatedSolid";
164 fSolidClosed =
false;
166 fMinExtent.
set(kInfinity,kInfinity,kInfinity);
167 fMaxExtent.
set(-kInfinity,-kInfinity,-kInfinity);
174void G4TessellatedSolid::DeleteObjects()
176 std::size_t size = fFacets.size();
177 for (std::size_t i = 0; i < size; ++i) {
delete fFacets[i]; }
179 delete fpPolyhedron; fpPolyhedron =
nullptr;
187 G4int fmaxVoxels = fVoxels.GetMaxVoxels(reductionRatio);
190 fVoxels.SetMaxVoxels(reductionRatio);
194 fVoxels.SetMaxVoxels(fmaxVoxels);
198 for (
G4int i = 0; i <
n; ++i)
200 G4VFacet *facetClone = (ts.
GetFacet(i))->GetClone();
217 G4Exception(
"G4TessellatedSolid::AddFacet()",
"GeomSolids1002",
218 JustWarning,
"Attempt to add facets when solid is closed.");
223 set<G4VertexInfo,G4VertexComparator>::iterator begin
224 = fFacetList.begin(), end = fFacetList.end(), pos, it;
227 value.
id = (
G4int)fFacetList.size();
228 value.
mag2 = p.
x() + p.
y() + p.
z();
234 pos = fFacetList.lower_bound(value);
237 while (!found && it != end)
242 if ((found = (facet == aFacet))) {
break; }
244 if (dif > kCarTolerance3) {
break; }
248 if (fFacets.size() > 1)
251 while (!found && it != begin)
257 found = (facet == aFacet);
258 if (found) {
break; }
260 if (dif > kCarTolerance3) {
break; }
267 fFacets.push_back(aFacet);
268 fFacetList.insert(value);
273 G4Exception(
"G4TessellatedSolid::AddFacet()",
"GeomSolids1002",
274 JustWarning,
"Attempt to add facet not properly defined.");
281G4int G4TessellatedSolid::SetAllUsingStack(
const std::vector<G4int>& voxel,
282 const std::vector<G4int>& max,
285 vector<G4int> xyz = voxel;
286 stack<vector<G4int> > pos;
290 vector<G4int> candidates;
307 for (
auto i = 0; i <= 2; ++i)
309 if (xyz[i] < max[i] - 1)
331void G4TessellatedSolid::PrecalculateInsides()
333 vector<G4int> voxel(3), maxVoxels(3);
334 for (
auto i = 0; i <= 2; ++i)
336 maxVoxels[i] = (
G4int)fVoxels.GetBoundary(i).size();
338 G4int size = maxVoxels[0] * maxVoxels[1] * maxVoxels[2];
340 G4SurfBits checked(size-1);
342 fInsides.ResetBitNumber(size-1);
345 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
347 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
349 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
351 G4int index = fVoxels.GetVoxelsIndex(voxel);
352 if (!checked[index] && fVoxels.IsEmpty(index))
354 for (
auto i = 0; i <= 2; ++i)
356 point[i] = fVoxels.GetBoundary(i)[voxel[i]];
359 SetAllUsingStack(voxel, maxVoxels, inside, checked);
372void G4TessellatedSolid::Voxelize ()
377 fVoxels.Voxelize(fFacets);
379 if (fVoxels.Empty().GetNbits() != 0u)
384 PrecalculateInsides();
400void G4TessellatedSolid::SetExtremeFacets()
403 std::size_t vsize = fVertexList.size();
404 std::vector<G4ThreeVector> vertices(vsize);
405 for (std::size_t i = 0; i < vsize; ++i) { vertices[i] = fVertexList[i]; }
408 std::mt19937 gen(12345678);
409 std::shuffle(vertices.begin(), vertices.end(), gen);
413 for (
auto & point : points) { point = vertices[0]; }
414 for (std::size_t i=1; i < vsize; ++i)
416 if (vertices[i].x() < points[0].x()) { points[0] = vertices[i]; }
417 if (vertices[i].x() > points[1].x()) { points[1] = vertices[i]; }
418 if (vertices[i].y() < points[2].y()) { points[2] = vertices[i]; }
419 if (vertices[i].y() > points[3].y()) { points[3] = vertices[i]; }
420 if (vertices[i].z() < points[4].z()) { points[4] = vertices[i]; }
421 if (vertices[i].z() > points[5].z()) { points[5] = vertices[i]; }
425 std::size_t size = fFacets.size();
426 for (std::size_t j = 0; j < size; ++j)
428 G4VFacet &facet = *fFacets[j];
431 if (!facet.
IsInside(points[0])) {
continue; }
432 if (!facet.
IsInside(points[1])) {
continue; }
433 if (!facet.
IsInside(points[2])) {
continue; }
434 if (!facet.
IsInside(points[3])) {
continue; }
435 if (!facet.
IsInside(points[4])) {
continue; }
436 if (!facet.
IsInside(points[5])) {
continue; }
440 for (std::size_t i=0; i < vsize; ++i)
448 if (isExtreme) { fExtremeFacets.insert(&facet); }
454void G4TessellatedSolid::CreateVertexList()
466 set<G4VertexInfo,G4VertexComparator> vertexListSorted;
467 set<G4VertexInfo,G4VertexComparator>::iterator begin
468 = vertexListSorted.begin(), end = vertexListSorted.end(),
pos, it;
473 std::size_t size = fFacets.size();
477 vector<G4int> newIndex(100);
479 for (std::size_t k = 0; k < size; ++k)
481 G4VFacet &facet = *fFacets[k];
487 value.
id = (
G4int)fVertexList.size();
488 value.
mag2 = p.
x() + p.
y() + p.
z();
494 pos = vertexListSorted.lower_bound(value);
501 found = (dif < kCarTolerance24);
502 if (found) {
break; }
503 dif = q.
x() + q.
y() + q.
z() - value.
mag2;
504 if (dif > kCarTolerance3) {
break; }
508 if (!found && (fVertexList.size() > 1))
517 found = (dif < kCarTolerance24);
518 if (found) {
break; }
519 dif = value.
mag2 - (q.
x() + q.
y() + q.
z());
520 if (dif > kCarTolerance3) {
break; }
529 G4cout <<
"Adding new vertex #" << i <<
" of facet " << k
533 fVertexList.push_back(p);
534 vertexListSorted.insert(value);
535 begin = vertexListSorted.begin();
536 end = vertexListSorted.end();
537 newIndex[i] = value.
id;
543 fMinExtent = fMaxExtent = p;
547 if (p.
x() > fMaxExtent.x())
549 fMaxExtent.setX(p.
x());
551 else if (p.
x() < fMinExtent.x())
553 fMinExtent.setX(p.
x());
555 if (p.
y() > fMaxExtent.y())
557 fMaxExtent.setY(p.
y());
559 else if (p.
y() < fMinExtent.y())
561 fMinExtent.setY(p.
y());
563 if (p.
z() > fMaxExtent.z())
565 fMaxExtent.setZ(p.
z());
567 else if (p.
z() < fMinExtent.z())
569 fMinExtent.setZ(p.
z());
577 G4cout <<
"Vertex #" << i <<
" of facet " << k
578 <<
" found, redirecting to " <<
id <<
G4endl;
592 vector<G4ThreeVector>(fVertexList).swap(fVertexList);
596 for (
auto res=vertexListSorted.cbegin(); res!=vertexListSorted.cend(); ++res)
598 G4int id = (*res).id;
601 if (previousValue && (previousValue - 1e-9 > mvalue))
602 G4cout <<
"Error in CreateVertexList: previousValue " << previousValue
603 <<
" is smaller than mvalue " << mvalue <<
G4endl;
604 previousValue = mvalue;
616 G4cout <<
"G4TessellatedSolid - Allocated memory without voxel overhead "
617 << without <<
"; with " << with <<
"; ratio: " << ratio <<
G4endl;
653 std::ostringstream message;
654 message <<
"Defects in solid: " <<
GetName()
655 <<
" - negative cubic volume, please check orientation of facets!";
656 G4Exception(
"G4TessellatedSolid::SetSolidClosed()",
661 std::ostringstream message;
662 message <<
"Defects in solid: " <<
GetName()
663 <<
" - some facets have wrong orientation!";
664 G4Exception(
"G4TessellatedSolid::SetSolidClosed()",
669 std::ostringstream message;
670 message <<
"Defects in solid: " <<
GetName()
671 <<
" - there are holes in the surface!";
672 G4Exception(
"G4TessellatedSolid::SetSolidClosed()",
704 std::size_t nface = fFacets.size();
709 for (std::size_t i = 0; i < nface; ++i)
715 auto ivolume =
static_cast<G4int>(volume <= 0.);
719 std::vector<int64_t> iedge(nedge);
721 for (std::size_t i = 0; i < nface; ++i)
725 for (
G4int k = 0; k < nnode; ++k)
729 auto inverse =
static_cast<int64_t
>(i2 > i1);
730 if (inverse != 0) { std::swap(i1, i2); }
731 iedge[kk++] = i1*1000000000 + i2*2 + inverse;
734 std::sort(iedge.begin(), iedge.end());
742 while (i < nedge - 1)
744 if (iedge[i + 1] - iedge[i] == 1)
748 else if (iedge[i + 1] == iedge[i])
759 return ivolume + iorder + ihole;
775 for (
G4int i = 0; i < size; ++i) {
788 return (
G4int)fFacets.size();
801 vector<G4int> startingVoxel(3);
802 fVoxels.GetVoxel(startingVoxel, p);
804 const G4double dirTolerance = 1.0E-14;
806 const vector<G4int> &startingCandidates =
807 fVoxels.GetCandidates(startingVoxel);
808 std::size_t limit = startingCandidates.size();
809 if (limit == 0 && (fInsides.GetNbits() != 0u))
811 G4int index = fVoxels.GetPointIndex(p);
818 for(std::size_t i = 0; i < limit; ++i)
820 G4int candidate = startingCandidates[i];
821 G4VFacet &facet = *fFacets[candidate];
823 if (dist < minDist) { minDist = dist; }
849 G4bool nearParallel =
false;
857 distOut = distIn = kInfinity;
869 vector<G4int> curVoxel(3);
870 curVoxel = startingVoxel;
878 const vector<G4int> &candidates =
879 started ? startingCandidates : fVoxels.GetCandidates(curVoxel);
881 if (
auto candidatesCount = (
G4int)candidates.size())
883 for (
G4int i = 0 ; i < candidatesCount; ++i)
885 G4int candidate = candidates[i];
887 G4VFacet& facet = *fFacets[candidate];
889 crossingO = facet.
Intersect(p,v,
true,distO,distFromSurfaceO,normalO);
890 crossingI = facet.
Intersect(p,v,
false,distI,distFromSurfaceI,normalI);
892 if (crossingO || crossingI)
896 nearParallel = (crossingO
897 && std::fabs(normalO.
dot(v))<dirTolerance)
898 || (crossingI && std::fabs(normalI.
dot(v))<dirTolerance);
901 if (crossingO && distO > 0.0 && distO < distOut)
905 if (crossingI && distI > 0.0 && distI < distIn)
913 if (nearParallel) {
break; }
919 G4int index = fVoxels.GetVoxelsIndex(curVoxel);
920 G4bool inside = fInsides[index];
926 G4double shift=fVoxels.DistanceToNext(currentPoint, direction, curVoxel);
927 if (shift == kInfinity) {
break; }
929 currentPoint += direction * (shift + shiftBonus);
931 while (fVoxels.UpdateCurrentVoxel(currentPoint, direction, curVoxel));
934 while (nearParallel && sm != fMaxTries);
948 std::ostringstream message;
949 G4long oldprc = message.precision(16);
950 message <<
"Cannot determine whether point is inside or outside volume!"
953 <<
"Geometry Type = " << fGeometryType <<
G4endl
954 <<
"Number of facets = " << fFacets.size() <<
G4endl
956 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
957 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
958 <<
"p.z() = " << p.
z()/mm <<
" mm";
959 message.precision(oldprc);
974 if (distIn == kInfinity && distOut == kInfinity)
1000 const G4double dirTolerance = 1.0E-14;
1006 std::size_t size = fFacets.size();
1007 for (std::size_t i = 0; i < size; ++i)
1009 G4VFacet& facet = *fFacets[i];
1011 if (dist < minDist) { minDist = dist; }
1041 G4bool crossingO =
false;
1042 G4bool crossingI =
false;
1047 for (
G4int i=0; i<nTry; ++i)
1049 G4bool nearParallel =
false;
1058 distOut = distIn = kInfinity;
1061 auto f = fFacets.cbegin();
1070 crossingO = ((*f)->Intersect(p,v,
true,distO,distFromSurfaceO,normalO));
1071 crossingI = ((*f)->Intersect(p,v,
false,distI,distFromSurfaceI,normalI));
1072 if (crossingO || crossingI)
1074 nearParallel = (crossingO && std::fabs(normalO.
dot(v))<dirTolerance)
1075 || (crossingI && std::fabs(normalI.
dot(v))<dirTolerance);
1078 if (crossingO && distO > 0.0 && distO < distOut) { distOut = distO; }
1079 if (crossingI && distI > 0.0 && distI < distIn) { distIn = distI; }
1082 }
while (!nearParallel && ++f != fFacets.cend());
1083 }
while (nearParallel && sm != fMaxTries);
1086 if (sm == fMaxTries)
1093 std::ostringstream message;
1094 G4long oldprc = message.precision(16);
1095 message <<
"Cannot determine whether point is inside or outside volume!"
1098 <<
"Geometry Type = " << fGeometryType <<
G4endl
1099 <<
"Number of facets = " << fFacets.size() <<
G4endl
1101 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1102 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1103 <<
"p.z() = " << p.
z()/mm <<
" mm";
1104 message.precision(oldprc);
1119 if (distIn == kInfinity && distOut == kInfinity)
1132 if (i == 0) { location = locationprime; }
1147 if (fVoxels.GetCountOfVoxels() > 1)
1149 vector<G4int> curVoxel(3);
1150 fVoxels.GetVoxel(curVoxel, p);
1151 const vector<G4int> &candidates = fVoxels.GetCandidates(curVoxel);
1152 if (
auto limit = (
G4int)candidates.size())
1155 for(
G4int i = 0 ; i < limit ; ++i)
1157 G4int candidate = candidates[i];
1158 G4VFacet& facet = *fFacets[candidate];
1172 std::size_t size = fFacets.size();
1173 for (std::size_t i = 0; i < size; ++i)
1198 if (fVoxels.GetCountOfVoxels() > 1)
1200 vector<G4int> curVoxel(3);
1201 fVoxels.GetVoxel(curVoxel, p);
1202 const vector<G4int> &candidates = fVoxels.GetCandidates(curVoxel);
1205 if (
auto limit = (
G4int)candidates.size())
1207 minDist = kInfinity;
1208 for(
G4int i = 0 ; i < limit ; ++i)
1210 G4int candidate = candidates[i];
1211 G4VFacet &fct = *fFacets[candidate];
1213 if (dist < minDist) { minDist = dist; }
1221 minDist = MinDistanceFacet(p,
true, facet);
1225 minDist = kInfinity;
1226 std::size_t size = fFacets.size();
1227 for (std::size_t i = 0; i < size; ++i)
1239 if (minDist != kInfinity)
1246 std::ostringstream message;
1247 message <<
"Point p is not on surface !?" <<
G4endl
1248 <<
" No facets found for point: " << p <<
" !" <<
G4endl
1249 <<
" Returning approximated value for normal.";
1251 G4Exception(
"G4TessellatedSolid::SurfaceNormal(p)",
1270G4TessellatedSolid::DistanceToInNoVoxels (
const G4ThreeVector& p,
1282 std::ostringstream message;
1283 G4int oldprc = message.precision(16) ;
1284 message <<
"Point p is already inside!?" <<
G4endl
1286 <<
" p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1287 <<
" p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1288 <<
" p.z() = " << p.
z()/mm <<
" mm" <<
G4endl
1290 message.precision(oldprc) ;
1291 G4Exception(
"G4TriangularFacet::DistanceToIn(p,v)",
1296 std::size_t size = fFacets.size();
1297 for (std::size_t i = 0; i < size; ++i)
1299 G4VFacet& facet = *fFacets[i];
1300 if (facet.
Intersect(p,v,
false,dist,distFromSurface,normal))
1334G4TessellatedSolid::DistanceToOutNoVoxels (
const G4ThreeVector& p,
1348 std::ostringstream message;
1349 G4int oldprc = message.precision(16) ;
1350 message <<
"Point p is already outside!?" <<
G4endl
1352 <<
" p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1353 <<
" p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1354 <<
" p.z() = " << p.
z()/mm <<
" mm" <<
G4endl
1356 message.precision(oldprc) ;
1357 G4Exception(
"G4TriangularFacet::DistanceToOut(p)",
1362 G4bool isExtreme =
false;
1363 std::size_t size = fFacets.size();
1364 for (std::size_t i = 0; i < size; ++i)
1366 G4VFacet& facet = *fFacets[i];
1367 if (facet.
Intersect(p,v,
true,dist,distFromSurface,normal))
1373 aConvex = (fExtremeFacets.find(&facet) != fExtremeFacets.end());
1376 aNormalVector = normal;
1379 if (dist >= 0.0 && dist < minDist)
1383 isExtreme = (fExtremeFacets.find(&facet) != fExtremeFacets.end());
1387 if (minDist < kInfinity)
1389 aNormalVector = minNormal;
1390 aConvex = isExtreme;
1396 Normal(p, aNormalVector);
1402void G4TessellatedSolid::
1403DistanceToOutCandidates(
const std::vector<G4int>& candidates,
1407 G4int& minCandidate )
const
1409 auto candidatesCount = (
G4int)candidates.size();
1414 for (
G4int i = 0 ; i < candidatesCount; ++i)
1416 G4int candidate = candidates[i];
1417 G4VFacet& facet = *fFacets[candidate];
1418 if (facet.
Intersect(aPoint,direction,
true,dist,distFromSurface,normal))
1427 minCandidate = candidate;
1430 if (dist >= 0.0 && dist < minDist)
1434 minCandidate = candidate;
1443G4TessellatedSolid::DistanceToOutCore(
const G4ThreeVector& aPoint,
1451 if (fVoxels.GetCountOfVoxels() > 1)
1453 minDistance = kInfinity;
1458 vector<G4int> curVoxel(3);
1459 if (!fVoxels.Contains(aPoint)) {
return 0.; }
1461 fVoxels.GetVoxel(curVoxel, currentPoint);
1465 const vector<G4int>* old =
nullptr;
1467 G4int minCandidate = -1;
1470 const vector<G4int>& candidates = fVoxels.GetCandidates(curVoxel);
1471 if (old == &candidates) { ++old; }
1472 if (old != &candidates && !candidates.empty())
1474 DistanceToOutCandidates(candidates, aPoint, direction, minDistance,
1475 aNormalVector, minCandidate);
1476 if (minDistance <= totalShift) {
break; }
1479 G4double shift=fVoxels.DistanceToNext(currentPoint, direction, curVoxel);
1480 if (shift == kInfinity) {
break; }
1482 totalShift += shift;
1483 if (minDistance <= totalShift) {
break; }
1485 currentPoint += direction * (shift + shiftBonus);
1489 while (fVoxels.UpdateCurrentVoxel(currentPoint, direction, curVoxel));
1491 if (minCandidate < 0)
1496 Normal(aPoint, aNormalVector);
1500 aConvex = (fExtremeFacets.find(fFacets[minCandidate])
1501 != fExtremeFacets.end());
1506 minDistance = DistanceToOutNoVoxels(aPoint, aDirection, aNormalVector,
1515DistanceToInCandidates(
const std::vector<G4int>& candidates,
1519 auto candidatesCount = (
G4int)candidates.size();
1525 for (
G4int i = 0 ; i < candidatesCount; ++i)
1527 G4int candidate = candidates[i];
1528 G4VFacet& facet = *fFacets[candidate];
1529 if (facet.
Intersect(aPoint,direction,
false,dist,distFromSurface,normal))
1539 && (dist >= 0.0) && (dist < minDistance))
1563G4TessellatedSolid::DistanceToInCore(
const G4ThreeVector& aPoint,
1569 if (fVoxels.GetCountOfVoxels() > 1)
1571 minDistance = kInfinity;
1574 G4double shift = fVoxels.DistanceToFirst(currentPoint, direction);
1575 if (shift == kInfinity) {
return shift; }
1577 if (shift != 0.0) { currentPoint += direction * (shift + shiftBonus); }
1582 vector<G4int> curVoxel(3);
1584 fVoxels.GetVoxel(curVoxel, currentPoint);
1587 const vector<G4int>& candidates = fVoxels.GetCandidates(curVoxel);
1588 if (!candidates.empty())
1590 G4double distance=DistanceToInCandidates(candidates, aPoint, direction);
1591 if (minDistance > distance) { minDistance = distance; }
1592 if (distance < totalShift) {
break; }
1595 shift = fVoxels.DistanceToNext(currentPoint, direction, curVoxel);
1596 if (shift == kInfinity ) {
break; }
1598 totalShift += shift;
1599 if (minDistance < totalShift) {
break; }
1601 currentPoint += direction * (shift + shiftBonus);
1603 while (fVoxels.UpdateCurrentVoxel(currentPoint, direction, curVoxel));
1607 minDistance = DistanceToInNoVoxels(aPoint, aDirection, aPstep);
1616G4TessellatedSolid::CompareSortedVoxel(
const std::pair<G4int, G4double>& l,
1617 const std::pair<G4int, G4double>& r)
1619 return l.second < r.second;
1631 G4int size = fVoxels.GetVoxelBoxesSize();
1632 vector<pair<G4int, G4double> > voxelsSorted(size);
1634 pair<G4int, G4double> info;
1636 for (
G4int i = 0; i < size; ++i)
1638 const G4VoxelBox& voxelBox = fVoxels.GetVoxelBox(i);
1641 G4double safety = fVoxels.MinDistanceToBox(pointShifted, voxelBox.
hlen);
1643 info.second = safety;
1644 voxelsSorted[i] = info;
1647 std::sort(voxelsSorted.begin(), voxelsSorted.end(),
1648 &G4TessellatedSolid::CompareSortedVoxel);
1650 for (
G4int i = 0; i < size; ++i)
1652 const pair<G4int,G4double>& inf = voxelsSorted[i];
1654 if (dist > minDist) {
break; }
1656 const vector<G4int>& candidates = fVoxels.GetVoxelBoxCandidates(inf.first);
1657 auto csize = (
G4int)candidates.size();
1658 for (
G4int j = 0; j < csize; ++j)
1660 G4int candidate = candidates[j];
1661 G4VFacet& facet = *fFacets[candidate];
1662 dist = simple ? facet.
Distance(p,minDist)
1682 std::ostringstream message;
1683 G4int oldprc = message.precision(16) ;
1684 message <<
"Point p is already inside!?" <<
G4endl
1686 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1687 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1688 <<
"p.z() = " << p.
z()/mm <<
" mm" <<
G4endl
1690 message.precision(oldprc) ;
1698 if (fVoxels.GetCountOfVoxels() > 1)
1700 if (!aAccurate) {
return fVoxels.DistanceToBoundingBox(p); }
1704 vector<G4int> startingVoxel(3);
1705 fVoxels.GetVoxel(startingVoxel, p);
1706 const vector<G4int> &candidates = fVoxels.GetCandidates(startingVoxel);
1707 if (candidates.empty() && (fInsides.GetNbits() != 0u))
1709 G4int index = fVoxels.GetPointIndex(p);
1710 if (fInsides[index]) {
return 0.; }
1715 minDist = MinDistanceFacet(p,
true, facet);
1719 minDist = kInfinity;
1720 std::size_t size = fFacets.size();
1721 for (std::size_t i = 0; i < size; ++i)
1725 if (dist < minDist) { minDist = dist; }
1739 std::ostringstream message;
1740 G4int oldprc = message.precision(16) ;
1741 message <<
"Point p is already outside!?" <<
G4endl
1743 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1744 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1745 <<
"p.z() = " << p.
z()/mm <<
" mm" <<
G4endl
1747 message.precision(oldprc) ;
1748 G4Exception(
"G4TriangularFacet::DistanceToOut(p)",
1757 if (fVoxels.GetCountOfVoxels() > 1)
1760 minDist = MinDistanceFacet(p,
true, facet);
1764 minDist = kInfinity;
1766 std::size_t size = fFacets.size();
1767 for (std::size_t i = 0; i < size; ++i)
1771 if (dist < minDist) { minDist = dist; }
1785 return fGeometryType;
1803 os <<
"Geometry Type = " << fGeometryType <<
G4endl;
1804 os <<
"Number of facets = " << fFacets.size() <<
G4endl;
1806 std::size_t size = fFacets.size();
1807 for (std::size_t i = 0; i < size; ++i)
1809 os <<
"FACET # = " << i + 1 <<
G4endl;
1841 if (fVoxels.GetCountOfVoxels() > 1)
1843 location = InsideVoxels(aPoint);
1847 location = InsideNoVoxels(aPoint);
1878 G4double dist = DistanceToInCore(p,v,kInfinity);
1880 if (dist < kInfinity)
1884 std::ostringstream message;
1885 message <<
"Invalid response from facet in solid '" <<
GetName() <<
"',"
1887 <<
"at point: " << p <<
"and direction: " << v;
1888 G4Exception(
"G4TessellatedSolid::DistanceToIn(p,v)",
1935 G4double dist = DistanceToOutCore(p, v, n, valid);
1942 if (dist < kInfinity)
1946 std::ostringstream message;
1947 message <<
"Invalid response from facet in solid '" <<
GetName() <<
"',"
1949 <<
"at point: " << p <<
"and direction: " << v;
1950 G4Exception(
"G4TessellatedSolid::DistanceToOut(p,v,..)",
1969 auto nVertices = (
G4int)fVertexList.size();
1970 auto nFacets = (
G4int)fFacets.size();
1971 auto polyhedron =
new G4Polyhedron(nVertices, nFacets);
1972 for (
auto i = 0; i < nVertices; ++i)
1974 polyhedron->SetVertex(i+1, fVertexList[i]);
1977 for (
auto i = 0; i < nFacets; ++i)
1982 if (n > 4) { n = 4; }
1983 for (
auto j = 0; j < n; ++j)
1987 polyhedron->SetFacet(i+1, v[0], v[1], v[2], v[3]);
1989 polyhedron->SetReferences();
2000 if (fpPolyhedron ==
nullptr ||
2001 fRebuildPolyhedron ||
2002 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
2003 fpPolyhedron->GetNumberOfRotationSteps())
2006 delete fpPolyhedron;
2008 fRebuildPolyhedron =
false;
2011 return fpPolyhedron;
2026 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
2028 std::ostringstream message;
2029 message <<
"Bad bounding box (min >= max) for solid: "
2031 <<
"\npMin = " << pMin
2032 <<
"\npMax = " << pMax;
2033 G4Exception(
"G4TessellatedSolid::BoundingLimits()",
2065 return (pMin < pMax) ? true :
false;
2076 std::vector<const G4ThreeVectorList *> pyramid(2);
2079 apex[0] = (bmin+bmax)*0.5;
2100 if (emin < pMin) { pMin = emin; }
2101 if (emax > pMax) { pMax = emax; }
2102 if (eminlim > pMin && emaxlim < pMax) {
break; }
2104 return (pMin < pMax);
2112 return fMinExtent.x();
2119 return fMaxExtent.x();
2126 return fMinExtent.y();
2133 return fMaxExtent.y();
2140 return fMinExtent.z();
2147 return fMaxExtent.z();
2154 return { fMinExtent.x(), fMaxExtent.x(),
2155 fMinExtent.y(), fMaxExtent.y(),
2156 fMinExtent.z(), fMaxExtent.z() };
2163 if (fCubicVolume != 0.) {
return fCubicVolume; }
2170 std::size_t size = fFacets.size();
2171 for (std::size_t i = 0; i < size; ++i)
2176 fCubicVolume += area * (facet.
GetVertex(0).dot(unit_normal));
2181 return fCubicVolume;
2188 if (fSurfaceArea != 0.) {
return fSurfaceArea; }
2191 std::size_t size = fFacets.size();
2192 for (std::size_t i = 0; i < size; ++i)
2195 fSurfaceArea += facet.
GetArea();
2199 return fSurfaceArea;
2209 return fFacets[i]->GetPointOnFace();
2221void G4TessellatedSolid::SetRandomVectors ()
2225 G4ThreeVector(-0.9577428892113370, 0.2732676269591740, 0.0897405271949221);
2227 G4ThreeVector(-0.8331264504940770,-0.5162067214954600,-0.1985722492445700);
2229 G4ThreeVector(-0.1516671651108820, 0.9666292616127460, 0.2064580868390110);
2231 G4ThreeVector( 0.6570250350323190,-0.6944539025883300, 0.2933460081893360);
2233 G4ThreeVector(-0.4820456281280320,-0.6331060000098690,-0.6056474264406270);
2235 G4ThreeVector( 0.7629032554236800 , 0.1016854697539910,-0.6384658864065180);
2237 G4ThreeVector( 0.7689540409061150, 0.5034929891988220, 0.3939600142169160);
2239 G4ThreeVector( 0.5765188359255740, 0.5997271636278330,-0.5549354566343150);
2241 G4ThreeVector( 0.6660632777862070,-0.6362809868288380, 0.3892379937580790);
2243 G4ThreeVector( 0.3824415020414780, 0.6541792713761380,-0.6525243125110690);
2245 G4ThreeVector(-0.5107726564526760, 0.6020905056811610, 0.6136760679616570);
2247 G4ThreeVector( 0.7459135439578050, 0.6618796061649330, 0.0743530220183488);
2249 G4ThreeVector( 0.1536405855311580, 0.8117477913978260,-0.5634359711967240);
2251 G4ThreeVector( 0.0744395301705579,-0.8707110101772920,-0.4861286795736560);
2253 G4ThreeVector(-0.1665874645185400, 0.6018553940549240,-0.7810369397872780);
2255 G4ThreeVector( 0.7766902003633100, 0.6014617505959970,-0.1870724331097450);
2257 G4ThreeVector(-0.8710128685847430,-0.1434320216603030,-0.4698551243971010);
2259 G4ThreeVector( 0.8901082092766820,-0.4388411398893870, 0.1229871120030100);
2261 G4ThreeVector(-0.6430417431544370,-0.3295938228697690, 0.6912779675984150);
2263 G4ThreeVector( 0.6331124368380410, 0.6306211461665000, 0.4488714875425340);
2272 G4int base =
sizeof(*this);
2276 std::size_t limit = fFacets.size();
2277 for (std::size_t i = 0; i < limit; ++i)
2283 for (
const auto & fExtremeFacet : fExtremeFacets)
2296 G4int sizeInsides = fInsides.GetNbytes();
2297 G4int sizeVoxels = fVoxels.AllocatedMemory();
2298 size += sizeInsides + sizeVoxels;
G4TemplateAutoLock< G4Mutex > G4AutoLock
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
double dot(const Hep3Vector &) const
void set(double x, double y, double z)
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4SurfBits provides a simple container of bits, to be used for optimization of tessellated surfaces....
void SetBitNumber(unsigned int bitnumber, G4bool value=true)
G4TessellatedSolid is a solid defined by a number of facets. It is important that the supplied facets...
virtual G4bool Normal(const G4ThreeVector &p, G4ThreeVector &n) const
G4double GetMinYExtent() const
G4int CheckStructure() const
G4double GetMinZExtent() const
EInside Inside(const G4ThreeVector &p) const override
G4TessellatedSolid & operator=(const G4TessellatedSolid &right)
G4double kCarToleranceHalf
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4Polyhedron * GetPolyhedron() const override
G4TessellatedSolid & operator+=(const G4TessellatedSolid &right)
G4bool AddFacet(G4VFacet *aFacet)
void DisplayAllocatedMemory()
G4int GetNumberOfFacets() const
G4double DistanceToOut(const G4ThreeVector &p) const override
G4ThreeVector GetPointOnSurface() const override
G4double GetMaxYExtent() const
G4double GetMaxZExtent() const
G4double GetMaxXExtent() const
G4bool GetSolidClosed() const
G4VFacet * GetFacet(G4int i) const
virtual G4double SafetyFromInside(const G4ThreeVector &p, G4bool aAccurate=false) const
G4double GetMinXExtent() const
void SetSolidClosed(const G4bool t)
G4int AllocatedMemoryWithoutVoxels()
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
G4VisExtent GetExtent() const override
G4bool IsFaceted() const override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4VSolid * Clone() const override
G4double GetSurfaceArea() override
G4int GetFacetIndex(const G4ThreeVector &p) const
virtual G4double SafetyFromOutside(const G4ThreeVector &p, G4bool aAccurate=false) const
G4double GetCubicVolume() override
std::ostream & StreamInfo(std::ostream &os) const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
~G4TessellatedSolid() override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4Polyhedron * CreatePolyhedron() const override
G4GeometryType GetEntityType() const override
G4VFacet is a base class defining the facets which are components of a G4TessellatedSolid shape.
virtual void SetVertexIndex(G4int i, G4int j)=0
virtual G4double Distance(const G4ThreeVector &, G4double minDist)=0
virtual G4bool Intersect(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool outgoing, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal)=0
virtual G4int AllocatedMemory()=0
virtual G4ThreeVector GetCircumcentre() const =0
std::ostream & StreamInfo(std::ostream &os) const
G4bool IsInside(const G4ThreeVector &p) const
virtual G4ThreeVector GetSurfaceNormal() const =0
virtual G4ThreeVector GetVertex(G4int i) const =0
virtual G4double GetArea() const =0
virtual G4int GetNumberOfVertices() const =0
virtual G4int GetVertexIndex(G4int i) const =0
virtual G4VFacet * GetClone()=0
virtual void SetVertices(std::vector< G4ThreeVector > *vertices)=0
virtual G4bool IsDefined() const =0
virtual void AddSolid(const G4Box &)=0
G4VSolid(const G4String &name)
G4VSolid & operator=(const G4VSolid &rhs)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
G4bool IsEmpty(G4int index) const
G4int GetVoxelsIndex(G4int x, G4int y, G4int z) const
T max(const T t1, const T t2)
brief Return the largest of the two arguments