64 using namespace CLHEP;
75 :
G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0),
76 fCubicVolume(0.), fSurfaceArea(0.), zTopCut(0.)
81 halfRadTol = 0.5*kRadTolerance;
86 if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.) || (pzMax <= 0.) )
88 std::ostringstream message;
89 message <<
"Invalid semi-axis or height - " <<
GetName();
90 G4Exception(
"G4EllipticalCone::G4EllipticalCone()",
"GeomSolids0002",
95 std::ostringstream message;
96 message <<
"Invalid z-coordinate for cutting plane - " <<
GetName();
97 G4Exception(
"G4EllipticalCone::G4EllipticalCone()",
"InvalidSetup",
111 :
G4VSolid(a), fRebuildPolyhedron(false), fpPolyhedron(0),
112 kRadTolerance(0.), halfRadTol(0.), halfCarTol(0.), fCubicVolume(0.),
113 fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zheight(0.),
114 semiAxisMax(0.), zTopCut(0.)
133 fRebuildPolyhedron(false), fpPolyhedron(0),
134 kRadTolerance(rhs.kRadTolerance),
135 halfRadTol(rhs.halfRadTol), halfCarTol(rhs.halfCarTol),
136 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
137 xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis), zheight(rhs.zheight),
138 semiAxisMax(rhs.semiAxisMax), zTopCut(rhs.zTopCut)
150 if (
this == &rhs) {
return *
this; }
158 kRadTolerance = rhs.kRadTolerance;
159 halfRadTol = rhs.halfRadTol; halfCarTol = rhs.halfCarTol;
160 fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
161 xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
162 zheight = rhs.zheight; semiAxisMax = rhs.semiAxisMax; zTopCut = rhs.zTopCut;
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::Extent()",
"GeomMgt0001",
215 if (
true)
return bbox.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
219 return exist = (pMin < pMax) ?
true :
false;
224 static const G4int NSTEPS = 48;
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;
274 if ( (p.
z() < -zTopCut - halfCarTol)
275 || (p.
z() > zTopCut + halfCarTol ) )
280 rad2oo=
sqr(p.
x()/( xSemiAxis + halfRadTol ))
281 +
sqr(p.
y()/( ySemiAxis + halfRadTol ));
283 if ( rad2oo >
sqr( zheight-p.
z() ) )
290 rad2oi =
sqr(p.
x()/( xSemiAxis - halfRadTol ))
291 +
sqr(p.
y()/( ySemiAxis - halfRadTol ));
293 if (rad2oi <
sqr( zheight-p.
z() ) )
295 in = ( ( p.
z() < -zTopCut + halfRadTol )
314 ry =
sqr(p.
y()/ySemiAxis);
320 if( (p.
z() < -zTopCut) && ((rx+ry) <
sqr(zTopCut + zheight)) )
325 if( (p.
z() > (zheight > zTopCut ? zheight : zTopCut)) &&
326 ((rx+ry) <
sqr(zheight-zTopCut)) )
331 if( p.
z() > rds + 2.*zTopCut - zheight )
333 if ( p.
z() > zTopCut )
338 return norm /= norm.
mag();
343 return norm /= norm.
mag();
356 - ( zheight - zTopCut ) );
359 return norm /= norm.
mag();
365 if( p.
z() < rds - 2.*zTopCut - zheight )
370 return norm /= norm.
mag();
375 return norm /= norm.
mag();
388 - ( zheight - zTopCut ) );
391 return norm /= norm.
mag();
397 G4double c = -zTopCut - k*(zTopCut + zheight);
399 if( p.
z() < -k*rds + c )
402 return norm /= norm.
mag();
423 if (sigz < halfCarTol)
442 if (
sqr(p.
x()/( xSemiAxis - halfCarTol ))
443 +
sqr(p.
y()/( ySemiAxis - halfCarTol )) <=
sqr( zheight+zTopCut ) )
458 yi = p.
y() + q*v.
y();
463 if (
sqr(xi/xSemiAxis) +
sqr(yi/ySemiAxis) <=
sqr( zheight + zTopCut ) )
468 return (sigz < -halfCarTol) ? q : 0;
470 else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
471 + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
485 sigz = p.
z() - zTopCut;
487 if (sigz > -halfCarTol)
494 if (
sqr(p.
x()/( xSemiAxis - halfCarTol ))
495 +
sqr(p.
y()/( ySemiAxis - halfCarTol )) <=
sqr( zheight-zTopCut ) )
503 yi = p.
y() + q*v.
y();
505 if (
sqr(xi/xSemiAxis) +
sqr(yi/ySemiAxis) <=
sqr( zheight - zTopCut ) )
507 return (sigz > -halfCarTol) ? q : 0;
509 else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
510 + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
529 if (
sqr((lambda*v.
x()+p.
x())/xSemiAxis) +
530 sqr((lambda*v.
y()+p.
y())/ySemiAxis) <=
531 sqr(zTopCut + zheight + 0.5*kRadTolerance) )
533 return distMin = std::fabs(lambda);
544 if (
sqr((lambda*v.
x() + p.
x())/xSemiAxis) +
545 sqr((lambda*v.
y() + p.
y())/ySemiAxis) <=
546 sqr(zheight - zTopCut + 0.5*kRadTolerance) )
548 return distMin = std::fabs(lambda);
552 if (p.
z() > zTopCut - halfCarTol
553 && p.
z() < zTopCut + halfCarTol )
561 if (p.
z() < -zTopCut + halfCarTol
562 && p.
z() > -zTopCut - halfCarTol)
577 v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
579 sqr(zheight - p.
z());
585 if ( discr < -halfCarTol )
590 if ( (discr >= - halfCarTol ) && (discr < halfCarTol ) )
592 return distMin = std::fabs(-B/(2.*A));
595 G4double plus = (-B+std::sqrt(discr))/(2.*A);
596 G4double minus = (-B-std::sqrt(discr))/(2.*A);
600 if ( ( std::fabs(plus) < halfCarTol )||( std::fabs(minus) < halfCarTol ) )
603 p.
y()/(ySemiAxis*ySemiAxis),
604 -( p.
z() - zheight ));
605 if ( truenorm*v >= 0)
618 if ( minus > halfCarTol && minus < distMin )
626 pin.
y()/(ySemiAxis*ySemiAxis),
627 - ( pin.
z() - zheight ));
634 if ( plus > halfCarTol && plus < distMin )
642 pin.
y()/(ySemiAxis*ySemiAxis),
643 - ( pin.
z() - zheight ) );
650 if (distMin < halfCarTol) distMin=0.;
661 G4double distR, distR2, distZ, maxDim;
667 if( (p.
z() <= -zTopCut) && (
sqr(p.
x()/xSemiAxis) +
sqr(p.
y()/ySemiAxis)
671 return distZ = std::fabs(zTopCut + p.
z());
674 if( (p.
z() >= zTopCut) && (
sqr(p.
x()/xSemiAxis)+
sqr(p.
y()/ySemiAxis)
677 return distZ = std::fabs(p.
z() - zTopCut);
684 maxDim = xSemiAxis >= ySemiAxis ? xSemiAxis:ySemiAxis;
685 distRad = std::sqrt(p.
x()*p.
x()+p.
y()*p.
y());
687 if( p.
z() > maxDim*distRad + zTopCut*(1.+maxDim)-
sqr(maxDim)*zheight )
689 distR2 =
sqr(p.
z() - zTopCut) +
sqr(distRad - maxDim*(zheight - zTopCut));
690 return std::sqrt( distR2 );
693 if( distRad > maxDim*( zheight - p.
z() ) )
695 if( p.
z() > maxDim*distRad - (zTopCut*(1.+maxDim)+
sqr(maxDim)*zheight) )
697 G4double zVal = (p.
z()-maxDim*(distRad-maxDim*zheight))/(1.+
sqr(maxDim));
698 G4double rVal = maxDim*(zheight - zVal);
699 return distR = std::sqrt(
sqr(p.
z() - zVal) +
sqr(distRad - rVal));
703 if( distRad <= maxDim*(zheight - p.
z()) )
705 distR2 =
sqr(distRad - maxDim*(zheight + zTopCut)) +
sqr(p.
z() + zTopCut);
706 return std::sqrt( distR2 );
724 enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
731 lambda = (-p.
z() - zTopCut)/v.
z();
733 if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis) +
734 sqr((p.
y() + lambda*v.
y())/ySemiAxis)) <
737 distMin = std::fabs(lambda);
739 if (!calcNorm) {
return distMin; }
741 distMin = std::fabs(lambda);
742 surface = kPlaneSurf;
747 lambda = (zTopCut - p.
z()) / v.
z();
749 if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis)
750 +
sqr((p.
y() + lambda*v.
y())/ySemiAxis) )
753 distMin = std::fabs(lambda);
754 if (!calcNorm) {
return distMin; }
756 distMin = std::fabs(lambda);
757 surface = kPlaneSurf;
765 v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
767 -
sqr(zheight - p.
z());
773 if(!calcNorm) {
return distMin = std::fabs(-B/(2.*A)); }
778 G4double plus = (-B+std::sqrt(discr))/(2.*A);
779 G4double minus = (-B-std::sqrt(discr))/(2.*A);
785 lambda = std::fabs(plus) < std::fabs(minus) ? plus : minus;
795 if ( std::fabs(lambda) < distMin )
799 distMin = std::fabs(lambda);
800 surface = kCurvedSurf;
805 p.
y()/(ySemiAxis*ySemiAxis),
806 -( p.
z() - zheight ));
807 if( truenorm.
dot(v) > 0 )
810 surface = kCurvedSurf;
820 if (surface == kNoSurf)
839 pexit.
y()/(ySemiAxis*ySemiAxis),
840 -( pexit.
z() - zheight ) );
841 truenorm /= truenorm.
mag();
848 std::ostringstream message;
849 G4int oldprc = message.precision(16);
850 message <<
"Undefined side for valid surface normal to solid."
853 <<
" p.x() = " << p.
x()/
mm <<
" mm" <<
G4endl
854 <<
" p.y() = " << p.
y()/
mm <<
" mm" <<
G4endl
855 <<
" p.z() = " << p.
z()/
mm <<
" mm" <<
G4endl
857 <<
" v.x() = " << v.
x() <<
G4endl
858 <<
" v.y() = " << v.
y() <<
G4endl
859 <<
" v.z() = " << v.
z() <<
G4endl
860 <<
"Proposed distance :" <<
G4endl
861 <<
" distMin = " << distMin/
mm <<
" mm";
862 message.precision(oldprc);
863 G4Exception(
"G4EllipticalCone::DistanceToOut(p,v,..)",
885 std::ostringstream message;
886 G4int oldprc = message.precision(16);
887 message <<
"Point p is outside !?" <<
G4endl
889 <<
" p.x() = " << p.
x()/
mm <<
" mm" <<
G4endl
890 <<
" p.y() = " << p.
y()/
mm <<
" mm" <<
G4endl
891 <<
" p.z() = " << p.
z()/
mm <<
" mm";
892 message.precision(oldprc) ;
893 G4Exception(
"G4Ellipsoid::DistanceToOut(p)",
"GeomSolids1002",
902 if (xSemiAxis < ySemiAxis)
905 py *= xSemiAxis/ySemiAxis;
910 px *= ySemiAxis/xSemiAxis;
913 G4double distZ = zTopCut - std::abs(pz) ;
914 if (distZ <= 0)
return 0;
917 G4double pr = std::sqrt(px*px+py*py);
918 if (pr >= rho)
return 0;
920 G4double distR = (rho-pr)/std::sqrt(1+axis*axis);
930 return G4String(
"G4EllipticalCone");
948 G4int oldprc = os.precision(16);
949 os <<
"-----------------------------------------------------------\n"
950 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
951 <<
" ===================================================\n"
952 <<
" Solid type: G4EllipticalCone\n"
955 <<
" semi-axis x: " << xSemiAxis/
mm <<
" mm \n"
956 <<
" semi-axis y: " << ySemiAxis/
mm <<
" mm \n"
957 <<
" height z: " << zheight/
mm <<
" mm \n"
958 <<
" half length in z: " << zTopCut/
mm <<
" mm \n"
959 <<
"-----------------------------------------------------------\n";
960 os.precision(oldprc);
974 G4double phi, sinphi, cosphi, aOne, aTwo, aThree,
975 chose, zRand, rRand1, rRand2;
978 +
sqr(ySemiAxis))*(zheight - zTopCut);
980 +
sqr(ySemiAxis))*(zheight + zTopCut);
984 aOne =
pi*(rOne + rTwo)*std::sqrt(
sqr(rOne - rTwo)+
sqr(2.*zTopCut));
985 aTwo =
pi*xSemiAxis*ySemiAxis*
sqr(zheight+zTopCut);
986 aThree =
pi*xSemiAxis*ySemiAxis*
sqr(zheight-zTopCut);
989 cosphi = std::cos(phi);
990 sinphi = std::sin(phi);
992 if(zTopCut >= zheight) aThree = 0.;
995 if((chose>=0.) && (chose<aOne))
999 ySemiAxis*(zheight-zRand)*sinphi,zRand);
1001 else if((chose>=aOne) && (chose<aOne+aTwo))
1007 }
while (( rRand2 >= rRand1 ) && (++it1 < 1000)) ;
1009 return G4ThreeVector(rRand1*xSemiAxis*(zheight+zTopCut)*cosphi,
1010 rRand1*ySemiAxis*(zheight+zTopCut)*sinphi, -zTopCut);
1020 }
while (( rRand2 >= rRand1 ) && (++it2 < 1000));
1022 return G4ThreeVector(rRand1*xSemiAxis*(zheight-zTopCut)*cosphi,
1023 rRand1*ySemiAxis*(zheight-zTopCut)*sinphi, zTopCut);
void set(double x, double y, double z)
ThreeVector shoot(const G4int Ap, const G4int Af)
static constexpr double mm
G4EllipticalCone & operator=(const G4EllipticalCone &rhs)
static const G4double kInfinity
G4double GetSemiAxisX() const
CLHEP::Hep3Vector G4ThreeVector
double dot(const Hep3Vector &) const
EInside Inside(const G4ThreeVector &p) const
double B(double temperature)
virtual void AddSolid(const G4Box &)=0
G4Polyhedron * CreatePolyhedron() const
#define G4MUTEX_INITIALIZER
static constexpr double twopi
std::ostream & StreamInfo(std::ostream &os) const
G4bool fRebuildPolyhedron
G4ThreeVector GetPointOnSurface() const
double A(double temperature)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4Polyhedron * fpPolyhedron
G4double GetRadialTolerance() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4EllipticalCone(const G4String &pName, G4double pxSemiAxis, G4double pySemiAxis, G4double zMax, G4double pzTopCut)
void Extent(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4double GetSemiAxisY() const
void SetSemiAxis(G4double x, G4double y, G4double z)
static G4int GetNumberOfRotationSteps()
void SetZCut(G4double newzTopCut)
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4double GetZTopCut() const
G4VSolid & operator=(const G4VSolid &rhs)
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
static constexpr double pi
G4Polyhedron * GetPolyhedron() const
G4GeometryType GetEntityType() const
G4VisExtent GetExtent() const
virtual ~G4EllipticalCone()
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
static G4GeometryTolerance * GetInstance()