38#if !defined(G4GEOM_USE_UTET)
75 if (degeneracyFlag !=
nullptr)
77 *degeneracyFlag = degenerate;
81 std::ostringstream message;
82 message <<
"Degenerate tetrahedron: " <<
GetName() <<
" !\n"
83 <<
" anchor: " << p0 <<
"\n"
84 <<
" p1 : " << p1 <<
"\n"
85 <<
" p2 : " << p2 <<
"\n"
86 <<
" p3 : " << p3 <<
"\n"
88 << std::abs((p1 - p0).cross(p2 - p0).dot(p3 - p0))/6.;
96 Initialize(p0, p1, p2, p3);
115 delete fpPolyhedron; fpPolyhedron =
nullptr;
125 halfTolerance = rhs.halfTolerance;
126 fCubicVolume = rhs.fCubicVolume;
127 fSurfaceArea = rhs.fSurfaceArea;
128 for (
G4int i = 0; i < 4; ++i) { fVertex[i] = rhs.fVertex[i]; }
129 for (
G4int i = 0; i < 4; ++i) { fNormal[i] = rhs.fNormal[i]; }
130 for (
G4int i = 0; i < 4; ++i) { fDist[i] = rhs.fDist[i]; }
131 for (
G4int i = 0; i < 4; ++i) { fArea[i] = rhs.fArea[i]; }
144 if (
this == &rhs) {
return *
this; }
152 halfTolerance = rhs.halfTolerance;
153 fCubicVolume = rhs.fCubicVolume;
154 fSurfaceArea = rhs.fSurfaceArea;
155 for (
G4int i = 0; i < 4; ++i) { fVertex[i] = rhs.fVertex[i]; }
156 for (
G4int i = 0; i < 4; ++i) { fNormal[i] = rhs.fNormal[i]; }
157 for (
G4int i = 0; i < 4; ++i) { fDist[i] = rhs.fDist[i]; }
158 for (
G4int i = 0; i < 4; ++i) { fArea[i] = rhs.fArea[i]; }
161 fRebuildPolyhedron =
false;
162 delete fpPolyhedron; fpPolyhedron =
nullptr;
181 G4double vol = std::abs((p1 - p0).cross(p2 - p0).dot(p3 - p0));
185 ss[0] = ((p1 - p0).cross(p2 - p0)).mag2();
186 ss[1] = ((p2 - p0).cross(p3 - p0)).mag2();
187 ss[2] = ((p3 - p0).cross(p1 - p0)).mag2();
188 ss[3] = ((p2 - p1).cross(p3 - p1)).mag2();
192 for (
G4int i = 1; i < 4; ++i)
194 if (ss[i] > ss[k]) { k = i; }
198 return (vol*vol <= ss[k]*hmin*hmin);
217 norm[0] = (p2 - p0).cross(p1 - p0);
218 norm[1] = (p3 - p0).cross(p2 - p0);
219 norm[2] = (p1 - p0).cross(p3 - p0);
220 norm[3] = (p2 - p1).cross(p3 - p1);
224 for (
auto & i : norm) { i = -i; }
228 for (
G4int i = 0; i < 4; ++i) { fNormal[i] = norm[i].
unit(); }
231 for (
G4int i = 0; i < 3; ++i) { fDist[i] = fNormal[i].dot(p0); }
232 fDist[3] = fNormal[3].dot(p1);
235 for (
G4int i = 0; i < 4; ++i) { fArea[i] = 0.5*norm[i].
mag(); }
238 for (
G4int i = 0; i < 3; ++i)
240 fBmin[i] = std::min(std::min(std::min(p0[i], p1[i]), p2[i]), p3[i]);
241 fBmax[i] = std::max(std::max(std::max(p0[i], p1[i]), p2[i]), p3[i]);
245 fCubicVolume = std::abs(volume)/6.;
246 fSurfaceArea = fArea[0] + fArea[1] + fArea[2] + fArea[3];
260 if (degeneracyFlag !=
nullptr)
262 *degeneracyFlag = degenerate;
266 std::ostringstream message;
267 message <<
"Degenerate tetrahedron is not permitted: " <<
GetName() <<
" !\n"
268 <<
" anchor: " << p0 <<
"\n"
269 <<
" p1 : " << p1 <<
"\n"
270 <<
" p2 : " << p2 <<
"\n"
271 <<
" p3 : " << p3 <<
"\n"
273 << std::abs((p1 - p0).cross(p2 - p0).dot(p3 - p0))/6.;
274 G4Exception(
"G4Tet::SetVertices()",
"GeomSolids0002",
279 Initialize(p0, p1, p2, p3);
282 fRebuildPolyhedron =
true;
306 std::vector<G4ThreeVector> vertices(4);
307 for (
G4int i = 0; i < 4; ++i) { vertices[i] = fVertex[i]; }
329 G4int iout[4] = { 0, 0, 0, 0 };
330 for (
G4int i = 0; i < 4; ++i)
332 iout[i] = (
G4int)(fVertex[i].x() < pMin.
x() ||
333 fVertex[i].y() < pMin.
y() ||
334 fVertex[i].z() < pMin.
z() ||
335 fVertex[i].x() > pMax.
x() ||
336 fVertex[i].y() > pMax.
y() ||
337 fVertex[i].z() > pMax.
z());
339 if (iout[0] + iout[1] + iout[2] + iout[3] != 0)
341 std::ostringstream message;
342 message <<
"Attempt to set bounding box that does not encapsulate solid: "
344 <<
" Specified bounding box limits:\n"
345 <<
" pmin: " << pMin <<
"\n"
346 <<
" pmax: " << pMax <<
"\n"
347 <<
" Tetrahedron vertices:\n"
348 <<
" anchor " << fVertex[0] << ((iout[0]) != 0 ?
" is outside\n" :
"\n")
349 <<
" p1 " << fVertex[1] << ((iout[1]) != 0 ?
" is outside\n" :
"\n")
350 <<
" p2 " << fVertex[2] << ((iout[2]) != 0 ?
" is outside\n" :
"\n")
351 <<
" p3 " << fVertex[3] << ((iout[3]) != 0 ?
" is outside" :
"");
352 G4Exception(
"G4Tet::SetBoundingLimits()",
"GeomSolids0002",
395 return exist = (pMin < pMax) ?
true :
false;
403 anchor[0].set(vec[0].x(),vec[0].y(),vec[0].z());
406 base[0].set(vec[1].x(),vec[1].y(),vec[1].z());
407 base[1].set(vec[2].x(),vec[2].y(),vec[2].z());
408 base[2].set(vec[3].x(),vec[3].y(),vec[3].z());
410 std::vector<const G4ThreeVectorList *> polygons(2);
411 polygons[0] = &anchor;
415 return exists = benv.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
426 for (
G4int i = 0; i < 4; ++i) { dd[i] = fNormal[i].dot(p) - fDist[i]; }
428 G4double dist = std::max(std::max(std::max(dd[0], dd[1]), dd[2]), dd[3]);
429 return (dist <= -halfTolerance) ?
440 for (
G4int i = 0; i < 4; ++i)
442 k[i] = (
G4double)(std::abs(fNormal[i].dot(p) - fDist[i]) <= halfTolerance);
444 G4double nsurf = k[0] + k[1] + k[2] + k[3];
446 k[0]*fNormal[0] + k[1]*fNormal[1] + k[2]*fNormal[2] + k[3]*fNormal[3];
458 std::ostringstream message;
459 G4long oldprc = message.precision(16);
460 message <<
"Point p is not on surface (!?) of solid: "
462 message <<
"Position:\n";
463 message <<
" p.x() = " << p.
x()/mm <<
" mm\n";
464 message <<
" p.y() = " << p.
y()/mm <<
" mm\n";
465 message <<
" p.z() = " << p.
z()/mm <<
" mm";
467 G4Exception(
"G4Tet::SurfaceNormal(p)",
"GeomSolids1002",
471 return ApproxSurfaceNormal(p);
483 for (
G4int i = 0; i < 4; ++i)
486 if (d > dist) { dist = d; iside = i; }
488 return fNormal[iside];
500 for (
G4int i = 0; i < 4; ++i)
503 G4double dist = fNormal[i].dot(p) - fDist[i];
504 if (dist >= -halfTolerance)
506 if (cosa >= 0.) {
return kInfinity; }
507 tin = std::max(tin, -dist/cosa);
511 tout = std::min(tout, -dist/cosa);
515 return (tout - tin <= halfTolerance) ?
516 kInfinity : ((tin < halfTolerance) ? 0. : tin);
526 for (
G4int i = 0; i < 4; ++i) { dd[i] = fNormal[i].dot(p) - fDist[i]; }
528 G4double dist = std::max(std::max(std::max(dd[0], dd[1]), dd[2]), dd[3]);
529 return (dist > 0.) ? dist : 0.;
544 G4int ind[4] = {0}, nside = 0;
545 for (
G4int i = 0; i < 4; ++i)
549 ind[nside] = (
G4int)(tmp > 0) * i;
550 nside += (
G4int)(tmp > 0);
551 dist[i] = fNormal[i].dot(p) - fDist[i];
557 for (
G4int i = 0; i < nside; ++i)
561 if (dist[k] >= -halfTolerance) { tout = 0.; iside = k;
break; }
564 if (tmp < tout) { tout = tmp; iside = k; }
583 for (
G4int i = 0; i < 4; ++i) { dd[i] = fDist[i] - fNormal[i].dot(p); }
585 G4double dist = std::min(std::min(std::min(dd[0], dd[1]), dd[2]), dd[3]);
586 return (dist > 0.) ? dist : 0.;
613 return new G4Tet(*
this);
622 G4long oldprc = os.precision(16);
623 os <<
"-----------------------------------------------------------\n"
624 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
625 <<
" ===================================================\n"
628 <<
" anchor: " << fVertex[0]/mm <<
" mm\n"
629 <<
" p1 : " << fVertex[1]/mm <<
" mm\n"
630 <<
" p2 : " << fVertex[2]/mm <<
" mm\n"
631 <<
" p3 : " << fVertex[3]/mm <<
" mm\n"
632 <<
"-----------------------------------------------------------\n";
633 os.precision(oldprc);
643 constexpr G4int iface[4][3] = { {0,1,2}, {0,2,3}, {0,3,1}, {1,2,3} };
648 i += (
G4int)(select > fArea[0]);
649 i += (
G4int)(select > fArea[0] + fArea[1]);
650 i += (
G4int)(select > fArea[0] + fArea[1] + fArea[2]);
660 return (r1 + r2 > 1.) ?
661 p0 + e1*(1. - r1) + e2*(1. - r2) : p0 + e1*r1 + e2*r2;
697 return { fBmin.x(), fBmax.x(),
698 fBmin.y(), fBmax.y(),
699 fBmin.z(), fBmax.z() };
713 G4int k2 = (invert) ? 3 : 2;
714 G4int k3 = (invert) ? 2 : 3;
718 for (
G4int i = 0; i < 3; ++i)
720 xyz[0][i] = fVertex[0][i];
721 xyz[1][i] = fVertex[1][i];
722 xyz[2][i] = fVertex[k2][i];
723 xyz[3][i] = fVertex[k3][i];
727 G4int faces[4][4] = { {1,3,2,0}, {1,4,3,0}, {1,2,4,0}, {2,3,4,0} };
740 if (fpPolyhedron ==
nullptr ||
741 fRebuildPolyhedron ||
742 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
743 fpPolyhedron->GetNumberOfRotationSteps())
748 fRebuildPolyhedron =
false;
G4TemplateAutoLock< G4Mutex > G4AutoLock
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
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
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
G4Polyhedron * CreatePolyhedron() const override
G4VSolid * Clone() const override
G4Polyhedron * GetPolyhedron() const override
G4bool IsFaceted() const override
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4GeometryType GetEntityType() const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4Tet & operator=(const G4Tet &rhs)
G4ThreeVector GetPointOnSurface() const override
G4double GetSurfaceArea() override
void SetBoundingLimits(const G4ThreeVector &pMin, const G4ThreeVector &pMax)
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
std::ostream & StreamInfo(std::ostream &os) const override
G4double GetCubicVolume() override
G4Tet(const G4String &pName, const G4ThreeVector &anchor, const G4ThreeVector &p2, const G4ThreeVector &p3, const G4ThreeVector &p4, G4bool *degeneracyFlag=nullptr)
G4VisExtent GetExtent() const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4bool CheckDegeneracy(const G4ThreeVector &p0, const G4ThreeVector &p1, const G4ThreeVector &p2, const G4ThreeVector &p3) const
std::vector< G4ThreeVector > GetVertices() const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
EInside Inside(const G4ThreeVector &p) const override
void SetVertices(const G4ThreeVector &anchor, const G4ThreeVector &p1, const G4ThreeVector &p2, const G4ThreeVector &p3, G4bool *degeneracyFlag=nullptr)
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
virtual void AddSolid(const G4Box &)=0
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4VSolid(const G4String &name)
G4VSolid & operator=(const G4VSolid &rhs)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])