38#if !(defined(G4GEOM_USE_UELLIPTICALCONE) && defined(G4GEOM_USE_SYS_USOLIDS))
83 if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.) || (pzMax <= 0.) )
85 std::ostringstream message;
86 message <<
"Invalid semi-axis or height for solid: " <<
GetName()
87 <<
"\n X semi-axis, Y semi-axis, height = "
88 << pxSemiAxis <<
", " << pySemiAxis <<
", " << pzMax;
89 G4Exception(
"G4EllipticalCone::G4EllipticalCone()",
"GeomSolids0002",
95 std::ostringstream message;
96 message <<
"Invalid z-coordinate for cutting plane for solid: " <<
GetName()
97 <<
"\n Z top cut = " << pzTopCut;
98 G4Exception(
"G4EllipticalCone::G4EllipticalCone()",
"GeomSolids0002",
113 xSemiAxis(0.), ySemiAxis(0.), zheight(0.), zTopCut(0.),
114 cosAxisMin(0.), invXX(0.), invYY(0.)
132 :
G4VSolid(rhs), halfCarTol(rhs.halfCarTol),
133 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
134 xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
135 zheight(rhs.zheight), zTopCut(rhs.zTopCut),
136 cosAxisMin(rhs.cosAxisMin), invXX(rhs.invXX), invYY(rhs.invYY)
148 if (
this == &rhs) {
return *
this; }
156 halfCarTol = rhs.halfCarTol;
157 fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
158 xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
159 zheight = rhs.zheight; zTopCut = rhs.zTopCut;
160 cosAxisMin = rhs.cosAxisMin; invXX = rhs.invXX; invYY = rhs.invYY;
179 pMin.
set(-xmax,-ymax,-zcut);
180 pMax.
set( xmax, ymax, zcut);
184 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
186 std::ostringstream message;
187 message <<
"Bad bounding box (min >= max) for solid: "
189 <<
"\npMin = " << pMin
190 <<
"\npMax = " << pMax;
191 G4Exception(
"G4EllipticalCone::BoundingLimits()",
"GeomMgt0001",
219 return exist = pMin < pMax;
224 static const G4int NSTEPS = 48;
225 static const G4double ang = twopi/NSTEPS;
226 static const G4double sinHalf = std::sin(0.5*ang);
227 static const G4double cosHalf = std::cos(0.5*ang);
228 static const G4double sinStep = 2.*sinHalf*cosHalf;
229 static const G4double cosStep = 1. - 2.*sinHalf*sinHalf;
240 for (
G4int k=0; k<NSTEPS; ++k)
242 baseA[k].set(sxmax*cosCur,symax*sinCur,-zcut);
243 baseB[k].set(sxmin*cosCur,symin*sinCur, zcut);
246 sinCur = sinCur*cosStep + cosCur*sinStep;
247 cosCur = cosCur*cosStep - sinTmp*sinStep;
250 std::vector<const G4ThreeVectorList *> polygons(2);
251 polygons[0] = &baseA;
252 polygons[1] = &baseB;
264 G4double hp = std::sqrt(p.
x()*p.
x()*invXX + p.
y()*p.
y()*invYY) + p.
z();
265 G4double ds = (hp - zheight)*cosAxisMin;
269 if (dist > halfCarTol)
return kOutside;
282 G4double hp = std::sqrt(p.
x()*p.
x()*invXX + p.
y()*p.
y()*invYY) + p.
z();
283 G4double ds = (hp - zheight)*cosAxisMin;
284 if (std::abs(ds) <= halfCarTol)
288 if (mag == 0)
return {0,0,1};
293 if (std::abs(dz) <= halfCarTol)
299 if (nsurf == 1)
return norm;
300 else if (nsurf > 1)
return norm.
unit();
306 std::ostringstream message;
307 G4long oldprc = message.precision(16);
308 message <<
"Point p is not on surface (!?) of solid: "
310 message <<
"Position:\n";
311 message <<
" p.x() = " << p.
x()/mm <<
" mm\n";
312 message <<
" p.y() = " << p.
y()/mm <<
" mm\n";
313 message <<
" p.z() = " << p.
z()/mm <<
" mm";
315 G4Exception(
"G4EllipticalCone::SurfaceNormal(p)",
"GeomSolids1002",
319 return ApproxSurfaceNormal(p);
330G4EllipticalCone::ApproxSurfaceNormal(
const G4ThreeVector& p)
const
332 G4double hp = std::sqrt(p.
x()*p.
x()*invXX + p.
y()*p.
y()*invYY) + p.
z();
333 G4double ds = (hp - zheight)*cosAxisMin;
335 if (ds > dz && std::abs(hp - p.
z()) > halfCarTol)
338 return { 0., 0., (
G4double)((p.
z() < 0) ? -1. : 1.) };
359 if (sigz < halfCarTol)
371 if (sigz < 0)
return kInfinity;
378 if (
sqr(p.
x()/( xSemiAxis - halfCarTol ))
379 +
sqr(p.
y()/( ySemiAxis - halfCarTol )) <=
sqr( zheight + zTopCut ) )
394 yi = p.
y() + q*v.
y();
399 if (
sqr(xi/xSemiAxis) +
sqr(yi/ySemiAxis) <=
sqr( zheight + zTopCut ) )
404 return (sigz < -halfCarTol) ? q : 0;
406 else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
407 + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
421 sigz = p.
z() - zTopCut;
423 if (sigz > -halfCarTol)
428 if (sigz > 0)
return kInfinity;
430 if (
sqr(p.
x()/( xSemiAxis - halfCarTol ))
431 +
sqr(p.
y()/( ySemiAxis - halfCarTol )) <=
sqr( zheight-zTopCut ) )
439 yi = p.
y() + q*v.
y();
441 if (
sqr(xi/xSemiAxis) +
sqr(yi/ySemiAxis) <=
sqr( zheight - zTopCut ) )
443 return (sigz > -halfCarTol) ? q : 0;
445 else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
446 + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
458 if (p.
z() < -zTopCut - halfCarTol)
465 if (
sqr((lambda*v.
x()+p.
x())/xSemiAxis) +
466 sqr((lambda*v.
y()+p.
y())/ySemiAxis) <=
467 sqr(zTopCut + zheight + halfCarTol) )
469 return distMin = std::fabs(lambda);
473 if (p.
z() > zTopCut + halfCarTol)
480 if (
sqr((lambda*v.
x() + p.
x())/xSemiAxis) +
481 sqr((lambda*v.
y() + p.
y())/ySemiAxis) <=
482 sqr(zheight - zTopCut + halfCarTol) )
484 return distMin = std::fabs(lambda);
488 if (p.
z() > zTopCut - halfCarTol
489 && p.
z() < zTopCut + halfCarTol )
492 {
return kInfinity; }
497 if (p.
z() < -zTopCut + halfCarTol
498 && p.
z() > -zTopCut - halfCarTol)
501 {
return distMin = kInfinity; }
513 v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
515 sqr(zheight - p.
z());
521 if ( discr < -halfCarTol )
526 if ( (discr >= -halfCarTol ) && (discr < halfCarTol ) )
528 return distMin = std::fabs(-
B/(2.*
A));
532 G4double minus = (-
B-std::sqrt(discr))/(2.*
A);
536 if ( ( std::fabs(plus) < halfCarTol )||( std::fabs(minus) < halfCarTol ) )
539 p.
y()/(ySemiAxis*ySemiAxis),
540 -( p.
z() - zheight ));
541 if ( truenorm*v >= 0)
554 if ( minus > halfCarTol && minus < distMin )
559 if(std::fabs(pin.
z())< zTopCut + halfCarTol)
562 pin.
y()/(ySemiAxis*ySemiAxis),
563 - ( pin.
z() - zheight ));
570 if ( plus > halfCarTol && plus < distMin )
575 if(std::fabs(pin.
z()) < zTopCut + halfCarTol)
578 pin.
y()/(ySemiAxis*ySemiAxis),
579 - ( pin.
z() - zheight ) );
586 if (distMin < halfCarTol) distMin=0.;
597 G4double hp = std::sqrt(p.
x()*p.
x()*invXX + p.
y()*p.
y()*invYY) + p.
z();
598 G4double ds = (hp - zheight)*cosAxisMin;
601 return (dist > 0) ? dist : 0.;
616 enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
623 lambda = (-p.
z() - zTopCut)/v.
z();
625 if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis) +
626 sqr((p.
y() + lambda*v.
y())/ySemiAxis)) <
627 sqr(zheight + zTopCut + halfCarTol) )
629 distMin = std::fabs(lambda);
631 if (!calcNorm) {
return distMin; }
633 distMin = std::fabs(lambda);
634 surface = kPlaneSurf;
639 lambda = (zTopCut - p.
z()) / v.
z();
641 if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis)
642 +
sqr((p.
y() + lambda*v.
y())/ySemiAxis) )
643 < (
sqr(zheight - zTopCut + halfCarTol)) )
645 distMin = std::fabs(lambda);
646 if (!calcNorm) {
return distMin; }
648 distMin = std::fabs(lambda);
649 surface = kPlaneSurf;
657 v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
659 -
sqr(zheight - p.
z());
663 if ( discr >= - halfCarTol && discr < halfCarTol )
665 if(!calcNorm) {
return distMin = std::fabs(-
B/(2.*
A)); }
668 else if ( discr > halfCarTol )
671 G4double minus = (-
B-std::sqrt(discr))/(2.*
A);
673 if ( plus > halfCarTol && minus > halfCarTol )
677 lambda = std::fabs(plus) < std::fabs(minus) ? plus : minus;
684 lambda = plus > -halfCarTol ? plus : 0;
687 if ( std::fabs(lambda) < distMin )
689 if( std::fabs(lambda) > halfCarTol)
691 distMin = std::fabs(lambda);
692 surface = kCurvedSurf;
697 p.
y()/(ySemiAxis*ySemiAxis),
698 -( p.
z() - zheight ));
699 if( truenorm.
dot(v) > 0 )
702 surface = kCurvedSurf;
712 if (surface == kNoSurf)
731 pexit.
y()/(ySemiAxis*ySemiAxis),
732 -( pexit.
z() - zheight ) );
733 truenorm /= truenorm.
mag();
740 std::ostringstream message;
741 G4long oldprc = message.precision(16);
742 message <<
"Undefined side for valid surface normal to solid."
745 <<
" p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
746 <<
" p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
747 <<
" p.z() = " << p.
z()/mm <<
" mm" <<
G4endl
749 <<
" v.x() = " << v.
x() <<
G4endl
750 <<
" v.y() = " << v.
y() <<
G4endl
751 <<
" v.z() = " << v.
z() <<
G4endl
752 <<
"Proposed distance :" <<
G4endl
753 <<
" distMin = " << distMin/mm <<
" mm";
754 message.precision(oldprc);
755 G4Exception(
"G4EllipticalCone::DistanceToOut(p,v,..)",
762 if (distMin < halfCarTol) { distMin=0; }
776 std::ostringstream message;
777 G4long oldprc = message.precision(16);
778 message <<
"Point p is outside (!?) of solid: " <<
GetName() <<
"\n"
780 <<
" p.x() = " << p.
x()/mm <<
" mm\n"
781 <<
" p.y() = " << p.
y()/mm <<
" mm\n"
782 <<
" p.z() = " << p.
z()/mm <<
" mm";
783 message.precision(oldprc) ;
784 G4Exception(
"G4Ellipsoid::DistanceToOut(p)",
"GeomSolids1002",
789 G4double hp = std::sqrt(p.
x()*p.
x()*invXX + p.
y()*p.
y()*invYY) + p.
z();
790 G4double ds = (zheight - hp)*cosAxisMin;
793 return (dist > 0) ? dist : 0.;
802 return {
"G4EllipticalCone"};
820 G4long oldprc = os.precision(16);
821 os <<
"-----------------------------------------------------------\n"
822 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
823 <<
" ===================================================\n"
824 <<
" Solid type: G4EllipticalCone\n"
827 <<
" semi-axis x: " << xSemiAxis/mm <<
" mm \n"
828 <<
" semi-axis y: " << ySemiAxis/mm <<
" mm \n"
829 <<
" height z: " << zheight/mm <<
" mm \n"
830 <<
" half length in z: " << zTopCut/mm <<
" mm \n"
831 <<
"-----------------------------------------------------------\n";
832 os.precision(oldprc);
846 G4double kmin = (zTopCut >= zheight ) ? 0. : (zheight - zTopCut)/zheight;
847 G4double kmax = (zTopCut >= zheight ) ? 2. : (zheight + zTopCut)/zheight;
851 G4double szmin = pi*x0*y0*kmax*kmax;
852 G4double szmax = pi*x0*y0*kmin*kmin;
853 G4double sside = s0*(kmax*kmax - kmin*kmin);
854 G4double ssurf[3] = { szmin, sside, szmax };
855 for (
auto i=1; i<3; ++i) { ssurf[i] += ssurf[i-1]; }
861 if (select <= ssurf[1]) k = 1;
862 if (select <= ssurf[0]) k = 0;
873 p.
set(rho.
x(),rho.
y(),-zTopCut);
886 G4double mu_max = R*std::sqrt(hh + R*R);
889 for (
auto i=0; i<1000; ++i)
902 p.
set(zh*xSemiAxis*x,zh*ySemiAxis*y,zheight-zh);
909 p.
set(rho.
x(),rho.
y(),zTopCut);
922 if (fCubicVolume == 0.0)
926 G4double v0 = CLHEP::pi*x0*y0*zheight/3.;
927 G4double kmin = (zTopCut >= zheight ) ? 0. : (zheight - zTopCut)/zheight;
928 G4double kmax = (zTopCut >= zheight ) ? 2. : (zheight + zTopCut)/zheight;
929 fCubicVolume = (kmax - kmin)*(kmax*kmax + kmax*kmin + kmin*kmin)*v0;
940 if (fSurfaceArea == 0.0)
945 G4double kmin = (zTopCut >= zheight ) ? 0. : (zheight - zTopCut)/zheight;
946 G4double kmax = (zTopCut >= zheight ) ? 2. : (zheight + zTopCut)/zheight;
947 fSurfaceArea = (kmax - kmin)*(kmax + kmin)*s0
948 + CLHEP::pi*x0*y0*(kmin*kmin + kmax*kmax);
968 return { pmin.
x(), pmax.
x(), pmin.
y(), pmax.
y(), pmin.
z(), pmax.
z() };
std::vector< G4ThreeVector > G4ThreeVectorList
G4double C(G4double temp)
G4double B(G4double 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
double dot(const Hep3Vector &) const
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
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
void SetSemiAxis(G4double x, G4double y, G4double z)
G4double GetSurfaceArea() override
G4VSolid * Clone() const override
EInside Inside(const G4ThreeVector &p) const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4VisExtent GetExtent() const override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4EllipticalCone(const G4String &pName, G4double pxSemiAxis, G4double pySemiAxis, G4double zMax, G4double pzTopCut)
G4double GetCubicVolume() override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
void SetZCut(G4double newzTopCut)
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4GeometryType GetEntityType() const override
G4double GetSemiAxisX() const
G4bool fRebuildPolyhedron
G4Polyhedron * GetPolyhedron() const override
G4Polyhedron * fpPolyhedron
G4ThreeVector GetPointOnSurface() const override
G4double GetSemiAxisY() const
~G4EllipticalCone() override
std::ostream & StreamInfo(std::ostream &os) const override
G4Polyhedron * CreatePolyhedron() const override
G4double GetZTopCut() const
G4EllipticalCone & operator=(const G4EllipticalCone &rhs)
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
virtual void AddSolid(const G4Box &)=0
G4VSolid & operator=(const G4VSolid &rhs)
static G4int GetNumberOfRotationSteps()