34#if !(defined(G4GEOM_USE_UELLIPTICALTUBE) && defined(G4GEOM_USE_SYS_USOLIDS))
63 :
G4VSolid(name), fDx(Dx), fDy(Dy), fDz(Dz)
66 fSurfaceArea = GetCachedSurfaceArea();
75 :
G4VSolid(a), halfTolerance(0.), fDx(0.), fDy(0.), fDz(0.),
76 fRsph(0.), fDDx(0.), fDDy(0.), fSx(0.), fSy(0.), fR(0.),
77 fQ1(0.), fQ2(0.), fScratch(0.)
87 delete fpPolyhedron; fpPolyhedron =
nullptr;
95 :
G4VSolid(rhs), halfTolerance(rhs.halfTolerance),
96 fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),
97 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
98 fRsph(rhs.fRsph), fDDx(rhs.fDDx), fDDy(rhs.fDDy),
99 fSx(rhs.fSx), fSy(rhs.fSy), fR(rhs.fR),
100 fQ1(rhs.fQ1), fQ2(rhs.fQ2), fScratch(rhs.fScratch)
112 if (
this == &rhs) {
return *
this; }
120 halfTolerance = rhs.halfTolerance;
124 fCubicVolume = rhs.fCubicVolume;
125 fSurfaceArea = rhs.fSurfaceArea;
135 fScratch = rhs.fScratch;
137 fRebuildPolyhedron =
false;
138 delete fpPolyhedron; fpPolyhedron =
nullptr;
147void G4EllipticalTube::CheckParameters()
153 if (fDx < dmin || fDy < dmin || fDz < dmin)
155 std::ostringstream message;
156 message <<
"Invalid (too small or negative) dimensions for Solid: "
160 <<
"\n Dz = " << fDz;
161 G4Exception(
"G4EllipticalTube::CheckParameters()",
"GeomSolids0002",
168 fRsph = std::sqrt(fDx * fDx + fDy * fDy + fDz * fDz);
172 fR = std::min(fDx, fDy);
177 fQ2 = 0.5 * (fR + halfTolerance * halfTolerance / fR);
189 pMin.
set(-fDx,-fDy,-fDz);
190 pMax.
set( fDx, fDy, fDz);
211 return bbox.
CalculateExtent(pAxis,pVoxelLimit, pTransform, pMin, pMax);
215 return exist = pMin < pMax;
224 const G4int NSTEPS = 24;
227 G4double sinHalf = std::sin(0.5*ang);
228 G4double cosHalf = std::cos(0.5*ang);
229 G4double sinStep = 2.*sinHalf*cosHalf;
230 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
237 for (
G4int k=0; k<NSTEPS; ++k)
239 baseA[k].set(sx*cosCur,sy*sinCur,-dz);
240 baseB[k].set(sx*cosCur,sy*sinCur, dz);
243 sinCur = sinCur*cosStep + cosCur*sinStep;
244 cosCur = cosCur*cosStep - sinTmp*sinStep;
247 std::vector<const G4ThreeVectorList *> polygons(2);
248 polygons[0] = &baseA;
249 polygons[1] = &baseB;
251 exist = benv.
CalculateExtent(pAxis, pVoxelLimit, pTransform, pMin, pMax);
264 G4double distR = fQ1 * (x * x + y * y) - fQ2;
266 G4double dist = std::max(distR, distZ);
268 if (dist > halfTolerance) {
return kOutside; }
284 G4double distR = fQ1 * (x * x + y * y) - fQ2;
285 if (std::abs(distR) <= halfTolerance)
293 if (std::abs(distZ) <= halfTolerance)
295 norm.
setZ(p.
z() < 0 ? -1. : 1.);
312 std::ostringstream message;
313 G4long oldprc = message.precision(16);
314 message <<
"Point p is not on surface (!?) of solid: "
316 message <<
"Position:\n";
317 message <<
" p.x() = " << p.
x()/mm <<
" mm\n";
318 message <<
" p.y() = " << p.
y()/mm <<
" mm\n";
319 message <<
" p.z() = " << p.
z()/mm <<
" mm";
321 G4Exception(
"G4EllipticalTube::SurfaceNormal(p)",
"GeomSolids1002",
325 return ApproxSurfaceNormal(p);
335G4EllipticalTube::ApproxSurfaceNormal(
const G4ThreeVector& p )
const
339 G4double distR = fQ1 * (x * x + y * y) - fQ2;
341 if (distR > distZ && (x * x + y * y) > 0)
345 return {0, 0, (p.
z() < 0 ? -1. : 1.)};
361 G4double safex = std::abs(pcur.
x()) - fDx;
362 G4double safey = std::abs(pcur.
y()) - fDy;
363 G4double safez = std::abs(pcur.
z()) - fDz;
365 if (safez >= -halfTolerance && pcur.
z() * v.
z() >= 0.) {
return kInfinity; }
366 if (safey >= -halfTolerance && pcur.
y() * v.
y() >= 0.) {
return kInfinity; }
367 if (safex >= -halfTolerance && pcur.
x() * v.
x() >= 0.) {
return kInfinity; }
372 if (std::max(std::max(safex, safey), safez) > Dmax)
374 offset = (1. - 1.e-08) * pcur.
mag() - 2. * fRsph;
377 return (dist == kInfinity) ? kInfinity : dist +
offset;
401 if (distR >= -halfTolerance && (
B >= 0. || parallelToZ)) {
return kInfinity; }
406 G4double dz = std::copysign(fDz, invz);
418 if (
D <=
A *
A * fScratch) {
return kInfinity; }
421 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
428 G4double tin = std::max(tzmin, trmin);
429 G4double tout = std::min(tzmax, trmax);
431 if (tout <= tin + halfTolerance) {
return kInfinity; }
447 G4double distB = std::max(std::max(distX, distY), distZ);
453 G4double distR = std::sqrt(x * x + y * y) - fR;
456 G4double dist = std::max(distB, distR);
457 return (dist < 0) ? 0 : dist;
476 G4double distZ = std::abs(pz) - fDz;
477 if (distZ >= -halfTolerance && pz * vz > 0)
482 n->set(0, 0, (pz < 0) ? -1. : 1.);
486 G4double tzmax = (vz == 0) ?
DBL_MAX : (std::copysign(fDz, vz) - pz) / vz;
500 if (distR >= -halfTolerance &&
B > 0.)
512 if (std::max(distZ, distR) > halfTolerance)
515 std::ostringstream message;
516 G4long oldprc = message.precision(16);
517 message <<
"Point p is outside (!?) of solid: "
519 message <<
"Position: " << p <<
G4endl;;
520 message <<
"Direction: " << v;
522 G4Exception(
"G4EllipticalTube::DistanceToOut(p,v)",
"GeomSolids1002",
529 *n = ApproxSurfaceNormal(p);
550 n->set(0, 0, (vz < 0) ? -1. : 1.);
554 if (
D <=
A *
A * fScratch)
565 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
571 G4double tmax = std::min(tzmax, trmax);
581 n->set(0, 0, (pnew.
z() < 0) ? -1. : 1.);
602 std::ostringstream message;
603 G4long oldprc = message.precision(16);
604 message <<
"Point p is outside (!?) of solid: " <<
GetName() <<
"\n"
606 <<
" p.x() = " << p.
x()/mm <<
" mm\n"
607 <<
" p.y() = " << p.
y()/mm <<
" mm\n"
608 <<
" p.z() = " << p.
z()/mm <<
" mm";
609 message.precision(oldprc) ;
610 G4Exception(
"G4ElliptocalTube::DistanceToOut(p)",
"GeomSolids1002",
621 G4double distR = fR - std::sqrt(x * x + y * y);
624 G4double dist = std::min(distZ, distR);
625 return (dist < 0) ? 0 : dist;
634 return {
"G4EllipticalTube"};
650G4double G4EllipticalTube::GetCachedSurfaceArea()
const
656 if (cached_Dx != fDx || cached_Dy != fDy || cached_Dz != fDz)
672 if (fCubicVolume == 0)
675 fCubicVolume = twopi * fDx * fDy * fDz;
687 if(fSurfaceArea == 0)
690 fSurfaceArea = GetCachedSurfaceArea();
702 G4long oldprc = os.precision(16);
703 os <<
"-----------------------------------------------------------\n"
704 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
705 <<
" ===================================================\n"
706 <<
" Solid type: G4EllipticalTube\n"
708 <<
" length Z: " << fDz/mm <<
" mm \n"
709 <<
" lateral surface equation: \n"
710 <<
" (X / " << fDx <<
")^2 + (Y / " << fDy <<
")^2 = 1 \n"
711 <<
"-----------------------------------------------------------\n";
712 os.precision(oldprc);
729 if (select < 2. * sbase)
733 x = rho * std::cos(phi);
734 y = rho * std::sin(phi);
735 z = (select < sbase) ? fDz : -fDz;
739 G4double s_max = std::max(fDx, fDy);
740 for (
auto i = 0; i < 10000; ++i)
750 return { fDx * x, fDy * y, z };
776 if (fpPolyhedron ==
nullptr ||
777 fRebuildPolyhedron ||
778 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
779 fpPolyhedron->GetNumberOfRotationSteps())
784 fRebuildPolyhedron =
false;
805 return { -fDx, fDx, -fDy, fDy, -fDz, fDz };
G4TemplateAutoLock< G4Mutex > G4AutoLock
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
G4double C(G4double temp)
G4double B(G4double temperature)
G4double D(G4double temp)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4ThreadLocal T * G4GeomSplitter< T >::offset
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
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
G4ThreeVector GetPointOnSurface() const override
G4EllipticalTube & operator=(const G4EllipticalTube &rhs)
G4double GetSurfaceArea() override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
EInside Inside(const G4ThreeVector &p) const override
G4Polyhedron * CreatePolyhedron() const override
G4GeometryType GetEntityType() const override
G4VisExtent GetExtent() const override
std::ostream & StreamInfo(std::ostream &os) const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4Polyhedron * GetPolyhedron() const override
G4VSolid * Clone() const override
~G4EllipticalTube() override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4EllipticalTube(const G4String &name, G4double Dx, G4double Dy, G4double Dz)
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4double GetCubicVolume() override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
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...
HepPolyhedron & Transform(const G4Transform3D &t)
#define G4ThreadLocalStatic