66 #if !defined(G4GEOM_USE_UTUBS)
82 using namespace CLHEP;
93 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
105 std::ostringstream message;
106 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
109 if ( (pRMin >= pRMax) || (pRMin < 0) )
111 std::ostringstream message;
112 message <<
"Invalid values for radii in solid: " <<
GetName()
114 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
129 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
130 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
131 sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
132 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
133 fPhiFullTube(false), halfCarTolerance(0.), halfRadTolerance(0.),
152 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
153 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
154 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
155 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi),
156 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT),
157 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
158 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullTube(rhs.fPhiFullTube),
159 halfCarTolerance(rhs.halfCarTolerance),
160 halfRadTolerance(rhs.halfRadTolerance),
161 halfAngTolerance(rhs.halfAngTolerance)
173 if (
this == &rhs) {
return *
this; }
227 pMin.set(vmin.x(),vmin.y(),-dz);
228 pMax.set(vmax.x(),vmax.y(), dz);
232 pMin.set(-rmax,-rmax,-dz);
233 pMax.set( rmax, rmax, dz);
238 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
240 std::ostringstream message;
241 message <<
"Bad bounding box (min >= max) for solid: "
243 <<
"\npMin = " << pMin
244 <<
"\npMax = " << pMax;
269 if (
true)
return bbox.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
273 return exist = (pMin < pMax) ?
true :
false;
284 const G4int NSTEPS = 24;
286 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-
deg)/astep) + 1;
289 G4double sinHalf = std::sin(0.5*ang);
290 G4double cosHalf = std::cos(0.5*ang);
291 G4double sinStep = 2.*sinHalf*cosHalf;
292 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
297 if (rmin == 0 && dphi ==
twopi)
303 for (
G4int k=0; k<NSTEPS; ++k)
305 baseA[k].set(rext*cosCur,rext*sinCur,-dz);
306 baseB[k].set(rext*cosCur,rext*sinCur, dz);
309 sinCur = sinCur*cosStep + cosCur*sinStep;
310 cosCur = cosCur*cosStep - sinTmp*sinStep;
312 std::vector<const G4ThreeVectorList *> polygons(2);
313 polygons[0] = &baseA;
314 polygons[1] = &baseB;
324 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
325 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
329 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
330 pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
331 pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
332 pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
333 pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
334 for (
G4int k=1; k<ksteps+1; ++k)
336 pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
337 pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
338 pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
339 pols[k][3].set(rext*cosCur,rext*sinCur, dz);
342 sinCur = sinCur*cosStep + cosCur*sinStep;
343 cosCur = cosCur*cosStep - sinTmp*sinStep;
345 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
346 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
347 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
348 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
351 std::vector<const G4ThreeVectorList *> polygons;
352 polygons.resize(ksteps+2);
353 for (
G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
371 r2 = p.x()*p.x() + p.y()*p.y() ;
374 else { tolRMin = 0 ; }
378 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
396 pPhi = std::atan2(p.y(),p.x()) ;
439 if ( tolRMin < 0 ) { tolRMin = 0; }
441 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
443 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance) )
449 pPhi = std::atan2(p.y(),p.x()) ;
480 r2 = p.x()*p.x() + p.y()*p.y() ;
484 if ( tolRMin < 0 ) { tolRMin = 0; }
486 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
488 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance))
494 pPhi = std::atan2(p.y(),p.x()) ;
533 G4int noSurfaces = 0;
542 rho = std::sqrt(p.x()*p.x() + p.y()*p.y());
544 distRMin = std::fabs(rho -
fRMin);
545 distRMax = std::fabs(rho -
fRMax);
546 distZ = std::fabs(std::fabs(p.z()) -
fDz);
552 pPhi = std::atan2(p.y(),p.x());
557 distSPhi = std::fabs(pPhi -
fSPhi);
596 if ( p.z() >= 0.) { sumnorm += nZ; }
597 else { sumnorm -= nZ; }
599 if ( noSurfaces == 0 )
602 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
605 G4cout<<
"G4Tubs::SN ( "<<p.x()<<
", "<<p.y()<<
", "<<p.z()<<
" ); "
607 G4cout.precision(oldprc) ;
611 else if ( noSurfaces == 1 ) { norm = sumnorm; }
612 else { norm = sumnorm.unit(); }
627 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
629 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
631 distRMin = std::fabs(rho -
fRMin) ;
632 distRMax = std::fabs(rho -
fRMax) ;
633 distZ = std::fabs(std::fabs(p.z()) -
fDz) ;
635 if (distRMin < distRMax)
637 if ( distZ < distRMin )
650 if ( distZ < distRMax )
663 phi = std::atan2(p.y(),p.x()) ;
665 if ( phi < 0 ) { phi +=
twopi; }
669 distSPhi = std::fabs(phi - (
fSPhi +
twopi))*rho ;
673 distSPhi = std::fabs(phi -
fSPhi)*rho ;
675 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
677 if (distSPhi < distEPhi)
679 if ( distSPhi < distMin )
686 if ( distEPhi < distMin )
725 "Undefined side for valid surface normal to solid.");
759 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
764 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
787 if (std::fabs(p.z()) >= tolIDz)
789 if ( p.z()*v.z() < 0 )
791 sd = (std::fabs(p.z()) -
fDz)/std::fabs(v.z()) ;
793 if(sd < 0.0) { sd = 0.0; }
795 xi = p.x() + sd*v.x() ;
796 yi = p.y() + sd*v.y() ;
797 rho2 = xi*xi + yi*yi ;
801 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
808 iden = std::sqrt(rho2) ;
820 if ( snxt<halfCarTolerance ) { snxt=0; }
837 t1 = 1.0 - v.z()*v.z() ;
838 t2 = p.x()*v.x() + p.y()*v.y() ;
839 t3 = p.x()*p.x() + p.y()*p.y() ;
845 if ((t3 >= tolORMax2) && (t2<0))
855 sd = c/(-b+std::sqrt(d));
860 G4double fTerm = sd-std::fmod(sd,dRmax);
865 zi = p.z() + sd*v.z() ;
866 if (std::fabs(zi)<=tolODz)
876 xi = p.x() + sd*v.x() ;
877 yi = p.y() + sd*v.y() ;
890 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.z()) <= tolIDz))
897 iden = std::sqrt(t3) ;
918 snxt = c/(-b+std::sqrt(d));
920 if ( snxt < halfCarTolerance ) { snxt=0; }
938 c = t3 - fRMax*
fRMax;
949 snxt= c/(-b+std::sqrt(d));
951 if ( snxt < halfCarTolerance ) { snxt=0; }
971 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
972 if (sd >= -halfCarTolerance)
976 if(sd < 0.0) { sd = 0.0; }
979 G4double fTerm = sd-std::fmod(sd,dRmax);
982 zi = p.z() + sd*v.z() ;
983 if (std::fabs(zi) <= tolODz)
993 xi = p.x() + sd*v.x() ;
994 yi = p.y() + sd*v.y() ;
1029 if ( Dist < halfCarTolerance )
1035 if ( sd < 0 ) { sd = 0.0; }
1036 zi = p.z() + sd*v.z() ;
1037 if ( std::fabs(zi) <= tolODz )
1039 xi = p.x() + sd*v.x() ;
1040 yi = p.y() + sd*v.y() ;
1041 rho2 = xi*xi + yi*yi ;
1043 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1044 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1047 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1069 if ( Dist < halfCarTolerance )
1075 if ( sd < 0 ) { sd = 0; }
1076 zi = p.z() + sd*v.z() ;
1077 if ( std::fabs(zi) <= tolODz )
1079 xi = p.x() + sd*v.x() ;
1080 yi = p.y() + sd*v.y() ;
1081 rho2 = xi*xi + yi*yi ;
1082 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1083 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1086 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1100 if ( snxt<halfCarTolerance ) { snxt=0; }
1132 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1135 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1136 safe1 =
fRMin - rho ;
1137 safe2 = rho -
fRMax ;
1138 safe3 = std::fabs(p.z()) -
fDz ;
1140 if ( safe1 > safe2 ) { safe = safe1; }
1141 else { safe = safe2; }
1142 if ( safe3 > safe ) { safe = safe3; }
1150 if ( cosPsi < std::cos(
fDPhi*0.5) )
1162 if ( safePhi > safe ) { safe = safePhi; }
1165 if ( safe < 0 ) { safe = 0; }
1182 G4double deltaR, t1, t2, t3, b, c,
d2, roMin2 ;
1186 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1192 pdist =
fDz - p.z() ;
1195 snxt = pdist/v.z() ;
1208 else if ( v.z() < 0 )
1210 pdist =
fDz + p.z() ;
1214 snxt = -pdist/v.z() ;
1244 t1 = 1.0 - v.z()*v.z() ;
1245 t2 = p.x()*v.x() + p.y()*v.y() ;
1246 t3 = p.x()*p.x() + p.y()*p.y() ;
1249 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1269 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1288 roMin2 = t3 - t2*t2/t1 ;
1304 srd = c/(-b+std::sqrt(d2));
1309 if ( calcNorm ) { *validNorm =
false; }
1320 srd = -b + std::sqrt(d2) ;
1344 srd = -b + std::sqrt(d2) ;
1367 vphi = std::atan2(v.y(),v.x()) ;
1373 if ( p.x() || p.y() )
1396 sphi = pDistS/compS ;
1400 xi = p.x() + sphi*v.x() ;
1401 yi = p.y() + sphi*v.y() ;
1440 sphi2 = pDistE/compE ;
1446 xi = p.x() + sphi2*v.x() ;
1447 yi = p.y() + sphi2*v.y() ;
1458 else { sphi = 0.0 ; }
1469 else { sphi = 0.0 ; }
1515 xi = p.x() + snxt*v.x() ;
1516 yi = p.y() + snxt*v.y() ;
1522 *validNorm = false ;
1533 *validNorm = false ;
1545 *validNorm = false ;
1562 std::ostringstream message;
1563 G4int oldprc = message.precision(16);
1564 message <<
"Undefined side for valid surface normal to solid."
1566 <<
"Position:" << G4endl << G4endl
1567 <<
"p.x() = " << p.x()/
mm <<
" mm" << G4endl
1568 <<
"p.y() = " << p.y()/
mm <<
" mm" << G4endl
1569 <<
"p.z() = " << p.z()/
mm <<
" mm" << G4endl << G4endl
1570 <<
"Direction:" << G4endl << G4endl
1571 <<
"v.x() = " << v.x() << G4endl
1572 <<
"v.y() = " << v.y() << G4endl
1573 <<
"v.z() = " << v.z() << G4endl << G4endl
1574 <<
"Proposed distance :" << G4endl << G4endl
1575 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1576 message.precision(oldprc) ;
1577 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1593 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1594 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1606 G4cout.precision(oldprc) ;
1607 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1614 safeR1 = rho -
fRMin ;
1615 safeR2 =
fRMax - rho ;
1617 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1618 else { safe = safeR2 ; }
1622 safe =
fRMax - rho ;
1624 safeZ =
fDz - std::fabs(p.z()) ;
1626 if ( safeZ < safe ) { safe = safeZ ; }
1640 if (safePhi < safe) { safe = safePhi ; }
1642 if ( safe < 0 ) { safe = 0 ; }
1662 return new G4Tubs(*
this);
1671 G4int oldprc = os.precision(16);
1672 os <<
"-----------------------------------------------------------\n"
1673 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1674 <<
" ===================================================\n"
1675 <<
" Solid type: G4Tubs\n"
1676 <<
" Parameters: \n"
1677 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1678 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1679 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1680 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1681 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1682 <<
"-----------------------------------------------------------\n";
1683 os.precision(oldprc);
1694 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1695 aOne, aTwo, aThr, aFou;
1704 cosphi = std::cos(phi);
1705 sinphi = std::sin(phi);
1713 if( (chose >=0) && (chose < aOne) )
1715 xRand = fRMax*cosphi;
1716 yRand = fRMax*sinphi;
1720 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1722 xRand = fRMin*cosphi;
1723 yRand = fRMin*sinphi;
1727 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1729 xRand = rRand*cosphi;
1730 yRand = rRand*sinphi;
1734 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1736 xRand = rRand*cosphi;
1737 yRand = rRand*sinphi;
1741 else if( (chose >= aOne + aTwo + 2.*aThr)
1742 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1744 xRand = rRand*std::cos(
fSPhi);
1745 yRand = rRand*std::sin(
fSPhi);
ThreeVector shoot(const G4int Ap, const G4int Af)
static constexpr double mm
static const G4double kInfinity
CLHEP::Hep3Vector G4ThreeVector
G4double halfCarTolerance
std::vector< ExP01TrackerHit * > a
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4Tubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
void Extent(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double GetCosEndPhi() const
G4ThreeVector GetPointOnSurface() const
virtual void AddSolid(const G4Box &)=0
virtual G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
static constexpr double twopi
std::ostream & StreamInfo(std::ostream &os) const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4GeometryType GetEntityType() const
G4GLOB_DLL std::ostream G4cout
G4double GetDeltaPhiAngle() const
static constexpr double degree
G4double GetSinEndPhi() const
G4Polyhedron * CreatePolyhedron() const
G4double GetRadialTolerance() const
G4double GetSinStartPhi() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4double GetInnerRadius() 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
EInside Inside(const G4ThreeVector &p) const
G4double halfRadTolerance
G4double GetZHalfLength() const
CLHEP::Hep2Vector G4TwoVector
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
static constexpr double pi
static constexpr double deg
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4double GetAngularTolerance() const
G4double GetCosStartPhi() const
static G4GeometryTolerance * GetInstance()
G4double GetOuterRadius() const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4Tubs & operator=(const G4Tubs &rhs)