38 #if !defined(G4GEOM_USE_UTUBS)
52 using namespace CLHEP;
63 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
75 std::ostringstream message;
76 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
79 if ( (pRMin >= pRMax) || (pRMin < 0) )
81 std::ostringstream message;
82 message <<
"Invalid values for radii in solid: " <<
GetName()
84 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
99 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
100 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
101 sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
102 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
103 fPhiFullTube(false), halfCarTolerance(0.), halfRadTolerance(0.),
123 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
124 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
125 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
126 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.sinCPhi),
127 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiOT),
128 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
129 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullTube(rhs.fPhiFullTube),
130 halfCarTolerance(rhs.halfCarTolerance),
131 halfRadTolerance(rhs.halfRadTolerance),
132 halfAngTolerance(rhs.halfAngTolerance)
145 if (
this == &rhs) {
return *
this; }
191 G4double diff1, diff2, maxDiff, newMin, newMax;
192 G4double xoff1, xoff2, yoff1, yoff2, delta;
195 xMin = xoffset -
fRMax;
196 xMax = xoffset +
fRMax;
218 yMin = yoffset -
fRMax;
219 yMax = yoffset +
fRMax;
241 zMin = zoffset -
fDz;
242 zMax = zoffset +
fDz;
267 yoff1 = yoffset - yMin;
268 yoff2 = yMax - yoffset;
270 if ( (yoff1 >= 0) && (yoff2 >= 0) )
280 delta = fRMax*fRMax - yoff1*yoff1;
281 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
282 delta = fRMax*fRMax - yoff2*yoff2;
283 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
284 maxDiff = (diff1 > diff2) ? diff1:diff2;
285 newMin = xoffset - maxDiff;
286 newMax = xoffset + maxDiff;
287 pMin = (newMin < xMin) ? xMin : newMin;
288 pMax = (newMax > xMax) ? xMax : newMax;
294 xoff1 = xoffset - xMin;
295 xoff2 = xMax - xoffset;
297 if ( (xoff1 >= 0) && (xoff2 >= 0) )
307 delta = fRMax*fRMax - xoff1*xoff1;
308 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
309 delta = fRMax*fRMax - xoff2*xoff2;
310 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
311 maxDiff = (diff1 > diff2) ? diff1 : diff2;
312 newMin = yoffset - maxDiff;
313 newMax = yoffset + maxDiff;
314 pMin = (newMin < yMin) ? yMin : newMin;
315 pMax = (newMax > yMax) ? yMax : newMax;
334 G4int i, noEntries, noBetweenSections4;
335 G4bool existsAfterClip =
false;
341 noEntries = vertices->size();
342 noBetweenSections4 = noEntries - 4;
344 for ( i = 0 ; i < noEntries ; i += 4 )
348 for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
354 existsAfterClip =
true;
372 existsAfterClip =
true;
378 return existsAfterClip;
394 r2 = p.x()*p.x() + p.y()*p.y() ;
397 else { tolRMin = 0 ; }
401 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
419 pPhi = std::atan2(p.y(),p.x()) ;
462 if ( tolRMin < 0 ) { tolRMin = 0; }
464 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
466 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance) )
472 pPhi = std::atan2(p.y(),p.x()) ;
503 r2 = p.x()*p.x() + p.y()*p.y() ;
507 if ( tolRMin < 0 ) { tolRMin = 0; }
509 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
511 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance))
517 pPhi = std::atan2(p.y(),p.x()) ;
556 G4int noSurfaces = 0;
565 rho = std::sqrt(p.x()*p.x() + p.y()*p.y());
567 distRMin = std::fabs(rho -
fRMin);
568 distRMax = std::fabs(rho -
fRMax);
569 distZ = std::fabs(std::fabs(p.z()) -
fDz);
575 pPhi = std::atan2(p.y(),p.x());
580 distSPhi = std::fabs(pPhi -
fSPhi);
619 if ( p.z() >= 0.) { sumnorm += nZ; }
620 else { sumnorm -= nZ; }
622 if ( noSurfaces == 0 )
625 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
628 G4cout<<
"G4Tubs::SN ( "<<p.x()<<
", "<<p.y()<<
", "<<p.z()<<
" ); "
630 G4cout.precision(oldprc) ;
634 else if ( noSurfaces == 1 ) { norm = sumnorm; }
635 else { norm = sumnorm.unit(); }
650 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
652 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
654 distRMin = std::fabs(rho -
fRMin) ;
655 distRMax = std::fabs(rho -
fRMax) ;
656 distZ = std::fabs(std::fabs(p.z()) -
fDz) ;
658 if (distRMin < distRMax)
660 if ( distZ < distRMin )
673 if ( distZ < distRMax )
686 phi = std::atan2(p.y(),p.x()) ;
688 if ( phi < 0 ) { phi += twopi; }
692 distSPhi = std::fabs(phi - (
fSPhi + twopi))*rho ;
696 distSPhi = std::fabs(phi -
fSPhi)*rho ;
698 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
700 if (distSPhi < distEPhi)
702 if ( distSPhi < distMin )
709 if ( distEPhi < distMin )
748 "Undefined side for valid surface normal to solid.");
782 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
787 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
810 if (std::fabs(p.z()) >= tolIDz)
812 if ( p.z()*v.z() < 0 )
814 sd = (std::fabs(p.z()) -
fDz)/std::fabs(v.z()) ;
816 if(sd < 0.0) { sd = 0.0; }
818 xi = p.x() + sd*v.x() ;
819 yi = p.y() + sd*v.y() ;
820 rho2 = xi*xi + yi*yi ;
824 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
831 iden = std::sqrt(rho2) ;
843 if ( snxt<halfCarTolerance ) { snxt=0; }
860 t1 = 1.0 - v.z()*v.z() ;
861 t2 = p.x()*v.x() + p.y()*v.y() ;
862 t3 = p.x()*p.x() + p.y()*p.y() ;
868 if ((t3 >= tolORMax2) && (t2<0))
878 sd = c/(-b+std::sqrt(d));
883 G4double fTerm = sd-std::fmod(sd,dRmax);
888 zi = p.z() + sd*v.z() ;
889 if (std::fabs(zi)<=tolODz)
899 xi = p.x() + sd*v.x() ;
900 yi = p.y() + sd*v.y() ;
913 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.z()) <= tolIDz))
920 iden = std::sqrt(t3) ;
941 snxt = c/(-b+std::sqrt(d));
943 if ( snxt < halfCarTolerance ) { snxt=0; }
961 c = t3 - fRMax*
fRMax;
972 snxt= c/(-b+std::sqrt(d));
974 if ( snxt < halfCarTolerance ) { snxt=0; }
994 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
995 if (sd >= -halfCarTolerance)
999 if(sd < 0.0) { sd = 0.0; }
1002 G4double fTerm = sd-std::fmod(sd,dRmax);
1005 zi = p.z() + sd*v.z() ;
1006 if (std::fabs(zi) <= tolODz)
1016 xi = p.x() + sd*v.x() ;
1017 yi = p.y() + sd*v.y() ;
1052 if ( Dist < halfCarTolerance )
1058 if ( sd < 0 ) { sd = 0.0; }
1059 zi = p.z() + sd*v.z() ;
1060 if ( std::fabs(zi) <= tolODz )
1062 xi = p.x() + sd*v.x() ;
1063 yi = p.y() + sd*v.y() ;
1064 rho2 = xi*xi + yi*yi ;
1066 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1067 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1070 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1092 if ( Dist < halfCarTolerance )
1098 if ( sd < 0 ) { sd = 0; }
1099 zi = p.z() + sd*v.z() ;
1100 if ( std::fabs(zi) <= tolODz )
1102 xi = p.x() + sd*v.x() ;
1103 yi = p.y() + sd*v.y() ;
1104 rho2 = xi*xi + yi*yi ;
1105 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1106 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1109 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1123 if ( snxt<halfCarTolerance ) { snxt=0; }
1155 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1158 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1159 safe1 =
fRMin - rho ;
1160 safe2 = rho -
fRMax ;
1161 safe3 = std::fabs(p.z()) -
fDz ;
1163 if ( safe1 > safe2 ) { safe = safe1; }
1164 else { safe = safe2; }
1165 if ( safe3 > safe ) { safe = safe3; }
1173 if ( cosPsi < std::cos(
fDPhi*0.5) )
1185 if ( safePhi > safe ) { safe = safePhi; }
1188 if ( safe < 0 ) { safe = 0; }
1205 G4double deltaR, t1, t2, t3, b, c,
d2, roMin2 ;
1209 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1215 pdist =
fDz - p.z() ;
1218 snxt = pdist/v.z() ;
1231 else if ( v.z() < 0 )
1233 pdist =
fDz + p.z() ;
1237 snxt = -pdist/v.z() ;
1267 t1 = 1.0 - v.z()*v.z() ;
1268 t2 = p.x()*v.x() + p.y()*v.y() ;
1269 t3 = p.x()*p.x() + p.y()*p.y() ;
1272 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1292 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1311 roMin2 = t3 - t2*t2/t1 ;
1327 srd = c/(-b+std::sqrt(d2));
1332 if ( calcNorm ) { *validNorm =
false; }
1343 srd = -b + std::sqrt(d2) ;
1367 srd = -b + std::sqrt(d2) ;
1390 vphi = std::atan2(v.y(),v.x()) ;
1396 if ( p.x() || p.y() )
1419 sphi = pDistS/compS ;
1423 xi = p.x() + sphi*v.x() ;
1424 yi = p.y() + sphi*v.y() ;
1463 sphi2 = pDistE/compE ;
1469 xi = p.x() + sphi2*v.x() ;
1470 yi = p.y() + sphi2*v.y() ;
1481 else { sphi = 0.0 ; }
1492 else { sphi = 0.0 ; }
1538 xi = p.x() + snxt*v.x() ;
1539 yi = p.y() + snxt*v.y() ;
1545 *validNorm = false ;
1556 *validNorm = false ;
1568 *validNorm = false ;
1585 std::ostringstream message;
1586 G4int oldprc = message.precision(16);
1587 message <<
"Undefined side for valid surface normal to solid."
1589 <<
"Position:" << G4endl << G4endl
1590 <<
"p.x() = " << p.x()/
mm <<
" mm" << G4endl
1591 <<
"p.y() = " << p.y()/
mm <<
" mm" << G4endl
1592 <<
"p.z() = " << p.z()/
mm <<
" mm" << G4endl << G4endl
1593 <<
"Direction:" << G4endl << G4endl
1594 <<
"v.x() = " << v.x() << G4endl
1595 <<
"v.y() = " << v.y() << G4endl
1596 <<
"v.z() = " << v.z() << G4endl << G4endl
1597 <<
"Proposed distance :" << G4endl << G4endl
1598 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1599 message.precision(oldprc) ;
1600 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1616 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1617 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1629 G4cout.precision(oldprc) ;
1630 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1637 safeR1 = rho -
fRMin ;
1638 safeR2 =
fRMax - rho ;
1640 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1641 else { safe = safeR2 ; }
1645 safe =
fRMax - rho ;
1647 safeZ =
fDz - std::fabs(p.z()) ;
1649 if ( safeZ < safe ) { safe = safeZ ; }
1663 if (safePhi < safe) { safe = safePhi ; }
1665 if ( safe < 0 ) { safe = 0 ; }
1686 G4double meshAngle, meshRMax, crossAngle,
1687 cosCrossAngle, sinCrossAngle, sAngle;
1688 G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
1689 G4int crossSection, noCrossSections;
1705 meshAngle =
fDPhi/(noCrossSections - 1) ;
1715 else { sAngle =
fSPhi ; }
1721 vertices->reserve(noCrossSections*4);
1722 for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
1726 crossAngle = sAngle + crossSection*meshAngle ;
1727 cosCrossAngle = std::cos(crossAngle) ;
1728 sinCrossAngle = std::sin(crossAngle) ;
1730 rMaxX = meshRMax*cosCrossAngle ;
1731 rMaxY = meshRMax*sinCrossAngle ;
1740 rMinX = meshRMin*cosCrossAngle ;
1741 rMinY = meshRMin*sinCrossAngle ;
1759 "Error in allocation of vertices. Out of memory !");
1788 G4int oldprc = os.precision(16);
1789 os <<
"-----------------------------------------------------------\n"
1790 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1791 <<
" ===================================================\n"
1792 <<
" Solid type: G4Tubs\n"
1793 <<
" Parameters: \n"
1794 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1795 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1796 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1797 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1798 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1799 <<
"-----------------------------------------------------------\n";
1800 os.precision(oldprc);
1811 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1812 aOne, aTwo, aThr, aFou;
1821 cosphi = std::cos(phi);
1822 sinphi = std::sin(phi);
1826 if( (
fSPhi == 0) && (
fDPhi == twopi) ) { aFou = 0; }
1830 if( (chose >=0) && (chose < aOne) )
1832 xRand = fRMax*cosphi;
1833 yRand = fRMax*sinphi;
1837 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1839 xRand = fRMin*cosphi;
1840 yRand = fRMin*sinphi;
1844 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1846 xRand = rRand*cosphi;
1847 yRand = rRand*sinphi;
1851 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1853 xRand = rRand*cosphi;
1854 yRand = rRand*sinphi;
1858 else if( (chose >= aOne + aTwo + 2.*aThr)
1859 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1861 xRand = rRand*std::cos(
fSPhi);
1862 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)
G4GeometryType GetEntityType() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
static const G4double kInfinity
G4double GetMinYExtent() const
CLHEP::Hep3Vector G4ThreeVector
G4bool IsYLimited() const
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4ThreeVector GetPointOnSurface() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4bool IsXLimited() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
const G4int kMinMeshSections
virtual void AddSolid(const G4Box &)=0
G4double GetMaxXExtent() const
G4OTubs & operator=(const G4OTubs &rhs)
G4double GetMinZExtent() const
G4GLOB_DLL std::ostream G4cout
G4Polyhedron * fpPolyhedron
G4double halfRadTolerance
G4double GetRadialTolerance() const
G4OTubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
virtual G4Polyhedron * GetPolyhedron() const
std::vector< G4ThreeVector > G4ThreeVectorList
G4Polyhedron * CreatePolyhedron() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4double GetMinXExtent() const
G4double GetMaxZExtent() const
G4double halfAngTolerance
G4double halfCarTolerance
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
static const double degree
G4double GetMaxYExtent() const
EInside Inside(const G4ThreeVector &p) const
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pTransform) const
virtual G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4double GetMaxExtent(const EAxis pAxis) const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4bool IsZLimited() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) 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()
std::ostream & StreamInfo(std::ostream &os) const
const G4int kMaxMeshSections