34#if !(defined(G4GEOM_USE_UELLIPTICALTUBE) && defined(G4GEOM_USE_SYS_USOLIDS))
65 :
G4VSolid(name), fDx(Dx), fDy(Dy), fDz(Dz)
76 :
G4VSolid(a), halfTolerance(0.), fDx(0.), fDy(0.), fDz(0.),
77 fRsph(0.), fDDx(0.), fDDy(0.), fSx(0.), fSy(0.), fR(0.),
78 fQ1(0.), fQ2(0.), fScratch(0.)
88 delete fpPolyhedron; fpPolyhedron =
nullptr;
96 :
G4VSolid(rhs), halfTolerance(rhs.halfTolerance),
97 fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),
98 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
99 fRsph(rhs.fRsph), fDDx(rhs.fDDx), fDDy(rhs.fDDy),
100 fSx(rhs.fSx), fSy(rhs.fSy), fR(rhs.fR),
101 fQ1(rhs.fQ1), fQ2(rhs.fQ2), fScratch(rhs.fScratch)
113 if (
this == &rhs) {
return *
this; }
121 halfTolerance = rhs.halfTolerance;
125 fCubicVolume = rhs.fCubicVolume;
126 fSurfaceArea = rhs.fSurfaceArea;
136 fScratch = rhs.fScratch;
138 fRebuildPolyhedron =
false;
139 delete fpPolyhedron; fpPolyhedron =
nullptr;
148void G4EllipticalTube::CheckParameters()
154 if (fDx < dmin || fDy < dmin || fDz < dmin)
156 std::ostringstream message;
157 message <<
"Invalid (too small or negative) dimensions for Solid: "
161 <<
"\n Dz = " << fDz;
162 G4Exception(
"G4EllipticalTube::CheckParameters()",
"GeomSolids0002",
169 fRsph = std::sqrt(fDx * fDx + fDy * fDy + fDz * fDz);
173 fR = std::min(fDx, fDy);
178 fQ2 = 0.5 * (fR + halfTolerance * halfTolerance / fR);
190 pMin.
set(-fDx,-fDy,-fDz);
191 pMax.
set( fDx, fDy, fDz);
212 return bbox.
CalculateExtent(pAxis,pVoxelLimit, pTransform, pMin, pMax);
216 return exist = pMin < pMax;
225 const G4int NSTEPS = 24;
228 G4double sinHalf = std::sin(0.5*ang);
229 G4double cosHalf = std::cos(0.5*ang);
230 G4double sinStep = 2.*sinHalf*cosHalf;
231 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
238 for (
G4int k=0; k<NSTEPS; ++k)
240 baseA[k].set(sx*cosCur,sy*sinCur,-dz);
241 baseB[k].set(sx*cosCur,sy*sinCur, dz);
244 sinCur = sinCur*cosStep + cosCur*sinStep;
245 cosCur = cosCur*cosStep - sinTmp*sinStep;
248 std::vector<const G4ThreeVectorList *> polygons(2);
249 polygons[0] = &baseA;
250 polygons[1] = &baseB;
252 exist = benv.
CalculateExtent(pAxis, pVoxelLimit, pTransform, pMin, pMax);
265 G4double distR = fQ1 * (x * x + y * y) - fQ2;
267 G4double dist = std::max(distR, distZ);
269 if (dist > halfTolerance)
return kOutside;
285 G4double distR = fQ1 * (x * x + y * y) - fQ2;
286 if (std::abs(distR) <= halfTolerance)
294 if (std::abs(distZ) <= halfTolerance)
296 norm.
setZ(p.
z() < 0 ? -1. : 1.);
301 if (nsurf == 1)
return norm;
302 else if (nsurf > 1)
return norm.
unit();
308 std::ostringstream message;
309 G4long oldprc = message.precision(16);
310 message <<
"Point p is not on surface (!?) of solid: "
312 message <<
"Position:\n";
313 message <<
" p.x() = " << p.
x()/mm <<
" mm\n";
314 message <<
" p.y() = " << p.
y()/mm <<
" mm\n";
315 message <<
" p.z() = " << p.
z()/mm <<
" mm";
317 G4Exception(
"G4EllipticalTube::SurfaceNormal(p)",
"GeomSolids1002",
321 return ApproxSurfaceNormal(p);
332G4EllipticalTube::ApproxSurfaceNormal(
const G4ThreeVector& p )
const
336 G4double distR = fQ1 * (x * x + y * y) - fQ2;
338 if (distR > distZ && (x * x + y * y) > 0)
341 return {0, 0, (p.
z() < 0 ? -1. : 1.)};
357 G4double safex = std::abs(pcur.
x()) - fDx;
358 G4double safey = std::abs(pcur.
y()) - fDy;
359 G4double safez = std::abs(pcur.
z()) - fDz;
361 if (safez >= -halfTolerance && pcur.
z() * v.
z() >= 0.)
return kInfinity;
362 if (safey >= -halfTolerance && pcur.
y() * v.
y() >= 0.)
return kInfinity;
363 if (safex >= -halfTolerance && pcur.
x() * v.
x() >= 0.)
return kInfinity;
368 if (std::max(std::max(safex, safey), safez) > Dmax)
370 offset = (1. - 1.e-08) * pcur.
mag() - 2. * fRsph;
373 return (dist == kInfinity) ? kInfinity : dist + offset;
397 if (distR >= -halfTolerance && (
B >= 0. || parallelToZ))
return kInfinity;
402 G4double dz = std::copysign(fDz, invz);
410 if (parallelToZ)
return (tzmin<halfTolerance) ? offset : tzmin + offset;
411 if (
D <=
A *
A * fScratch)
return kInfinity;
414 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
421 G4double tin = std::max(tzmin, trmin);
422 G4double tout = std::min(tzmax, trmax);
424 if (tout <= tin + halfTolerance)
return kInfinity;
425 return (tin<halfTolerance) ? offset : tin + offset;
439 G4double distB = std::max(std::max(distX, distY), distZ);
445 G4double distR = std::sqrt(x * x + y * y) - fR;
448 G4double dist = std::max(distB, distR);
449 return (dist < 0) ? 0 : dist;
468 G4double distZ = std::abs(pz) - fDz;
469 if (distZ >= -halfTolerance && pz * vz > 0)
474 n->set(0, 0, (pz < 0) ? -1. : 1.);
478 G4double tzmax = (vz == 0) ?
DBL_MAX : (std::copysign(fDz, vz) - pz) / vz;
492 if (distR >= -halfTolerance &&
B > 0.)
504 if (std::max(distZ, distR) > halfTolerance)
507 std::ostringstream message;
508 G4long oldprc = message.precision(16);
509 message <<
"Point p is outside (!?) of solid: "
511 message <<
"Position: " << p <<
G4endl;;
512 message <<
"Direction: " << v;
514 G4Exception(
"G4EllipticalTube::DistanceToOut(p,v)",
"GeomSolids1002",
521 *n = ApproxSurfaceNormal(p);
542 n->set(0, 0, (vz < 0) ? -1. : 1.);
546 if (
D <=
A *
A * fScratch)
557 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
563 G4double tmax = std::min(tzmax, trmax);
572 n->set(0, 0, (pnew.
z() < 0) ? -1. : 1.);
590 std::ostringstream message;
591 G4long oldprc = message.precision(16);
592 message <<
"Point p is outside (!?) of solid: " <<
GetName() <<
"\n"
594 <<
" p.x() = " << p.
x()/mm <<
" mm\n"
595 <<
" p.y() = " << p.
y()/mm <<
" mm\n"
596 <<
" p.z() = " << p.
z()/mm <<
" mm";
597 message.precision(oldprc) ;
598 G4Exception(
"G4ElliptocalTube::DistanceToOut(p)",
"GeomSolids1002",
609 G4double distR = fR - std::sqrt(x * x + y * y);
612 G4double dist = std::min(distZ, distR);
613 return (dist < 0) ? 0 : dist;
622 return {
"G4EllipticalTube"};
640 if (fCubicVolume == 0.)
642 fCubicVolume = twopi * fDx * fDy * fDz;
651G4double G4EllipticalTube::GetCachedSurfaceArea()
const
657 if (cached_Dx != fDx || cached_Dy != fDy || cached_Dz != fDz)
673 if(fSurfaceArea == 0.)
675 fSurfaceArea = GetCachedSurfaceArea();
686 G4long oldprc = os.precision(16);
687 os <<
"-----------------------------------------------------------\n"
688 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
689 <<
" ===================================================\n"
690 <<
" Solid type: G4EllipticalTube\n"
692 <<
" length Z: " << fDz/mm <<
" mm \n"
693 <<
" lateral surface equation: \n"
694 <<
" (X / " << fDx <<
")^2 + (Y / " << fDy <<
")^2 = 1 \n"
695 <<
"-----------------------------------------------------------\n";
696 os.precision(oldprc);
711 G4double ssurf = GetCachedSurfaceArea();
715 if (select > sbase) k = 1;
716 if (select > 2. * sbase) k = 2;
725 p.
set(rho.
x(), rho.
y(), -fDz);
731 p.
set(rho.
x(), rho.
y(), fDz);
767 if (fpPolyhedron ==
nullptr ||
768 fRebuildPolyhedron ||
775 fRebuildPolyhedron =
false;
796 return { -fDx, fDx, -fDy, fDy, -fDz, fDz };
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)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
void set(double x, double y, double z)
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
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
virtual void AddSolid(const G4Box &)=0
G4VSolid & operator=(const G4VSolid &rhs)
static G4int GetNumberOfRotationSteps()
HepPolyhedron & Transform(const G4Transform3D &t)
#define G4ThreadLocalStatic