64 #if !defined(G4GEOM_USE_UTUBS)
79 using namespace CLHEP;
90 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
102 std::ostringstream message;
103 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
106 if ( (pRMin >= pRMax) || (pRMin < 0) )
108 std::ostringstream message;
109 message <<
"Invalid values for radii in solid: " <<
GetName()
111 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
126 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
127 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
128 sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
129 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
130 fPhiFullTube(false), halfCarTolerance(0.), halfRadTolerance(0.),
150 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
151 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
152 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
153 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.sinCPhi),
154 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiOT),
155 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
156 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullTube(rhs.fPhiFullTube),
157 halfCarTolerance(rhs.halfCarTolerance),
158 halfRadTolerance(rhs.halfRadTolerance),
159 halfAngTolerance(rhs.halfAngTolerance)
171 if (
this == &rhs) {
return *
this; }
228 G4double diff1, diff2, maxDiff, newMin, newMax;
229 G4double xoff1, xoff2, yoff1, yoff2, delta;
232 xMin = xoffset -
fRMax;
233 xMax = xoffset +
fRMax;
255 yMin = yoffset -
fRMax;
256 yMax = yoffset +
fRMax;
278 zMin = zoffset -
fDz;
279 zMax = zoffset +
fDz;
304 yoff1 = yoffset - yMin;
305 yoff2 = yMax - yoffset;
307 if ( (yoff1 >= 0) && (yoff2 >= 0) )
317 delta = fRMax*fRMax - yoff1*yoff1;
318 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
319 delta = fRMax*fRMax - yoff2*yoff2;
320 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
321 maxDiff = (diff1 > diff2) ? diff1:diff2;
322 newMin = xoffset - maxDiff;
323 newMax = xoffset + maxDiff;
324 pMin = (newMin < xMin) ? xMin : newMin;
325 pMax = (newMax > xMax) ? xMax : newMax;
331 xoff1 = xoffset - xMin;
332 xoff2 = xMax - xoffset;
334 if ( (xoff1 >= 0) && (xoff2 >= 0) )
344 delta = fRMax*fRMax - xoff1*xoff1;
345 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
346 delta = fRMax*fRMax - xoff2*xoff2;
347 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
348 maxDiff = (diff1 > diff2) ? diff1 : diff2;
349 newMin = yoffset - maxDiff;
350 newMax = yoffset + maxDiff;
351 pMin = (newMin < yMin) ? yMin : newMin;
352 pMax = (newMax > yMax) ? yMax : newMax;
371 G4int i, noEntries, noBetweenSections4;
372 G4bool existsAfterClip =
false;
378 noEntries = vertices->size();
379 noBetweenSections4 = noEntries - 4;
381 for ( i = 0 ; i < noEntries ; i += 4 )
385 for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
391 existsAfterClip =
true;
409 existsAfterClip =
true;
415 return existsAfterClip;
431 r2 = p.x()*p.x() + p.y()*p.y() ;
434 else { tolRMin = 0 ; }
438 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
456 pPhi = std::atan2(p.y(),p.x()) ;
499 if ( tolRMin < 0 ) { tolRMin = 0; }
501 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
503 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance) )
509 pPhi = std::atan2(p.y(),p.x()) ;
540 r2 = p.x()*p.x() + p.y()*p.y() ;
544 if ( tolRMin < 0 ) { tolRMin = 0; }
546 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
548 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance))
554 pPhi = std::atan2(p.y(),p.x()) ;
593 G4int noSurfaces = 0;
602 rho = std::sqrt(p.x()*p.x() + p.y()*p.y());
604 distRMin = std::fabs(rho -
fRMin);
605 distRMax = std::fabs(rho -
fRMax);
606 distZ = std::fabs(std::fabs(p.z()) -
fDz);
612 pPhi = std::atan2(p.y(),p.x());
617 distSPhi = std::fabs(pPhi -
fSPhi);
656 if ( p.z() >= 0.) { sumnorm += nZ; }
657 else { sumnorm -= nZ; }
659 if ( noSurfaces == 0 )
662 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
665 G4cout<<
"G4Tubs::SN ( "<<p.x()<<
", "<<p.y()<<
", "<<p.z()<<
" ); "
667 G4cout.precision(oldprc) ;
671 else if ( noSurfaces == 1 ) { norm = sumnorm; }
672 else { norm = sumnorm.unit(); }
687 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
689 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
691 distRMin = std::fabs(rho -
fRMin) ;
692 distRMax = std::fabs(rho -
fRMax) ;
693 distZ = std::fabs(std::fabs(p.z()) -
fDz) ;
695 if (distRMin < distRMax)
697 if ( distZ < distRMin )
710 if ( distZ < distRMax )
723 phi = std::atan2(p.y(),p.x()) ;
725 if ( phi < 0 ) { phi += twopi; }
729 distSPhi = std::fabs(phi - (
fSPhi + twopi))*rho ;
733 distSPhi = std::fabs(phi -
fSPhi)*rho ;
735 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
737 if (distSPhi < distEPhi)
739 if ( distSPhi < distMin )
746 if ( distEPhi < distMin )
785 "Undefined side for valid surface normal to solid.");
819 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
824 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
847 if (std::fabs(p.z()) >= tolIDz)
849 if ( p.z()*v.z() < 0 )
851 sd = (std::fabs(p.z()) -
fDz)/std::fabs(v.z()) ;
853 if(sd < 0.0) { sd = 0.0; }
855 xi = p.x() + sd*v.x() ;
856 yi = p.y() + sd*v.y() ;
857 rho2 = xi*xi + yi*yi ;
861 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
868 iden = std::sqrt(rho2) ;
880 if ( snxt<halfCarTolerance ) { snxt=0; }
897 t1 = 1.0 - v.z()*v.z() ;
898 t2 = p.x()*v.x() + p.y()*v.y() ;
899 t3 = p.x()*p.x() + p.y()*p.y() ;
905 if ((t3 >= tolORMax2) && (t2<0))
915 sd = c/(-b+std::sqrt(d));
920 G4double fTerm = sd-std::fmod(sd,dRmax);
925 zi = p.z() + sd*v.z() ;
926 if (std::fabs(zi)<=tolODz)
936 xi = p.x() + sd*v.x() ;
937 yi = p.y() + sd*v.y() ;
950 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.z()) <= tolIDz))
957 iden = std::sqrt(t3) ;
978 snxt = c/(-b+std::sqrt(d));
980 if ( snxt < halfCarTolerance ) { snxt=0; }
998 c = t3 - fRMax*
fRMax;
1009 snxt= c/(-b+std::sqrt(d));
1011 if ( snxt < halfCarTolerance ) { snxt=0; }
1031 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1032 if (sd >= -halfCarTolerance)
1036 if(sd < 0.0) { sd = 0.0; }
1039 G4double fTerm = sd-std::fmod(sd,dRmax);
1042 zi = p.z() + sd*v.z() ;
1043 if (std::fabs(zi) <= tolODz)
1053 xi = p.x() + sd*v.x() ;
1054 yi = p.y() + sd*v.y() ;
1089 if ( Dist < halfCarTolerance )
1095 if ( sd < 0 ) { sd = 0.0; }
1096 zi = p.z() + sd*v.z() ;
1097 if ( std::fabs(zi) <= tolODz )
1099 xi = p.x() + sd*v.x() ;
1100 yi = p.y() + sd*v.y() ;
1101 rho2 = xi*xi + yi*yi ;
1103 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1104 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1107 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1129 if ( Dist < halfCarTolerance )
1135 if ( sd < 0 ) { sd = 0; }
1136 zi = p.z() + sd*v.z() ;
1137 if ( std::fabs(zi) <= tolODz )
1139 xi = p.x() + sd*v.x() ;
1140 yi = p.y() + sd*v.y() ;
1141 rho2 = xi*xi + yi*yi ;
1142 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1143 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1146 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1160 if ( snxt<halfCarTolerance ) { snxt=0; }
1192 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1195 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1196 safe1 =
fRMin - rho ;
1197 safe2 = rho -
fRMax ;
1198 safe3 = std::fabs(p.z()) -
fDz ;
1200 if ( safe1 > safe2 ) { safe = safe1; }
1201 else { safe = safe2; }
1202 if ( safe3 > safe ) { safe = safe3; }
1210 if ( cosPsi < std::cos(
fDPhi*0.5) )
1222 if ( safePhi > safe ) { safe = safePhi; }
1225 if ( safe < 0 ) { safe = 0; }
1242 G4double deltaR, t1, t2, t3, b, c,
d2, roMin2 ;
1246 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1252 pdist =
fDz - p.z() ;
1255 snxt = pdist/v.z() ;
1268 else if ( v.z() < 0 )
1270 pdist =
fDz + p.z() ;
1274 snxt = -pdist/v.z() ;
1304 t1 = 1.0 - v.z()*v.z() ;
1305 t2 = p.x()*v.x() + p.y()*v.y() ;
1306 t3 = p.x()*p.x() + p.y()*p.y() ;
1309 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1329 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1348 roMin2 = t3 - t2*t2/t1 ;
1364 srd = c/(-b+std::sqrt(d2));
1369 if ( calcNorm ) { *validNorm =
false; }
1380 srd = -b + std::sqrt(d2) ;
1404 srd = -b + std::sqrt(d2) ;
1427 vphi = std::atan2(v.y(),v.x()) ;
1433 if ( p.x() || p.y() )
1456 sphi = pDistS/compS ;
1460 xi = p.x() + sphi*v.x() ;
1461 yi = p.y() + sphi*v.y() ;
1500 sphi2 = pDistE/compE ;
1506 xi = p.x() + sphi2*v.x() ;
1507 yi = p.y() + sphi2*v.y() ;
1518 else { sphi = 0.0 ; }
1529 else { sphi = 0.0 ; }
1575 xi = p.x() + snxt*v.x() ;
1576 yi = p.y() + snxt*v.y() ;
1582 *validNorm = false ;
1593 *validNorm = false ;
1605 *validNorm = false ;
1622 std::ostringstream message;
1623 G4int oldprc = message.precision(16);
1624 message <<
"Undefined side for valid surface normal to solid."
1626 <<
"Position:" << G4endl << G4endl
1627 <<
"p.x() = " << p.x()/
mm <<
" mm" << G4endl
1628 <<
"p.y() = " << p.y()/
mm <<
" mm" << G4endl
1629 <<
"p.z() = " << p.z()/
mm <<
" mm" << G4endl << G4endl
1630 <<
"Direction:" << G4endl << G4endl
1631 <<
"v.x() = " << v.x() << G4endl
1632 <<
"v.y() = " << v.y() << G4endl
1633 <<
"v.z() = " << v.z() << G4endl << G4endl
1634 <<
"Proposed distance :" << G4endl << G4endl
1635 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1636 message.precision(oldprc) ;
1637 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1653 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1654 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1666 G4cout.precision(oldprc) ;
1667 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1674 safeR1 = rho -
fRMin ;
1675 safeR2 =
fRMax - rho ;
1677 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1678 else { safe = safeR2 ; }
1682 safe =
fRMax - rho ;
1684 safeZ =
fDz - std::fabs(p.z()) ;
1686 if ( safeZ < safe ) { safe = safeZ ; }
1700 if (safePhi < safe) { safe = safePhi ; }
1702 if ( safe < 0 ) { safe = 0 ; }
1723 G4double meshAngle, meshRMax, crossAngle,
1724 cosCrossAngle, sinCrossAngle, sAngle;
1725 G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
1726 G4int crossSection, noCrossSections;
1742 meshAngle =
fDPhi/(noCrossSections - 1) ;
1752 else { sAngle =
fSPhi ; }
1758 vertices->reserve(noCrossSections*4);
1759 for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
1763 crossAngle = sAngle + crossSection*meshAngle ;
1764 cosCrossAngle = std::cos(crossAngle) ;
1765 sinCrossAngle = std::sin(crossAngle) ;
1767 rMaxX = meshRMax*cosCrossAngle ;
1768 rMaxY = meshRMax*sinCrossAngle ;
1777 rMinX = meshRMin*cosCrossAngle ;
1778 rMinY = meshRMin*sinCrossAngle ;
1796 "Error in allocation of vertices. Out of memory !");
1816 return new G4Tubs(*
this);
1825 G4int oldprc = os.precision(16);
1826 os <<
"-----------------------------------------------------------\n"
1827 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1828 <<
" ===================================================\n"
1829 <<
" Solid type: G4Tubs\n"
1830 <<
" Parameters: \n"
1831 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1832 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1833 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1834 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1835 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1836 <<
"-----------------------------------------------------------\n";
1837 os.precision(oldprc);
1848 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1849 aOne, aTwo, aThr, aFou;
1858 cosphi = std::cos(phi);
1859 sinphi = std::sin(phi);
1863 if( (
fSPhi == 0) && (
fDPhi == twopi) ) { aFou = 0; }
1867 if( (chose >=0) && (chose < aOne) )
1869 xRand = fRMax*cosphi;
1870 yRand = fRMax*sinphi;
1874 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1876 xRand = fRMin*cosphi;
1877 yRand = fRMin*sinphi;
1881 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1883 xRand = rRand*cosphi;
1884 yRand = rRand*sinphi;
1888 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1890 xRand = rRand*cosphi;
1891 yRand = rRand*sinphi;
1895 else if( (chose >= aOne + aTwo + 2.*aThr)
1896 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1898 xRand = rRand*std::cos(
fSPhi);
1899 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