81 using namespace CLHEP;
92 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
100 std::ostringstream message;
101 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
104 if ( (pRMin >= pRMax) || (pRMin < 0) )
106 std::ostringstream message;
107 message <<
"Invalid values for radii in solid: " <<
GetName()
109 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
124 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
125 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
126 sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
127 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
146 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
147 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
148 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
149 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.sinCPhi),
150 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiOT),
151 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
152 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullTube(rhs.fPhiFullTube)
164 if (
this == &rhs) {
return *
this; }
218 G4double diff1, diff2, maxDiff, newMin, newMax;
219 G4double xoff1, xoff2, yoff1, yoff2, delta;
222 xMin = xoffset -
fRMax;
223 xMax = xoffset +
fRMax;
245 yMin = yoffset -
fRMax;
246 yMax = yoffset +
fRMax;
268 zMin = zoffset -
fDz;
269 zMax = zoffset +
fDz;
294 yoff1 = yoffset - yMin;
295 yoff2 = yMax - yoffset;
297 if ( (yoff1 >= 0) && (yoff2 >= 0) )
307 delta = fRMax*fRMax - yoff1*yoff1;
308 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
309 delta = fRMax*fRMax - yoff2*yoff2;
310 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
311 maxDiff = (diff1 > diff2) ? diff1:diff2;
312 newMin = xoffset - maxDiff;
313 newMax = xoffset + maxDiff;
314 pMin = (newMin < xMin) ? xMin : newMin;
315 pMax = (newMax > xMax) ? xMax : newMax;
321 xoff1 = xoffset - xMin;
322 xoff2 = xMax - xoffset;
324 if ( (xoff1 >= 0) && (xoff2 >= 0) )
334 delta = fRMax*fRMax - xoff1*xoff1;
335 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
336 delta = fRMax*fRMax - xoff2*xoff2;
337 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
338 maxDiff = (diff1 > diff2) ? diff1 : diff2;
339 newMin = yoffset - maxDiff;
340 newMax = yoffset + maxDiff;
341 pMin = (newMin < yMin) ? yMin : newMin;
342 pMax = (newMax > yMax) ? yMax : newMax;
361 G4int i, noEntries, noBetweenSections4;
362 G4bool existsAfterClip =
false;
368 noEntries = vertices->size();
369 noBetweenSections4 = noEntries - 4;
371 for ( i = 0 ; i < noEntries ; i += 4 )
375 for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
379 if ( (pMin != kInfinity) || (pMax != -kInfinity) )
381 existsAfterClip =
true;
399 existsAfterClip =
true;
405 return existsAfterClip;
422 if (std::fabs(p.
z()) <=
fDz - halfCarTolerance)
424 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
426 if (
fRMin) { tolRMin =
fRMin + halfRadTolerance ; }
427 else { tolRMin = 0 ; }
429 tolRMax =
fRMax - halfRadTolerance ;
431 if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
442 if ( (tolRMin==0) && (std::fabs(p.
x())<=halfCarTolerance)
443 && (std::fabs(p.
y())<=halfCarTolerance) )
449 pPhi = std::atan2(p.
y(),p.
x()) ;
450 if ( pPhi < -halfAngTolerance ) { pPhi +=
twopi; }
454 if ( (std::fabs(pPhi) < halfAngTolerance)
459 if ( (pPhi >=
fSPhi + halfAngTolerance)
460 && (pPhi <=
fSPhi +
fDPhi - halfAngTolerance) )
464 else if ( (pPhi >=
fSPhi - halfAngTolerance)
465 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance) )
472 if ( (pPhi <=
fSPhi +
twopi - halfAngTolerance)
473 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance) ) {;}
474 else if ( (pPhi <=
fSPhi +
twopi + halfAngTolerance)
475 && (pPhi >=
fSPhi +
fDPhi - halfAngTolerance) )
489 tolRMin =
fRMin - halfRadTolerance ;
490 tolRMax =
fRMax + halfRadTolerance ;
492 if ( tolRMin < 0 ) { tolRMin = 0; }
494 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
496 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance) )
502 pPhi = std::atan2(p.
y(),p.
x()) ;
504 if ( pPhi < -halfAngTolerance) { pPhi +=
twopi; }
507 if ( (std::fabs(pPhi) < halfAngTolerance)
512 if ( (pPhi >=
fSPhi - halfAngTolerance)
513 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance) )
520 if ( (pPhi <=
fSPhi +
twopi - halfAngTolerance)
521 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance) ) {;}
531 else if (std::fabs(p.
z()) <=
fDz + halfCarTolerance)
533 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
534 tolRMin =
fRMin - halfRadTolerance ;
535 tolRMax =
fRMax + halfRadTolerance ;
537 if ( tolRMin < 0 ) { tolRMin = 0; }
539 if ( (r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax) )
541 if (
fPhiFullTube || (r2 <=halfRadTolerance*halfRadTolerance))
547 pPhi = std::atan2(p.
y(),p.
x()) ;
549 if ( pPhi < -halfAngTolerance ) { pPhi +=
twopi; }
552 if ( (std::fabs(pPhi) < halfAngTolerance)
557 if ( (pPhi >=
fSPhi - halfAngTolerance)
558 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance) )
565 if ( (pPhi <=
fSPhi +
twopi - halfAngTolerance)
566 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance) ) {;}
586 G4int noSurfaces = 0;
589 G4double distSPhi = kInfinity, distEPhi = kInfinity;
598 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
600 distRMin = std::fabs(rho -
fRMin);
601 distRMax = std::fabs(rho -
fRMax);
602 distZ = std::fabs(std::fabs(p.
z()) -
fDz);
606 if ( rho > halfCarTolerance )
608 pPhi = std::atan2(p.
y(),p.
x());
610 if(pPhi <
fSPhi- halfCarTolerance) { pPhi +=
twopi; }
613 distSPhi = std::fabs(pPhi -
fSPhi);
624 if ( rho > halfCarTolerance ) { nR =
G4ThreeVector(p.
x()/rho,p.
y()/rho,0); }
626 if( distRMax <= halfCarTolerance )
631 if(
fRMin && (distRMin <= halfCarTolerance) )
638 if (distSPhi <= halfAngTolerance)
643 if (distEPhi <= halfAngTolerance)
649 if (distZ <= halfCarTolerance)
652 if ( p.
z() >= 0.) { sumnorm += nZ; }
653 else { sumnorm -= nZ; }
655 if ( noSurfaces == 0 )
658 G4Exception(
"G4Tubs::SurfaceNormal(p)",
"GeomSolids1002",
661 G4cout<<
"G4Tubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
663 G4cout.precision(oldprc) ;
667 else if ( noSurfaces == 1 ) { norm = sumnorm; }
668 else { norm = sumnorm.
unit(); }
683 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
685 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
687 distRMin = std::fabs(rho -
fRMin) ;
688 distRMax = std::fabs(rho -
fRMax) ;
689 distZ = std::fabs(std::fabs(p.
z()) -
fDz) ;
691 if (distRMin < distRMax)
693 if ( distZ < distRMin )
706 if ( distZ < distRMax )
719 phi = std::atan2(p.
y(),p.
x()) ;
721 if ( phi < 0 ) { phi +=
twopi; }
725 distSPhi = std::fabs(phi - (
fSPhi +
twopi))*rho ;
729 distSPhi = std::fabs(phi -
fSPhi)*rho ;
731 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
733 if (distSPhi < distEPhi)
735 if ( distSPhi < distMin )
742 if ( distEPhi < distMin )
781 "Undefined side for valid surface normal to solid.");
815 G4double tolORMax2, tolIRMin2, tolODz, tolIDz ;
823 G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
830 tolORMin2 = (
fRMin - halfRadTolerance)*(
fRMin - halfRadTolerance) ;
831 tolIRMin2 = (
fRMin + halfRadTolerance)*(
fRMin + halfRadTolerance) ;
838 tolORMax2 = (
fRMax + halfRadTolerance)*(
fRMax + halfRadTolerance) ;
839 tolIRMax2 = (
fRMax - halfRadTolerance)*(
fRMax - halfRadTolerance) ;
843 tolIDz =
fDz - halfCarTolerance ;
844 tolODz =
fDz + halfCarTolerance ;
846 if (std::fabs(p.
z()) >= tolIDz)
848 if ( p.
z()*v.
z() < 0 )
850 sd = (std::fabs(p.
z()) -
fDz)/std::fabs(v.
z()) ;
852 if(sd < 0.0) { sd = 0.0; }
854 xi = p.
x() + sd*v.
x() ;
855 yi = p.
y() + sd*v.
y() ;
856 rho2 = xi*xi + yi*yi ;
860 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
867 iden = std::sqrt(rho2) ;
879 if ( snxt<halfCarTolerance ) { snxt=0; }
896 t1 = 1.0 - v.
z()*v.
z() ;
897 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
898 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
904 if ((t3 >= tolORMax2) && (t2<0))
914 sd = c/(-b+std::sqrt(d));
919 G4double fTerm = sd-std::fmod(sd,dRmax);
924 zi = p.
z() + sd*v.
z() ;
925 if (std::fabs(zi)<=tolODz)
935 xi = p.
x() + sd*v.
x() ;
936 yi = p.
y() + sd*v.
y() ;
949 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.
z()) <= tolIDz))
956 iden = std::sqrt(t3) ;
977 snxt = c/(-b+std::sqrt(d));
979 if ( snxt < halfCarTolerance ) { snxt=0; }
997 c = t3 - fRMax*
fRMax;
1008 snxt= c/(-b+std::sqrt(d));
1010 if ( snxt < halfCarTolerance ) { snxt=0; }
1030 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1031 if (sd >= -halfCarTolerance)
1035 if(sd < 0.0) { sd = 0.0; }
1038 G4double fTerm = sd-std::fmod(sd,dRmax);
1041 zi = p.
z() + sd*v.
z() ;
1042 if (std::fabs(zi) <= tolODz)
1052 xi = p.
x() + sd*v.
x() ;
1053 yi = p.
y() + sd*v.
y() ;
1088 if ( Dist < halfCarTolerance )
1094 if ( sd < 0 ) { sd = 0.0; }
1095 zi = p.
z() + sd*v.
z() ;
1096 if ( std::fabs(zi) <= tolODz )
1098 xi = p.
x() + sd*v.
x() ;
1099 yi = p.
y() + sd*v.
y() ;
1100 rho2 = xi*xi + yi*yi ;
1102 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1103 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1106 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1128 if ( Dist < halfCarTolerance )
1134 if ( sd < 0 ) { sd = 0; }
1135 zi = p.
z() + sd*v.
z() ;
1136 if ( std::fabs(zi) <= tolODz )
1138 xi = p.
x() + sd*v.
x() ;
1139 yi = p.
y() + sd*v.
y() ;
1140 rho2 = xi*xi + yi*yi ;
1141 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1142 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1145 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1159 if ( snxt<halfCarTolerance ) { snxt=0; }
1191 G4double safe=0.0, rho, safe1, safe2, safe3 ;
1194 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1195 safe1 =
fRMin - rho ;
1196 safe2 = rho -
fRMax ;
1197 safe3 = std::fabs(p.
z()) -
fDz ;
1199 if ( safe1 > safe2 ) { safe = safe1; }
1200 else { safe = safe2; }
1201 if ( safe3 > safe ) { safe = safe3; }
1209 if ( cosPsi < std::cos(
fDPhi*0.5) )
1221 if ( safePhi > safe ) { safe = safePhi; }
1224 if ( safe < 0 ) { safe = 0; }
1240 G4double snxt, srd=kInfinity, sphi=kInfinity, pdist ;
1248 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1254 pdist =
fDz - p.
z() ;
1255 if ( pdist > halfCarTolerance )
1257 snxt = pdist/v.
z() ;
1270 else if ( v.
z() < 0 )
1272 pdist =
fDz + p.
z() ;
1274 if ( pdist > halfCarTolerance )
1276 snxt = -pdist/v.
z() ;
1306 t1 = 1.0 - v.
z()*v.
z() ;
1307 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1308 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1311 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1331 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1350 roMin2 = t3 - t2*t2/
t1 ;
1366 srd = c/(-b+std::sqrt(d2));
1371 if ( calcNorm ) { *validNorm =
false; }
1382 srd = -b + std::sqrt(d2) ;
1406 srd = -b + std::sqrt(d2) ;
1429 vphi = std::atan2(v.
y(),v.
x()) ;
1431 if ( vphi <
fSPhi - halfAngTolerance ) { vphi +=
twopi; }
1432 else if ( vphi >
fSPhi +
fDPhi + halfAngTolerance ) { vphi -=
twopi; }
1435 if ( p.
x() || p.
y() )
1449 if( ( (
fDPhi <=
pi) && ( (pDistS <= halfCarTolerance)
1450 && (pDistE <= halfCarTolerance) ) )
1451 || ( (
fDPhi >
pi) && !((pDistS > halfCarTolerance)
1452 && (pDistE > halfCarTolerance) ) ) )
1458 sphi = pDistS/compS ;
1460 if (sphi >= -halfCarTolerance)
1462 xi = p.
x() + sphi*v.
x() ;
1463 yi = p.
y() + sphi*v.
y() ;
1471 if (((
fSPhi-halfAngTolerance)<=vphi)
1484 if ( pDistS > -halfCarTolerance )
1502 sphi2 = pDistE/compE ;
1506 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1508 xi = p.
x() + sphi2*v.
x() ;
1509 yi = p.
y() + sphi2*v.
y() ;
1515 if( !((
fSPhi-halfAngTolerance <= vphi)
1519 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1520 else { sphi = 0.0 ; }
1530 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1531 else { sphi = 0.0 ; }
1546 if ( (
fSPhi - halfAngTolerance <= vphi)
1547 && (vphi <=
fSPhi +
fDPhi + halfAngTolerance ) )
1577 xi = p.
x() + snxt*v.
x() ;
1578 yi = p.
y() + snxt*v.
y() ;
1584 *validNorm = false ;
1595 *validNorm = false ;
1607 *validNorm = false ;
1624 std::ostringstream message;
1625 G4int oldprc = message.precision(16);
1626 message <<
"Undefined side for valid surface normal to solid."
1628 <<
"Position:" << G4endl << G4endl
1629 <<
"p.x() = " << p.
x()/
mm <<
" mm" << G4endl
1630 <<
"p.y() = " << p.
y()/
mm <<
" mm" << G4endl
1631 <<
"p.z() = " << p.
z()/
mm <<
" mm" << G4endl << G4endl
1632 <<
"Direction:" << G4endl << G4endl
1633 <<
"v.x() = " << v.
x() << G4endl
1634 <<
"v.y() = " << v.
y() << G4endl
1635 <<
"v.z() = " << v.
z() << G4endl << G4endl
1636 <<
"Proposed distance :" << G4endl << G4endl
1637 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1638 message.precision(oldprc) ;
1639 G4Exception(
"G4Tubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1644 if ( snxt<halfCarTolerance ) { snxt=0 ; }
1655 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi ;
1656 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1668 G4cout.precision(oldprc) ;
1669 G4Exception(
"G4Tubs::DistanceToOut(p)",
"GeomSolids1002",
1676 safeR1 = rho -
fRMin ;
1677 safeR2 =
fRMax - rho ;
1679 if ( safeR1 < safeR2 ) { safe = safeR1 ; }
1680 else { safe = safeR2 ; }
1684 safe =
fRMax - rho ;
1686 safeZ =
fDz - std::fabs(p.
z()) ;
1688 if ( safeZ < safe ) { safe = safeZ ; }
1702 if (safePhi < safe) { safe = safePhi ; }
1704 if ( safe < 0 ) { safe = 0 ; }
1725 G4double meshAngle, meshRMax, crossAngle,
1726 cosCrossAngle, sinCrossAngle, sAngle;
1727 G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
1728 G4int crossSection, noCrossSections;
1744 meshAngle =
fDPhi/(noCrossSections - 1) ;
1754 else { sAngle =
fSPhi ; }
1760 vertices->reserve(noCrossSections*4);
1761 for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
1765 crossAngle = sAngle + crossSection*meshAngle ;
1766 cosCrossAngle = std::cos(crossAngle) ;
1767 sinCrossAngle = std::sin(crossAngle) ;
1769 rMaxX = meshRMax*cosCrossAngle ;
1770 rMaxY = meshRMax*sinCrossAngle ;
1779 rMinX = meshRMin*cosCrossAngle ;
1780 rMinY = meshRMin*sinCrossAngle ;
1798 "Error in allocation of vertices. Out of memory !");
1818 return new G4Tubs(*
this);
1827 G4int oldprc = os.precision(16);
1828 os <<
"-----------------------------------------------------------\n"
1829 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1830 <<
" ===================================================\n"
1831 <<
" Solid type: G4Tubs\n"
1832 <<
" Parameters: \n"
1833 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1834 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1835 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1836 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1837 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1838 <<
"-----------------------------------------------------------\n";
1839 os.precision(oldprc);
1850 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1851 aOne, aTwo, aThr, aFou;
1860 cosphi = std::cos(phi);
1861 sinphi = std::sin(phi);
1867 chose = RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
1869 if( (chose >=0) && (chose < aOne) )
1871 xRand = fRMax*cosphi;
1872 yRand = fRMax*sinphi;
1873 zRand = RandFlat::shoot(-1.*
fDz,
fDz);
1876 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1878 xRand = fRMin*cosphi;
1879 yRand = fRMin*sinphi;
1880 zRand = RandFlat::shoot(-1.*
fDz,
fDz);
1883 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1885 xRand = rRand*cosphi;
1886 yRand = rRand*sinphi;
1890 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1892 xRand = rRand*cosphi;
1893 yRand = rRand*sinphi;
1897 else if( (chose >= aOne + aTwo + 2.*aThr)
1898 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1900 xRand = rRand*std::cos(
fSPhi);
1901 yRand = rRand*std::sin(
fSPhi);
1902 zRand = RandFlat::shoot(-1.*
fDz,
fDz);
1909 zRand = RandFlat::shoot(-1.*
fDz,
fDz);