64 #if !defined(G4GEOM_USE_UTUBS) 78 using namespace CLHEP;
89 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
101 std::ostringstream message;
102 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
105 if ( (pRMin >= pRMax) || (pRMin < 0) )
107 std::ostringstream message;
108 message <<
"Invalid values for radii in solid: " <<
GetName()
110 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
169 if (
this == &rhs) {
return *
this; }
226 G4double diff1, diff2, maxDiff, newMin, newMax;
227 G4double xoff1, xoff2, yoff1, yoff2, delta;
230 xMin = xoffset -
fRMax;
231 xMax = xoffset +
fRMax;
253 yMin = yoffset -
fRMax;
254 yMax = yoffset +
fRMax;
276 zMin = zoffset -
fDz;
277 zMax = zoffset +
fDz;
302 yoff1 = yoffset - yMin;
303 yoff2 = yMax - yoffset;
305 if ( (yoff1 >= 0) && (yoff2 >= 0) )
315 delta = fRMax*fRMax - yoff1*yoff1;
316 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
317 delta = fRMax*fRMax - yoff2*yoff2;
318 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
319 maxDiff = (diff1 > diff2) ? diff1:diff2;
320 newMin = xoffset - maxDiff;
321 newMax = xoffset + maxDiff;
322 pMin = (newMin < xMin) ? xMin : newMin;
323 pMax = (newMax > xMax) ? xMax : newMax;
329 xoff1 = xoffset - xMin;
330 xoff2 = xMax - xoffset;
332 if ( (xoff1 >= 0) && (xoff2 >= 0) )
342 delta = fRMax*fRMax - xoff1*xoff1;
343 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
344 delta = fRMax*fRMax - xoff2*xoff2;
345 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
346 maxDiff = (diff1 > diff2) ? diff1 : diff2;
347 newMin = yoffset - maxDiff;
348 newMax = yoffset + maxDiff;
349 pMin = (newMin < yMin) ? yMin : newMin;
350 pMax = (newMax > yMax) ? yMax : newMax;
369 G4int i, noEntries, noBetweenSections4;
370 G4bool existsAfterClip =
false;
376 noEntries = vertices->size();
377 noBetweenSections4 = noEntries - 4;
379 for ( i = 0 ; i < noEntries ; i += 4 )
383 for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
389 existsAfterClip =
true;
407 existsAfterClip =
true;
413 return existsAfterClip;
429 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
432 else { tolRMin = 0 ; }
436 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
454 pPhi = std::atan2(p.
y(),p.
x()) ;
497 if ( tolRMin < 0 ) { tolRMin = 0; }
499 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
501 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance) )
507 pPhi = std::atan2(p.
y(),p.
x()) ;
538 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
542 if ( tolRMin < 0 ) { tolRMin = 0; }
544 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
546 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance))
552 pPhi = std::atan2(p.
y(),p.
x()) ;
591 G4int noSurfaces = 0;
600 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
602 distRMin = std::fabs(rho -
fRMin);
603 distRMax = std::fabs(rho -
fRMax);
604 distZ = std::fabs(std::fabs(p.
z()) -
fDz);
610 pPhi = std::atan2(p.
y(),p.
x());
615 distSPhi = std::fabs(pPhi -
fSPhi);
654 if ( p.
z() >= 0.) { sumnorm += nZ; }
655 else { sumnorm -= nZ; }
657 if ( noSurfaces == 0 )
660 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
663 G4cout<<
"G4Tubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); " 665 G4cout.precision(oldprc) ;
669 else if ( noSurfaces == 1 ) { norm = sumnorm; }
670 else { norm = sumnorm.
unit(); }
685 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
687 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
689 distRMin = std::fabs(rho -
fRMin) ;
690 distRMax = std::fabs(rho -
fRMax) ;
691 distZ = std::fabs(std::fabs(p.
z()) -
fDz) ;
693 if (distRMin < distRMax)
695 if ( distZ < distRMin )
708 if ( distZ < distRMax )
721 phi = std::atan2(p.
y(),p.
x()) ;
723 if ( phi < 0 ) { phi +=
twopi; }
727 distSPhi = std::fabs(phi - (
fSPhi +
twopi))*rho ;
731 distSPhi = std::fabs(phi -
fSPhi)*rho ;
733 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
735 if (distSPhi < distEPhi)
737 if ( distSPhi < distMin )
744 if ( distEPhi < distMin )
783 "Undefined side for valid surface normal to solid.");
817 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
822 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
845 if (std::fabs(p.
z()) >= tolIDz)
847 if ( p.
z()*v.
z() < 0 )
849 sd = (std::fabs(p.
z()) -
fDz)/std::fabs(v.
z()) ;
851 if(sd < 0.0) { sd = 0.0; }
853 xi = p.
x() + sd*v.
x() ;
854 yi = p.
y() + sd*v.
y() ;
855 rho2 = xi*xi + yi*yi ;
859 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
866 iden = std::sqrt(rho2) ;
878 if ( snxt<halfCarTolerance ) { snxt=0; }
895 t1 = 1.0 - v.
z()*v.
z() ;
896 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
897 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
903 if ((t3 >= tolORMax2) && (t2<0))
913 sd = c/(-b+std::sqrt(d));
918 G4double fTerm = sd-std::fmod(sd,dRmax);
923 zi = p.
z() + sd*v.
z() ;
924 if (std::fabs(zi)<=tolODz)
934 xi = p.
x() + sd*v.
x() ;
935 yi = p.
y() + sd*v.
y() ;
948 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.
z()) <= tolIDz))
955 iden = std::sqrt(t3) ;
976 snxt = c/(-b+std::sqrt(d));
978 if ( snxt < halfCarTolerance ) { snxt=0; }
996 c = t3 - fRMax*
fRMax;
1007 snxt= c/(-b+std::sqrt(d));
1009 if ( snxt < halfCarTolerance ) { snxt=0; }
1029 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1030 if (sd >= -halfCarTolerance)
1034 if(sd < 0.0) { sd = 0.0; }
1037 G4double fTerm = sd-std::fmod(sd,dRmax);
1040 zi = p.
z() + sd*v.
z() ;
1041 if (std::fabs(zi) <= tolODz)
1051 xi = p.
x() + sd*v.
x() ;
1052 yi = p.
y() + sd*v.
y() ;
1087 if ( Dist < halfCarTolerance )
1093 if ( sd < 0 ) { sd = 0.0; }
1094 zi = p.
z() + sd*v.
z() ;
1095 if ( std::fabs(zi) <= tolODz )
1097 xi = p.
x() + sd*v.
x() ;
1098 yi = p.
y() + sd*v.
y() ;
1099 rho2 = xi*xi + yi*yi ;
1101 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1102 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1105 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1127 if ( Dist < halfCarTolerance )
1133 if ( sd < 0 ) { sd = 0; }
1134 zi = p.
z() + sd*v.
z() ;
1135 if ( std::fabs(zi) <= tolODz )
1137 xi = p.
x() + sd*v.
x() ;
1138 yi = p.
y() + sd*v.
y() ;
1139 rho2 = xi*xi + yi*yi ;
1140 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1141 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1144 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1158 if ( snxt<halfCarTolerance ) { snxt=0; }
1190 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1193 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1194 safe1 =
fRMin - rho ;
1195 safe2 = rho -
fRMax ;
1196 safe3 = std::fabs(p.
z()) -
fDz ;
1198 if ( safe1 > safe2 ) { safe = safe1; }
1199 else { safe = safe2; }
1200 if ( safe3 > safe ) { safe = safe3; }
1208 if ( cosPsi < std::cos(
fDPhi*0.5) )
1220 if ( safePhi > safe ) { safe = safePhi; }
1223 if ( safe < 0 ) { safe = 0; }
1244 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1250 pdist =
fDz - p.
z() ;
1253 snxt = pdist/v.
z() ;
1266 else if ( v.
z() < 0 )
1268 pdist =
fDz + p.
z() ;
1272 snxt = -pdist/v.
z() ;
1302 t1 = 1.0 - v.
z()*v.
z() ;
1303 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1304 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1307 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1327 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1346 roMin2 = t3 - t2*t2/
t1 ;
1362 srd = c/(-b+std::sqrt(d2));
1367 if ( calcNorm ) { *validNorm =
false; }
1378 srd = -b + std::sqrt(d2) ;
1402 srd = -b + std::sqrt(d2) ;
1425 vphi = std::atan2(v.
y(),v.
x()) ;
1431 if ( p.
x() || p.
y() )
1454 sphi = pDistS/compS ;
1458 xi = p.
x() + sphi*v.
x() ;
1459 yi = p.
y() + sphi*v.
y() ;
1498 sphi2 = pDistE/compE ;
1504 xi = p.
x() + sphi2*v.
x() ;
1505 yi = p.
y() + sphi2*v.
y() ;
1516 else { sphi = 0.0 ; }
1527 else { sphi = 0.0 ; }
1573 xi = p.
x() + snxt*v.
x() ;
1574 yi = p.
y() + snxt*v.
y() ;
1580 *validNorm = false ;
1591 *validNorm = false ;
1603 *validNorm = false ;
1620 std::ostringstream message;
1621 G4int oldprc = message.precision(16);
1622 message <<
"Undefined side for valid surface normal to solid." 1624 <<
"Position:" << G4endl << G4endl
1625 <<
"p.x() = " << p.
x()/
mm <<
" mm" << G4endl
1626 <<
"p.y() = " << p.
y()/
mm <<
" mm" << G4endl
1627 <<
"p.z() = " << p.
z()/
mm <<
" mm" << G4endl << G4endl
1628 <<
"Direction:" << G4endl << G4endl
1629 <<
"v.x() = " << v.
x() << G4endl
1630 <<
"v.y() = " << v.
y() << G4endl
1631 <<
"v.z() = " << v.
z() << G4endl << G4endl
1632 <<
"Proposed distance :" << G4endl << G4endl
1633 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1634 message.precision(oldprc) ;
1635 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1651 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1652 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1664 G4cout.precision(oldprc) ;
1665 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1672 safeR1 = rho -
fRMin ;
1673 safeR2 =
fRMax - rho ;
1675 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1676 else { safe = safeR2 ; }
1680 safe =
fRMax - rho ;
1682 safeZ =
fDz - std::fabs(p.
z()) ;
1684 if ( safeZ < safe ) { safe = safeZ ; }
1698 if (safePhi < safe) { safe = safePhi ; }
1700 if ( safe < 0 ) { safe = 0 ; }
1721 G4double meshAngle, meshRMax, crossAngle,
1722 cosCrossAngle, sinCrossAngle, sAngle;
1723 G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
1724 G4int crossSection, noCrossSections;
1740 meshAngle =
fDPhi/(noCrossSections - 1) ;
1750 else { sAngle =
fSPhi ; }
1756 vertices->reserve(noCrossSections*4);
1757 for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
1761 crossAngle = sAngle + crossSection*meshAngle ;
1762 cosCrossAngle = std::cos(crossAngle) ;
1763 sinCrossAngle = std::sin(crossAngle) ;
1765 rMaxX = meshRMax*cosCrossAngle ;
1766 rMaxY = meshRMax*sinCrossAngle ;
1775 rMinX = meshRMin*cosCrossAngle ;
1776 rMinY = meshRMin*sinCrossAngle ;
1794 "Error in allocation of vertices. Out of memory !");
1814 return new G4Tubs(*
this);
1823 G4int oldprc = os.precision(16);
1824 os <<
"-----------------------------------------------------------\n" 1825 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n" 1826 <<
" ===================================================\n" 1827 <<
" Solid type: G4Tubs\n" 1828 <<
" Parameters: \n" 1829 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n" 1830 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n" 1831 <<
" half length Z: " <<
fDz/
mm <<
" mm \n" 1832 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n" 1833 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n" 1834 <<
"-----------------------------------------------------------\n";
1835 os.precision(oldprc);
1846 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1847 aOne, aTwo, aThr, aFou;
1856 cosphi = std::cos(phi);
1857 sinphi = std::sin(phi);
1865 if( (chose >=0) && (chose < aOne) )
1867 xRand = fRMax*cosphi;
1868 yRand = fRMax*sinphi;
1872 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1874 xRand = fRMin*cosphi;
1875 yRand = fRMin*sinphi;
1879 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1881 xRand = rRand*cosphi;
1882 yRand = rRand*sinphi;
1886 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1888 xRand = rRand*cosphi;
1889 yRand = rRand*sinphi;
1893 else if( (chose >= aOne + aTwo + 2.*aThr)
1894 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1896 xRand = rRand*std::cos(
fSPhi);
1897 yRand = rRand*std::sin(
fSPhi);
ThreeVector shoot(const G4int Ap, const G4int Af)
void ClipBetweenSections(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
G4double GetMinXExtent() const
static const G4double kInfinity
std::ostream & StreamInfo(std::ostream &os) const
G4double GetMinYExtent() const
CLHEP::Hep3Vector G4ThreeVector
G4double halfCarTolerance
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4Tubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
G4double GetMinZExtent() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
G4bool IsYLimited() const
virtual G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
void ClipCrossSection(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
G4bool IsXLimited() const
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pTransform) const
const G4int kMinMeshSections
virtual void AddSolid(const G4Box &)=0
G4double GetMaxZExtent() const
G4double GetMaxXExtent() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4GLOB_DLL std::ostream G4cout
G4double GetRadialTolerance() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
static const double twopi
std::vector< G4ThreeVector > G4ThreeVectorList
G4double GetAngularTolerance() const
G4double GetMinExtent(const EAxis pAxis) const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4ThreeVector GetPointOnSurface() const
G4double halfAngTolerance
G4bool IsZLimited() const
G4double halfRadTolerance
G4Polyhedron * CreatePolyhedron() const
G4GeometryType GetEntityType() const
static const double degree
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double GetMaxExtent(const EAxis pAxis) const
EInside Inside(const G4ThreeVector &p) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4double GetMaxYExtent() const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
const G4double kMeshAngleDefault
static G4GeometryTolerance * GetInstance()
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4Tubs & operator=(const G4Tubs &rhs)
const G4int kMaxMeshSections
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const