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)
144 if (
this == &rhs) {
return *
this; }
189 G4double diff1, diff2, maxDiff, newMin, newMax;
190 G4double xoff1, xoff2, yoff1, yoff2, delta;
193 xMin = xoffset -
fRMax;
194 xMax = xoffset +
fRMax;
216 yMin = yoffset -
fRMax;
217 yMax = yoffset +
fRMax;
239 zMin = zoffset -
fDz;
240 zMax = zoffset +
fDz;
265 yoff1 = yoffset - yMin;
266 yoff2 = yMax - yoffset;
268 if ( (yoff1 >= 0) && (yoff2 >= 0) )
278 delta = fRMax*fRMax - yoff1*yoff1;
279 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
280 delta = fRMax*fRMax - yoff2*yoff2;
281 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
282 maxDiff = (diff1 > diff2) ? diff1:diff2;
283 newMin = xoffset - maxDiff;
284 newMax = xoffset + maxDiff;
285 pMin = (newMin < xMin) ? xMin : newMin;
286 pMax = (newMax > xMax) ? xMax : newMax;
292 xoff1 = xoffset - xMin;
293 xoff2 = xMax - xoffset;
295 if ( (xoff1 >= 0) && (xoff2 >= 0) )
305 delta = fRMax*fRMax - xoff1*xoff1;
306 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
307 delta = fRMax*fRMax - xoff2*xoff2;
308 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
309 maxDiff = (diff1 > diff2) ? diff1 : diff2;
310 newMin = yoffset - maxDiff;
311 newMax = yoffset + maxDiff;
312 pMin = (newMin < yMin) ? yMin : newMin;
313 pMax = (newMax > yMax) ? yMax : newMax;
332 G4int i, noEntries, noBetweenSections4;
333 G4bool existsAfterClip =
false;
339 noEntries = vertices->size();
340 noBetweenSections4 = noEntries - 4;
342 for ( i = 0 ; i < noEntries ; i += 4 )
346 for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
352 existsAfterClip =
true;
370 existsAfterClip =
true;
376 return existsAfterClip;
392 r2 = p.x()*p.x() + p.y()*p.y() ;
395 else { tolRMin = 0 ; }
399 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
417 pPhi = std::atan2(p.y(),p.x()) ;
460 if ( tolRMin < 0 ) { tolRMin = 0; }
462 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
464 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance) )
470 pPhi = std::atan2(p.y(),p.x()) ;
501 r2 = p.x()*p.x() + p.y()*p.y() ;
505 if ( tolRMin < 0 ) { tolRMin = 0; }
507 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
509 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance))
515 pPhi = std::atan2(p.y(),p.x()) ;
554 G4int noSurfaces = 0;
563 rho = std::sqrt(p.x()*p.x() + p.y()*p.y());
565 distRMin = std::fabs(rho -
fRMin);
566 distRMax = std::fabs(rho -
fRMax);
567 distZ = std::fabs(std::fabs(p.z()) -
fDz);
573 pPhi = std::atan2(p.y(),p.x());
578 distSPhi = std::fabs(pPhi -
fSPhi);
617 if ( p.z() >= 0.) { sumnorm += nZ; }
618 else { sumnorm -= nZ; }
620 if ( noSurfaces == 0 )
623 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
626 G4cout<<
"G4Tubs::SN ( "<<p.x()<<
", "<<p.y()<<
", "<<p.z()<<
" ); "
628 G4cout.precision(oldprc) ;
632 else if ( noSurfaces == 1 ) { norm = sumnorm; }
633 else { norm = sumnorm.unit(); }
648 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
650 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
652 distRMin = std::fabs(rho -
fRMin) ;
653 distRMax = std::fabs(rho -
fRMax) ;
654 distZ = std::fabs(std::fabs(p.z()) -
fDz) ;
656 if (distRMin < distRMax)
658 if ( distZ < distRMin )
671 if ( distZ < distRMax )
684 phi = std::atan2(p.y(),p.x()) ;
686 if ( phi < 0 ) { phi += twopi; }
690 distSPhi = std::fabs(phi - (
fSPhi + twopi))*rho ;
694 distSPhi = std::fabs(phi -
fSPhi)*rho ;
696 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
698 if (distSPhi < distEPhi)
700 if ( distSPhi < distMin )
707 if ( distEPhi < distMin )
746 "Undefined side for valid surface normal to solid.");
780 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
785 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
808 if (std::fabs(p.z()) >= tolIDz)
810 if ( p.z()*v.z() < 0 )
812 sd = (std::fabs(p.z()) -
fDz)/std::fabs(v.z()) ;
814 if(sd < 0.0) { sd = 0.0; }
816 xi = p.x() + sd*v.x() ;
817 yi = p.y() + sd*v.y() ;
818 rho2 = xi*xi + yi*yi ;
822 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
829 iden = std::sqrt(rho2) ;
841 if ( snxt<halfCarTolerance ) { snxt=0; }
858 t1 = 1.0 - v.z()*v.z() ;
859 t2 = p.x()*v.x() + p.y()*v.y() ;
860 t3 = p.x()*p.x() + p.y()*p.y() ;
866 if ((t3 >= tolORMax2) && (t2<0))
876 sd = c/(-b+std::sqrt(d));
881 G4double fTerm = sd-std::fmod(sd,dRmax);
886 zi = p.z() + sd*v.z() ;
887 if (std::fabs(zi)<=tolODz)
897 xi = p.x() + sd*v.x() ;
898 yi = p.y() + sd*v.y() ;
911 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.z()) <= tolIDz))
918 iden = std::sqrt(t3) ;
939 snxt = c/(-b+std::sqrt(d));
941 if ( snxt < halfCarTolerance ) { snxt=0; }
959 c = t3 - fRMax*
fRMax;
970 snxt= c/(-b+std::sqrt(d));
972 if ( snxt < halfCarTolerance ) { snxt=0; }
992 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
993 if (sd >= -halfCarTolerance)
997 if(sd < 0.0) { sd = 0.0; }
1000 G4double fTerm = sd-std::fmod(sd,dRmax);
1003 zi = p.z() + sd*v.z() ;
1004 if (std::fabs(zi) <= tolODz)
1014 xi = p.x() + sd*v.x() ;
1015 yi = p.y() + sd*v.y() ;
1050 if ( Dist < halfCarTolerance )
1056 if ( sd < 0 ) { sd = 0.0; }
1057 zi = p.z() + sd*v.z() ;
1058 if ( std::fabs(zi) <= tolODz )
1060 xi = p.x() + sd*v.x() ;
1061 yi = p.y() + sd*v.y() ;
1062 rho2 = xi*xi + yi*yi ;
1064 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1065 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1068 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1090 if ( Dist < halfCarTolerance )
1096 if ( sd < 0 ) { sd = 0; }
1097 zi = p.z() + sd*v.z() ;
1098 if ( std::fabs(zi) <= tolODz )
1100 xi = p.x() + sd*v.x() ;
1101 yi = p.y() + sd*v.y() ;
1102 rho2 = xi*xi + yi*yi ;
1103 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1104 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1107 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1121 if ( snxt<halfCarTolerance ) { snxt=0; }
1153 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1156 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1157 safe1 =
fRMin - rho ;
1158 safe2 = rho -
fRMax ;
1159 safe3 = std::fabs(p.z()) -
fDz ;
1161 if ( safe1 > safe2 ) { safe = safe1; }
1162 else { safe = safe2; }
1163 if ( safe3 > safe ) { safe = safe3; }
1171 if ( cosPsi < std::cos(
fDPhi*0.5) )
1183 if ( safePhi > safe ) { safe = safePhi; }
1186 if ( safe < 0 ) { safe = 0; }
1203 G4double deltaR, t1, t2, t3, b, c,
d2, roMin2 ;
1207 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1213 pdist =
fDz - p.z() ;
1216 snxt = pdist/v.z() ;
1229 else if ( v.z() < 0 )
1231 pdist =
fDz + p.z() ;
1235 snxt = -pdist/v.z() ;
1265 t1 = 1.0 - v.z()*v.z() ;
1266 t2 = p.x()*v.x() + p.y()*v.y() ;
1267 t3 = p.x()*p.x() + p.y()*p.y() ;
1270 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1290 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1309 roMin2 = t3 - t2*t2/t1 ;
1325 srd = c/(-b+std::sqrt(d2));
1330 if ( calcNorm ) { *validNorm =
false; }
1341 srd = -b + std::sqrt(d2) ;
1365 srd = -b + std::sqrt(d2) ;
1388 vphi = std::atan2(v.y(),v.x()) ;
1394 if ( p.x() || p.y() )
1417 sphi = pDistS/compS ;
1421 xi = p.x() + sphi*v.x() ;
1422 yi = p.y() + sphi*v.y() ;
1461 sphi2 = pDistE/compE ;
1467 xi = p.x() + sphi2*v.x() ;
1468 yi = p.y() + sphi2*v.y() ;
1479 else { sphi = 0.0 ; }
1490 else { sphi = 0.0 ; }
1536 xi = p.x() + snxt*v.x() ;
1537 yi = p.y() + snxt*v.y() ;
1543 *validNorm = false ;
1554 *validNorm = false ;
1566 *validNorm = false ;
1583 std::ostringstream message;
1584 G4int oldprc = message.precision(16);
1585 message <<
"Undefined side for valid surface normal to solid."
1587 <<
"Position:" << G4endl << G4endl
1588 <<
"p.x() = " << p.x()/
mm <<
" mm" << G4endl
1589 <<
"p.y() = " << p.y()/
mm <<
" mm" << G4endl
1590 <<
"p.z() = " << p.z()/
mm <<
" mm" << G4endl << G4endl
1591 <<
"Direction:" << G4endl << G4endl
1592 <<
"v.x() = " << v.x() << G4endl
1593 <<
"v.y() = " << v.y() << G4endl
1594 <<
"v.z() = " << v.z() << G4endl << G4endl
1595 <<
"Proposed distance :" << G4endl << G4endl
1596 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1597 message.precision(oldprc) ;
1598 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1614 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1615 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1627 G4cout.precision(oldprc) ;
1628 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1635 safeR1 = rho -
fRMin ;
1636 safeR2 =
fRMax - rho ;
1638 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1639 else { safe = safeR2 ; }
1643 safe =
fRMax - rho ;
1645 safeZ =
fDz - std::fabs(p.z()) ;
1647 if ( safeZ < safe ) { safe = safeZ ; }
1661 if (safePhi < safe) { safe = safePhi ; }
1663 if ( safe < 0 ) { safe = 0 ; }
1684 G4double meshAngle, meshRMax, crossAngle,
1685 cosCrossAngle, sinCrossAngle, sAngle;
1686 G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
1687 G4int crossSection, noCrossSections;
1703 meshAngle =
fDPhi/(noCrossSections - 1) ;
1713 else { sAngle =
fSPhi ; }
1719 vertices->reserve(noCrossSections*4);
1720 for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
1724 crossAngle = sAngle + crossSection*meshAngle ;
1725 cosCrossAngle = std::cos(crossAngle) ;
1726 sinCrossAngle = std::sin(crossAngle) ;
1728 rMaxX = meshRMax*cosCrossAngle ;
1729 rMaxY = meshRMax*sinCrossAngle ;
1738 rMinX = meshRMin*cosCrossAngle ;
1739 rMinY = meshRMin*sinCrossAngle ;
1757 "Error in allocation of vertices. Out of memory !");
1786 G4int oldprc = os.precision(16);
1787 os <<
"-----------------------------------------------------------\n"
1788 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1789 <<
" ===================================================\n"
1790 <<
" Solid type: G4Tubs\n"
1791 <<
" Parameters: \n"
1792 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1793 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1794 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1795 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1796 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1797 <<
"-----------------------------------------------------------\n";
1798 os.precision(oldprc);
1809 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1810 aOne, aTwo, aThr, aFou;
1819 cosphi = std::cos(phi);
1820 sinphi = std::sin(phi);
1824 if( (
fSPhi == 0) && (
fDPhi == twopi) ) { aFou = 0; }
1828 if( (chose >=0) && (chose < aOne) )
1830 xRand = fRMax*cosphi;
1831 yRand = fRMax*sinphi;
1835 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1837 xRand = fRMin*cosphi;
1838 yRand = fRMin*sinphi;
1842 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1844 xRand = rRand*cosphi;
1845 yRand = rRand*sinphi;
1849 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1851 xRand = rRand*cosphi;
1852 yRand = rRand*sinphi;
1856 else if( (chose >= aOne + aTwo + 2.*aThr)
1857 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1859 xRand = rRand*std::cos(
fSPhi);
1860 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
G4double halfRadTolerance
G4double GetRadialTolerance() const
G4OTubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
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