37#if !(defined(G4GEOM_USE_UELLIPSOID) && defined(G4GEOM_USE_SYS_USOLIDS))
73 :
G4VSolid(name), fDx(xSemiAxis), fDy(ySemiAxis), fDz(zSemiAxis),
74 fZBottomCut(zBottomCut), fZTopCut(zTopCut)
85 :
G4VSolid(a), fDx(0.), fDy(0.), fDz(0.), fZBottomCut(0.), fZTopCut(0.)
95 delete fpPolyhedron; fpPolyhedron =
nullptr;
104 fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),
105 fZBottomCut(rhs.fZBottomCut), fZTopCut(rhs.fZTopCut),
106 halfTolerance(rhs.halfTolerance),
107 fXmax(rhs.fXmax), fYmax(rhs.fYmax),
108 fRsph(rhs.fRsph), fR(rhs.fR),
109 fSx(rhs.fSx), fSy(rhs.fSy), fSz(rhs.fSz),
110 fZMidCut(rhs.fZMidCut), fZDimCut(rhs.fZDimCut),
111 fQ1(rhs.fQ1), fQ2(rhs.fQ2),
112 fCubicVolume(rhs.fCubicVolume),
113 fSurfaceArea(rhs.fSurfaceArea),
114 fLateralArea(rhs.fLateralArea)
126 if (
this == &rhs) {
return *
this; }
137 fZBottomCut = rhs.fZBottomCut;
138 fZTopCut = rhs.fZTopCut;
140 halfTolerance = rhs.halfTolerance;
148 fZMidCut = rhs.fZMidCut;
149 fZDimCut = rhs.fZDimCut;
153 fCubicVolume = rhs.fCubicVolume;
154 fSurfaceArea = rhs.fSurfaceArea;
155 fLateralArea = rhs.fLateralArea;
157 fRebuildPolyhedron =
false;
158 delete fpPolyhedron; fpPolyhedron =
nullptr;
167void G4Ellipsoid::CheckParameters()
174 if (fDx < dmin || fDy < dmin || fDz < dmin)
176 std::ostringstream message;
177 message <<
"Invalid (too small or negative) dimensions for Solid: "
179 <<
" semi-axis x: " << fDx <<
"\n"
180 <<
" semi-axis y: " << fDy <<
"\n"
181 <<
" semi-axis z: " << fDz;
182 G4Exception(
"G4Ellipsoid::CheckParameters()",
"GeomSolids0002",
191 if (fZBottomCut == 0. && fZTopCut == 0.)
196 if (fZBottomCut >=
C || fZTopCut <= -C || fZBottomCut >= fZTopCut)
198 std::ostringstream message;
199 message <<
"Invalid Z cuts for Solid: "
201 <<
" bottom cut: " << fZBottomCut <<
"\n"
202 <<
" top cut: " << fZTopCut;
203 G4Exception(
"G4Ellipsoid::CheckParameters()",
"GeomSolids0002",
207 fZBottomCut = std::max(fZBottomCut, -
C);
208 fZTopCut = std::min(fZTopCut,
C);
213 if (fZBottomCut > 0.)
216 G4double scale = std::sqrt((1. - ratio) * (1 + ratio));
223 G4double scale = std::sqrt((1. - ratio) * (1 + ratio));
229 fRsph = std::max(std::max(
A,
B),
C);
230 fR = std::min(std::min(
A,
B),
C);
236 fZMidCut = 0.5 * (fZTopCut + fZBottomCut) * fSz;
237 fZDimCut = 0.5 * (fZTopCut - fZBottomCut) * fSz;
241 fQ2 = 0.5 * fR + halfTolerance * halfTolerance * fQ1;
267 pMin.
set(-fXmax,-fYmax, fZBottomCut);
268 pMax.
set( fXmax, fYmax, fZTopCut);
300 G4double rr = x * x + y * y + z * z;
301 G4double distZ = std::abs(z - fZMidCut) - fZDimCut;
303 G4double dist = std::max(distZ, distR);
305 if (dist > halfTolerance) {
return kOutside; }
322 G4double distZ = std::abs(z - fZMidCut) - fZDimCut;
323 if (std::abs(distZ) <= halfTolerance)
325 norm.
setZ(std::copysign(1., z - fZMidCut));
330 G4double distR = fQ1*(x*x + y*y + z*z) - fQ2;
331 if (std::abs(distR) <= halfTolerance)
349 std::ostringstream message;
350 G4long oldprc = message.precision(16);
351 message <<
"Point p is not on surface (!?) of solid: "
353 message <<
"Position:\n";
354 message <<
" p.x() = " << p.
x()/mm <<
" mm\n";
355 message <<
" p.y() = " << p.
y()/mm <<
" mm\n";
356 message <<
" p.z() = " << p.
z()/mm <<
" mm";
358 G4Exception(
"G4Ellipsoid::SurfaceNormal(p)",
"GeomSolids1002",
362 return ApproxSurfaceNormal(p);
375 G4double rr = x * x + y * y + z * z;
376 G4double distZ = std::abs(z - fZMidCut) - fZDimCut;
377 G4double distR = std::sqrt(rr) - fR;
378 if (distR > distZ && rr > 0.)
382 return { 0., 0., std::copysign(1., z - fZMidCut) };
397 G4double safex = std::abs(p.
x()) - fXmax;
398 G4double safey = std::abs(p.
y()) - fYmax;
402 if (safex >= -halfTolerance && p.
x() * v.
x() >= 0.) {
return kInfinity; }
403 if (safey >= -halfTolerance && p.
y() * v.
y() >= 0.) {
return kInfinity; }
404 if (safet >= -halfTolerance && v.
z() >= 0.) {
return kInfinity; }
405 if (safeb >= -halfTolerance && v.
z() <= 0.) {
return kInfinity; }
409 G4double safe = std::max(std::max(std::max(safex, safey), safet), safeb);
410 if (safe > 32. * fRsph)
412 offset = (1. - 1.e-08) * safe - 2. * fRsph;
415 return (dist == kInfinity) ? kInfinity : dist +
offset;
431 G4double distZ = std::abs(pzcut) - dzcut;
432 if (distZ >= -halfTolerance && pzcut * vz >= 0.) {
return kInfinity; }
434 G4double rr = px * px + py * py + pz * pz;
435 G4double pv = px * vx + py * vy + pz * vz;
437 if (distR >= -halfTolerance && pv >= 0.) {
return kInfinity; }
439 G4double A = vx * vx + vy * vy + vz * vz;
445 if (
D <= EPS) {
return kInfinity; }
450 G4double dz = std::copysign(dzcut, invz);
451 G4double tzmin = (pzcut - dz) * invz;
452 G4double tzmax = (pzcut + dz) * invz;
456 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
464 G4double tmin = std::max(tzmin, trmin);
465 G4double tmax = std::min(tzmax, trmax);
467 if (tmax - tmin <= halfTolerance) {
return kInfinity; }
483 G4double distX = std::abs(px) - fXmax;
484 G4double distY = std::abs(py) - fYmax;
485 G4double distZ = std::max(pz - fZTopCut, fZBottomCut - pz);
486 G4double distB = std::max(std::max(distX, distY), distZ);
492 G4double distR = std::sqrt(x*x + y*y + z*z) - fR;
495 G4double dist = std::max(distB, distR);
496 return (dist < 0.) ? 0. : dist;
515 G4double distZ = std::abs(pzcut) - dzcut;
516 if (distZ >= -halfTolerance && pzcut * vz > 0.)
521 n->set(0., 0., std::copysign(1., pzcut));
532 G4double rr = px * px + py * py + pz * pz;
533 G4double pv = px * vx + py * vy + pz * vz;
535 if (distR >= -halfTolerance && pv > 0.)
547 if (std::max(distZ, distR) > halfTolerance)
550 std::ostringstream message;
551 G4long oldprc = message.precision(16);
552 message <<
"Point p is outside (!?) of solid: "
554 message <<
"Position: " << p <<
G4endl;;
555 message <<
"Direction: " << v;
557 G4Exception(
"G4Ellipsoid::DistanceToOut(p,v)",
"GeomSolids1002",
564 *n = ApproxSurfaceNormal(p);
571 G4double A = vx * vx + vy * vy + vz * vz;
595 : (std::copysign(dzcut, vz) - pzcut) / vz;
599 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
604 G4double tmax = std::min(tzmax, trmax);
613 n->set(0., 0., (pznew > fZMidCut) ? 1. : -1.);
617 G4double nx = (px + tmax * vx) * fSx;
618 G4double ny = (py + tmax * vy) * fSy;
619 G4double nz = (pz + tmax * vz) * fSz;
633 G4double distZ = std::min(fZTopCut - p.
z(), p.
z() - fZBottomCut);
639 G4double distR = fR - std::sqrt(x*x + y*y + z*z);
642 G4double dist = std::min(distZ, distR);
643 return (dist < 0.) ? 0. : dist;
652 return {
"G4Ellipsoid"};
670 G4long oldprc = os.precision(16);
671 os <<
"-----------------------------------------------------------\n"
672 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
673 <<
" ===================================================\n"
676 <<
" semi-axis x: " <<
GetDx()/mm <<
" mm \n"
677 <<
" semi-axis y: " <<
GetDy()/mm <<
" mm \n"
678 <<
" semi-axis z: " <<
GetDz()/mm <<
" mm \n"
680 <<
" upper cut in z: " <<
GetZTopCut()/mm <<
" mm \n"
681 <<
"-----------------------------------------------------------\n";
682 os.precision(oldprc);
690G4double G4Ellipsoid::LateralSurfaceArea()
const
692 constexpr G4int NPHI = 1000.;
693 constexpr G4double dPhi = CLHEP::halfpi/NPHI;
702 G4double zmax = std::min(fZTopCut, fDz);
703 G4double zmin = std::max(fZBottomCut,-fDz);
719 ((zmax_c*std::sqrt(kk + tmax*tmax) - zmin_c*std::sqrt(kk + tmin*tmin)) +
720 (std::asinh(tmax*invk) - std::asinh(tmin*invk))*kk/root);
722 else if (kk > 1. + eps)
729 ((zmax_c*std::sqrt(kk - tmax*tmax) - zmin_c*std::sqrt(kk - tmin*tmin)) +
730 (std::asin(tmax*invk) - std::asin(tmin*invk))*kk/root);
734 area = CLHEP::twopi*fDx*(zmax - zmin);
740 for (
G4int i = 0; i < NPHI; ++i)
742 G4double sinPhi = std::sin(dPhi*(i + 0.5));
743 G4double kk = cc_aa + (cc_bb - cc_aa)*sinPhi*sinPhi;
751 ((zmax_c*std::sqrt(kk + tmax*tmax) - zmin_c*std::sqrt(kk + tmin*tmin)) +
752 (std::asinh(tmax*invk) - std::asinh(tmin*invk))*kk/root);
754 else if (kk > 1. + eps)
761 ((zmax_c*std::sqrt(kk - tmax*tmax) - zmin_c*std::sqrt(kk - tmin*tmin)) +
762 (std::asin(tmax*invk) - std::asin(tmin*invk))*kk/root);
766 area += 4.*ab*dPhi*(zmax_c - zmin_c);
778 if (fCubicVolume == 0)
781 G4double piAB_3 = CLHEP::pi * fDx * fDy / 3.;
782 fCubicVolume = 4. * piAB_3 * fDz;
783 if (fZBottomCut > -fDz)
785 G4double hbot = 1. + fZBottomCut / fDz;
786 fCubicVolume -= piAB_3 * hbot * hbot * (2. * fDz - fZBottomCut);
790 G4double htop = 1. - fZTopCut / fDz;
791 fCubicVolume -= piAB_3 * htop * htop * (2. * fDz + fZTopCut);
804 if (fSurfaceArea == 0.)
807 G4double piAB = CLHEP::pi * fDx * fDy;
808 fSurfaceArea = LateralSurfaceArea();
809 if (fZBottomCut > -fDz)
811 G4double hbot = 1. + fZBottomCut / fDz;
812 fSurfaceArea += piAB * hbot * (2. - hbot);
816 G4double htop = 1. - fZTopCut / fDz;
817 fSurfaceArea += piAB * htop * (2. - htop);
841 G4double Sbot = piAB * Hbot * (2. - Hbot);
842 G4double Stop = piAB * Htop * (2. - Htop);
845 if (fLateralArea == 0.)
848 fLateralArea = LateralSurfaceArea();
856 k += (
G4int)(select > Sbot);
857 k += (
G4int)(select > Sbot + Slat);
868 G4double scale = std::sqrt(Hbot * (2. - Hbot));
870 p.
set(
A * rho * cosphi,
B * rho * sinphi, Zbot);
877 for (
G4int i = 0; i < 10000; ++i)
881 G4double rho = std::sqrt((1. + z) * (1. - z));
888 p.
set(
A * x,
B * y,
C * z);
893 G4double scale = std::sqrt(Htop * (2. - Htop));
895 p.
set(
A * rho * cosphi,
B * rho * sinphi, Ztop);
917 return { -fXmax, fXmax, -fYmax, fYmax, fZBottomCut, fZTopCut };
935 if (fpPolyhedron ==
nullptr ||
936 fRebuildPolyhedron ||
937 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
938 fpPolyhedron->GetNumberOfRotationSteps())
943 fRebuildPolyhedron =
false;
G4TemplateAutoLock< G4Mutex > G4AutoLock
const G4double kCarTolerance
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 CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
G4Ellipsoid(const G4String &name, G4double xSemiAxis, G4double ySemiAxis, G4double zSemiAxis, G4double zBottomCut=0., G4double zTopCut=0.)
EInside Inside(const G4ThreeVector &p) const override
G4Polyhedron * CreatePolyhedron() const override
G4double GetSurfaceArea() override
G4VSolid * Clone() const override
G4ThreeVector GetPointOnSurface() const override
G4double GetZTopCut() const
G4double GetZBottomCut() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4double GetCubicVolume() override
G4GeometryType GetEntityType() const override
G4Polyhedron * GetPolyhedron() const override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4VisExtent GetExtent() const override
G4Ellipsoid & operator=(const G4Ellipsoid &rhs)
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
std::ostream & StreamInfo(std::ostream &os) 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...
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
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...