60 using namespace CLHEP;
71 :
G4VSolid(pName), fpPolyhedron(0), fCubicVolume(0.), fSurfaceArea(0.),
77 halfRadTol = 0.5*kRadTolerance;
82 if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.) || (pzMax <= 0.) )
84 std::ostringstream message;
85 message <<
"Invalid semi-axis or height - " <<
GetName();
86 G4Exception(
"G4EllipticalCone::G4EllipticalCone()",
"GeomSolids0002",
91 std::ostringstream message;
92 message <<
"Invalid z-coordinate for cutting plane - " <<
GetName();
93 G4Exception(
"G4EllipticalCone::G4EllipticalCone()",
"InvalidSetup",
107 :
G4VSolid(a), fpPolyhedron(0), kRadTolerance(0.),
108 halfRadTol(0.), halfCarTol(0.), fCubicVolume(0.),
109 fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zheight(0.),
110 semiAxisMax(0.), zTopCut(0.)
128 fpPolyhedron(0), kRadTolerance(rhs.kRadTolerance),
129 halfRadTol(rhs.halfRadTol), halfCarTol(rhs.halfCarTol),
130 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
131 xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis), zheight(rhs.zheight),
132 semiAxisMax(rhs.semiAxisMax), zTopCut(rhs.zTopCut)
144 if (
this == &rhs) {
return *
this; }
153 halfRadTol = rhs.halfRadTol; halfCarTol = rhs.halfCarTol;
154 fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
155 xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
156 zheight = rhs.zheight; semiAxisMax = rhs.semiAxisMax; zTopCut = rhs.zTopCut;
190 G4double rFudge = 1.0/std::cos(0.5*sigPhi);
191 G4double dxFudgeBot = xSemiAxis*2.*zheight*rFudge,
192 dyFudgeBot = ySemiAxis*2.*zheight*rFudge;
193 G4double dxFudgeTop = xSemiAxis*(zheight-zTopCut)*rFudge,
194 dyFudgeTop = ySemiAxis*(zheight-zTopCut)*rFudge;
204 cosPhi = std::cos(phi),
205 sinPhi = std::sin(phi);
206 G4ThreeVector v0( dxFudgeTop*cosPhi, dyFudgeTop*sinPhi, +zTopCut ),
207 v1( dxFudgeBot*cosPhi, dyFudgeBot*sinPhi, -zTopCut ),
214 if (numPhi == 1) phi = 0;
215 cosPhi = std::cos(phi),
216 sinPhi = std::sin(phi);
218 w0 =
G4ThreeVector( dxFudgeTop*cosPhi, dyFudgeTop*sinPhi, +zTopCut );
219 w1 =
G4ThreeVector( dxFudgeBot*cosPhi, dyFudgeBot*sinPhi, -zTopCut );
244 phiPoly.
SetNormal( (v1-v0).cross(w0-v0).unit() );
254 }
while( --numPhi > 0 );
295 if ( (p.
z() < -zTopCut - halfCarTol)
296 || (p.
z() > zTopCut + halfCarTol ) )
301 rad2oo=
sqr(p.
x()/( xSemiAxis + halfRadTol ))
302 +
sqr(p.
y()/( ySemiAxis + halfRadTol ));
304 if ( rad2oo >
sqr( zheight-p.
z() ) )
311 rad2oi =
sqr(p.
x()/( xSemiAxis - halfRadTol ))
312 +
sqr(p.
y()/( ySemiAxis - halfRadTol ));
314 if (rad2oi <
sqr( zheight-p.
z() ) )
316 in = ( ( p.
z() < -zTopCut + halfRadTol )
335 ry =
sqr(p.
y()/ySemiAxis);
341 if( (p.
z() < -zTopCut) && ((rx+ry) <
sqr(zTopCut + zheight)) )
346 if( (p.
z() > (zheight > zTopCut ? zheight : zTopCut)) &&
347 ((rx+ry) <
sqr(zheight-zTopCut)) )
352 if( p.
z() > rds + 2.*zTopCut - zheight )
354 if ( p.
z() > zTopCut )
359 return norm /= norm.
mag();
364 return norm /= norm.
mag();
377 - ( zheight - zTopCut ) );
380 return norm /= norm.
mag();
386 if( p.
z() < rds - 2.*zTopCut - zheight )
391 return norm /= norm.
mag();
396 return norm /= norm.
mag();
409 - ( zheight - zTopCut ) );
412 return norm /= norm.
mag();
418 G4double c = -zTopCut - k*(zTopCut + zheight);
420 if( p.
z() < -k*rds +
c )
423 return norm /= norm.
mag();
444 if (sigz < halfCarTol)
456 if (sigz < 0)
return kInfinity;
463 if (
sqr(p.
x()/( xSemiAxis - halfCarTol ))
464 +
sqr(p.
y()/( ySemiAxis - halfCarTol )) <=
sqr( zheight+zTopCut ) )
479 yi = p.
y() + q*v.
y();
484 if (
sqr(xi/xSemiAxis) +
sqr(yi/ySemiAxis) <=
sqr( zheight + zTopCut ) )
489 return (sigz < -halfCarTol) ? q : 0;
491 else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
492 + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
506 sigz = p.
z() - zTopCut;
508 if (sigz > -halfCarTol)
513 if (sigz > 0)
return kInfinity;
515 if (
sqr(p.
x()/( xSemiAxis - halfCarTol ))
516 +
sqr(p.
y()/( ySemiAxis - halfCarTol )) <=
sqr( zheight-zTopCut ) )
524 yi = p.
y() + q*v.
y();
526 if (
sqr(xi/xSemiAxis) +
sqr(yi/ySemiAxis) <=
sqr( zheight - zTopCut ) )
528 return (sigz > -halfCarTol) ? q : 0;
530 else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
531 + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
550 if (
sqr((lambda*v.
x()+p.
x())/xSemiAxis) +
551 sqr((lambda*v.
y()+p.
y())/ySemiAxis) <=
552 sqr(zTopCut + zheight + 0.5*kRadTolerance) )
554 return distMin = std::fabs(lambda);
565 if (
sqr((lambda*v.
x() + p.
x())/xSemiAxis) +
566 sqr((lambda*v.
y() + p.
y())/ySemiAxis) <=
567 sqr(zheight - zTopCut + 0.5*kRadTolerance) )
569 return distMin = std::fabs(lambda);
573 if (p.
z() > zTopCut - halfCarTol
574 && p.
z() < zTopCut + halfCarTol )
577 {
return kInfinity; }
582 if (p.
z() < -zTopCut + halfCarTol
583 && p.
z() > -zTopCut - halfCarTol)
586 {
return distMin = kInfinity; }
598 v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
600 sqr(zheight - p.
z());
606 if ( discr < -halfCarTol )
611 if ( (discr >= - halfCarTol ) && (discr < halfCarTol ) )
613 return distMin = std::fabs(-B/(2.*A));
616 G4double plus = (-B+std::sqrt(discr))/(2.*A);
617 G4double minus = (-B-std::sqrt(discr))/(2.*A);
621 if ( ( std::fabs(plus) < halfCarTol )||( std::fabs(minus) < halfCarTol ) )
624 p.
y()/(ySemiAxis*ySemiAxis),
625 -( p.
z() - zheight ));
626 if ( truenorm*v >= 0)
639 if ( minus > halfCarTol && minus < distMin )
647 pin.
y()/(ySemiAxis*ySemiAxis),
648 - ( pin.
z() - zheight ));
655 if ( plus > halfCarTol && plus < distMin )
663 pin.
y()/(ySemiAxis*ySemiAxis),
664 - ( pin.
z() - zheight ) );
671 if (distMin < halfCarTol) distMin=0.;
682 G4double distR, distR2, distZ, maxDim;
688 if( (p.
z() <= -zTopCut) && (
sqr(p.
x()/xSemiAxis) +
sqr(p.
y()/ySemiAxis)
692 return distZ = std::fabs(zTopCut + p.
z());
695 if( (p.
z() >= zTopCut) && (
sqr(p.
x()/xSemiAxis)+
sqr(p.
y()/ySemiAxis)
698 return distZ = std::fabs(p.
z() - zTopCut);
705 maxDim = xSemiAxis >= ySemiAxis ? xSemiAxis:ySemiAxis;
706 distRad = std::sqrt(p.
x()*p.
x()+p.
y()*p.
y());
708 if( p.
z() > maxDim*distRad + zTopCut*(1.+maxDim)-
sqr(maxDim)*zheight )
710 distR2 =
sqr(p.
z() - zTopCut) +
sqr(distRad - maxDim*(zheight - zTopCut));
711 return std::sqrt( distR2 );
714 if( distRad > maxDim*( zheight - p.
z() ) )
716 if( p.
z() > maxDim*distRad - (zTopCut*(1.+maxDim)+
sqr(maxDim)*zheight) )
718 G4double zVal = (p.
z()-maxDim*(distRad-maxDim*zheight))/(1.+
sqr(maxDim));
719 G4double rVal = maxDim*(zheight - zVal);
720 return distR = std::sqrt(
sqr(p.
z() - zVal) +
sqr(distRad - rVal));
724 if( distRad <= maxDim*(zheight - p.
z()) )
726 distR2 =
sqr(distRad - maxDim*(zheight + zTopCut)) +
sqr(p.
z() + zTopCut);
727 return std::sqrt( distR2 );
745 enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
752 lambda = (-p.
z() - zTopCut)/v.
z();
754 if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis) +
755 sqr((p.
y() + lambda*v.
y())/ySemiAxis)) <
758 distMin = std::fabs(lambda);
760 if (!calcNorm) {
return distMin; }
762 distMin = std::fabs(lambda);
763 surface = kPlaneSurf;
768 lambda = (zTopCut - p.
z()) / v.
z();
770 if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis)
771 +
sqr((p.
y() + lambda*v.
y())/ySemiAxis) )
774 distMin = std::fabs(lambda);
775 if (!calcNorm) {
return distMin; }
777 distMin = std::fabs(lambda);
778 surface = kPlaneSurf;
786 v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
788 -
sqr(zheight - p.
z());
794 if(!calcNorm) {
return distMin = std::fabs(-B/(2.*A)); }
799 G4double plus = (-B+std::sqrt(discr))/(2.*A);
800 G4double minus = (-B-std::sqrt(discr))/(2.*A);
806 lambda = std::fabs(plus) < std::fabs(minus) ? plus : minus;
816 if ( std::fabs(lambda) < distMin )
820 distMin = std::fabs(lambda);
821 surface = kCurvedSurf;
826 p.
y()/(ySemiAxis*ySemiAxis),
827 -( p.
z() - zheight ));
828 if( truenorm.
dot(v) > 0 )
831 surface = kCurvedSurf;
841 if (surface == kNoSurf)
860 pexit.
y()/(ySemiAxis*ySemiAxis),
861 -( pexit.
z() - zheight ) );
862 truenorm /= truenorm.
mag();
869 std::ostringstream message;
870 G4int oldprc = message.precision(16);
871 message <<
"Undefined side for valid surface normal to solid."
874 <<
" p.x() = " << p.
x()/
mm <<
" mm" <<
G4endl
875 <<
" p.y() = " << p.
y()/
mm <<
" mm" <<
G4endl
876 <<
" p.z() = " << p.
z()/
mm <<
" mm" <<
G4endl
878 <<
" v.x() = " << v.
x() <<
G4endl
879 <<
" v.y() = " << v.
y() <<
G4endl
880 <<
" v.z() = " << v.
z() <<
G4endl
881 <<
"Proposed distance :" <<
G4endl
882 <<
" distMin = " << distMin/
mm <<
" mm";
883 message.precision(oldprc);
884 G4Exception(
"G4EllipticalCone::DistanceToOut(p,v,..)",
902 G4double rds,roo,roo1, distR, distZ, distMin=0.;
903 G4double minAxis = xSemiAxis < ySemiAxis ? xSemiAxis : ySemiAxis;
909 std::ostringstream message;
910 G4int oldprc = message.precision(16);
911 message <<
"Point p is outside !?" <<
G4endl
913 <<
" p.x() = " << p.
x()/
mm <<
" mm" <<
G4endl
914 <<
" p.y() = " << p.
y()/
mm <<
" mm" <<
G4endl
915 <<
" p.z() = " << p.
z()/
mm <<
" mm";
916 message.precision(oldprc) ;
917 G4Exception(
"G4Ellipsoid::DistanceToOut(p)",
"GeomSolids1002",
926 if(
sqr(p.
x()/minAxis)+
sqr(p.
y()/minAxis) <
sqr(zheight - p.
z()) )
928 rds = std::sqrt(
sqr(p.
x()) +
sqr(p.
y()));
929 roo = minAxis*(zheight-p.
z());
930 roo1 = minAxis*(zheight-zTopCut);
932 distZ=zTopCut - std::fabs(p.
z()) ;
933 distR=(roo-rds)/(std::sqrt(1+
sqr(minAxis)));
937 distMin=(zTopCut-p.
z())*(roo-rds)/(roo-roo1);
952 return G4String(
"G4EllipticalCone");
970 G4int oldprc = os.precision(16);
971 os <<
"-----------------------------------------------------------\n"
972 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
973 <<
" ===================================================\n"
974 <<
" Solid type: G4EllipticalCone\n"
977 <<
" semi-axis x: " << xSemiAxis/
mm <<
" mm \n"
978 <<
" semi-axis y: " << ySemiAxis/
mm <<
" mm \n"
979 <<
" height z: " << zheight/
mm <<
" mm \n"
980 <<
" half length in z: " << zTopCut/
mm <<
" mm \n"
981 <<
"-----------------------------------------------------------\n";
982 os.precision(oldprc);
996 G4double phi, sinphi, cosphi, aOne, aTwo, aThree,
997 chose, zRand, rRand1, rRand2;
1000 +
sqr(ySemiAxis))*(zheight - zTopCut);
1002 +
sqr(ySemiAxis))*(zheight + zTopCut);
1004 aOne =
pi*(rOne + rTwo)*std::sqrt(
sqr(rOne - rTwo)+
sqr(2.*zTopCut));
1005 aTwo =
pi*xSemiAxis*ySemiAxis*
sqr(zheight+zTopCut);
1006 aThree =
pi*xSemiAxis*ySemiAxis*
sqr(zheight-zTopCut);
1009 cosphi = std::cos(phi);
1010 sinphi = std::sin(phi);
1012 if(zTopCut >= zheight) aThree = 0.;
1015 if((chose>=0.) && (chose<aOne))
1019 ySemiAxis*(zheight-zRand)*sinphi,zRand);
1021 else if((chose>=aOne) && (chose<aOne+aTwo))
1027 }
while ( rRand2 >= rRand1 ) ;
1030 return G4ThreeVector(rRand1*xSemiAxis*(zheight+zTopCut)*cosphi,
1031 rRand1*ySemiAxis*(zheight+zTopCut)*sinphi, -zTopCut);
1041 }
while ( rRand2 >= rRand1 ) ;
1043 return G4ThreeVector(rRand1*xSemiAxis*(zheight-zTopCut)*cosphi,
1044 rRand1*ySemiAxis*(zheight-zTopCut)*sinphi, zTopCut);
1061 maxDim = xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis;
1062 maxDim = maxDim > zTopCut ? maxDim : zTopCut;
ThreeVector shoot(const G4int Ap, const G4int Af)
G4EllipticalCone & operator=(const G4EllipticalCone &rhs)
CLHEP::Hep3Vector G4ThreeVector
double dot(const Hep3Vector &) const
G4bool GetExtent(G4double &min, G4double &max) const
EInside Inside(const G4ThreeVector &p) const
void SetNormal(const G4ThreeVector &newNormal)
virtual G4bool PartialClip(const G4VoxelLimits &voxelLimit, const EAxis IgnoreMe)
virtual void AddVertexInOrder(const G4ThreeVector vertex)
virtual void ClearAllVertices()
virtual void AddSolid(const G4Box &)=0
G4Polyhedron * CreatePolyhedron() const
std::ostream & StreamInfo(std::ostream &os) const
G4ThreeVector GetPointOnSurface() 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 AddSurface(const G4ClippablePolygon &surface)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
void DescribeYourselfTo(G4VGraphicsScene &scene) const
void SetSemiAxis(G4double x, G4double y, G4double z)
static G4int GetNumberOfRotationSteps()
T max(const T t1, const T t2)
brief Return the largest of the two arguments
void SetZCut(G4double newzTopCut)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4VSolid & operator=(const G4VSolid &rhs)
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
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()
const G4int kMaxMeshSections