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)
339 if (nsurf == 1)
return norm;
340 else if (nsurf > 1)
return norm.
unit();
344 std::ostringstream message;
345 G4int oldprc = message.precision(16);
346 message <<
"Point p is not on surface (!?) of solid: "
348 message <<
"Position:\n";
349 message <<
" p.x() = " << p.
x()/mm <<
" mm\n";
350 message <<
" p.y() = " << p.
y()/mm <<
" mm\n";
351 message <<
" p.z() = " << p.
z()/mm <<
" mm";
353 G4Exception(
"G4Ellipsoid::SurfaceNormal(p)",
"GeomSolids1002",
357 return ApproxSurfaceNormal(p);
371 G4double rr = x * x + y * y + z * z;
372 G4double distZ = std::abs(z - fZMidCut) - fZDimCut;
373 G4double distR = std::sqrt(rr) - fR;
374 if (distR > distZ && rr > 0.)
377 return G4ThreeVector(0., 0., std::copysign(1., z - fZMidCut));
392 G4double safex = std::abs(p.
x()) - fXmax;
393 G4double safey = std::abs(p.
y()) - fYmax;
397 if (safex >= -halfTolerance && p.
x() * v.
x() >= 0.)
return kInfinity;
398 if (safey >= -halfTolerance && p.
y() * v.
y() >= 0.)
return kInfinity;
399 if (safet >= -halfTolerance && v.
z() >= 0.)
return kInfinity;
400 if (safeb >= -halfTolerance && v.
z() <= 0.)
return kInfinity;
404 G4double safe = std::max(std::max(std::max(safex, safey), safet), safeb);
405 if (safe > 32. * fRsph)
407 offset = (1. - 1.e-08) * safe - 2. * fRsph;
410 return (dist == kInfinity) ? kInfinity : dist + offset;
426 G4double distZ = std::abs(pzcut) - dzcut;
427 if (distZ >= -halfTolerance && pzcut * vz >= 0.)
return kInfinity;
429 G4double rr = px * px + py * py + pz * pz;
430 G4double pv = px * vx + py * vy + pz * vz;
432 if (distR >= -halfTolerance && pv >= 0.)
return kInfinity;
434 G4double A = vx * vx + vy * vy + vz * vz;
440 if (
D <=
EPS)
return kInfinity;
445 G4double dz = std::copysign(dzcut, invz);
446 G4double tzmin = (pzcut - dz) * invz;
447 G4double tzmax = (pzcut + dz) * invz;
451 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
459 G4double tmin = std::max(tzmin, trmin);
460 G4double tmax = std::min(tzmax, trmax);
462 if (tmax - tmin <= halfTolerance)
return kInfinity;
463 return (tmin < halfTolerance) ? offset : tmin + offset;
477 G4double distX = std::abs(px) - fXmax;
478 G4double distY = std::abs(py) - fYmax;
479 G4double distZ = std::max(pz - fZTopCut, fZBottomCut - pz);
480 G4double distB = std::max(std::max(distX, distY), distZ);
486 G4double distR = std::sqrt(x*x + y*y + z*z) - fR;
489 G4double dist = std::max(distB, distR);
490 return (dist < 0.) ? 0. : dist;
509 G4double distZ = std::abs(pzcut) - dzcut;
510 if (distZ >= -halfTolerance && pzcut * vz > 0.)
515 n->set(0., 0., std::copysign(1., pzcut));
526 G4double rr = px * px + py * py + pz * pz;
527 G4double pv = px * vx + py * vy + pz * vz;
529 if (distR >= -halfTolerance && pv > 0.)
541 if (std::max(distZ, distR) > halfTolerance)
544 std::ostringstream message;
545 G4int oldprc = message.precision(16);
546 message <<
"Point p is outside (!?) of solid: "
548 message <<
"Position: " << p <<
G4endl;;
549 message <<
"Direction: " << v;
551 G4Exception(
"G4Ellipsoid::DistanceToOut(p,v)",
"GeomSolids1002",
558 *n = ApproxSurfaceNormal(p);
565 G4double A = vx * vx + vy * vy + vz * vz;
587 G4double tzmax = (vz == 0.) ?
DBL_MAX : (std::copysign(dzcut, vz) - pzcut) / vz;
591 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
596 G4double tmax = std::min(tzmax, trmax);
605 n->set(0., 0., (pznew > fZMidCut) ? 1. : -1.);
609 G4double nx = (px + tmax * vx) * fSx;
610 G4double ny = (py + tmax * vy) * fSy;
611 G4double nz = (pz + tmax * vz) * fSz;
625 G4double distZ = std::min(fZTopCut - p.
z(), p.
z() - fZBottomCut);
631 G4double distR = fR - std::sqrt(x*x + y*y + z*z);
634 G4double dist = std::min(distZ, distR);
635 return (dist < 0.) ? 0. : dist;
662 G4int oldprc = os.precision(16);
663 os <<
"-----------------------------------------------------------\n"
664 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
665 <<
" ===================================================\n"
668 <<
" semi-axis x: " <<
GetDx()/mm <<
" mm \n"
669 <<
" semi-axis y: " <<
GetDy()/mm <<
" mm \n"
670 <<
" semi-axis z: " <<
GetDz()/mm <<
" mm \n"
672 <<
" upper cut in z: " <<
GetZTopCut()/mm <<
" mm \n"
673 <<
"-----------------------------------------------------------\n";
674 os.precision(oldprc);
684 if (fCubicVolume == 0.)
686 G4double piAB_3 = CLHEP::pi * fDx * fDy / 3.;
687 fCubicVolume = 4. * piAB_3 * fDz;
688 if (fZBottomCut > -fDz)
690 G4double hbot = 1. + fZBottomCut / fDz;
691 fCubicVolume -= piAB_3 * hbot * hbot * (2. * fDz - fZBottomCut);
695 G4double htop = 1. - fZTopCut / fDz;
696 fCubicVolume -= piAB_3 * htop * htop * (2. * fDz + fZTopCut);
706G4double G4Ellipsoid::LateralSurfaceArea()
const
708 const G4int Nphi = 100;
709 const G4int Nz = 200;
716 for (
G4int iz = 0; iz < Nz; ++iz)
719 rho[iz] = std::sqrt((1. + z) * (1. - z));
721 rho[Nz] = std::sqrt((1. + ztop) * (1. - ztop));
726 dz = (ztop - zbot) / Nz;
728 G4double dphi = CLHEP::halfpi / Nphi;
729 for (
G4int iphi = 0; iphi < Nphi; ++iphi)
732 G4double phi2 = (iphi == Nphi - 1) ? CLHEP::halfpi : phi1 + dphi;
733 G4double cos1 = std::cos(phi1) * fDx;
734 G4double cos2 = std::cos(phi2) * fDx;
735 G4double sin1 = std::sin(phi1) * fDy;
736 G4double sin2 = std::sin(phi2) * fDy;
737 for (
G4int iz = 0; iz < Nz; ++iz)
740 G4double z2 = (iz == Nz - 1) ? ztop : z1 + dz;
747 area += ((p4 - p1).cross(p3 - p2)).mag();
759 if (fSurfaceArea == 0.)
761 G4double piAB = CLHEP::pi * fDx * fDy;
762 fSurfaceArea = LateralSurfaceArea();
763 if (fZBottomCut > -fDz)
765 G4double hbot = 1. + fZBottomCut / fDz;
766 fSurfaceArea += piAB * hbot * (2. - hbot);
770 G4double htop = 1. - fZTopCut / fDz;
771 fSurfaceArea += piAB * htop * (2. - htop);
793 G4double Sbot = piAB * Hbot * (2. - Hbot);
794 G4double Stop = piAB * Htop * (2. - Htop);
797 if (fLateralArea == 0.)
800 fLateralArea = LateralSurfaceArea();
808 if (select > Sbot) k = 1;
809 if (select > Sbot + Slat) k = 2;
817 G4double scale = std::sqrt(Hbot * (2. - Hbot));
819 p.
set(rho.
x(), rho.
y(), Zbot);
826 for (
G4int i = 0; i < 1000; ++i)
830 G4double rho = std::sqrt((1. + z) * (1. - z));
832 x = rho * std::cos(phi);
833 y = rho * std::sin(phi);
838 G4double mu = std::sqrt(xbc * xbc + yac * yac + zab * zab);
841 p.
set(
A * x,
B * y,
C * z);
846 G4double scale = std::sqrt(Htop * (2. - Htop));
848 p.
set(rho.
x(), rho.
y(), Ztop);
870 return G4VisExtent(-fXmax, fXmax, -fYmax, fYmax, fZBottomCut, fZTopCut);
888 if (fpPolyhedron ==
nullptr ||
889 fRebuildPolyhedron ||
896 fRebuildPolyhedron =
false;
double B(double temperature)
double A(double temperature)
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 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
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4Ellipsoid(const G4String &name, G4double xSemiAxis, G4double ySemiAxis, G4double zSemiAxis, G4double zBottomCut=0., G4double zTopCut=0.)
std::ostream & StreamInfo(std::ostream &os) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4Polyhedron * GetPolyhedron() const
G4Polyhedron * CreatePolyhedron() const
G4double GetZTopCut() const
G4double GetZBottomCut() const
EInside Inside(const G4ThreeVector &p) const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4double GetSurfaceArea()
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4Ellipsoid & operator=(const G4Ellipsoid &rhs)
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4double GetCubicVolume()
G4ThreeVector GetPointOnSurface() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4VisExtent GetExtent() const
G4GeometryType GetEntityType() const
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
virtual void AddSolid(const G4Box &)=0
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4VSolid & operator=(const G4VSolid &rhs)
static G4int GetNumberOfRotationSteps()