37#if !defined(G4GEOM_USE_UTUBS)
62 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz),
64 fInvRmax( pRMax > 0.0 ? 1.0/pRMax : 0.0 ),
65 fInvRmin( pRMin > 0.0 ? 1.0/pRMin : 0.0 )
76 std::ostringstream message;
77 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
80 if ( (pRMin >= pRMax) || (pRMin < 0) )
82 std::ostringstream message;
83 message <<
"Invalid values for radii in solid: " <<
GetName()
85 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
100 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
101 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
102 sinCPhi(0.), cosCPhi(0.), cosHDPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
103 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
104 fPhiFullTube(false), fInvRmax(0.), fInvRmin(0.),
105 halfCarTolerance(0.), halfRadTolerance(0.),
124 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
125 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
126 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
127 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi), cosHDPhi(rhs.cosHDPhi),
128 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT),
129 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
130 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullTube(rhs.fPhiFullTube),
131 fInvRmax(rhs.fInvRmax), fInvRmin(rhs.fInvRmin),
132 halfCarTolerance(rhs.halfCarTolerance),
133 halfRadTolerance(rhs.halfRadTolerance),
134 halfAngTolerance(rhs.halfAngTolerance)
146 if (
this == &rhs) {
return *
this; }
202 pMin.
set(vmin.
x(),vmin.
y(),-dz);
203 pMax.
set(vmax.
x(),vmax.
y(), dz);
207 pMin.
set(-rmax,-rmax,-dz);
208 pMax.
set( rmax, rmax, dz);
213 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
215 std::ostringstream message;
216 message <<
"Bad bounding box (min >= max) for solid: "
218 <<
"\npMin = " << pMin
219 <<
"\npMax = " << pMax;
220 G4Exception(
"G4Tubs::BoundingLimits()",
"GeomMgt0001",
249 return exist = (pMin < pMax) ?
true :
false;
260 const G4int NSTEPS = 24;
262 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
265 G4double sinHalf = std::sin(0.5*ang);
266 G4double cosHalf = std::cos(0.5*ang);
267 G4double sinStep = 2.*sinHalf*cosHalf;
268 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
273 if (rmin == 0 && dphi == twopi)
279 for (
G4int k=0; k<NSTEPS; ++k)
281 baseA[k].set(rext*cosCur,rext*sinCur,-dz);
282 baseB[k].set(rext*cosCur,rext*sinCur, dz);
285 sinCur = sinCur*cosStep + cosCur*sinStep;
286 cosCur = cosCur*cosStep - sinTmp*sinStep;
288 std::vector<const G4ThreeVectorList *> polygons(2);
289 polygons[0] = &baseA;
290 polygons[1] = &baseB;
300 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
301 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
305 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
306 pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
307 pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
308 pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
309 pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
310 for (
G4int k=1; k<ksteps+1; ++k)
312 pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
313 pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
314 pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
315 pols[k][3].set(rext*cosCur,rext*sinCur, dz);
318 sinCur = sinCur*cosStep + cosCur*sinStep;
319 cosCur = cosCur*cosStep - sinTmp*sinStep;
321 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
322 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
323 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
324 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
327 std::vector<const G4ThreeVectorList *> polygons;
328 polygons.resize(ksteps+2);
329 for (
G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
347 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
350 else { tolRMin = 0 ; }
354 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
372 pPhi = std::atan2(p.
y(),p.
x()) ;
415 if ( tolRMin < 0 ) { tolRMin = 0; }
417 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
425 pPhi = std::atan2(p.
y(),p.
x()) ;
456 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
460 if ( tolRMin < 0 ) { tolRMin = 0; }
462 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
470 pPhi = std::atan2(p.
y(),p.
x()) ;
509 G4int noSurfaces = 0;
512 G4double distSPhi = kInfinity, distEPhi = kInfinity;
518 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
520 distRMin = std::fabs(rho -
fRMin);
521 distRMax = std::fabs(rho -
fRMax);
522 distZ = std::fabs(std::fabs(p.
z()) -
fDz);
528 pPhi = std::atan2(p.
y(),p.
x());
533 distSPhi = std::fabs( pPhi -
fSPhi );
572 if ( p.
z() >= 0.) { sumnorm += nZ; }
573 else { sumnorm -= nZ; }
575 if ( noSurfaces == 0 )
578 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
581 G4cout<<
"G4Tubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
583 G4cout.precision(oldprc) ;
587 else if ( noSurfaces == 1 ) { norm = sumnorm; }
588 else { norm = sumnorm.
unit(); }
603 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
605 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
607 distRMin = std::fabs(rho -
fRMin) ;
608 distRMax = std::fabs(rho -
fRMax) ;
609 distZ = std::fabs(std::fabs(p.
z()) -
fDz) ;
611 if (distRMin < distRMax)
613 if ( distZ < distRMin )
626 if ( distZ < distRMax )
639 phi = std::atan2(p.
y(),p.
x()) ;
641 if ( phi < 0 ) { phi += twopi; }
645 distSPhi = std::fabs(phi - (
fSPhi + twopi))*rho ;
649 distSPhi = std::fabs(phi -
fSPhi)*rho ;
651 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
653 if (distSPhi < distEPhi)
655 if ( distSPhi < distMin )
662 if ( distEPhi < distMin )
701 "Undefined side for valid surface normal to solid.");
735 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
740 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
763 if (std::fabs(p.
z()) >= tolIDz)
765 if ( p.
z()*v.
z() < 0 )
767 sd = (std::fabs(p.
z()) -
fDz)/std::fabs(v.
z()) ;
769 if(sd < 0.0) { sd = 0.0; }
771 xi = p.
x() + sd*v.
x() ;
772 yi = p.
y() + sd*v.
y() ;
773 rho2 = xi*xi + yi*yi ;
777 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
784 iden = std::sqrt(rho2) ;
813 t1 = 1.0 - v.
z()*v.
z() ;
814 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
815 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
821 if ((t3 >= tolORMax2) && (t2<0))
831 sd = c/(-b+std::sqrt(d));
836 G4double fTerm = sd-std::fmod(sd,dRmax);
841 zi = p.
z() + sd*v.
z() ;
842 if (std::fabs(zi)<=tolODz)
852 xi = p.
x() + sd*v.
x() ;
853 yi = p.
y() + sd*v.
y() ;
866 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.
z()) <= tolIDz))
873 iden = std::sqrt(t3) ;
894 snxt = c/(-b+std::sqrt(d));
925 snxt= c/(-b+std::sqrt(d));
947 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
952 if(sd < 0.0) { sd = 0.0; }
955 G4double fTerm = sd-std::fmod(sd,dRmax);
958 zi = p.
z() + sd*v.
z() ;
959 if (std::fabs(zi) <= tolODz)
969 xi = p.
x() + sd*v.
x() ;
970 yi = p.
y() + sd*v.
y() ;
1011 if ( sd < 0 ) { sd = 0.0; }
1012 zi = p.
z() + sd*v.
z() ;
1013 if ( std::fabs(zi) <= tolODz )
1015 xi = p.
x() + sd*v.
x() ;
1016 yi = p.
y() + sd*v.
y() ;
1017 rho2 = xi*xi + yi*yi ;
1019 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1020 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1023 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1051 if ( sd < 0 ) { sd = 0; }
1052 zi = p.
z() + sd*v.
z() ;
1053 if ( std::fabs(zi) <= tolODz )
1055 xi = p.
x() + sd*v.
x() ;
1056 yi = p.
y() + sd*v.
y() ;
1057 rho2 = xi*xi + yi*yi ;
1058 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1059 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1062 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1108 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1111 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1112 safe1 =
fRMin - rho ;
1113 safe2 = rho -
fRMax ;
1114 safe3 = std::fabs(p.
z()) -
fDz ;
1116 if ( safe1 > safe2 ) { safe = safe1; }
1117 else { safe = safe2; }
1118 if ( safe3 > safe ) { safe = safe3; }
1138 if ( safePhi > safe ) { safe = safePhi; }
1141 if ( safe < 0 ) { safe = 0; }
1157 G4double snxt, srd=kInfinity, sphi=kInfinity, pdist ;
1158 G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
1162 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1168 pdist =
fDz - p.
z() ;
1171 snxt = pdist/v.
z() ;
1184 else if ( v.
z() < 0 )
1186 pdist =
fDz + p.
z() ;
1190 snxt = -pdist/v.
z() ;
1220 t1 = 1.0 - v.
z()*v.
z() ;
1221 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1222 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1225 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1245 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1265 roMin2 = t3 - t2*t2/t1 ;
1281 srd = c/(-b+std::sqrt(d2));
1299 srd = -b + std::sqrt(d2) ;
1324 srd = -b + std::sqrt(d2) ;
1348 vphi = std::atan2(v.
y(),v.
x()) ;
1354 if ( p.
x() || p.
y() )
1377 sphi = pDistS/compS ;
1381 xi = p.
x() + sphi*v.
x() ;
1382 yi = p.
y() + sphi*v.
y() ;
1421 sphi2 = pDistE/compE ;
1427 xi = p.
x() + sphi2*v.
x() ;
1428 yi = p.
y() + sphi2*v.
y() ;
1439 else { sphi = 0.0 ; }
1450 else { sphi = 0.0 ; }
1496 xi = p.
x() + snxt*v.
x() ;
1497 yi = p.
y() + snxt*v.
y() ;
1503 *validNorm = false ;
1514 *validNorm = false ;
1526 *validNorm = false ;
1543 std::ostringstream message;
1544 G4int oldprc = message.precision(16);
1545 message <<
"Undefined side for valid surface normal to solid."
1548 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1549 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1552 <<
"v.x() = " << v.
x() <<
G4endl
1553 <<
"v.y() = " << v.
y() <<
G4endl
1556 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
1557 message.precision(oldprc) ;
1558 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1574 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1575 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1587 G4cout.precision(oldprc) ;
1588 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1595 safeR1 = rho -
fRMin ;
1596 safeR2 =
fRMax - rho ;
1598 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1599 else { safe = safeR2 ; }
1603 safe =
fRMax - rho ;
1605 safeZ =
fDz - std::fabs(p.
z()) ;
1607 if ( safeZ < safe ) { safe = safeZ ; }
1621 if (safePhi < safe) { safe = safePhi ; }
1623 if ( safe < 0 ) { safe = 0 ; }
1643 return new G4Tubs(*
this);
1652 G4int oldprc = os.precision(16);
1653 os <<
"-----------------------------------------------------------\n"
1654 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1655 <<
" ===================================================\n"
1656 <<
" Solid type: G4Tubs\n"
1657 <<
" Parameters: \n"
1658 <<
" inner radius : " <<
fRMin/mm <<
" mm \n"
1659 <<
" outer radius : " <<
fRMax/mm <<
" mm \n"
1660 <<
" half length Z: " <<
fDz/mm <<
" mm \n"
1661 <<
" starting phi : " <<
fSPhi/degree <<
" degrees \n"
1662 <<
" delta phi : " <<
fDPhi/degree <<
" degrees \n"
1663 <<
"-----------------------------------------------------------\n";
1664 os.precision(oldprc);
1687 G4double ssurf[6] = { scut, scut, sbase, sbase, hz*lext, hz*lint };
1688 ssurf[1] += ssurf[0];
1689 ssurf[2] += ssurf[1];
1690 ssurf[3] += ssurf[2];
1691 ssurf[4] += ssurf[3];
1692 ssurf[5] += ssurf[4];
1698 k -= (select <= ssurf[4]);
1699 k -= (select <= ssurf[3]);
1700 k -= (select <= ssurf[2]);
1701 k -= (select <= ssurf[1]);
1702 k -= (select <= ssurf[0]);
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
void set(double x, double y, double z)
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
G4GeometryType GetEntityType() const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
virtual G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4Tubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
G4double GetZHalfLength() const
G4Polyhedron * CreatePolyhedron() const
EInside Inside(const G4ThreeVector &p) const
G4ThreeVector GetPointOnSurface() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
std::ostream & StreamInfo(std::ostream &os) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4double GetCosStartPhi() const
G4double GetCosEndPhi() const
G4double GetInnerRadius() const
G4Tubs & operator=(const G4Tubs &rhs)
G4double GetOuterRadius() const
static constexpr G4double kNormTolerance
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double GetSinEndPhi() const
G4double FastInverseRxy(const G4ThreeVector &pos, G4double invRad, G4double normalTolerance) const
G4double halfRadTolerance
G4double halfAngTolerance
G4double halfCarTolerance
G4double GetDeltaPhiAngle() const
G4double GetSinStartPhi() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
virtual void AddSolid(const G4Box &)=0
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const