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;
125 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
126 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
127 sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
128 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
129 fPhiFullTube(false), halfCarTolerance(0.), halfRadTolerance(0.),
148 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
149 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
150 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
151 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.sinCPhi),
152 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiOT),
153 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
154 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullTube(rhs.fPhiFullTube),
155 halfCarTolerance(rhs.halfCarTolerance),
156 halfRadTolerance(rhs.halfRadTolerance),
157 halfAngTolerance(rhs.halfAngTolerance)
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; }
1240 G4double deltaR, t1, t2, t3, b, c,
d2, roMin2 ;
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);
1861 if( (
fSPhi == 0) && (
fDPhi == twopi) ) { aFou = 0; }
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);
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)
static const G4double kInfinity
G4double GetMinYExtent() const
CLHEP::Hep3Vector G4ThreeVector
G4double halfCarTolerance
G4bool IsYLimited() const
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4Tubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool IsXLimited() const
const G4int kMinMeshSections
G4ThreeVector GetPointOnSurface() const
virtual void AddSolid(const G4Box &)=0
virtual G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
std::ostream & StreamInfo(std::ostream &os) const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4double GetMaxXExtent() const
G4double GetMinZExtent() const
G4GeometryType GetEntityType() const
G4GLOB_DLL std::ostream G4cout
G4Polyhedron * CreatePolyhedron() const
G4double GetRadialTolerance() const
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4double halfAngTolerance
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4double GetMinXExtent() const
G4double GetMaxZExtent() const
EInside Inside(const G4ThreeVector &p) const
G4double halfRadTolerance
static const double degree
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double GetMaxYExtent() const
G4double GetMaxExtent(const EAxis pAxis) const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4bool IsZLimited() const
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()
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4Tubs & operator=(const G4Tubs &rhs)
const G4int kMaxMeshSections
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pTransform) const