62 using namespace CLHEP;
75 :
G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0),
76 fCubicVolume(0.), fSurfaceArea(0.), zBottomCut(0.), zTopCut(0.)
87 if ( (pxSemiAxis<=0.) || (pySemiAxis<=0.) || (pzSemiAxis<=0.) )
89 std::ostringstream message;
90 message <<
"Invalid semi-axis - " <<
GetName();
91 G4Exception(
"G4Ellipsoid::G4Ellipsoid()",
"GeomSolids0002",
96 if ( pzBottomCut == 0 && pzTopCut == 0 )
100 else if ( (pzBottomCut < pzSemiAxis) && (pzTopCut > -pzSemiAxis)
101 && (pzBottomCut < pzTopCut) )
107 std::ostringstream message;
108 message <<
"Invalid z-coordinate for cutting plane - " <<
GetName();
109 G4Exception(
"G4Ellipsoid::G4Ellipsoid()",
"GeomSolids0002",
120 :
G4VSolid(a), fRebuildPolyhedron(false), fpPolyhedron(0), kRadTolerance(0.),
121 halfCarTolerance(0.), halfRadTolerance(0.), fCubicVolume(0.),
122 fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zSemiAxis(0.),
123 semiAxisMax(0.), zBottomCut(0.), zTopCut(0.)
142 fRebuildPolyhedron(false), fpPolyhedron(0),
143 kRadTolerance(rhs.kRadTolerance),
144 halfCarTolerance(rhs.halfCarTolerance),
145 halfRadTolerance(rhs.halfRadTolerance),
146 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
147 xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
148 zSemiAxis(rhs.zSemiAxis), semiAxisMax(rhs.semiAxisMax),
149 zBottomCut(rhs.zBottomCut), zTopCut(rhs.zTopCut)
161 if (
this == &rhs) {
return *
this; }
289 xoff = (xoffset < xMin) ? (xMin-xoffset)
290 : (xoffset > xMax) ? (xoffset-xMax) : 0.0;
291 yoff = (yoffset < yMin) ? (yMin-yoffset)
292 : (yoffset > yMax) ? (yoffset-yMax) : 0.0;
314 maxDiff= 1.0-
sqr(yoff/ySemiAxis);
315 if (maxDiff < 0.0) {
return false; }
316 maxDiff= xSemiAxis * std::sqrt(maxDiff);
317 newMin=xoffset-maxDiff;
318 newMax=xoffset+maxDiff;
319 pMin=(newMin<xMin) ? xMin : newMin;
320 pMax=(newMax>xMax) ? xMax : newMax;
336 maxDiff= 1.0-
sqr(xoff/xSemiAxis);
337 if (maxDiff < 0.0) {
return false; }
338 maxDiff= ySemiAxis * std::sqrt(maxDiff);
339 newMin=yoffset-maxDiff;
340 newMax=yoffset+maxDiff;
341 pMin=(newMin<yMin) ? yMin : newMin;
342 pMax=(newMax>yMax) ? yMax : newMax;
359 G4int i,j,noEntries,noBetweenSections;
360 G4bool existsAfterClip=
false;
364 G4int noPolygonVertices=0;
371 noEntries=vertices->size();
372 noBetweenSections=noEntries-noPolygonVertices;
375 for (i=0;i<noEntries;i+=noPolygonVertices)
377 for(j=0;j<(noPolygonVertices/2)-1;j++)
379 ThetaPolygon.push_back((*vertices)[i+j]);
380 ThetaPolygon.push_back((*vertices)[i+j+1]);
381 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-2-j]);
382 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1-j]);
384 ThetaPolygon.clear();
387 for (i=0;i<noBetweenSections;i+=noPolygonVertices)
389 for(j=0;j<noPolygonVertices-1;j++)
391 ThetaPolygon.push_back((*vertices)[i+j]);
392 ThetaPolygon.push_back((*vertices)[i+j+1]);
393 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j+1]);
394 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j]);
396 ThetaPolygon.clear();
398 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1]);
399 ThetaPolygon.push_back((*vertices)[i]);
400 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices]);
401 ThetaPolygon.push_back((*vertices)[i+2*noPolygonVertices-1]);
403 ThetaPolygon.clear();
407 existsAfterClip=
true;
429 existsAfterClip=
true;
435 return existsAfterClip;
460 if (rad2oo > 1.0) {
return in=
kOutside; }
489 G4double distR, distZBottom, distZTop;
501 distR = std::fabs( (p*norm - 1.0) * radius ) / 2.0;
505 distZBottom = std::fabs( p.z() -
zBottomCut );
506 distZTop = std::fabs( p.z() -
zTopCut );
508 if ( (distZBottom < distR) || (distZTop < distR) )
510 return G4ThreeVector(0.,0.,(distZBottom < distZTop) ? -1.0 : 1.0);
512 return ( norm *= radius );
531 if (v.z() <= 0.0) {
return distMin; }
538 return distMin= distZ;
543 if (v.z() >= 0.0) {
return distMin;}
549 return distMin= distZ;
566 G4double distR= (-B - std::sqrt(C)) / (2.0*A);
582 distR = (-B + std::sqrt(C) ) / (2.0*A);
583 if(distR>0.) { distMin=0.; }
587 distR= (-B + std::sqrt(C)) / (2.0*A);
588 intZ = p.z()+distR*v.z();
594 if (norm.dot(v)<0.) { distMin = distR; }
597 if ( (distMin!=
kInfinity) && (distMin>dRmax) )
600 G4double fTerm = distMin-std::fmod(distMin,dRmax);
627 distR= (p*norm - 1.0) * radius / 2.0;
641 return (distR < 0.0) ? 0.0 : distR;
643 else if (distR < 0.0)
649 return (distZ < distR) ? distZ : distR;
664 enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
677 if (!calcNorm) {
return 0.0;}
688 if (!calcNorm) {
return 0.0;}
705 C= (p * nearnorm) - 1.0;
706 B= 2.0 * (v * nearnorm);
711 G4double distR= (-B + std::sqrt(C) ) / (2.0*A);
715 if (!calcNorm) {
return 0.0;}
720 surface= kCurvedSurf;
728 if (surface == kNoSurf)
746 truenorm *= 1.0/truenorm.mag();
751 std::ostringstream message;
752 G4int oldprc = message.precision(16);
753 message <<
"Undefined side for valid surface normal to solid."
756 <<
" p.x() = " << p.x()/
mm <<
" mm" <<
G4endl
757 <<
" p.y() = " << p.y()/
mm <<
" mm" <<
G4endl
758 <<
" p.z() = " << p.z()/
mm <<
" mm" <<
G4endl
760 <<
" v.x() = " << v.x() <<
G4endl
761 <<
" v.y() = " << v.y() <<
G4endl
762 <<
" v.z() = " << v.z() <<
G4endl
763 <<
"Proposed distance :" <<
G4endl
764 <<
" distMin = " << distMin/
mm <<
" mm";
765 message.precision(oldprc);
788 std::ostringstream message;
789 G4int oldprc = message.precision(16);
790 message <<
"Point p is outside !?" <<
G4endl
792 <<
" p.x() = " << p.x()/
mm <<
" mm" <<
G4endl
793 <<
" p.y() = " << p.y()/
mm <<
" mm" <<
G4endl
794 <<
" p.z() = " << p.z()/
mm <<
" mm";
795 message.precision(oldprc) ;
796 G4Exception(
"G4Ellipsoid::DistanceToOut(p)",
"GeomSolids1002",
811 if ( (tmp > 0.0) && (1.0 < radius*tmp) ) {radius = 1.0/tmp;}
815 distR = (1.0 - p*norm) * radius / 2.0;
820 if (distZ < 0.0) {distZ=
zTopCut - p.z();}
824 if ( (distZ < 0.0) || (distR < 0.0) )
830 return (distZ < distR) ? distZ : distR;
847 G4int& noPolygonVertices)
const
851 G4double meshAnglePhi, meshRMaxFactor,
852 crossAnglePhi, coscrossAnglePhi, sincrossAnglePhi, sAnglePhi;
853 G4double meshTheta, crossTheta, startTheta;
854 G4double rMaxX, rMaxY, rMaxZ, rMaxMax, rx, ry, rz;
855 G4int crossSectionPhi, noPhiCrossSections, crossSectionTheta, noThetaSections;
871 meshAnglePhi=twopi/(noPhiCrossSections-1);
876 sAnglePhi = -meshAnglePhi*0.5;
892 meshTheta=
pi/(noThetaSections-2);
897 startTheta = -meshTheta*0.5;
899 meshRMaxFactor = 1.0/std::cos(0.5*
900 std::sqrt(meshAnglePhi*meshAnglePhi+meshTheta*meshTheta));
903 rMaxX=
xSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
904 rMaxY=
ySemiAxis + rMaxMax*(meshRMaxFactor-1.0);
905 rMaxZ=
zSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
909 if (vertices && cosCrossTheta && sinCrossTheta)
911 for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
916 crossTheta=startTheta+crossSectionTheta*meshTheta;
917 cosCrossTheta[crossSectionTheta]=std::cos(crossTheta);
918 sinCrossTheta[crossSectionTheta]=std::sin(crossTheta);
920 for (crossSectionPhi=0; crossSectionPhi<noPhiCrossSections;
923 crossAnglePhi=sAnglePhi+crossSectionPhi*meshAnglePhi;
924 coscrossAnglePhi=std::cos(crossAnglePhi);
925 sincrossAnglePhi=std::sin(crossAnglePhi);
926 for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
931 rx= sinCrossTheta[crossSectionTheta]*coscrossAnglePhi*rMaxX;
932 ry= sinCrossTheta[crossSectionTheta]*sincrossAnglePhi*rMaxY;
933 rz= cosCrossTheta[crossSectionTheta]*rMaxZ;
942 noPolygonVertices = noThetaSections ;
947 G4Exception(
"G4Ellipsoid::CreateRotatedVertices()",
949 "Error in allocation of vertices. Out of memory !");
952 delete[] cosCrossTheta;
953 delete[] sinCrossTheta;
982 G4int oldprc = os.precision(16);
983 os <<
"-----------------------------------------------------------\n"
984 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
985 <<
" ===================================================\n"
986 <<
" Solid type: G4Ellipsoid\n"
993 <<
" lower cut plane level z: " <<
zBottomCut/
mm <<
" mm \n"
994 <<
" upper cut plane level z: " <<
zTopCut/
mm <<
" mm \n"
995 <<
"-----------------------------------------------------------\n";
996 os.precision(oldprc);
1007 G4double aTop, aBottom, aCurved, chose, xRand, yRand, zRand, phi;
1008 G4double cosphi, sinphi, costheta, sintheta,
alpha, beta, max1, max2, max3;
1018 cosphi = std::cos(phi); sinphi = std::sin(phi);
1020 sintheta = std::sqrt(1.-
sqr(costheta));
1022 alpha = 1.-
sqr(max2/max1); beta = 1.-
sqr(max3/max1);
1029 aCurved = 4.*
pi*max1*max2*(1.-1./6.*(alpha+beta)-
1030 1./120.*(3.*
sqr(alpha)+2.*alpha*beta+3.*
sqr(beta)));
1037 aTop = 0; aBottom = 0;
1049 else if(chose >= aCurved && chose < aCurved + aTop)
G4Polyhedron * GetPolyhedron() const
ThreeVector shoot(const G4int Ap, const G4int Af)
G4double halfRadTolerance
G4GeometryType GetEntityType() const
G4bool fRebuildPolyhedron
static const G4double kInfinity
G4double GetMinYExtent() const
CLHEP::Hep3Vector G4ThreeVector
G4bool IsYLimited() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
EInside Inside(const G4ThreeVector &p) const
G4bool IsXLimited() const
virtual void AddSolid(const G4Box &)=0
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
#define G4MUTEX_INITIALIZER
void SetZCuts(G4double newzBottomCut, G4double newzTopCut)
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4Ellipsoid(const G4String &pName, G4double pxSemiAxis, G4double pySemiAxis, G4double pzSemiAxis, G4double pzBottomCut=0, G4double pzTopCut=0)
G4double GetMaxXExtent() const
G4double GetMinZExtent() const
void CalculateClippedPolygonExtent(G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
G4VisExtent GetExtent() const
G4Polyhedron * fpPolyhedron
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pT, G4int &noPV) const
G4double GetRadialTolerance() const
G4Ellipsoid & operator=(const G4Ellipsoid &rhs)
G4Polyhedron * CreatePolyhedron() const
std::vector< G4ThreeVector > G4ThreeVectorList
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double halfCarTolerance
static const G4double A[nN]
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4double GetMinXExtent() const
std::ostream & StreamInfo(std::ostream &os) const
G4double GetMaxZExtent() const
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
void SetSemiAxis(G4double x, G4double y, G4double z)
G4double GetMaxYExtent() const
G4VSolid & operator=(const G4VSolid &rhs)
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
G4ThreeVector GetPointOnSurface() const
G4double GetMaxExtent(const EAxis pAxis) const
static const G4double alpha
G4bool IsZLimited() const
G4double GetMinExtent(const EAxis pAxis) const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
const G4double kMeshAngleDefault
static G4GeometryTolerance * GetInstance()