52 using namespace CLHEP;
63 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
75 std::ostringstream message;
76 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
79 if ( (pRMin >= pRMax) || (pRMin < 0) )
81 std::ostringstream message;
82 message <<
"Invalid values for radii in solid: " <<
GetName()
84 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
99 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
100 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
101 sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
102 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
103 fPhiFullTube(false), halfCarTolerance(0.), halfRadTolerance(0.),
123 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
124 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
125 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
126 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi),
127 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT),
128 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
129 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullTube(rhs.fPhiFullTube),
130 halfCarTolerance(rhs.halfCarTolerance),
131 halfRadTolerance(rhs.halfRadTolerance),
132 halfAngTolerance(rhs.halfAngTolerance)
144 if (
this == &rhs) {
return *
this; }
186 pMin.
set(vmin.
x(),vmin.
y(),-dz);
187 pMax.
set(vmax.
x(),vmax.
y(), dz);
191 pMin.
set(-rmax,-rmax,-dz);
192 pMax.
set( rmax, rmax, dz);
197 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
199 std::ostringstream message;
200 message <<
"Bad bounding box (min >= max) for solid: "
202 <<
"\npMin = " << pMin
203 <<
"\npMax = " << pMax;
228 if (
true)
return bbox.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
232 return exist = (pMin < pMax) ?
true :
false;
243 const G4int NSTEPS = 24;
245 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-
deg)/astep) + 1;
248 G4double sinHalf = std::sin(0.5*ang);
249 G4double cosHalf = std::cos(0.5*ang);
250 G4double sinStep = 2.*sinHalf*cosHalf;
251 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
256 if (rmin == 0 && dphi ==
twopi)
262 for (
G4int k=0; k<NSTEPS; ++k)
264 baseA[k].set(rext*cosCur,rext*sinCur,-dz);
265 baseB[k].set(rext*cosCur,rext*sinCur, dz);
268 sinCur = sinCur*cosStep + cosCur*sinStep;
269 cosCur = cosCur*cosStep - sinTmp*sinStep;
271 std::vector<const G4ThreeVectorList *> polygons(2);
272 polygons[0] = &baseA;
273 polygons[1] = &baseB;
283 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
284 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
288 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
289 pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
290 pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
291 pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
292 pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
293 for (
G4int k=1; k<ksteps+1; ++k)
295 pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
296 pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
297 pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
298 pols[k][3].set(rext*cosCur,rext*sinCur, dz);
301 sinCur = sinCur*cosStep + cosCur*sinStep;
302 cosCur = cosCur*cosStep - sinTmp*sinStep;
304 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
305 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
306 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
307 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
310 std::vector<const G4ThreeVectorList *> polygons;
311 polygons.resize(ksteps+2);
312 for (
G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
330 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
333 else { tolRMin = 0 ; }
337 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
355 pPhi = std::atan2(p.
y(),p.
x()) ;
398 if ( tolRMin < 0 ) { tolRMin = 0; }
400 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
402 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance) )
408 pPhi = std::atan2(p.
y(),p.
x()) ;
439 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
443 if ( tolRMin < 0 ) { tolRMin = 0; }
445 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
447 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance))
453 pPhi = std::atan2(p.
y(),p.
x()) ;
492 G4int noSurfaces = 0;
501 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
503 distRMin = std::fabs(rho -
fRMin);
504 distRMax = std::fabs(rho -
fRMax);
505 distZ = std::fabs(std::fabs(p.
z()) -
fDz);
511 pPhi = std::atan2(p.
y(),p.
x());
516 distSPhi = std::fabs(pPhi -
fSPhi);
555 if ( p.
z() >= 0.) { sumnorm += nZ; }
556 else { sumnorm -= nZ; }
558 if ( noSurfaces == 0 )
561 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
564 G4cout<<
"G4Tubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
566 G4cout.precision(oldprc) ;
570 else if ( noSurfaces == 1 ) { norm = sumnorm; }
571 else { norm = sumnorm.
unit(); }
586 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
588 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
590 distRMin = std::fabs(rho -
fRMin) ;
591 distRMax = std::fabs(rho -
fRMax) ;
592 distZ = std::fabs(std::fabs(p.
z()) -
fDz) ;
594 if (distRMin < distRMax)
596 if ( distZ < distRMin )
609 if ( distZ < distRMax )
622 phi = std::atan2(p.
y(),p.
x()) ;
624 if ( phi < 0 ) { phi +=
twopi; }
628 distSPhi = std::fabs(phi - (
fSPhi +
twopi))*rho ;
632 distSPhi = std::fabs(phi -
fSPhi)*rho ;
634 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
636 if (distSPhi < distEPhi)
638 if ( distSPhi < distMin )
645 if ( distEPhi < distMin )
684 "Undefined side for valid surface normal to solid.");
718 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
723 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
746 if (std::fabs(p.
z()) >= tolIDz)
748 if ( p.
z()*v.
z() < 0 )
750 sd = (std::fabs(p.
z()) -
fDz)/std::fabs(v.
z()) ;
752 if(sd < 0.0) { sd = 0.0; }
754 xi = p.
x() + sd*v.
x() ;
755 yi = p.
y() + sd*v.
y() ;
756 rho2 = xi*xi + yi*yi ;
760 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
767 iden = std::sqrt(rho2) ;
779 if ( snxt<halfCarTolerance ) { snxt=0; }
796 t1 = 1.0 - v.
z()*v.
z() ;
797 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
798 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
804 if ((t3 >= tolORMax2) && (t2<0))
814 sd = c/(-b+std::sqrt(d));
819 G4double fTerm = sd-std::fmod(sd,dRmax);
824 zi = p.
z() + sd*v.
z() ;
825 if (std::fabs(zi)<=tolODz)
835 xi = p.
x() + sd*v.
x() ;
836 yi = p.
y() + sd*v.
y() ;
849 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.
z()) <= tolIDz))
856 iden = std::sqrt(t3) ;
877 snxt = c/(-b+std::sqrt(d));
879 if ( snxt < halfCarTolerance ) { snxt=0; }
897 c = t3 - fRMax*
fRMax;
908 snxt= c/(-b+std::sqrt(d));
910 if ( snxt < halfCarTolerance ) { snxt=0; }
930 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
931 if (sd >= -halfCarTolerance)
935 if(sd < 0.0) { sd = 0.0; }
938 G4double fTerm = sd-std::fmod(sd,dRmax);
941 zi = p.
z() + sd*v.
z() ;
942 if (std::fabs(zi) <= tolODz)
952 xi = p.
x() + sd*v.
x() ;
953 yi = p.
y() + sd*v.
y() ;
988 if ( Dist < halfCarTolerance )
994 if ( sd < 0 ) { sd = 0.0; }
995 zi = p.
z() + sd*v.
z() ;
996 if ( std::fabs(zi) <= tolODz )
998 xi = p.
x() + sd*v.
x() ;
999 yi = p.
y() + sd*v.
y() ;
1000 rho2 = xi*xi + yi*yi ;
1002 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1003 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1006 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1028 if ( Dist < halfCarTolerance )
1034 if ( sd < 0 ) { sd = 0; }
1035 zi = p.
z() + sd*v.
z() ;
1036 if ( std::fabs(zi) <= tolODz )
1038 xi = p.
x() + sd*v.
x() ;
1039 yi = p.
y() + sd*v.
y() ;
1040 rho2 = xi*xi + yi*yi ;
1041 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1042 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1045 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1059 if ( snxt<halfCarTolerance ) { snxt=0; }
1091 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1094 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1095 safe1 =
fRMin - rho ;
1096 safe2 = rho -
fRMax ;
1097 safe3 = std::fabs(p.
z()) -
fDz ;
1099 if ( safe1 > safe2 ) { safe = safe1; }
1100 else { safe = safe2; }
1101 if ( safe3 > safe ) { safe = safe3; }
1109 if ( cosPsi < std::cos(
fDPhi*0.5) )
1121 if ( safePhi > safe ) { safe = safePhi; }
1124 if ( safe < 0 ) { safe = 0; }
1141 G4double deltaR, t1, t2, t3, b, c,
d2, roMin2 ;
1145 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1151 pdist =
fDz - p.
z() ;
1154 snxt = pdist/v.
z() ;
1167 else if ( v.
z() < 0 )
1169 pdist =
fDz + p.
z() ;
1173 snxt = -pdist/v.
z() ;
1203 t1 = 1.0 - v.
z()*v.
z() ;
1204 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1205 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1208 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1228 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1247 roMin2 = t3 - t2*t2/t1 ;
1263 srd = c/(-b+std::sqrt(d2));
1268 if ( calcNorm ) { *validNorm =
false; }
1279 srd = -b + std::sqrt(d2) ;
1303 srd = -b + std::sqrt(d2) ;
1326 vphi = std::atan2(v.
y(),v.
x()) ;
1332 if ( p.
x() || p.
y() )
1355 sphi = pDistS/compS ;
1359 xi = p.
x() + sphi*v.
x() ;
1360 yi = p.
y() + sphi*v.
y() ;
1400 sphi2 = pDistE/compE ;
1406 xi = p.
x() + sphi2*v.
x() ;
1407 yi = p.
y() + sphi2*v.
y() ;
1419 else { sphi = 0.0 ; }
1430 else { sphi = 0.0 ; }
1476 xi = p.
x() + snxt*v.
x() ;
1477 yi = p.
y() + snxt*v.
y() ;
1483 *validNorm = false ;
1494 *validNorm = false ;
1506 *validNorm = false ;
1523 std::ostringstream message;
1524 G4int oldprc = message.precision(16);
1525 message <<
"Undefined side for valid surface normal to solid."
1527 <<
"Position:" << G4endl << G4endl
1528 <<
"p.x() = " << p.
x()/
mm <<
" mm" << G4endl
1529 <<
"p.y() = " << p.
y()/
mm <<
" mm" << G4endl
1530 <<
"p.z() = " << p.
z()/
mm <<
" mm" << G4endl << G4endl
1531 <<
"Direction:" << G4endl << G4endl
1532 <<
"v.x() = " << v.
x() << G4endl
1533 <<
"v.y() = " << v.
y() << G4endl
1534 <<
"v.z() = " << v.
z() << G4endl << G4endl
1535 <<
"Proposed distance :" << G4endl << G4endl
1536 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1537 message.precision(oldprc) ;
1538 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1554 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1555 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1567 G4cout.precision(oldprc) ;
1568 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1575 safeR1 = rho -
fRMin ;
1576 safeR2 =
fRMax - rho ;
1578 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1579 else { safe = safeR2 ; }
1583 safe =
fRMax - rho ;
1585 safeZ =
fDz - std::fabs(p.
z()) ;
1587 if ( safeZ < safe ) { safe = safeZ ; }
1601 if (safePhi < safe) { safe = safePhi ; }
1603 if ( safe < 0 ) { safe = 0 ; }
1632 G4int oldprc = os.precision(16);
1633 os <<
"-----------------------------------------------------------\n"
1634 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1635 <<
" ===================================================\n"
1636 <<
" Solid type: G4Tubs\n"
1637 <<
" Parameters: \n"
1638 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1639 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1640 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1641 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1642 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1643 <<
"-----------------------------------------------------------\n";
1644 os.precision(oldprc);
1655 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1656 aOne, aTwo, aThr, aFou;
1665 cosphi = std::cos(phi);
1666 sinphi = std::sin(phi);
1674 if( (chose >=0) && (chose < aOne) )
1676 xRand = fRMax*cosphi;
1677 yRand = fRMax*sinphi;
1681 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1683 xRand = fRMin*cosphi;
1684 yRand = fRMin*sinphi;
1688 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1690 xRand = rRand*cosphi;
1691 yRand = rRand*sinphi;
1695 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1697 xRand = rRand*cosphi;
1698 yRand = rRand*sinphi;
1702 else if( (chose >= aOne + aTwo + 2.*aThr)
1703 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1705 xRand = rRand*std::cos(
fSPhi);
1706 yRand = rRand*std::sin(
fSPhi);
G4double GetCosStartPhi() const
void set(double x, double y, double z)
ThreeVector shoot(const G4int Ap, const G4int Af)
G4GeometryType GetEntityType() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
static constexpr double mm
static const G4double kInfinity
CLHEP::Hep3Vector G4ThreeVector
G4double GetSinStartPhi() const
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4ThreeVector GetPointOnSurface() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
virtual void AddSolid(const G4Box &)=0
static constexpr double twopi
G4OTubs & operator=(const G4OTubs &rhs)
G4GLOB_DLL std::ostream G4cout
static constexpr double degree
G4double halfRadTolerance
G4double GetRadialTolerance() const
G4OTubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi)
G4double GetSinEndPhi() 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
std::vector< G4ThreeVector > G4ThreeVectorList
G4double GetZHalfLength() const
G4Polyhedron * CreatePolyhedron() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4double GetOuterRadius() const
G4double halfAngTolerance
G4double halfCarTolerance
G4double GetCosEndPhi() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
G4double GetInnerRadius() const
void Extent(G4ThreeVector &pMin, G4ThreeVector &pMax) const
static constexpr double pi
G4double GetDeltaPhiAngle() const
EInside Inside(const G4ThreeVector &p) const
static constexpr double deg
virtual G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4double GetAngularTolerance() const
static G4GeometryTolerance * GetInstance()
std::ostream & StreamInfo(std::ostream &os) const