37#if !defined(G4GEOM_USE_UTUBS)
62enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kPZ,kMZ};
65enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ};
79 fInvRmax( pRMax > 0.0 ? 1.0/pRMax : 0.0 ),
80 fInvRmin( pRMin > 0.0 ? 1.0/pRMin : 0.0 )
91 std::ostringstream message;
92 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
95 if ( (pRMin >= pRMax) || (pRMin < 0) )
97 std::ostringstream message;
98 message <<
"Invalid values for radii in solid: " <<
GetName()
100 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
127 if (
this == &rhs) {
return *
this; }
183 pMin.
set(vmin.
x(),vmin.
y(),-dz);
184 pMax.
set(vmax.
x(),vmax.
y(), dz);
188 pMin.
set(-rmax,-rmax,-dz);
189 pMax.
set( rmax, rmax, dz);
194 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
196 std::ostringstream message;
197 message <<
"Bad bounding box (min >= max) for solid: "
199 <<
"\npMin = " << pMin
200 <<
"\npMax = " << pMax;
201 G4Exception(
"G4Tubs::BoundingLimits()",
"GeomMgt0001",
230 return exist = pMin < pMax;
241 const G4int NSTEPS = 24;
243 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
246 G4double sinHalf = std::sin(0.5*ang);
247 G4double cosHalf = std::cos(0.5*ang);
248 G4double sinStep = 2.*sinHalf*cosHalf;
249 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
254 if (rmin == 0 && dphi == twopi)
260 for (
G4int k=0; k<NSTEPS; ++k)
262 baseA[k].set(rext*cosCur,rext*sinCur,-dz);
263 baseB[k].set(rext*cosCur,rext*sinCur, dz);
266 sinCur = sinCur*cosStep + cosCur*sinStep;
267 cosCur = cosCur*cosStep - sinTmp*sinStep;
269 std::vector<const G4ThreeVectorList *> polygons(2);
270 polygons[0] = &baseA;
271 polygons[1] = &baseB;
281 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
282 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
286 for (
G4int k=0; k<ksteps+2; ++k)
290 pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
291 pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
292 pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
293 pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
294 for (
G4int k=1; k<ksteps+1; ++k)
296 pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
297 pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
298 pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
299 pols[k][3].set(rext*cosCur,rext*sinCur, dz);
302 sinCur = sinCur*cosStep + cosCur*sinStep;
303 cosCur = cosCur*cosStep - sinTmp*sinStep;
305 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
306 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
307 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
308 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
311 std::vector<const G4ThreeVectorList *> polygons;
312 polygons.resize(ksteps+2);
313 for (
G4int k=0; k<ksteps+2; ++k)
315 polygons[k] = &pols[k];
334 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
337 else { tolRMin = 0 ; }
341 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
359 pPhi = std::atan2(p.
y(),p.
x()) ;
402 if ( tolRMin < 0 ) { tolRMin = 0; }
404 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
412 pPhi = std::atan2(p.
y(),p.
x()) ;
443 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
447 if ( tolRMin < 0 ) { tolRMin = 0; }
449 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
457 pPhi = std::atan2(p.
y(),p.
x()) ;
496 G4int noSurfaces = 0;
499 G4double distSPhi = kInfinity, distEPhi = kInfinity;
505 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
507 distRMin = std::fabs(rho -
fRMin);
508 distRMax = std::fabs(rho -
fRMax);
509 distZ = std::fabs(std::fabs(p.
z()) -
fDz);
515 pPhi = std::atan2(p.
y(),p.
x());
520 distSPhi = std::fabs( pPhi -
fSPhi );
523 else if (
fRMin == 0.0 )
559 if ( p.
z() >= 0.) { sumnorm += nZ; }
560 else { sumnorm -= nZ; }
562 if ( noSurfaces == 0 )
565 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
568 G4cout<<
"G4Tubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
570 G4cout.precision(oldprc) ;
574 else if ( noSurfaces == 1 ) { norm = sumnorm; }
575 else { norm = sumnorm.
unit(); }
590 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
592 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
594 distRMin = std::fabs(rho -
fRMin) ;
595 distRMax = std::fabs(rho -
fRMax) ;
596 distZ = std::fabs(std::fabs(p.
z()) -
fDz) ;
598 if (distRMin < distRMax)
600 if ( distZ < distRMin )
613 if ( distZ < distRMax )
626 phi = std::atan2(p.
y(),p.
x()) ;
628 if ( phi < 0 ) { phi += twopi; }
632 distSPhi = std::fabs(phi - (
fSPhi + twopi))*rho ;
636 distSPhi = std::fabs(phi -
fSPhi)*rho ;
638 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
640 if (distSPhi < distEPhi)
642 if ( distSPhi < distMin )
649 if ( distEPhi < distMin )
688 "Undefined side for valid surface normal to solid.");
722 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
727 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
750 if (std::fabs(p.
z()) >= tolIDz)
752 if ( p.
z()*v.
z() < 0 )
754 sd = (std::fabs(p.
z()) -
fDz)/std::fabs(v.
z()) ;
756 if(sd < 0.0) { sd = 0.0; }
758 xi = p.
x() + sd*v.
x() ;
759 yi = p.
y() + sd*v.
y() ;
760 rho2 = xi*xi + yi*yi ;
764 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
771 iden = std::sqrt(rho2) ;
800 t1 = 1.0 - v.
z()*v.
z() ;
801 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
802 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
808 if ((t3 >= tolORMax2) && (t2<0))
818 sd = c/(-b+std::sqrt(d));
823 G4double fTerm = sd-std::fmod(sd,dRmax);
828 zi = p.
z() + sd*v.
z() ;
829 if (std::fabs(zi)<=tolODz)
837 xi = p.
x() + sd*v.
x() ;
838 yi = p.
y() + sd*v.
y() ;
853 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.
z()) <= tolIDz))
860 iden = std::sqrt(t3) ;
880 snxt = c/(-b+std::sqrt(d));
907 snxt= c/(-b+std::sqrt(d));
926 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
931 if(sd < 0.0) { sd = 0.0; }
934 G4double fTerm = sd-std::fmod(sd,dRmax);
937 zi = p.
z() + sd*v.
z() ;
938 if (std::fabs(zi) <= tolODz)
947 xi = p.
x() + sd*v.
x() ;
948 yi = p.
y() + sd*v.
y() ;
988 if ( sd < 0 ) { sd = 0.0; }
989 zi = p.
z() + sd*v.
z() ;
990 if ( std::fabs(zi) <= tolODz )
992 xi = p.
x() + sd*v.
x() ;
993 yi = p.
y() + sd*v.
y() ;
994 rho2 = xi*xi + yi*yi ;
996 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
997 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1000 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1028 if ( sd < 0 ) { sd = 0; }
1029 zi = p.
z() + sd*v.
z() ;
1030 if ( std::fabs(zi) <= tolODz )
1032 xi = p.
x() + sd*v.
x() ;
1033 yi = p.
y() + sd*v.
y() ;
1034 rho2 = xi*xi + yi*yi ;
1035 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1036 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1039 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1085 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1088 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1089 safe1 =
fRMin - rho ;
1090 safe2 = rho -
fRMax ;
1091 safe3 = std::fabs(p.
z()) -
fDz ;
1093 if ( safe1 > safe2 ) { safe = safe1; }
1094 else { safe = safe2; }
1095 if ( safe3 > safe ) { safe = safe3; }
1115 if ( safePhi > safe ) { safe = safePhi; }
1118 if ( safe < 0 ) { safe = 0; }
1133 ESide side=kNull , sider=kNull, sidephi=kNull ;
1134 G4double snxt, srd=kInfinity, sphi=kInfinity, pdist ;
1135 G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
1139 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1145 pdist =
fDz - p.
z() ;
1148 snxt = pdist/v.
z() ;
1161 else if ( v.
z() < 0 )
1163 pdist =
fDz + p.
z() ;
1167 snxt = -pdist/v.
z() ;
1197 t1 = 1.0 - v.
z()*v.
z() ;
1198 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1199 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1202 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1222 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1242 roMin2 = t3 - t2*t2/t1 ;
1258 srd = c/(-b+std::sqrt(d2));
1276 srd = -b + std::sqrt(d2) ;
1301 srd = -b + std::sqrt(d2) ;
1325 vphi = std::atan2(v.
y(),v.
x()) ;
1331 if ( (p.
x() != 0.0) || (p.
y() != 0.0) )
1354 sphi = pDistS/compS ;
1358 xi = p.
x() + sphi*v.
x() ;
1359 yi = p.
y() + sphi*v.
y() ;
1398 sphi2 = pDistE/compE ;
1404 xi = p.
x() + sphi2*v.
x() ;
1405 yi = p.
y() + sphi2*v.
y() ;
1416 else { sphi = 0.0 ; }
1427 else { sphi = 0.0 ; }
1473 xi = p.
x() + snxt*v.
x() ;
1474 yi = p.
y() + snxt*v.
y() ;
1480 *validNorm = false ;
1491 *validNorm = false ;
1503 *validNorm = false ;
1520 std::ostringstream message;
1521 G4long oldprc = message.precision(16);
1522 message <<
"Undefined side for valid surface normal to solid."
1525 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1526 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1529 <<
"v.x() = " << v.
x() <<
G4endl
1530 <<
"v.y() = " << v.
y() <<
G4endl
1533 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
1534 message.precision(oldprc) ;
1535 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1551 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1552 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1564 G4cout.precision(oldprc) ;
1565 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1572 safeR1 = rho -
fRMin ;
1573 safeR2 =
fRMax - rho ;
1575 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1576 else { safe = safeR2 ; }
1580 safe =
fRMax - rho ;
1582 safeZ =
fDz - std::fabs(p.
z()) ;
1584 if ( safeZ < safe ) { safe = safeZ ; }
1598 if (safePhi < safe) { safe = safePhi ; }
1600 if ( safe < 0 ) { safe = 0 ; }
1620 return new G4Tubs(*
this);
1629 G4long oldprc = os.precision(16);
1630 os <<
"-----------------------------------------------------------\n"
1631 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1632 <<
" ===================================================\n"
1633 <<
" Solid type: G4Tubs\n"
1634 <<
" Parameters: \n"
1635 <<
" inner radius : " <<
fRMin/mm <<
" mm \n"
1636 <<
" outer radius : " <<
fRMax/mm <<
" mm \n"
1637 <<
" half length Z: " <<
fDz/mm <<
" mm \n"
1638 <<
" starting phi : " <<
fSPhi/degree <<
" degrees \n"
1639 <<
" delta phi : " <<
fDPhi/degree <<
" degrees \n"
1640 <<
"-----------------------------------------------------------\n";
1641 os.precision(oldprc);
1664 G4double ssurf[6] = { scut, scut, sbase, sbase, hz*lext, hz*lint };
1665 ssurf[1] += ssurf[0];
1666 ssurf[2] += ssurf[1];
1667 ssurf[3] += ssurf[2];
1668 ssurf[4] += ssurf[3];
1669 ssurf[5] += ssurf[4];
1675 k -= (
G4int)(select <= ssurf[4]);
1676 k -= (
G4int)(select <= ssurf[3]);
1677 k -= (
G4int)(select <= ssurf[2]);
1678 k -= (
G4int)(select <= ssurf[1]);
1679 k -= (
G4int)(select <= ssurf[0]);
1699 return { r*std::cos(phi), r*std::sin(phi), -
fDz };
1705 return { r*std::cos(phi), r*std::sin(phi),
fDz };
1724 return {0., 0., 0.};
G4TemplateAutoLock< G4Mutex > G4AutoLock
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
G4GLOB_DLL std::ostream G4cout
void set(double x, double y, double z)
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
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(const G4String &pName)
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4Tubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
G4double GetZHalfLength() const
G4ThreeVector GetPointOnSurface() const override
G4double GetSurfaceArea() override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4double GetCosStartPhi() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4double GetCosEndPhi() const
G4double GetInnerRadius() const
G4double GetCubicVolume() override
G4Tubs & operator=(const G4Tubs &rhs)
G4double GetOuterRadius() const
static constexpr G4double kNormTolerance
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
EInside Inside(const G4ThreeVector &p) const override
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4Polyhedron * CreatePolyhedron() const override
G4double GetSinEndPhi() const
std::ostream & StreamInfo(std::ostream &os) const override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4double FastInverseRxy(const G4ThreeVector &pos, G4double invRad, G4double normalTolerance) const
G4GeometryType GetEntityType() const override
G4double halfRadTolerance
G4double halfAngTolerance
G4double halfCarTolerance
G4double GetDeltaPhiAngle() const
G4double GetSinStartPhi() const
G4VSolid * Clone() const override
virtual void AddSolid(const G4Box &)=0
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4VSolid(const G4String &name)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...