35 #if !defined(G4GEOM_USE_UCTUBS)
51 using namespace CLHEP;
63 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
75 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
78 if ( (pRMin >= pRMax) || (pRMin < 0) )
81 message <<
"Invalid values for radii in solid: " <<
GetName()
83 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
94 if ( ( !pLowNorm.
x()) && ( !pLowNorm.
y())
95 && ( !pHighNorm.
x()) && (!pHighNorm.
y()) )
98 message <<
"Inexisting Low/High Normal to Z plane or Parallel to Z."
100 <<
"Normals to Z plane are (" << pLowNorm <<
" and "
101 << pHighNorm <<
") in solid: " <<
GetName();
102 G4Exception(
"G4CutTubs::G4CutTubs()",
"GeomSolids1001",
108 if (pLowNorm.
mag2() == 0.) { pLowNorm.
setZ(-1.); }
109 if (pHighNorm.
mag2()== 0.) { pHighNorm.
setZ(1.); }
114 if (pLowNorm.
mag2() != 1.) { pLowNorm = pLowNorm.
unit(); }
115 if (pHighNorm.
mag2()!= 1.) { pHighNorm = pHighNorm.
unit(); }
119 if( (pLowNorm.
mag2() != 0.) && (pHighNorm.
mag2()!= 0. ) )
121 if( ( pLowNorm.
z()>= 0. ) || ( pHighNorm.
z() <= 0.))
124 message <<
"Invalid Low or High Normal to Z plane; "
125 "has to point outside Solid." <<
G4endl
126 <<
"Invalid Norm to Z plane (" << pLowNorm <<
" or "
127 << pHighNorm <<
") in solid: " <<
GetName();
128 G4Exception(
"G4CutTubs::G4CutTubs()",
"GeomSolids0002",
158 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
159 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
160 sinCPhi(0.), cosCPhi(0.), cosHDPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
161 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
162 halfCarTolerance(0.), halfRadTolerance(0.), halfAngTolerance(0.),
181 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
182 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
183 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
184 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi), cosHDPhi(rhs.cosHDPhi),
185 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT),
186 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
187 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi),
188 fPhiFullCutTube(rhs.fPhiFullCutTube),
189 halfCarTolerance(rhs.halfCarTolerance),
190 halfRadTolerance(rhs.halfRadTolerance),
191 halfAngTolerance(rhs.halfAngTolerance),
192 fLowNorm(rhs.fLowNorm), fHighNorm(rhs.fHighNorm)
204 if (
this == &rhs) {
return *
this; }
245 G4double mag, topx, topy, dists, diste;
252 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
253 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
254 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
255 dists = sinSphi*topx - cosSphi*topy;
256 diste = -sinEphi*topx + cosEphi*topy;
260 if (dists > 0 && diste > 0)iftop =
false;
265 if (dists <= 0 && diste <= 0) iftop =
true;
269 zmin = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() -
dz;
273 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() -
dz;
274 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() -
dz;
275 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() -
dz;
276 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() -
dz;
284 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
285 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
286 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
287 dists = sinSphi*topx - cosSphi*topy;
288 diste = -sinEphi*topx + cosEphi*topy;
292 if (dists > 0 && diste > 0) iftop =
false;
297 if (dists <= 0 && diste <= 0) iftop =
true;
301 zmax = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() +
dz;
305 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() +
dz;
306 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() +
dz;
307 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() +
dz;
308 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() +
dz;
321 pMin.
set(vmin.
x(),vmin.
y(), zmin);
322 pMax.
set(vmax.
x(),vmax.
y(), zmax);
326 pMin.
set(-rmax,-rmax, zmin);
327 pMax.
set( rmax, rmax, zmax);
332 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
335 message <<
"Bad bounding box (min >= max) for solid: "
337 <<
"\npMin = " << pMin
338 <<
"\npMax = " <<
pMax;
339 G4Exception(
"G4CutTubs::BoundingLimits()",
"GeomMgt0001",
368 return exist = (pMin <
pMax) ?
true :
false;
380 const G4int NSTEPS = 24;
382 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-
deg)/astep) + 1;
385 G4double sinHalf = std::sin(0.5*ang);
386 G4double cosHalf = std::cos(0.5*ang);
387 G4double sinStep = 2.*sinHalf*cosHalf;
388 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
393 if (rmin == 0 && dphi ==
twopi)
401 baseA[
k].set(rext*cosCur,rext*sinCur,zmin);
402 baseB[
k].set(rext*cosCur,rext*sinCur,zmax);
405 sinCur = sinCur*cosStep + cosCur*sinStep;
406 cosCur = cosCur*cosStep - sinTmp*sinStep;
408 std::vector<const G4ThreeVectorList *> polygons(2);
409 polygons[0] = &baseA;
410 polygons[1] = &baseB;
420 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
421 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
425 for (
G4int k=0;
k<ksteps+2; ++
k) pols[
k].resize(4);
426 pols[0][0].set(rmin*cosStart,rmin*sinStart,zmax);
427 pols[0][1].set(rmin*cosStart,rmin*sinStart,zmin);
428 pols[0][2].set(rmax*cosStart,rmax*sinStart,zmin);
429 pols[0][3].set(rmax*cosStart,rmax*sinStart,zmax);
432 pols[
k][0].set(rmin*cosCur,rmin*sinCur,zmax);
433 pols[
k][1].set(rmin*cosCur,rmin*sinCur,zmin);
434 pols[
k][2].set(rext*cosCur,rext*sinCur,zmin);
435 pols[
k][3].set(rext*cosCur,rext*sinCur,zmax);
438 sinCur = sinCur*cosStep + cosCur*sinStep;
439 cosCur = cosCur*cosStep - sinTmp*sinStep;
441 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd,zmax);
442 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,zmin);
443 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,zmin);
444 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd,zmax);
447 std::vector<const G4ThreeVectorList *> polygons;
448 polygons.resize(ksteps+2);
449 for (
G4int k=0;
k<ksteps+2; ++
k) { polygons[
k] = &pols[
k]; }
481 if ( tolRMin < 0 ) { tolRMin = 0; }
483 if (r2 < tolRMin*tolRMin || r2 > tolRMax*tolRMax) {
return kOutside; }
502 if ((phi0 >= sphi && phi0 <= ephi) ||
503 (phi1 >= sphi && phi1 <= ephi) ||
504 (phi2 >= sphi && phi2 <= ephi)) in =
kSurface;
509 if ((phi0 >= sphi && phi0 <= ephi) ||
510 (phi1 >= sphi && phi1 <= ephi) ||
511 (phi2 >= sphi && phi2 <= ephi)) in =
kInside;
525 else { tolRMin = 0; }
527 if (((r2 <= tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax)) &&
544 G4int noSurfaces = 0;
546 G4double distZLow,distZHigh, distRMin, distRMax;
554 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
556 distRMin = std::fabs(rho -
fRMin);
557 distRMax = std::fabs(rho -
fRMax);
561 distZLow =std::fabs((p+vZ).dot(
fLowNorm));
565 distZHigh = std::fabs((p-vZ).dot(
fHighNorm));
571 pPhi = std::atan2(p.
y(),p.
x());
576 distSPhi = std::fabs(pPhi -
fSPhi);
622 if ( noSurfaces == 0 )
625 G4Exception(
"G4CutTubs::SurfaceNormal(p)",
"GeomSolids1002",
628 G4cout<<
"G4CutTubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
630 G4cout.precision(oldprc) ;
634 else if ( noSurfaces == 1 ) { norm = sumnorm; }
635 else { norm = sumnorm.
unit(); }
653 G4double distRMin, distRMax, distSPhi, distEPhi, distMin ;
656 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
658 distRMin = std::fabs(rho -
fRMin) ;
659 distRMax = std::fabs(rho -
fRMax) ;
663 distZLow =std::fabs((p+vZ).dot(
fLowNorm));
667 distZHigh = std::fabs((p-vZ).dot(
fHighNorm));
670 if (distRMin < distRMax)
672 if ( distZ < distRMin )
685 if ( distZ < distRMax )
698 phi = std::atan2(p.
y(),p.
x()) ;
700 if ( phi < 0 ) { phi +=
twopi; }
704 distSPhi = std::fabs(phi - (
fSPhi +
twopi))*rho ;
708 distSPhi = std::fabs(phi -
fSPhi)*rho ;
710 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
712 if (distSPhi < distEPhi)
714 if ( distSPhi < distMin )
721 if ( distEPhi < distMin )
741 if ( distZHigh > distZLow ) { norm =
fHighNorm ; }
760 "Undefined side for valid surface normal to solid.");
800 G4double Dist, sd=0, xi, yi, zi, rho2, inum, iden, cosPsi, Comp,calf ;
834 if(sd < 0.0) { sd = 0.0; }
836 xi = p.
x() + sd*v.
x() ;
837 yi = p.
y() + sd*v.
y() ;
838 rho2 = xi*xi + yi*yi ;
842 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
849 iden = std::sqrt(rho2) ;
874 sd = -distZHigh/calf;
876 if(sd < 0.0) { sd = 0.0; }
878 xi = p.
x() + sd*v.
x() ;
879 yi = p.
y() + sd*v.
y() ;
880 rho2 = xi*xi + yi*yi ;
884 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
891 iden = std::sqrt(rho2) ;
922 t1 = 1.0 - v.
z()*v.
z() ;
923 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
924 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
930 if ((t3 >= tolORMax2) && (t2<0))
939 sd = c/(-b+std::sqrt(d));
944 G4double fTerm = sd-std::fmod(sd,dRmax);
949 zi = p.
z() + sd*v.
z() ;
950 xi = p.
x() + sd*v.
x() ;
951 yi = p.
y() + sd*v.
y() ;
966 xi = p.
x() + sd*v.
x() ;
967 yi = p.
y() + sd*v.
y() ;
980 if ((t3 > tolIRMin2) && (t2 < 0)
988 iden = std::sqrt(t3) ;
1009 snxt = c/(-b+std::sqrt(d));
1029 c = t3 - fRMax*
fRMax;
1040 snxt= c/(-b+std::sqrt(d));
1063 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1068 if (sd < 0.0) { sd = 0.0; }
1071 G4double fTerm = sd-std::fmod(sd,dRmax);
1074 zi = p.
z() + sd*v.
z() ;
1075 xi = p.
x() + sd*v.
x() ;
1076 yi = p.
y() + sd*v.
y() ;
1132 if ( sd < 0 ) { sd = 0.0; }
1133 zi = p.
z() + sd*v.
z() ;
1134 xi = p.
x() + sd*v.
x() ;
1135 yi = p.
y() + sd*v.
y() ;
1142 rho2 = xi*xi + yi*yi ;
1143 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1144 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1147 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1176 if ( sd < 0 ) { sd = 0; }
1177 zi = p.
z() + sd*v.
z() ;
1178 xi = p.
x() + sd*v.
x() ;
1179 yi = p.
y() + sd*v.
y() ;
1186 xi = p.
x() + sd*v.
x() ;
1187 yi = p.
y() + sd*v.
y() ;
1188 rho2 = xi*xi + yi*yi ;
1189 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1190 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1193 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1244 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho,cosPsi;
1249 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1251 safRMin =
fRMin- rho ;
1252 safRMax = rho -
fRMax ;
1266 if ( safRMin > safe ) { safe = safRMin; }
1267 if ( safRMax> safe ) { safe = safRMax; }
1289 if ( safePhi > safe ) { safe = safePhi; }
1292 if ( safe < 0 ) { safe = 0; }
1313 G4double distZLow,distZHigh,calfH,calfL;
1318 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1338 snxt = -distZHigh/calfH ;
1356 sz = -distZLow/calfL ;
1373 if((calfH<=0)&&(calfL<=0))
1389 t1 = 1.0 - v.
z()*v.
z() ;
1390 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1391 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1394 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1414 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1433 roMin2 = t3 - t2*t2/
t1 ;
1449 srd = c/(-b+std::sqrt(d2));
1454 if ( calcNorm ) { *validNorm =
false; }
1465 srd = -b + std::sqrt(d2) ;
1489 srd = -b + std::sqrt(d2) ;
1511 vphi = std::atan2(v.
y(),v.
x()) ;
1517 if ( p.
x() || p.
y() )
1540 sphi = pDistS/compS ;
1544 xi = p.
x() + sphi*v.
x() ;
1545 yi = p.
y() + sphi*v.
y() ;
1585 sphi2 = pDistE/compE ;
1591 xi = p.
x() + sphi2*v.
x() ;
1592 yi = p.
y() + sphi2*v.
y() ;
1603 else { sphi = 0.0 ; }
1614 else { sphi = 0.0 ; }
1660 xi = p.
x() + snxt*v.
x() ;
1661 yi = p.
y() + snxt*v.
y() ;
1667 *validNorm =
false ;
1678 *validNorm =
false ;
1690 *validNorm =
false ;
1708 G4int oldprc = message.precision(16);
1709 message <<
"Undefined side for valid surface normal to solid."
1711 <<
"Position:" << G4endl << G4endl
1712 <<
"p.x() = " << p.
x()/
mm <<
" mm" << G4endl
1713 <<
"p.y() = " << p.
y()/
mm <<
" mm" << G4endl
1714 <<
"p.z() = " << p.
z()/
mm <<
" mm" << G4endl << G4endl
1715 <<
"Direction:" << G4endl << G4endl
1716 <<
"v.x() = " << v.
x() << G4endl
1717 <<
"v.y() = " << v.
y() << G4endl
1718 <<
"v.z() = " << v.
z() << G4endl << G4endl
1719 <<
"Proposed distance :" << G4endl << G4endl
1720 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1721 message.precision(oldprc) ;
1722 G4Exception(
"G4CutTubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1737 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho;
1740 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1742 safRMin = rho -
fRMin ;
1743 safRMax =
fRMax - rho ;
1749 safZLow = std::fabs((p+vZ).dot(
fLowNorm));
1753 safZHigh = std::fabs((p-vZ).dot(
fHighNorm));
1756 if ( safRMin < safe ) { safe = safRMin; }
1757 if ( safRMax< safe ) { safe = safRMax; }
1771 if (safePhi < safe) { safe = safePhi ; }
1773 if ( safe < 0 ) { safe = 0; }
1802 G4int oldprc = os.precision(16);
1803 os <<
"-----------------------------------------------------------\n"
1804 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1805 <<
" ===================================================\n"
1806 <<
" Solid type: G4CutTubs\n"
1807 <<
" Parameters: \n"
1808 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1809 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1810 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1811 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1812 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1813 <<
" low Norm : " <<
fLowNorm <<
" \n"
1815 <<
"-----------------------------------------------------------\n";
1816 os.precision(oldprc);
1827 G4double xRand, yRand, zRand,
phi, cosphi, sinphi, chose,
1828 aOne, aTwo, aThr, aFou;
1837 cosphi = std::cos(phi);
1838 sinphi = std::sin(phi);
1846 if( (chose >=0) && (chose < aOne) )
1848 xRand = fRMax*cosphi;
1849 yRand = fRMax*sinphi;
1854 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1856 xRand = fRMin*cosphi;
1857 yRand = fRMin*sinphi;
1862 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1864 xRand = rRand*cosphi;
1865 yRand = rRand*sinphi;
1869 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1871 xRand = rRand*cosphi;
1872 yRand = rRand*sinphi;
1876 else if( (chose >= aOne + aTwo + 2.*aThr)
1877 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1907 typedef G4int G4int4[4];
1913 G4double3* xyz =
new G4double3[
nn];
1914 G4int4* faces =
new G4int4[nf] ;
1937 for(
G4int i=0; i<nf ; ++i)
1942 faces[i][
k]=iNodes[
k];
1966 G4double zXLow1,zXLow2,zYLow1,zYLow2;
1967 G4double zXHigh1,zXHigh2,zYHigh1,zYHigh2;
1977 if ( (zXLow1>zXHigh1) ||(zXLow2>zXHigh2)
1978 || (zYLow1>zYHigh1) ||(zYLow2>zYHigh2)) {
return true; }
2019 G4bool in_range_low =
false;
2020 G4bool in_range_hi =
false;
2025 if (phiLow<0) { phiLow+=
twopi; }
2027 if (ddp<0) { ddp +=
twopi; }
2030 xc =
fRMin*std::cos(phiLow);
2031 yc =
fRMin*std::sin(phiLow);
2033 xc =
fRMax*std::cos(phiLow);
2034 yc =
fRMax*std::sin(phiLow);
2036 if (in_range_low) { zmin =
std::min(zmin,
z1); }
2038 in_range_low =
true;
2045 if (phiHigh<0) { phiHigh+=
twopi; }
2047 if (ddp<0) { ddp +=
twopi; }
2050 xc =
fRMin*std::cos(phiHigh);
2051 yc =
fRMin*std::sin(phiHigh);
2053 xc =
fRMax*std::cos(phiHigh);
2054 yc =
fRMax*std::sin(phiHigh);
2056 if (in_range_hi) { zmax =
std::min(zmax,
z1); }
2087 for (i = 1; i < 4; ++i)
2089 if(z[i] < z[i-1])
z1=z[i];
2101 for (i = 1; i < 4; ++i)
2103 if(z[4+i] > z[4+i-1]) {
z1=z[4+i]; }
2106 if (in_range_hi) { zmax =
std::max(zmax,
z1); }