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) {
if (ss[i] > ss[k]) k = i; }
195 return (vol*vol <= ss[k]*hmin*hmin);
214 norm[0] = (p2 - p0).cross(p1 - p0);
215 norm[1] = (p3 - p0).cross(p2 - p0);
216 norm[2] = (p1 - p0).cross(p3 - p0);
217 norm[3] = (p2 - p1).cross(p3 - p1);
221 for (
auto & i : norm) { i = -i; }
225 for (
G4int i = 0; i < 4; ++i) { fNormal[i] = norm[i].
unit(); }
228 for (
G4int i = 0; i < 3; ++i) { fDist[i] = fNormal[i].
dot(p0); }
229 fDist[3] = fNormal[3].
dot(p1);
232 for (
G4int i = 0; i < 4; ++i) { fArea[i] = 0.5*norm[i].
mag(); }
235 for (
G4int i = 0; i < 3; ++i)
237 fBmin[i] = std::min(std::min(std::min(p0[i], p1[i]), p2[i]), p3[i]);
238 fBmax[i] = std::max(std::max(std::max(p0[i], p1[i]), p2[i]), p3[i]);
242 fCubicVolume = std::abs(volume)/6.;
243 fSurfaceArea = fArea[0] + fArea[1] + fArea[2] + fArea[3];
257 if (degeneracyFlag !=
nullptr)
259 *degeneracyFlag = degenerate;
263 std::ostringstream message;
264 message <<
"Degenerate tetrahedron is not permitted: " <<
GetName() <<
" !\n"
265 <<
" anchor: " << p0 <<
"\n"
266 <<
" p1 : " << p1 <<
"\n"
267 <<
" p2 : " << p2 <<
"\n"
268 <<
" p3 : " << p3 <<
"\n"
270 << std::abs((p1 - p0).cross(p2 - p0).dot(p3 - p0))/6.;
271 G4Exception(
"G4Tet::SetVertices()",
"GeomSolids0002",
276 Initialize(p0, p1, p2, p3);
279 fRebuildPolyhedron =
true;
303 std::vector<G4ThreeVector> vertices(4);
304 for (
G4int i = 0; i < 4; ++i) { vertices[i] = fVertex[i]; }
326 G4int iout[4] = { 0, 0, 0, 0 };
327 for (
G4int i = 0; i < 4; ++i)
329 iout[i] = (
G4int)(fVertex[i].x() < pMin.
x() ||
330 fVertex[i].
y() < pMin.
y() ||
331 fVertex[i].
z() < pMin.
z() ||
332 fVertex[i].
x() > pMax.
x() ||
333 fVertex[i].
y() > pMax.
y() ||
334 fVertex[i].
z() > pMax.
z());
336 if (iout[0] + iout[1] + iout[2] + iout[3] != 0)
338 std::ostringstream message;
339 message <<
"Attempt to set bounding box that does not encapsulate solid: "
341 <<
" Specified bounding box limits:\n"
342 <<
" pmin: " << pMin <<
"\n"
343 <<
" pmax: " << pMax <<
"\n"
344 <<
" Tetrahedron vertices:\n"
345 <<
" anchor " << fVertex[0] << ((iout[0]) != 0 ?
" is outside\n" :
"\n")
346 <<
" p1 " << fVertex[1] << ((iout[1]) != 0 ?
" is outside\n" :
"\n")
347 <<
" p2 " << fVertex[2] << ((iout[2]) != 0 ?
" is outside\n" :
"\n")
348 <<
" p3 " << fVertex[3] << ((iout[3]) != 0 ?
" is outside" :
"");
349 G4Exception(
"G4Tet::SetBoundingLimits()",
"GeomSolids0002",
392 return exist = (pMin < pMax) ?
true :
false;
400 anchor[0].set(vec[0].x(),vec[0].y(),vec[0].z());
403 base[0].set(vec[1].x(),vec[1].y(),vec[1].z());
404 base[1].set(vec[2].x(),vec[2].y(),vec[2].z());
405 base[2].set(vec[3].x(),vec[3].y(),vec[3].z());
407 std::vector<const G4ThreeVectorList *> polygons(2);
408 polygons[0] = &anchor;
412 return exists = benv.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
423 for (
G4int i = 0; i < 4; ++i) { dd[i] = fNormal[i].
dot(p) - fDist[i]; }
425 G4double dist = std::max(std::max(std::max(dd[0], dd[1]), dd[2]), dd[3]);
426 return (dist <= -halfTolerance) ?
437 for (
G4int i = 0; i < 4; ++i)
439 k[i] = (
G4double)(std::abs(fNormal[i].dot(p) - fDist[i]) <= halfTolerance);
441 G4double nsurf = k[0] + k[1] + k[2] + k[3];
443 k[0]*fNormal[0] + k[1]*fNormal[1] + k[2]*fNormal[2] + k[3]*fNormal[3];
445 if (nsurf == 1.)
return norm;
446 else if (nsurf > 1.)
return norm.
unit();
449 std::ostringstream message;
450 G4long oldprc = message.precision(16);
451 message <<
"Point p is not on surface (!?) of solid: "
453 message <<
"Position:\n";
454 message <<
" p.x() = " << p.
x()/mm <<
" mm\n";
455 message <<
" p.y() = " << p.
y()/mm <<
" mm\n";
456 message <<
" p.z() = " << p.
z()/mm <<
" mm";
458 G4Exception(
"G4Tet::SurfaceNormal(p)",
"GeomSolids1002",
462 return ApproxSurfaceNormal(p);
475 for (
G4int i = 0; i < 4; ++i)
478 if (d > dist) { dist = d; iside = i; }
480 return fNormal[iside];
492 for (
G4int i = 0; i < 4; ++i)
496 if (dist >= -halfTolerance)
498 if (cosa >= 0.) {
return kInfinity; }
499 tin = std::max(tin, -dist/cosa);
503 tout = std::min(tout, -dist/cosa);
507 return (tout - tin <= halfTolerance) ?
508 kInfinity : ((tin < halfTolerance) ? 0. : tin);
518 for (
G4int i = 0; i < 4; ++i) { dd[i] = fNormal[i].
dot(p) - fDist[i]; }
520 G4double dist = std::max(std::max(std::max(dd[0], dd[1]), dd[2]), dd[3]);
521 return (dist > 0.) ? dist : 0.;
536 G4int ind[4] = {0}, nside = 0;
537 for (
G4int i = 0; i < 4; ++i)
541 ind[nside] = (
G4int)(tmp > 0) * i;
542 nside += (
G4int)(tmp > 0);
543 dist[i] = fNormal[i].
dot(p) - fDist[i];
549 for (
G4int i = 0; i < nside; ++i)
553 if (dist[k] >= -halfTolerance) { tout = 0.; iside = k;
break; }
556 if (tmp < tout) { tout = tmp; iside = k; }
575 for (
G4int i = 0; i < 4; ++i) { dd[i] = fDist[i] - fNormal[i].
dot(p); }
577 G4double dist = std::min(std::min(std::min(dd[0], dd[1]), dd[2]), dd[3]);
578 return (dist > 0.) ? dist : 0.;
596 return new G4Tet(*
this);
605 G4long oldprc = os.precision(16);
606 os <<
"-----------------------------------------------------------\n"
607 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
608 <<
" ===================================================\n"
611 <<
" anchor: " << fVertex[0]/mm <<
" mm\n"
612 <<
" p1 : " << fVertex[1]/mm <<
" mm\n"
613 <<
" p2 : " << fVertex[2]/mm <<
" mm\n"
614 <<
" p3 : " << fVertex[3]/mm <<
" mm\n"
615 <<
"-----------------------------------------------------------\n";
616 os.precision(oldprc);
626 constexpr G4int iface[4][3] = { {0,1,2}, {0,2,3}, {0,3,1}, {1,2,3} };
631 i += (
G4int)(select > fArea[0]);
632 i += (
G4int)(select > fArea[0] + fArea[1]);
633 i += (
G4int)(select > fArea[0] + fArea[1] + fArea[2]);
643 return (r1 + r2 > 1.) ?
644 p0 + e1*(1. - r1) + e2*(1. - r2) : p0 + e1*r1 + e2*r2;
680 return { fBmin.
x(), fBmax.
x(),
681 fBmin.
y(), fBmax.
y(),
682 fBmin.
z(), fBmax.
z() };
696 G4int k2 = (invert) ? 3 : 2;
697 G4int k3 = (invert) ? 2 : 3;
701 for (
G4int i = 0; i < 3; ++i)
703 xyz[0][i] = fVertex[0][i];
704 xyz[1][i] = fVertex[1][i];
705 xyz[2][i] = fVertex[k2][i];
706 xyz[3][i] = fVertex[k3][i];
710 G4int faces[4][4] = { {1,3,2,0}, {1,4,3,0}, {1,2,4,0}, {2,3,4,0} };
723 if (fpPolyhedron ==
nullptr ||
724 fRebuildPolyhedron ||
731 fRebuildPolyhedron =
false;
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
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
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
G4Polyhedron * CreatePolyhedron() const override
G4VSolid * Clone() const override
G4Polyhedron * GetPolyhedron() 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)
G4Tet(const G4String &pName, const G4ThreeVector &anchor, const G4ThreeVector &p1, const G4ThreeVector &p2, const G4ThreeVector &p3, G4bool *degeneracyFlag=nullptr)
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
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
G4VSolid & operator=(const G4VSolid &rhs)
static G4int GetNumberOfRotationSteps()
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])