37#if !defined(G4GEOM_USE_UTUBS)
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;
124 if (
this == &rhs) {
return *
this; }
180 pMin.
set(vmin.
x(),vmin.
y(),-dz);
181 pMax.
set(vmax.
x(),vmax.
y(), dz);
185 pMin.
set(-rmax,-rmax,-dz);
186 pMax.
set( rmax, rmax, dz);
191 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
193 std::ostringstream message;
194 message <<
"Bad bounding box (min >= max) for solid: "
196 <<
"\npMin = " << pMin
197 <<
"\npMax = " << pMax;
198 G4Exception(
"G4Tubs::BoundingLimits()",
"GeomMgt0001",
227 return exist = pMin < pMax;
238 const G4int NSTEPS = 24;
240 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
243 G4double sinHalf = std::sin(0.5*ang);
244 G4double cosHalf = std::cos(0.5*ang);
245 G4double sinStep = 2.*sinHalf*cosHalf;
246 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
251 if (rmin == 0 && dphi == twopi)
257 for (
G4int k=0; k<NSTEPS; ++k)
259 baseA[k].set(rext*cosCur,rext*sinCur,-dz);
260 baseB[k].set(rext*cosCur,rext*sinCur, dz);
263 sinCur = sinCur*cosStep + cosCur*sinStep;
264 cosCur = cosCur*cosStep - sinTmp*sinStep;
266 std::vector<const G4ThreeVectorList *> polygons(2);
267 polygons[0] = &baseA;
268 polygons[1] = &baseB;
278 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
279 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
283 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
284 pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
285 pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
286 pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
287 pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
288 for (
G4int k=1; k<ksteps+1; ++k)
290 pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
291 pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
292 pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
293 pols[k][3].set(rext*cosCur,rext*sinCur, dz);
296 sinCur = sinCur*cosStep + cosCur*sinStep;
297 cosCur = cosCur*cosStep - sinTmp*sinStep;
299 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
300 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
301 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
302 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
305 std::vector<const G4ThreeVectorList *> polygons;
306 polygons.resize(ksteps+2);
307 for (
G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
325 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
328 else { tolRMin = 0 ; }
332 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
350 pPhi = std::atan2(p.
y(),p.
x()) ;
393 if ( tolRMin < 0 ) { tolRMin = 0; }
395 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
403 pPhi = std::atan2(p.
y(),p.
x()) ;
434 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
438 if ( tolRMin < 0 ) { tolRMin = 0; }
440 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
448 pPhi = std::atan2(p.
y(),p.
x()) ;
487 G4int noSurfaces = 0;
490 G4double distSPhi = kInfinity, distEPhi = kInfinity;
496 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
498 distRMin = std::fabs(rho -
fRMin);
499 distRMax = std::fabs(rho -
fRMax);
500 distZ = std::fabs(std::fabs(p.
z()) -
fDz);
506 pPhi = std::atan2(p.
y(),p.
x());
511 distSPhi = std::fabs( pPhi -
fSPhi );
514 else if (
fRMin == 0.0 )
550 if ( p.
z() >= 0.) { sumnorm += nZ; }
551 else { sumnorm -= nZ; }
553 if ( noSurfaces == 0 )
556 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
559 G4cout<<
"G4Tubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
561 G4cout.precision(oldprc) ;
565 else if ( noSurfaces == 1 ) { norm = sumnorm; }
566 else { norm = sumnorm.
unit(); }
581 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
583 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
585 distRMin = std::fabs(rho -
fRMin) ;
586 distRMax = std::fabs(rho -
fRMax) ;
587 distZ = std::fabs(std::fabs(p.
z()) -
fDz) ;
589 if (distRMin < distRMax)
591 if ( distZ < distRMin )
604 if ( distZ < distRMax )
617 phi = std::atan2(p.
y(),p.
x()) ;
619 if ( phi < 0 ) { phi += twopi; }
623 distSPhi = std::fabs(phi - (
fSPhi + twopi))*rho ;
627 distSPhi = std::fabs(phi -
fSPhi)*rho ;
629 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
631 if (distSPhi < distEPhi)
633 if ( distSPhi < distMin )
640 if ( distEPhi < distMin )
679 "Undefined side for valid surface normal to solid.");
713 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
718 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
741 if (std::fabs(p.
z()) >= tolIDz)
743 if ( p.
z()*v.
z() < 0 )
745 sd = (std::fabs(p.
z()) -
fDz)/std::fabs(v.
z()) ;
747 if(sd < 0.0) { sd = 0.0; }
749 xi = p.
x() + sd*v.
x() ;
750 yi = p.
y() + sd*v.
y() ;
751 rho2 = xi*xi + yi*yi ;
755 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
762 iden = std::sqrt(rho2) ;
791 t1 = 1.0 - v.
z()*v.
z() ;
792 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
793 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
799 if ((t3 >= tolORMax2) && (t2<0))
809 sd = c/(-b+std::sqrt(d));
814 G4double fTerm = sd-std::fmod(sd,dRmax);
819 zi = p.
z() + sd*v.
z() ;
820 if (std::fabs(zi)<=tolODz)
830 xi = p.
x() + sd*v.
x() ;
831 yi = p.
y() + sd*v.
y() ;
844 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.
z()) <= tolIDz))
851 iden = std::sqrt(t3) ;
872 snxt = c/(-b+std::sqrt(d));
903 snxt= c/(-b+std::sqrt(d));
925 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
930 if(sd < 0.0) { sd = 0.0; }
933 G4double fTerm = sd-std::fmod(sd,dRmax);
936 zi = p.
z() + sd*v.
z() ;
937 if (std::fabs(zi) <= tolODz)
947 xi = p.
x() + sd*v.
x() ;
948 yi = p.
y() + sd*v.
y() ;
989 if ( sd < 0 ) { sd = 0.0; }
990 zi = p.
z() + sd*v.
z() ;
991 if ( std::fabs(zi) <= tolODz )
993 xi = p.
x() + sd*v.
x() ;
994 yi = p.
y() + sd*v.
y() ;
995 rho2 = xi*xi + yi*yi ;
997 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
998 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1001 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1029 if ( sd < 0 ) { sd = 0; }
1030 zi = p.
z() + sd*v.
z() ;
1031 if ( std::fabs(zi) <= tolODz )
1033 xi = p.
x() + sd*v.
x() ;
1034 yi = p.
y() + sd*v.
y() ;
1035 rho2 = xi*xi + yi*yi ;
1036 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1037 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1040 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1086 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1089 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1090 safe1 =
fRMin - rho ;
1091 safe2 = rho -
fRMax ;
1092 safe3 = std::fabs(p.
z()) -
fDz ;
1094 if ( safe1 > safe2 ) { safe = safe1; }
1095 else { safe = safe2; }
1096 if ( safe3 > safe ) { safe = safe3; }
1116 if ( safePhi > safe ) { safe = safePhi; }
1119 if ( safe < 0 ) { safe = 0; }
1135 G4double snxt, srd=kInfinity, sphi=kInfinity, pdist ;
1136 G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
1140 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1146 pdist =
fDz - p.
z() ;
1149 snxt = pdist/v.
z() ;
1162 else if ( v.
z() < 0 )
1164 pdist =
fDz + p.
z() ;
1168 snxt = -pdist/v.
z() ;
1198 t1 = 1.0 - v.
z()*v.
z() ;
1199 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1200 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1203 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1223 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1243 roMin2 = t3 - t2*t2/t1 ;
1259 srd = c/(-b+std::sqrt(d2));
1277 srd = -b + std::sqrt(d2) ;
1302 srd = -b + std::sqrt(d2) ;
1326 vphi = std::atan2(v.
y(),v.
x()) ;
1332 if ( (p.
x() != 0.0) || (p.
y() != 0.0) )
1355 sphi = pDistS/compS ;
1359 xi = p.
x() + sphi*v.
x() ;
1360 yi = p.
y() + sphi*v.
y() ;
1399 sphi2 = pDistE/compE ;
1405 xi = p.
x() + sphi2*v.
x() ;
1406 yi = p.
y() + sphi2*v.
y() ;
1417 else { sphi = 0.0 ; }
1428 else { sphi = 0.0 ; }
1474 xi = p.
x() + snxt*v.
x() ;
1475 yi = p.
y() + snxt*v.
y() ;
1481 *validNorm = false ;
1492 *validNorm = false ;
1504 *validNorm = false ;
1521 std::ostringstream message;
1522 G4long oldprc = message.precision(16);
1523 message <<
"Undefined side for valid surface normal to solid."
1526 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1527 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1530 <<
"v.x() = " << v.
x() <<
G4endl
1531 <<
"v.y() = " << v.
y() <<
G4endl
1534 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
1535 message.precision(oldprc) ;
1536 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1552 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1553 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1565 G4cout.precision(oldprc) ;
1566 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1573 safeR1 = rho -
fRMin ;
1574 safeR2 =
fRMax - rho ;
1576 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1577 else { safe = safeR2 ; }
1581 safe =
fRMax - rho ;
1583 safeZ =
fDz - std::fabs(p.
z()) ;
1585 if ( safeZ < safe ) { safe = safeZ ; }
1599 if (safePhi < safe) { safe = safePhi ; }
1601 if ( safe < 0 ) { safe = 0 ; }
1621 return new G4Tubs(*
this);
1630 G4long oldprc = os.precision(16);
1631 os <<
"-----------------------------------------------------------\n"
1632 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1633 <<
" ===================================================\n"
1634 <<
" Solid type: G4Tubs\n"
1635 <<
" Parameters: \n"
1636 <<
" inner radius : " <<
fRMin/mm <<
" mm \n"
1637 <<
" outer radius : " <<
fRMax/mm <<
" mm \n"
1638 <<
" half length Z: " <<
fDz/mm <<
" mm \n"
1639 <<
" starting phi : " <<
fSPhi/degree <<
" degrees \n"
1640 <<
" delta phi : " <<
fDPhi/degree <<
" degrees \n"
1641 <<
"-----------------------------------------------------------\n";
1642 os.precision(oldprc);
1665 G4double ssurf[6] = { scut, scut, sbase, sbase, hz*lext, hz*lint };
1666 ssurf[1] += ssurf[0];
1667 ssurf[2] += ssurf[1];
1668 ssurf[3] += ssurf[2];
1669 ssurf[4] += ssurf[3];
1670 ssurf[5] += ssurf[4];
1676 k -= (
G4int)(select <= ssurf[4]);
1677 k -= (
G4int)(select <= ssurf[3]);
1678 k -= (
G4int)(select <= ssurf[2]);
1679 k -= (
G4int)(select <= ssurf[1]);
1680 k -= (
G4int)(select <= ssurf[0]);
1700 return { r*std::cos(phi), r*std::sin(phi), -
fDz };
1706 return { r*std::cos(phi), r*std::sin(phi),
fDz };
1725 return {0., 0., 0.};
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
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(const G4String &pName)
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() 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
G4ThreeVector GetPointOnSurface() const override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4double GetCosStartPhi() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4double GetCosEndPhi() const
G4double GetInnerRadius() const
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
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4VSolid(const G4String &name)