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",
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;
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;
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)
ThreeVector shoot(const G4int Ap, const G4int Af)
G4double halfRadTolerance
G4ThreeVector GetPointOnSurface() const
G4double GetMinXExtent() const
G4bool fRebuildPolyhedron
G4Polyhedron * CreatePolyhedron() const
static const G4double kInfinity
G4double GetMinYExtent() const
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
CLHEP::Hep3Vector G4ThreeVector
G4VisExtent GetExtent() const
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pT, G4int &noPV) const
G4double GetMinZExtent() const
G4bool IsYLimited() const
std::ostream & StreamInfo(std::ostream &os) const
G4bool IsXLimited() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
virtual void AddSolid(const G4Box &)=0
G4double GetMaxZExtent() const
#define G4MUTEX_INITIALIZER
G4Polyhedron * GetPolyhedron() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
EInside Inside(const G4ThreeVector &p) const
void SetZCuts(G4double newzBottomCut, G4double newzTopCut)
G4Ellipsoid(const G4String &pName, G4double pxSemiAxis, G4double pySemiAxis, G4double pzSemiAxis, G4double pzBottomCut=0, G4double pzTopCut=0)
G4double GetMaxXExtent() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4double GetRadialTolerance() const
double A(double temperature)
G4Polyhedron * fpPolyhedron
static const double twopi
G4Ellipsoid & operator=(const G4Ellipsoid &rhs)
std::vector< G4ThreeVector > G4ThreeVectorList
G4double GetMinExtent(const EAxis pAxis) const
G4double halfCarTolerance
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
double dot(const Hep3Vector &) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
G4bool IsZLimited() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
static G4int GetNumberOfRotationSteps()
void SetSemiAxis(G4double x, G4double y, G4double z)
G4double GetMaxExtent(const EAxis pAxis) const
G4VSolid & operator=(const G4VSolid &rhs)
void CalculateClippedPolygonExtent(G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
static const G4double alpha
G4double GetMaxYExtent() const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4GeometryType GetEntityType() const
const G4double kMeshAngleDefault
static G4GeometryTolerance * GetInstance()
static int max3(int a, int b, int c)
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const