70 :
G4VSolid(pName), fpPolyhedron(0), fCubicVolume(0.), fSurfaceArea(0.),
71 zBottomCut(0.), zTopCut(0.)
79 if ( (pxSemiAxis<=0.) || (pySemiAxis<=0.) || (pzSemiAxis<=0.) )
81 std::ostringstream message;
82 message <<
"Invalid semi-axis - " <<
GetName();
83 G4Exception(
"G4Ellipsoid::G4Ellipsoid()",
"GeomSolids0002",
88 if ( pzBottomCut == 0 && pzTopCut == 0 )
92 else if ( (pzBottomCut < pzSemiAxis) && (pzTopCut > -pzSemiAxis)
93 && (pzBottomCut < pzTopCut) )
99 std::ostringstream message;
100 message <<
"Invalid z-coordinate for cutting plane - " <<
GetName();
101 G4Exception(
"G4Ellipsoid::G4Ellipsoid()",
"GeomSolids0002",
112 :
G4VSolid(a), fpPolyhedron(0), kRadTolerance(0.), fCubicVolume(0.),
113 fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zSemiAxis(0.),
114 semiAxisMax(0.), zBottomCut(0.), zTopCut(0.)
132 fpPolyhedron(0), kRadTolerance(rhs.kRadTolerance),
133 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
134 xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
135 zSemiAxis(rhs.zSemiAxis), semiAxisMax(rhs.semiAxisMax),
136 zBottomCut(rhs.zBottomCut), zTopCut(rhs.zTopCut)
148 if (
this == &rhs) {
return *
this; }
157 fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
158 xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
159 zSemiAxis = rhs.zSemiAxis; semiAxisMax = rhs.semiAxisMax;
160 zBottomCut = rhs.zBottomCut; zTopCut = rhs.zTopCut;
190 xMin=xoffset - xSemiAxis;
191 xMax=xoffset + xSemiAxis;
213 yMin=yoffset - ySemiAxis;
214 yMax=yoffset + ySemiAxis;
236 zMin=zoffset + (-zSemiAxis > zBottomCut ? -zSemiAxis : zBottomCut);
237 zMax=zoffset + ( zSemiAxis < zTopCut ? zSemiAxis : zTopCut);
260 xoff = (xoffset < xMin) ? (xMin-xoffset)
261 : (xoffset > xMax) ? (xoffset-xMax) : 0.0;
262 yoff = (yoffset < yMin) ? (yMin-yoffset)
263 : (yoffset > yMax) ? (yoffset-yMax) : 0.0;
285 maxDiff= 1.0-
sqr(yoff/ySemiAxis);
286 if (maxDiff < 0.0) {
return false; }
287 maxDiff= xSemiAxis * std::sqrt(maxDiff);
288 newMin=xoffset-maxDiff;
289 newMax=xoffset+maxDiff;
290 pMin=(newMin<xMin) ? xMin : newMin;
291 pMax=(newMax>xMax) ? xMax : newMax;
307 maxDiff= 1.0-
sqr(xoff/xSemiAxis);
308 if (maxDiff < 0.0) {
return false; }
309 maxDiff= ySemiAxis * std::sqrt(maxDiff);
310 newMin=yoffset-maxDiff;
311 newMax=yoffset+maxDiff;
312 pMin=(newMin<yMin) ? yMin : newMin;
313 pMax=(newMax>yMax) ? yMax : newMax;
330 G4int i,j,noEntries,noBetweenSections;
331 G4bool existsAfterClip=
false;
335 G4int noPolygonVertices=0;
342 noEntries=vertices->size();
343 noBetweenSections=noEntries-noPolygonVertices;
346 for (i=0;i<noEntries;i+=noPolygonVertices)
348 for(j=0;j<(noPolygonVertices/2)-1;j++)
350 ThetaPolygon.push_back((*vertices)[i+j]);
351 ThetaPolygon.push_back((*vertices)[i+j+1]);
352 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-2-j]);
353 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1-j]);
355 ThetaPolygon.clear();
358 for (i=0;i<noBetweenSections;i+=noPolygonVertices)
360 for(j=0;j<noPolygonVertices-1;j++)
362 ThetaPolygon.push_back((*vertices)[i+j]);
363 ThetaPolygon.push_back((*vertices)[i+j+1]);
364 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j+1]);
365 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j]);
367 ThetaPolygon.clear();
369 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1]);
370 ThetaPolygon.push_back((*vertices)[i]);
371 ThetaPolygon.push_back((*vertices)[i+noPolygonVertices]);
372 ThetaPolygon.push_back((*vertices)[i+2*noPolygonVertices-1]);
374 ThetaPolygon.clear();
376 if ( (pMin!=kInfinity) || (pMax!=-kInfinity) )
378 existsAfterClip=
true;
400 existsAfterClip=
true;
406 return existsAfterClip;
422 static const G4double halfRadTolerance=kRadTolerance*0.5;
426 if (p.
z() < zBottomCut-halfRadTolerance) {
return in=
kOutside; }
427 if (p.
z() > zTopCut+halfRadTolerance) {
return in=
kOutside; }
429 rad2oo=
sqr(p.
x()/(xSemiAxis+halfRadTolerance))
430 +
sqr(p.
y()/(ySemiAxis+halfRadTolerance))
431 +
sqr(p.
z()/(zSemiAxis+halfRadTolerance));
433 if (rad2oo > 1.0) {
return in=
kOutside; }
435 rad2oi=
sqr(p.
x()*(1.0+halfRadTolerance/xSemiAxis)/xSemiAxis)
436 +
sqr(p.
y()*(1.0+halfRadTolerance/ySemiAxis)/ySemiAxis)
437 +
sqr(p.
z()*(1.0+halfRadTolerance/zSemiAxis)/zSemiAxis);
444 in = ( (p.
z() < zBottomCut+halfRadTolerance)
446 if ( rad2oi > 1.0-halfRadTolerance ) { in=
kSurface; }
462 G4double distR, distZBottom, distZTop;
468 p.
y()/(ySemiAxis*ySemiAxis),
469 p.
z()/(zSemiAxis*zSemiAxis));
474 distR = std::fabs( (p*norm - 1.0) * radius ) / 2.0;
478 distZBottom = std::fabs( p.
z() - zBottomCut );
479 distZTop = std::fabs( p.
z() - zTopCut );
481 if ( (distZBottom < distR) || (distZTop < distR) )
483 return G4ThreeVector(0.,0.,(distZBottom < distZTop) ? -1.0 : 1.0);
485 return ( norm *= radius );
498 static const G4double halfRadTolerance=kRadTolerance*0.5;
500 G4double distMin = std::min(xSemiAxis,ySemiAxis);
501 const G4double dRmax = 100.*std::min(distMin,zSemiAxis);
505 if (p.
z() <= zBottomCut+halfCarTolerance)
507 if (v.
z() <= 0.0) {
return distMin; }
508 G4double distZ = (zBottomCut - p.
z()) / v.
z();
510 if ( (distZ > -halfRadTolerance) && (
Inside(p+distZ*v) !=
kOutside) )
513 if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
514 return distMin= distZ;
517 if (p.
z() >= zTopCut-halfCarTolerance)
519 if (v.
z() >= 0.0) {
return distMin;}
521 if ( (distZ > -halfRadTolerance) && (
Inside(p+distZ*v) !=
kOutside) )
524 if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
525 return distMin= distZ;
533 A=
sqr(v.
x()/xSemiAxis) +
sqr(v.
y()/ySemiAxis) +
sqr(v.
z()/zSemiAxis);
534 C=
sqr(p.
x()/xSemiAxis) +
sqr(p.
y()/ySemiAxis) +
sqr(p.
z()/zSemiAxis) - 1.0;
535 B= 2.0 * ( p.
x()*v.
x()/(xSemiAxis*xSemiAxis)
536 + p.
y()*v.
y()/(ySemiAxis*ySemiAxis)
537 + p.
z()*v.
z()/(zSemiAxis*zSemiAxis) );
542 G4double distR= (-B - std::sqrt(C)) / (2.0*A);
544 if ( (distR > halfRadTolerance)
545 && (intZ >= zBottomCut-halfRadTolerance)
546 && (intZ <= zTopCut+halfRadTolerance) )
550 else if( (distR >- halfRadTolerance)
551 && (intZ >= zBottomCut-halfRadTolerance)
552 && (intZ <= zTopCut+halfRadTolerance) )
558 distR = (-B + std::sqrt(C) ) / (2.0*A);
559 if(distR>0.) { distMin=0.; }
563 distR= (-B + std::sqrt(C)) / (2.0*A);
564 intZ = p.
z()+distR*v.
z();
565 if ( (distR > halfRadTolerance)
566 && (intZ >= zBottomCut-halfRadTolerance)
567 && (intZ <= zTopCut+halfRadTolerance) )
570 if (norm.
dot(v)<0.) { distMin = distR; }
573 if ( (distMin!=kInfinity) && (distMin>dRmax) )
576 G4double fTerm = distMin-std::fmod(distMin,dRmax);
581 if (std::fabs(distMin)<halfRadTolerance) { distMin=0.; }
597 p.
y()/(ySemiAxis*ySemiAxis),
598 p.
z()/(zSemiAxis*zSemiAxis));
603 distR= (p*norm - 1.0) * radius / 2.0;
607 distZ= zBottomCut - p.
z();
610 distZ = p.
z() - zTopCut;
617 return (distR < 0.0) ? 0.0 : distR;
619 else if (distR < 0.0)
625 return (distZ < distR) ? distZ : distR;
640 enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
649 G4double distZ = (zBottomCut - p.
z()) / v.
z();
653 if (!calcNorm) {
return 0.0;}
664 if (!calcNorm) {
return 0.0;}
673 p.
y()/(ySemiAxis*ySemiAxis),
674 p.
z()/(zSemiAxis*zSemiAxis));
680 A=
sqr(v.
x()/xSemiAxis) +
sqr(v.
y()/ySemiAxis) +
sqr(v.
z()/zSemiAxis);
681 C= (p * nearnorm) - 1.0;
682 B= 2.0 * (v * nearnorm);
687 G4double distR= (-B + std::sqrt(C) ) / (2.0*A);
691 if (!calcNorm) {
return 0.0;}
696 surface= kCurvedSurf;
704 if (surface == kNoSurf)
720 pexit.
y()/(ySemiAxis*ySemiAxis),
721 pexit.
z()/(zSemiAxis*zSemiAxis));
722 truenorm *= 1.0/truenorm.
mag();
727 std::ostringstream message;
728 G4int oldprc = message.precision(16);
729 message <<
"Undefined side for valid surface normal to solid."
732 <<
" p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
733 <<
" p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
734 <<
" p.z() = " << p.
z()/mm <<
" mm" <<
G4endl
736 <<
" v.x() = " << v.
x() <<
G4endl
737 <<
" v.y() = " << v.
y() <<
G4endl
738 <<
" v.z() = " << v.
z() <<
G4endl
739 <<
"Proposed distance :" <<
G4endl
740 <<
" distMin = " << distMin/mm <<
" mm";
741 message.precision(oldprc);
764 std::ostringstream message;
765 G4int oldprc = message.precision(16);
766 message <<
"Point p is outside !?" <<
G4endl
768 <<
" p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
769 <<
" p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
770 <<
" p.z() = " << p.
z()/mm <<
" mm";
771 message.precision(oldprc) ;
772 G4Exception(
"G4Ellipsoid::DistanceToOut(p)",
"GeomSolids1002",
780 p.
y()/(ySemiAxis*ySemiAxis),
781 p.
z()/(zSemiAxis*zSemiAxis));
787 if ( (tmp > 0.0) && (1.0 < radius*tmp) ) {radius = 1.0/tmp;}
791 distR = (1.0 - p*norm) * radius / 2.0;
795 distZ = p.
z() - zBottomCut;
796 if (distZ < 0.0) {distZ= zTopCut - p.
z();}
800 if ( (distZ < 0.0) || (distR < 0.0) )
806 return (distZ < distR) ? distZ : distR;
823 G4int& noPolygonVertices)
const
827 G4double meshAnglePhi, meshRMaxFactor,
828 crossAnglePhi, coscrossAnglePhi, sincrossAnglePhi, sAnglePhi;
829 G4double meshTheta, crossTheta, startTheta;
830 G4double rMaxX, rMaxY, rMaxZ, rMaxMax, rx, ry, rz;
831 G4int crossSectionPhi, noPhiCrossSections, crossSectionTheta, noThetaSections;
847 meshAnglePhi=twopi/(noPhiCrossSections-1);
852 sAnglePhi = -meshAnglePhi*0.5;
868 meshTheta= pi/(noThetaSections-2);
873 startTheta = -meshTheta*0.5;
875 meshRMaxFactor = 1.0/std::cos(0.5*
876 std::sqrt(meshAnglePhi*meshAnglePhi+meshTheta*meshTheta));
877 rMaxMax= (xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis);
878 if (zSemiAxis > rMaxMax) rMaxMax= zSemiAxis;
879 rMaxX= xSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
880 rMaxY= ySemiAxis + rMaxMax*(meshRMaxFactor-1.0);
881 rMaxZ= zSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
885 if (vertices && cosCrossTheta && sinCrossTheta)
887 for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
892 crossTheta=startTheta+crossSectionTheta*meshTheta;
893 cosCrossTheta[crossSectionTheta]=std::cos(crossTheta);
894 sinCrossTheta[crossSectionTheta]=std::sin(crossTheta);
896 for (crossSectionPhi=0; crossSectionPhi<noPhiCrossSections;
899 crossAnglePhi=sAnglePhi+crossSectionPhi*meshAnglePhi;
900 coscrossAnglePhi=std::cos(crossAnglePhi);
901 sincrossAnglePhi=std::sin(crossAnglePhi);
902 for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
907 rx= sinCrossTheta[crossSectionTheta]*coscrossAnglePhi*rMaxX;
908 ry= sinCrossTheta[crossSectionTheta]*sincrossAnglePhi*rMaxY;
909 rz= cosCrossTheta[crossSectionTheta]*rMaxZ;
918 noPolygonVertices = noThetaSections ;
923 G4Exception(
"G4Ellipsoid::CreateRotatedVertices()",
925 "Error in allocation of vertices. Out of memory !");
928 delete[] cosCrossTheta;
929 delete[] sinCrossTheta;
958 G4int oldprc = os.precision(16);
959 os <<
"-----------------------------------------------------------\n"
960 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
961 <<
" ===================================================\n"
962 <<
" Solid type: G4Ellipsoid\n"
965 <<
" semi-axis x: " << xSemiAxis/mm <<
" mm \n"
966 <<
" semi-axis y: " << ySemiAxis/mm <<
" mm \n"
967 <<
" semi-axis z: " << zSemiAxis/mm <<
" mm \n"
968 <<
" max semi-axis: " << semiAxisMax/mm <<
" mm \n"
969 <<
" lower cut plane level z: " << zBottomCut/mm <<
" mm \n"
970 <<
" upper cut plane level z: " << zTopCut/mm <<
" mm \n"
971 <<
"-----------------------------------------------------------\n";
972 os.precision(oldprc);
983 G4double aTop, aBottom, aCurved, chose, xRand, yRand, zRand, phi;
984 G4double cosphi, sinphi, costheta, sintheta, alpha, beta, max1, max2, max3;
986 max1 = xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis;
987 max1 = max1 > zSemiAxis ? max1 : zSemiAxis;
988 if (max1 == xSemiAxis) { max2 = ySemiAxis; max3 = zSemiAxis; }
989 else if (max1 == ySemiAxis) { max2 = xSemiAxis; max3 = zSemiAxis; }
990 else { max2 = xSemiAxis; max3 = ySemiAxis; }
994 cosphi = std::cos(phi); sinphi = std::sin(phi);
996 sintheta = std::sqrt(1.-
sqr(costheta));
998 alpha = 1.-
sqr(max2/max1); beta = 1.-
sqr(max3/max1);
1000 aTop = pi*xSemiAxis*ySemiAxis*(1 -
sqr(zTopCut/zSemiAxis));
1001 aBottom = pi*xSemiAxis*ySemiAxis*(1 -
sqr(zBottomCut/zSemiAxis));
1005 aCurved = 4.*pi*max1*max2*(1.-1./6.*(alpha+beta)-
1006 1./120.*(3.*
sqr(alpha)+2.*alpha*beta+3.*
sqr(beta)));
1008 aCurved *= 0.5*(1.2*zTopCut/zSemiAxis - 1.2*zBottomCut/zSemiAxis);
1010 if( ( zTopCut >= zSemiAxis && zBottomCut <= -1.*zSemiAxis )
1011 || ( zTopCut == 0 && zBottomCut ==0 ) )
1013 aTop = 0; aBottom = 0;
1020 xRand = xSemiAxis*sintheta*cosphi;
1021 yRand = ySemiAxis*sintheta*sinphi;
1022 zRand = zSemiAxis*costheta;
1025 else if(chose >= aCurved && chose < aCurved + aTop)
1028 * std::sqrt(1-
sqr(zTopCut/zSemiAxis));
1030 * std::sqrt(1.-
sqr(zTopCut/zSemiAxis)-
sqr(xRand/xSemiAxis));
1037 * std::sqrt(1-
sqr(zBottomCut/zSemiAxis));
1039 * std::sqrt(1.-
sqr(zBottomCut/zSemiAxis)-
sqr(xRand/xSemiAxis));
1059 -semiAxisMax, semiAxisMax,
1060 -semiAxisMax, semiAxisMax);
1067 return new G4NURBSbox(semiAxisMax, semiAxisMax, semiAxisMax);
1073 zBottomCut, zTopCut);
CLHEP::Hep3Vector G4ThreeVector
std::vector< G4ThreeVector > G4ThreeVectorList
double dot(const Hep3Vector &) const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
void SetZCuts(G4double newzBottomCut, G4double newzTopCut)
std::ostream & StreamInfo(std::ostream &os) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4Polyhedron * GetPolyhedron() const
G4Polyhedron * CreatePolyhedron() const
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pT, G4int &noPV) const
G4Ellipsoid(const G4String &pName, G4double pxSemiAxis, G4double pySemiAxis, G4double pzSemiAxis, G4double pzBottomCut=0, G4double pzTopCut=0)
G4Polyhedron * fpPolyhedron
EInside Inside(const G4ThreeVector &p) const
G4NURBS * CreateNURBS() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
void SetSemiAxis(G4double x, G4double y, G4double z)
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
G4Ellipsoid & operator=(const G4Ellipsoid &rhs)
G4ThreeVector GetPointOnSurface() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4VisExtent GetExtent() const
G4GeometryType GetEntityType() const
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
virtual void AddSolid(const G4Box &)=0
G4VSolid & operator=(const G4VSolid &rhs)
void CalculateClippedPolygonExtent(G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
G4double GetMinExtent(const EAxis pAxis) const
G4bool IsYLimited() const
G4double GetMinZExtent() const
G4bool IsXLimited() const
G4double GetMaxExtent(const EAxis pAxis) const
G4double GetMaxYExtent() const
G4double GetMaxZExtent() const
G4double GetMinYExtent() const
G4double GetMinXExtent() const
G4bool IsZLimited() const
G4double GetMaxXExtent() const
static G4int GetNumberOfRotationSteps()
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
const G4double kMeshAngleDefault