73 using namespace CLHEP;
120 std::ostringstream message;
121 message <<
"Invalid swept radius for Solid: " <<
GetName() <<
G4endl
122 <<
" pRtor = " << pRtor <<
", pRmax = " << pRmax;
129 if ( pRmin < pRmax - 1.e2*kCarTolerance && pRmin >= 0 )
131 if (pRmin >= 1.
e2*kCarTolerance) {
fRmin = pRmin ; }
132 else {
fRmin = 0.0 ; }
137 std::ostringstream message;
138 message <<
"Invalid values of radii for Solid: " <<
GetName() <<
G4endl
139 <<
" pRmin = " << pRmin <<
", pRmax = " << pRmax;
152 if ( pDPhi >= twopi ) {
fDPhi = twopi ; }
155 if (pDPhi > 0) {
fDPhi = pDPhi ; }
158 std::ostringstream message;
159 message <<
"Invalid Z delta-Phi for Solid: " <<
GetName() <<
G4endl
160 <<
" pDPhi = " << pDPhi;
182 :
G4CSGSolid(a), fRmin(0.), fRmax(0.), fRtor(0.), fSPhi(0.),
183 fDPhi(0.), fRminTolerance(0.), fRmaxTolerance(0. ),
184 kRadTolerance(0.), kAngTolerance(0.),
185 halfCarTolerance(0.), halfAngTolerance(0.)
201 :
G4CSGSolid(rhs), fRmin(rhs.fRmin),fRmax(rhs.fRmax),
202 fRtor(rhs.fRtor),fSPhi(rhs.fSPhi),fDPhi(rhs.fDPhi),
203 fRminTolerance(rhs.fRminTolerance), fRmaxTolerance(rhs.fRmaxTolerance),
204 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
205 halfCarTolerance(rhs.halfCarTolerance),
206 halfAngTolerance(rhs.halfAngTolerance)
218 if (
this == &rhs) {
return *
this; }
258 std::vector<G4double>& roots )
const
266 G4double pDotV = p.x()*v.x() + p.y()*v.y() + p.z()*v.z() ;
267 G4double pRad2 = p.x()*p.x() + p.y()*p.y() + p.z()*p.z() ;
271 c[2] = 2*(pRad2 + 2*pDotV*pDotV - Rtor2 - r2 + 2*Rtor2*v.z()*v.z()) ;
272 c[3] = 4*(pDotV*(pRad2 - Rtor2 - r2) + 2*Rtor2*p.z()*v.z()) ;
273 c[4] = pRad2*pRad2 - 2*pRad2*(Rtor2+r2)
274 + 4*Rtor2*p.z()*p.z() + (Rtor2-r2)*(Rtor2-r2) ;
278 num = torusEq.
FindRoots( c, 4, srd, si );
280 for ( i = 0; i < num; i++ )
282 if( si[i] == 0. ) { roots.push_back(srd[i]) ; }
285 std::sort(roots.begin() , roots.end() ) ;
298 G4bool IsDistanceToIn )
const
307 std::vector<G4double> roots ;
308 std::vector<G4double> rootsrefined ;
315 for (
size_t k = 0 ; k<roots.size() ; k++ )
325 if ( rootsrefined.size()==roots.size() )
327 t = t + rootsrefined[k] ;
333 G4double theta = std::atan2(ptmp.y(),ptmp.x());
355 if ( IsDistanceToIn ==
true )
364 p.y()*(1-
fRtor/std::sqrt(p.x()*p.x()
370 if ( r ==
GetRmin() ) { scal = -scal ; }
371 if ( scal < 0 ) {
return 0.0 ; }
378 if ( IsDistanceToIn ==
false )
386 p.y()*(1-
fRtor/std::sqrt(p.x()*p.x()
392 if ( r ==
GetRmin() ) { scal = -scal ; }
393 if ( scal > 0 ) {
return 0.0 ; }
430 G4double RTorus,delta,diff1,diff2,maxDiff,newMin,newMax;
478 zMin = zoffset -
fRmax ;
479 zMax = zoffset +
fRmax ;
508 if ( yoff1 >= 0 && yoff2 >= 0 )
522 delta = RTorus*RTorus - yoff1*yoff1;
523 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
524 delta = RTorus*RTorus - yoff2*yoff2;
525 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
526 maxDiff = (diff1 > diff2) ? diff1:diff2 ;
527 newMin = xoffset - maxDiff ;
528 newMax = xoffset + maxDiff ;
529 pMin = (newMin < xMin) ? xMin : newMin ;
530 pMax = (newMax > xMax) ? xMax : newMax ;
535 xoff1 = xoffset - xMin ;
536 xoff2 = xMax - xoffset ;
537 if (xoff1 >= 0 && xoff2 >= 0 )
550 delta = RTorus*RTorus - xoff1*xoff1;
551 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
552 delta = RTorus*RTorus - xoff2*xoff2;
553 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
554 maxDiff = (diff1 > diff2) ? diff1 : diff2 ;
555 newMin = yoffset - maxDiff ;
556 newMax = yoffset + maxDiff ;
557 pMin = (newMin < yMin) ? yMin : newMin ;
558 pMax = (newMax > yMax) ? yMax : newMax ;
577 G4int i, noEntries, noBetweenSections4 ;
578 G4bool existsAfterClip = false ;
583 G4int noPolygonVertices ;
589 noEntries = vertices->size() ;
590 noBetweenSections4 = noEntries - noPolygonVertices ;
592 for (i=0;i<noEntries;i+=noPolygonVertices)
596 for (i=0;i<noBetweenSections4;i+=noPolygonVertices)
602 existsAfterClip = true ;
620 existsAfterClip = true ;
626 return existsAfterClip;
636 G4double r2, pt2, pPhi, tolRMin, tolRMax ;
642 r2 = p.x()*p.x() + p.y()*p.y() ;
650 if (pt2 >= tolRMin*tolRMin && pt2 <= tolRMax*tolRMax )
652 if (
fDPhi == twopi || pt2 == 0 )
661 pPhi = std::atan2(p.y(),p.x()) ;
698 if (tolRMin < 0 ) { tolRMin = 0 ; }
700 if ( (pt2 >= tolRMin*tolRMin) && (pt2 <= tolRMax*tolRMax) )
702 if ( (
fDPhi == twopi) || (pt2 == 0) )
708 pPhi = std::atan2(p.y(),p.x()) ;
747 G4int noSurfaces = 0;
761 rho2 = p.x()*p.x() + p.y()*p.y();
762 rho = std::sqrt(rho2);
763 pt2 = rho2+p.z()*p.z() +
fRtor * (
fRtor-2*rho);
765 pt = std::sqrt(pt2) ;
770 if( rho > delta && pt != 0.0 )
783 pPhi = std::atan2(p.y(),p.x());
785 if(pPhi <
fSPhi-delta) { pPhi += twopi; }
786 else if(pPhi >
fSPhi+
fDPhi+delta) { pPhi -= twopi; }
788 distSPhi = std::fabs( pPhi -
fSPhi );
794 if( distRMax <= delta )
799 else if(
fRmin && (distRMin <= delta) )
810 if (distSPhi <= dAngle)
815 if (distEPhi <= dAngle)
821 if ( noSurfaces == 0 )
831 ed <<
" ERROR> Surface Normal was called for Torus,"
832 <<
" with point not on surface." <<
G4endl;
836 ed <<
" ERROR> Surface Normal has not found a surface, "
837 <<
" despite the point being on the surface. " <<
G4endl;
848 ed <<
" Coordinates of point : " << p <<
G4endl;
849 ed <<
" Parameters of solid : " << G4endl << *
this <<
G4endl;
853 G4Exception(
"G4Torus::SurfaceNormal(p)",
"GeomSolids1002",
855 "Failing to find normal, even though point is on surface!" );
859 static const char* NameInside[3]= {
"Inside",
"Surface",
"Outside" };
860 ed <<
" The point is " << NameInside[inIt] <<
" the solid. "<<
G4endl;
861 G4Exception(
"G4Torus::SurfaceNormal(p)",
"GeomSolids1002",
867 else if ( noSurfaces == 1 ) { norm = sumnorm; }
868 else { norm = sumnorm.unit(); }
885 G4double distRMin,distRMax,distSPhi,distEPhi,distMin;
887 rho2 = p.x()*p.x() + p.y()*p.y();
888 rho = std::sqrt(rho2) ;
890 pt = std::sqrt(pt2) ;
893 G4cout <<
" G4Torus::ApproximateSurfaceNormal called for point " << p
897 distRMax = std::fabs(pt -
fRmax) ;
901 distRMin = std::fabs(pt -
fRmin) ;
903 if (distRMin < distRMax)
919 if ( (
fDPhi < twopi) && rho )
921 phi = std::atan2(p.y(),p.x()) ;
923 if (phi < 0) { phi += twopi ; }
925 if (
fSPhi < 0 ) { distSPhi = std::fabs(phi-(
fSPhi+twopi))*rho ; }
926 else { distSPhi = std::fabs(phi-
fSPhi)*rho ; }
928 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
930 if (distSPhi < distEPhi)
932 if (distSPhi<distMin) side =
kNSPhi ;
936 if (distEPhi < distMin) { side =
kNEPhi ; }
943 -p.y()*(1-
fRtor/rho)/pt,
948 p.y()*(1-
fRtor/rho)/pt,
961 "Undefined side for valid surface normal to solid.");
1002 G4double cPhi,sinCPhi=0.,cosCPhi=0.;
1015 if (
fDPhi < twopi )
1019 cPhi =
fSPhi + hDPhi ;
1020 sinCPhi = std::sin(cPhi) ;
1021 cosCPhi = std::cos(cPhi) ;
1047 if ( sd[0] < snxt ) { snxt = sd[0] ; }
1062 sinSPhi = std::sin(
fSPhi) ;
1063 cosSPhi = std::cos(
fSPhi) ;
1064 Comp = v.x()*sinSPhi - v.y()*cosSPhi ;
1068 Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ;
1075 if ( sphi < 0 ) { sphi = 0 ; }
1077 xi = p.x() + sphi*v.x() ;
1078 yi = p.y() + sphi*v.y() ;
1079 zi = p.z() + sphi*v.z() ;
1080 rhoi2 = xi*xi + yi*yi ;
1081 it2 = std::fabs(rhoi2 + zi*zi + Rtor2 - 2*fRtor*std::sqrt(rhoi2)) ;
1083 if ( it2 >= tolORMin2 && it2 <= tolORMax2 )
1088 if ((yi*cosCPhi-xi*sinCPhi)<=0) { snxt=sphi; }
1094 sinEPhi=std::sin(ePhi);
1095 cosEPhi=std::cos(ePhi);
1096 Comp=-(v.x()*sinEPhi-v.y()*cosEPhi);
1100 Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ;
1108 if (sphi < 0 ) { sphi = 0 ; }
1110 xi = p.x() + sphi*v.x() ;
1111 yi = p.y() + sphi*v.y() ;
1112 zi = p.z() + sphi*v.z() ;
1113 rhoi2 = xi*xi + yi*yi ;
1114 it2 = std::fabs(rhoi2 + zi*zi + Rtor2 - 2*fRtor*std::sqrt(rhoi2)) ;
1116 if (it2 >= tolORMin2 && it2 <= tolORMax2)
1121 if ((yi*cosCPhi-xi*sinCPhi)>=0) { snxt=sphi; }
1142 G4double phiC, cosPhiC, sinPhiC, safePhi, ePhi, cosPsi ;
1145 rho2 = p.x()*p.x() + p.y()*p.y() ;
1146 rho = std::sqrt(rho2) ;
1148 pt = std::sqrt(pt2) ;
1150 safe1 =
fRmin - pt ;
1151 safe2 = pt -
fRmax ;
1153 if (safe1 > safe2) { safe = safe1; }
1154 else { safe = safe2; }
1156 if (
fDPhi < twopi && rho )
1159 cosPhiC = std::cos(phiC) ;
1160 sinPhiC = std::sin(phiC) ;
1161 cosPsi = (p.x()*cosPhiC + p.y()*sinPhiC)/rho ;
1163 if (cosPsi < std::cos(
fDPhi*0.5) )
1165 if ((p.y()*cosPhiC - p.x()*sinPhiC) <= 0 )
1167 safePhi = std::fabs(p.x()*std::sin(
fSPhi) - p.y()*std::cos(
fSPhi)) ;
1172 safePhi = std::fabs(p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1174 if (safePhi > safe) { safe = safePhi ; }
1177 if (safe < 0 ) { safe = 0 ; }
1198 G4double sinSPhi, cosSPhi, ePhi, sinEPhi, cosEPhi;
1200 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, zi, vphi ;
1212 G4double rho2 = p.x()*p.x()+p.y()*p.y();
1220 pt2= std::fabs( pt2 );
1225 G4double pDotV = p.x()*v.x() + p.y()*v.y() + p.z()*v.z() ;
1229 G4double vDotNmax = pDotV -
fRtor*(v.x()*p.x() + v.y()*p.y())/rho ;
1232 if( (pt2 > tolRMax*tolRMax) && (vDotNmax >= 0) )
1238 if ( calcNorm && (pDotxyNmax >= -2.*fRmaxTolerance) )
1241 p.y()*(1 -
fRtor/rho)/pt,
1258 if ( (pt2 < tolRMin*tolRMin) && (vDotNmax < 0) )
1260 if (calcNorm) { *validNorm = false ; }
1290 if ( calcNorm && (snxt == 0.0) )
1292 *validNorm = false ;
1300 sinSPhi = std::sin(
fSPhi) ;
1301 cosSPhi = std::cos(
fSPhi) ;
1303 sinEPhi = std::sin(ePhi) ;
1304 cosEPhi = std::cos(ePhi) ;
1305 cPhi =
fSPhi + fDPhi*0.5 ;
1306 sinCPhi = std::sin(cPhi) ;
1307 cosCPhi = std::cos(cPhi) ;
1312 vphi = std::atan2(v.y(),v.x()) ;
1317 if ( p.x() || p.y() )
1319 pDistS = p.x()*sinSPhi - p.y()*cosSPhi ;
1320 pDistE = -p.x()*sinEPhi + p.y()*cosEPhi ;
1324 compS = -sinSPhi*v.x() + cosSPhi*v.y() ;
1325 compE = sinEPhi*v.x() - cosEPhi*v.y() ;
1337 sphi = pDistS/compS ;
1341 xi = p.x() + sphi*v.x() ;
1342 yi = p.y() + sphi*v.y() ;
1357 else if ( yi*cosCPhi-xi*sinCPhi >=0 )
1378 sphi2 = pDistE/compE ;
1384 xi = p.x() + sphi2*v.x() ;
1385 yi = p.y() + sphi2*v.y() ;
1401 if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
1423 vphi = std::atan2(v.y(),v.x());
1446 G4double rhoi2,rhoi,it2,it,iDotxyNmax ;
1455 xi = p.x() + snxt*v.x() ;
1456 yi =p.y() + snxt*v.y() ;
1457 zi = p.z() + snxt*v.z() ;
1458 rhoi2 = xi*xi + yi*yi ;
1459 rhoi = std::sqrt(rhoi2) ;
1461 it = std::sqrt(it2) ;
1462 iDotxyNmax = (1-
fRtor/rhoi) ;
1463 if(iDotxyNmax >= -2.*fRmaxTolerance)
1466 yi*(1-
fRtor/rhoi)/it,
1472 *validNorm = false ;
1477 *validNorm = false ;
1488 *validNorm = false ;
1500 *validNorm = false ;
1510 std::ostringstream message;
1511 G4int oldprc = message.precision(16);
1512 message <<
"Undefined side for valid surface normal to solid."
1514 <<
"Position:" << G4endl << G4endl
1515 <<
"p.x() = " << p.x()/
mm <<
" mm" << G4endl
1516 <<
"p.y() = " << p.y()/
mm <<
" mm" << G4endl
1517 <<
"p.z() = " << p.z()/
mm <<
" mm" << G4endl << G4endl
1518 <<
"Direction:" << G4endl << G4endl
1519 <<
"v.x() = " << v.x() << G4endl
1520 <<
"v.y() = " << v.y() << G4endl
1521 <<
"v.z() = " << v.z() << G4endl << G4endl
1522 <<
"Proposed distance :" << G4endl << G4endl
1523 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl;
1524 message.precision(oldprc);
1543 G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi;
1544 rho2 = p.x()*p.x() + p.y()*p.y() ;
1545 rho = std::sqrt(rho2) ;
1547 pt = std::sqrt(pt2) ;
1559 G4cout.precision(oldprc);
1560 G4Exception(
"G4Torus::DistanceToOut(p)",
"GeomSolids1002",
1567 safeR1 = pt -
fRmin ;
1568 safeR2 =
fRmax - pt ;
1570 if (safeR1 < safeR2) { safe = safeR1 ; }
1571 else { safe = safeR2 ; }
1583 cosPhiC = std::cos(phiC) ;
1584 sinPhiC = std::sin(phiC) ;
1586 if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
1588 safePhi = -(p.x()*std::sin(
fSPhi) - p.y()*std::cos(
fSPhi)) ;
1593 safePhi = (p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1595 if (safePhi < safe) { safe = safePhi ; }
1597 if (safe < 0) { safe = 0 ; }
1614 G4int& noPolygonVertices )
const
1618 G4double meshAngle,meshRMax,crossAngle,cosCrossAngle,sinCrossAngle,sAngle;
1620 G4int crossSection,noCrossSections;
1634 meshAngle =
fDPhi/(noCrossSections - 1) ;
1635 meshRMax = (
fRtor +
fRmax)/std::cos(meshAngle*0.5) ;
1642 sAngle = -meshAngle*0.5 ;
1652 vertices->reserve(noCrossSections*4) ;
1653 for (crossSection=0;crossSection<noCrossSections;crossSection++)
1657 crossAngle=sAngle+crossSection*meshAngle;
1658 cosCrossAngle=std::cos(crossAngle);
1659 sinCrossAngle=std::sin(crossAngle);
1661 rMaxX=meshRMax*cosCrossAngle;
1662 rMaxY=meshRMax*sinCrossAngle;
1675 noPolygonVertices = 4 ;
1682 "Error in allocation of vertices. Out of memory !");
1711 G4int oldprc = os.precision(16);
1712 os <<
"-----------------------------------------------------------\n"
1713 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1714 <<
" ===================================================\n"
1715 <<
" Solid type: G4Torus\n"
1716 <<
" Parameters: \n"
1717 <<
" inner radius: " <<
fRmin/
mm <<
" mm \n"
1718 <<
" outer radius: " <<
fRmax/
mm <<
" mm \n"
1719 <<
" swept radius: " <<
fRtor/
mm <<
" mm \n"
1720 <<
" starting phi: " <<
fSPhi/
degree <<
" degrees \n"
1721 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1722 <<
"-----------------------------------------------------------\n";
1723 os.precision(oldprc);
1734 G4double cosu, sinu,cosv, sinv, aOut, aIn, aSide, chose, phi, theta, rRand;
1739 cosu = std::cos(phi); sinu = std::sin(phi);
1740 cosv = std::cos(theta); sinv = std::sin(theta);
1748 if ((
fSPhi == 0) && (
fDPhi == twopi)){ aSide = 0; }
1756 else if( (chose >= aOut) && (chose < aOut + aIn) )
1761 else if( (chose >= aOut + aIn) && (chose < aOut + aIn + aSide) )
1765 (
fRtor+rRand*cosv)*std::sin(
fSPhi), rRand*sinv);
EInside Inside(const G4ThreeVector &p) const
void ClipCrossSection(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
ThreeVector shoot(const G4int Ap, const G4int Af)
G4Polyhedron * CreatePolyhedron() const
static const G4double kInfinity
G4double GetMinYExtent() const
std::ostringstream G4ExceptionDescription
CLHEP::Hep3Vector G4ThreeVector
G4bool fRebuildPolyhedron
G4Torus & operator=(const G4Torus &rhs)
std::ostream & StreamInfo(std::ostream &os) const
G4bool IsYLimited() const
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double SolveNumericJT(const G4ThreeVector &p, const G4ThreeVector &v, G4double r, G4bool IsDistanceToIn) const
G4bool IsXLimited() const
const G4int kMinMeshSections
virtual void AddSolid(const G4Box &)=0
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4double GetMaxXExtent() const
G4double GetMinZExtent() const
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pTransform, G4int &noPolygonVertices) const
G4GLOB_DLL std::ostream G4cout
G4double GetRadialTolerance() const
std::vector< G4ThreeVector > G4ThreeVectorList
G4Torus(const G4String &pName, G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4ThreeVector GetPointOnSurface() const
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
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
G4double halfCarTolerance
G4double GetMaxZExtent() const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
G4double halfAngTolerance
static const double degree
G4GeometryType GetEntityType() const
void TorusRootsJT(const G4ThreeVector &p, const G4ThreeVector &v, G4double r, std::vector< G4double > &roots) const
G4double GetMaxYExtent() const
void SetAllParameters(G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
G4double GetMaxExtent(const EAxis pAxis) const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4bool IsZLimited() const
G4int FindRoots(G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
G4double GetAngularTolerance() const
void ClipBetweenSections(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
G4double GetMinExtent(const EAxis pAxis) const
const G4double kMeshAngleDefault
static G4GeometryTolerance * GetInstance()
const G4int kMaxMeshSections
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const