35#if !defined(G4GEOM_USE_UCTUBS)
68 :
G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz),
69 fSPhi(0.), fDPhi(0.), fZMin(0.), fZMax(0.)
75 halfRadTolerance = kRadTolerance*0.5;
76 halfAngTolerance = kAngTolerance*0.5;
80 std::ostringstream message;
81 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
84 if ( (pRMin >= pRMax) || (pRMin < 0) )
86 std::ostringstream message;
87 message <<
"Invalid values for radii in solid: " <<
GetName()
89 <<
" pRMin = " << pRMin <<
", pRMax = " << pRMax;
100 if ( ( pLowNorm.
x() == 0.0) && ( pLowNorm.
y() == 0.0)
101 && ( pHighNorm.
x() == 0.0) && (pHighNorm.
y() == 0.0) )
103 std::ostringstream message;
104 message <<
"Inexisting Low/High Normal to Z plane or Parallel to Z."
106 <<
"Normals to Z plane are " << pLowNorm <<
" and "
107 << pHighNorm <<
" in solid: " <<
GetName() <<
" \n";
108 G4Exception(
"G4CutTubs::G4CutTubs()",
"GeomSolids1001",
114 if (pLowNorm.
mag2() == 0.) { pLowNorm.
setZ(-1.); }
115 if (pHighNorm.
mag2()== 0.) { pHighNorm.
setZ(1.); }
120 if (pLowNorm.
mag2() != 1.) { pLowNorm = pLowNorm.
unit(); }
121 if (pHighNorm.
mag2()!= 1.) { pHighNorm = pHighNorm.
unit(); }
125 if( (pLowNorm.
mag2() != 0.) && (pHighNorm.
mag2()!= 0. ) )
127 if( ( pLowNorm.
z()>= 0. ) || ( pHighNorm.
z() <= 0.))
129 std::ostringstream message;
130 message <<
"Invalid Low or High Normal to Z plane; "
131 "has to point outside Solid." <<
G4endl
132 <<
"Invalid Norm to Z plane (" << pLowNorm <<
" or "
133 << pHighNorm <<
") in solid: " <<
GetName();
134 G4Exception(
"G4CutTubs::G4CutTubs()",
"GeomSolids0002",
139 fHighNorm = pHighNorm;
146 std::ostringstream message;
147 message <<
"Invalid normals to Z plane in solid : " <<
GetName() <<
G4endl
148 <<
"Cut planes are crossing inside lateral surface !!!\n"
149 <<
" Solid type: G4CutTubs\n"
151 <<
" inner radius : " << fRMin/mm <<
" mm \n"
152 <<
" outer radius : " << fRMax/mm <<
" mm \n"
153 <<
" half length Z: " << fDz/mm <<
" mm \n"
154 <<
" starting phi : " << fSPhi/degree <<
" degrees \n"
155 <<
" delta phi : " << fDPhi/degree <<
" degrees \n"
156 <<
" low Norm : " << fLowNorm <<
" \n"
157 <<
" high Norm : " << fHighNorm;
158 G4Exception(
"G4CutTubs::G4CutTubs()",
"GeomSolids0002",
193 if (
this == &rhs) {
return *
this; }
201 kRadTolerance = rhs.kRadTolerance; kAngTolerance = rhs.kAngTolerance;
202 fRMin = rhs.fRMin; fRMax = rhs.fRMax; fDz = rhs.fDz;
203 fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
204 fZMin = rhs.fZMin; fZMax = rhs.fZMax;
205 sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPhi;
206 cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = rhs.cosHDPhiIT;
207 sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPhi;
208 sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPhi;
209 fPhiFullCutTube = rhs.fPhiFullCutTube;
210 halfCarTolerance = rhs.halfCarTolerance;
211 halfRadTolerance = rhs.halfRadTolerance;
212 halfAngTolerance = rhs.halfAngTolerance;
213 fLowNorm = rhs.fLowNorm; fHighNorm = rhs.fHighNorm;
224 constexpr G4int nphi = 200, nrho = 100;
236 G4double volume = dz*dphi*(rmax*rmax - rmin*rmin);
247 G4double delrho = (rmax - rmin)/nrho;
250 for (
G4int irho=0; irho<nrho; ++irho)
253 G4double r2 = rmin + delrho*(irho + 1);
255 G4double sector = 0.5*delphi*(r2*r2 - r1*r1);
256 for (
G4int iphi=0; iphi<nphi; ++iphi)
258 G4double phi = sphi + delphi*(iphi + 0.5);
259 G4double h = nx*rho*std::cos(phi) + ny*rho*std::sin(phi) + 2.*dz;
275 constexpr G4int nphi = 400;
302 for (
G4int iphi=0; iphi<nphi; ++iphi)
304 G4double phi = sphi + delphi*(iphi + 0.5);
307 sinner += rmin*(nx*cosphi + ny*sinphi) + 2.*dz;
308 souter += rmax*(nx*cosphi + ny*sinphi) + 2.*dz;
310 sinner *= delphi*rmin;
311 souter *= delphi*rmax;
314 G4double scut = (dphi == twopi) ? 0. : 2.*dz*(rmax - rmin);
315 G4double szero = 0.5*dphi*(rmax*rmax - rmin*rmin);
316 G4double slow = szero/std::abs(nbot.
z());
317 G4double shigh = szero/std::abs(ntop.
z());
318 fSurfaceArea = sinner + souter + 2.*scut + slow + shigh;
340 G4double mag, topx, topy, dists, diste;
347 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
348 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
349 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
350 dists = sinSphi*topx - cosSphi*topy;
351 diste = -sinEphi*topx + cosEphi*topy;
355 if (dists > 0 && diste > 0)iftop =
false;
360 if (dists <= 0 && diste <= 0) iftop =
true;
364 zmin = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() - dz;
368 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() - dz;
369 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() - dz;
370 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() - dz;
371 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() - dz;
372 zmin = std::min(std::min(std::min(z1,z2),z3),z4);
379 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
380 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
381 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
382 dists = sinSphi*topx - cosSphi*topy;
383 diste = -sinEphi*topx + cosEphi*topy;
387 if (dists > 0 && diste > 0) iftop =
false;
392 if (dists <= 0 && diste <= 0) iftop =
true;
396 zmax = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() + dz;
400 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() + dz;
401 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() + dz;
402 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() + dz;
403 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() + dz;
404 zmax = std::max(std::max(std::max(z1,z2),z3),z4);
416 pMin.
set(vmin.
x(),vmin.
y(), zmin);
417 pMax.
set(vmax.
x(),vmax.
y(), zmax);
421 pMin.
set(-rmax,-rmax, zmin);
422 pMax.
set( rmax, rmax, zmax);
427 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
429 std::ostringstream message;
430 message <<
"Bad bounding box (min >= max) for solid: "
432 <<
"\npMin = " << pMin
433 <<
"\npMax = " << pMax;
434 G4Exception(
"G4CutTubs::BoundingLimits()",
"GeomMgt0001",
463 return exist = pMin < pMax;
475 const G4int NSTEPS = 24;
477 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
480 G4double sinHalf = std::sin(0.5*ang);
481 G4double cosHalf = std::cos(0.5*ang);
482 G4double sinStep = 2.*sinHalf*cosHalf;
483 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
488 if (rmin == 0 && dphi == twopi)
494 for (
G4int k=0; k<NSTEPS; ++k)
496 baseA[k].set(rext*cosCur,rext*sinCur,zmin);
497 baseB[k].set(rext*cosCur,rext*sinCur,zmax);
500 sinCur = sinCur*cosStep + cosCur*sinStep;
501 cosCur = cosCur*cosStep - sinTmp*sinStep;
503 std::vector<const G4ThreeVectorList *> polygons(2);
504 polygons[0] = &baseA;
505 polygons[1] = &baseB;
515 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
516 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
520 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
521 pols[0][0].set(rmin*cosStart,rmin*sinStart,zmax);
522 pols[0][1].set(rmin*cosStart,rmin*sinStart,zmin);
523 pols[0][2].set(rmax*cosStart,rmax*sinStart,zmin);
524 pols[0][3].set(rmax*cosStart,rmax*sinStart,zmax);
525 for (
G4int k=1; k<ksteps+1; ++k)
527 pols[k][0].set(rmin*cosCur,rmin*sinCur,zmax);
528 pols[k][1].set(rmin*cosCur,rmin*sinCur,zmin);
529 pols[k][2].set(rext*cosCur,rext*sinCur,zmin);
530 pols[k][3].set(rext*cosCur,rext*sinCur,zmax);
533 sinCur = sinCur*cosStep + cosCur*sinStep;
534 cosCur = cosCur*cosStep - sinTmp*sinStep;
536 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd,zmax);
537 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,zmin);
538 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,zmin);
539 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd,zmax);
542 std::vector<const G4ThreeVectorList *> polygons;
543 polygons.resize(ksteps+2);
544 for (
G4int k=0; k<ksteps+2; ++k) { polygons[k] = &pols[k]; }
562 G4double zinLow =(p+vZ).dot(fLowNorm);
563 if (zinLow > halfCarTolerance) {
return kOutside; }
567 G4double zinHigh = (p-vZ).dot(fHighNorm);
568 if (zinHigh > halfCarTolerance) {
return kOutside; }
574 G4double tolRMin = fRMin - halfRadTolerance;
575 G4double tolRMax = fRMax + halfRadTolerance;
576 if ( tolRMin < 0 ) { tolRMin = 0; }
578 if (r2 < tolRMin*tolRMin || r2 > tolRMax*tolRMax) {
return kOutside; }
584 if ((tolRMin == 0) && (std::fabs(p.
x()) <= halfCarTolerance)
585 && (std::fabs(p.
y()) <= halfCarTolerance))
595 G4double sphi = fSPhi - halfAngTolerance;
596 G4double ephi = sphi + fDPhi + kAngTolerance;
597 if ((phi0 >= sphi && phi0 <= ephi) ||
598 (phi1 >= sphi && phi1 <= ephi) ||
599 (phi2 >= sphi && phi2 <= ephi)) in =
kSurface;
602 sphi += kAngTolerance;
603 ephi -= kAngTolerance;
604 if ((phi0 >= sphi && phi0 <= ephi) ||
605 (phi1 >= sphi && phi1 <= ephi) ||
606 (phi2 >= sphi && phi2 <= ephi)) in =
kInside;
612 if ((zinLow >= -halfCarTolerance) || (zinHigh >= -halfCarTolerance))
619 if (fRMin != 0.0) { tolRMin = fRMin + halfRadTolerance; }
620 else { tolRMin = 0; }
621 tolRMax = fRMax - halfRadTolerance;
622 if (((r2 <= tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax)) &&
623 (r2 >= halfRadTolerance*halfRadTolerance))
639 G4int noSurfaces = 0;
641 G4double distZLow,distZHigh, distRMin, distRMax;
642 G4double distSPhi = kInfinity, distEPhi = kInfinity;
649 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
651 distRMin = std::fabs(rho - fRMin);
652 distRMax = std::fabs(rho - fRMax);
656 distZLow =std::fabs((p+vZ).dot(fLowNorm));
660 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
662 if (!fPhiFullCutTube)
664 if ( rho > halfCarTolerance )
666 pPhi = std::atan2(p.
y(),p.
x());
668 if(pPhi < fSPhi- halfCarTolerance) { pPhi += twopi; }
669 else if(pPhi > fSPhi+fDPhi+ halfCarTolerance) { pPhi -= twopi; }
671 distSPhi = std::fabs(pPhi - fSPhi);
672 distEPhi = std::fabs(pPhi - fSPhi - fDPhi);
674 else if( fRMin == 0.0 )
682 if ( rho > halfCarTolerance ) { nR =
G4ThreeVector(p.
x()/rho,p.
y()/rho,0); }
684 if( distRMax <= halfCarTolerance )
689 if( (fRMin != 0.0) && (distRMin <= halfCarTolerance) )
696 if (distSPhi <= halfAngTolerance)
701 if (distEPhi <= halfAngTolerance)
707 if (distZLow <= halfCarTolerance)
712 if (distZHigh <= halfCarTolerance)
715 sumnorm += fHighNorm;
717 if ( noSurfaces == 0 )
720 G4Exception(
"G4CutTubs::SurfaceNormal(p)",
"GeomSolids1002",
723 G4cout<<
"G4CutTubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
725 G4cout.precision(oldprc) ;
729 else if ( noSurfaces == 1 ) { norm = sumnorm; }
730 else { norm = sumnorm.
unit(); }
748 G4double distRMin, distRMax, distSPhi, distEPhi, distMin ;
751 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
753 distRMin = std::fabs(rho - fRMin) ;
754 distRMax = std::fabs(rho - fRMax) ;
758 distZLow =std::fabs((p+vZ).dot(fLowNorm));
762 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
763 distZ=std::min(distZLow,distZHigh);
765 if (distRMin < distRMax)
767 if ( distZ < distRMin )
780 if ( distZ < distRMax )
791 if (!fPhiFullCutTube && (rho != 0.0) )
793 phi = std::atan2(p.
y(),p.
x()) ;
795 if ( phi < 0 ) { phi += twopi; }
799 distSPhi = std::fabs(phi - (fSPhi + twopi))*rho ;
803 distSPhi = std::fabs(phi - fSPhi)*rho ;
805 distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
807 if (distSPhi < distEPhi)
809 if ( distSPhi < distMin )
816 if ( distEPhi < distMin )
836 if ( distZHigh > distZLow ) { norm = fHighNorm ; }
837 else { norm = fLowNorm; }
855 "Undefined side for valid surface normal to solid.");
895 G4double Dist, sd=0, xi, yi, zi, rho2, inum, iden, cosPsi, Comp,calf ;
900 if (fRMin > kRadTolerance)
902 tolORMin2 = (fRMin - halfRadTolerance)*(fRMin - halfRadTolerance) ;
903 tolIRMin2 = (fRMin + halfRadTolerance)*(fRMin + halfRadTolerance) ;
910 tolORMax2 = (fRMax + halfRadTolerance)*(fRMax + halfRadTolerance) ;
911 tolIRMax2 = (fRMax - halfRadTolerance)*(fRMax - halfRadTolerance) ;
917 distZLow =(p+vZ).dot(fLowNorm);
921 distZHigh = (p-vZ).dot(fHighNorm);
923 if ( distZLow >= -halfCarTolerance )
925 calf = v.
dot(fLowNorm);
929 if(sd < 0.0) { sd = 0.0; }
931 xi = p.
x() + sd*v.
x() ;
932 yi = p.
y() + sd*v.
y() ;
933 rho2 = xi*xi + yi*yi ;
937 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
939 if (!fPhiFullCutTube && (rho2 != 0.0))
943 inum = xi*cosCPhi + yi*sinCPhi ;
944 iden = std::sqrt(rho2) ;
946 if (cosPsi >= cosHDPhiIT) {
return sd ; }
956 if ( sd<halfCarTolerance )
958 if(calf>=0) { sd=kInfinity; }
964 if(distZHigh >= -halfCarTolerance )
966 calf = v.
dot(fHighNorm);
969 sd = -distZHigh/calf;
971 if(sd < 0.0) { sd = 0.0; }
973 xi = p.
x() + sd*v.
x() ;
974 yi = p.
y() + sd*v.
y() ;
975 rho2 = xi*xi + yi*yi ;
979 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
981 if (!fPhiFullCutTube && (rho2 != 0.0))
985 inum = xi*cosCPhi + yi*sinCPhi ;
986 iden = std::sqrt(rho2) ;
988 if (cosPsi >= cosHDPhiIT) {
return sd ; }
998 if ( sd<halfCarTolerance )
1000 if(calf>=0) { sd=kInfinity; }
1017 t1 = 1.0 - v.
z()*v.
z() ;
1018 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1019 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1023 c = t3 - fRMax*fRMax ;
1025 if ((t3 >= tolORMax2) && (t2<0))
1034 sd = c/(-b+std::sqrt(d));
1039 G4double fTerm = sd-std::fmod(sd,dRmax);
1044 zi = p.
z() + sd*v.
z() ;
1045 xi = p.
x() + sd*v.
x() ;
1046 yi = p.
y() + sd*v.
y() ;
1047 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1048 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1050 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1051 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1055 if (fPhiFullCutTube)
1061 xi = p.
x() + sd*v.
x() ;
1062 yi = p.
y() + sd*v.
y() ;
1063 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMax ;
1064 if (cosPsi >= cosHDPhiIT) {
return sd ; }
1075 if ((t3 > tolIRMin2) && (t2 < 0)
1076 && (std::fabs(p.
z()) <= std::fabs(
GetCutZ(p))-halfCarTolerance ))
1080 if (!fPhiFullCutTube)
1082 inum = p.
x()*cosCPhi + p.
y()*sinCPhi ;
1083 iden = std::sqrt(t3) ;
1084 cosPsi = inum/iden ;
1085 if (cosPsi >= cosHDPhiIT)
1104 snxt = c/(-b+std::sqrt(d));
1106 if ( snxt < halfCarTolerance ) { snxt=0; }
1124 c = t3 - fRMax*fRMax;
1135 snxt= c/(-b+std::sqrt(d));
1137 if ( snxt < halfCarTolerance ) { snxt=0; }
1151 c = (t3 - fRMin*fRMin)/t1 ;
1158 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1159 if (sd >= -10*halfCarTolerance)
1163 if (sd < 0.0) { sd = 0.0; }
1166 G4double fTerm = sd-std::fmod(sd,dRmax);
1169 zi = p.
z() + sd*v.
z() ;
1170 xi = p.
x() + sd*v.
x() ;
1171 yi = p.
y() + sd*v.
y() ;
1172 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1173 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1175 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1176 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1180 if ( fPhiFullCutTube )
1186 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMin ;
1187 if (cosPsi >= cosHDPhiIT)
1211 if ( !fPhiFullCutTube )
1215 Comp = v.
x()*sinSPhi - v.
y()*cosSPhi ;
1219 Dist = (p.
y()*cosSPhi - p.
x()*sinSPhi) ;
1221 if ( Dist < halfCarTolerance )
1227 if ( sd < 0 ) { sd = 0.0; }
1228 zi = p.
z() + sd*v.
z() ;
1229 xi = p.
x() + sd*v.
x() ;
1230 yi = p.
y() + sd*v.
y() ;
1231 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1232 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1234 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1235 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1237 rho2 = xi*xi + yi*yi ;
1238 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1239 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1240 && ( v.
y()*cosSPhi - v.
x()*sinSPhi > 0 )
1241 && ( v.
x()*cosSPhi + v.
y()*sinSPhi >= 0 ) )
1242 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1243 && (v.
y()*cosSPhi - v.
x()*sinSPhi > 0)
1244 && (v.
x()*cosSPhi + v.
y()*sinSPhi < 0) ) )
1249 if ((yi*cosCPhi-xi*sinCPhi) <= halfCarTolerance) { snxt = sd; }
1259 Comp = -(v.
x()*sinEPhi - v.
y()*cosEPhi) ;
1263 Dist = -(p.
y()*cosEPhi - p.
x()*sinEPhi) ;
1265 if ( Dist < halfCarTolerance )
1271 if ( sd < 0 ) { sd = 0; }
1272 zi = p.
z() + sd*v.
z() ;
1273 xi = p.
x() + sd*v.
x() ;
1274 yi = p.
y() + sd*v.
y() ;
1275 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1276 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1278 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1279 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1281 xi = p.
x() + sd*v.
x() ;
1282 yi = p.
y() + sd*v.
y() ;
1283 rho2 = xi*xi + yi*yi ;
1284 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1285 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1286 && (v.
x()*sinEPhi - v.
y()*cosEPhi > 0)
1287 && (v.
x()*cosEPhi + v.
y()*sinEPhi >= 0) )
1288 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1289 && (v.
x()*sinEPhi - v.
y()*cosEPhi > 0)
1290 && (v.
x()*cosEPhi + v.
y()*sinEPhi < 0) ) )
1295 if ( (yi*cosCPhi-xi*sinCPhi) >= -halfCarTolerance )
1306 if ( snxt<halfCarTolerance ) { snxt=0; }
1339 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho,cosPsi;
1344 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1346 safRMin = fRMin- rho ;
1347 safRMax = rho - fRMax ;
1353 safZLow = (p+vZ).dot(fLowNorm);
1357 safZHigh = (p-vZ).dot(fHighNorm);
1359 safe = std::max(safZLow,safZHigh);
1361 if ( safRMin > safe ) { safe = safRMin; }
1362 if ( safRMax> safe ) { safe = safRMax; }
1366 if ( (!fPhiFullCutTube) && ((rho) != 0.0) )
1370 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/rho ;
1372 if ( cosPsi < cosHDPhi )
1376 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0 )
1378 safePhi = std::fabs(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
1382 safePhi = std::fabs(p.
x()*sinEPhi - p.
y()*cosEPhi) ;
1384 if ( safePhi > safe ) { safe = safePhi; }
1387 if ( safe < 0 ) { safe = 0; }
1406 G4double snxt=kInfinity, srd=kInfinity,sz=kInfinity, sphi=kInfinity ;
1407 G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
1408 G4double distZLow,distZHigh,calfH,calfL;
1413 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1420 distZLow =(p+vZ).dot(fLowNorm);
1424 distZHigh = (p-vZ).dot(fHighNorm);
1426 calfH = v.
dot(fHighNorm);
1427 calfL = v.
dot(fLowNorm);
1431 if ( distZHigh < halfCarTolerance )
1433 snxt = -distZHigh/calfH ;
1449 if ( distZLow < halfCarTolerance )
1451 sz = -distZLow/calfL ;
1468 if((calfH<=0)&&(calfL<=0))
1484 t1 = 1.0 - v.
z()*v.
z() ;
1485 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1486 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1488 if ( snxt > 10*(fDz+fRMax) ) { roi2 = 2*fRMax*fRMax; }
1489 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1495 if ( (t2 >= 0.0) && (roi2 > fRMax*(fRMax + kRadTolerance)) )
1499 deltaR = t3 - fRMax*fRMax ;
1504 if ( deltaR < -kRadTolerance*fRMax )
1509 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1528 roMin2 = t3 - t2*t2/t1 ;
1530 if ( (fRMin != 0.0) && (roMin2 < fRMin*(fRMin - kRadTolerance)) )
1532 deltaR = t3 - fRMin*fRMin ;
1542 if (deltaR > kRadTolerance*fRMin)
1544 srd = c/(-b+std::sqrt(d2));
1549 if ( calcNorm ) { *validNorm =
false; }
1555 deltaR = t3 - fRMax*fRMax ;
1560 srd = -b + std::sqrt(d2) ;
1575 else if ( roi2 > fRMax*(fRMax + kRadTolerance) )
1578 deltaR = t3 - fRMax*fRMax ;
1584 srd = -b + std::sqrt(d2) ;
1601 if ( !fPhiFullCutTube )
1606 vphi = std::atan2(v.
y(),v.
x()) ;
1608 if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
1609 else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; }
1612 if ( (p.
x() != 0.0) || (p.
y() != 0.0) )
1616 pDistS = p.
x()*sinSPhi - p.
y()*cosSPhi ;
1617 pDistE = -p.
x()*sinEPhi + p.
y()*cosEPhi ;
1621 compS = -sinSPhi*v.
x() + cosSPhi*v.
y() ;
1622 compE = sinEPhi*v.
x() - cosEPhi*v.
y() ;
1626 if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
1627 && (pDistE <= halfCarTolerance) ) )
1628 || ( (fDPhi > pi) && ((pDistS <= halfCarTolerance)
1629 || (pDistE <= halfCarTolerance) ) ) )
1635 sphi = pDistS/compS ;
1637 if (sphi >= -halfCarTolerance)
1639 xi = p.
x() + sphi*v.
x() ;
1640 yi = p.
y() + sphi*v.
y() ;
1649 if (((fSPhi-halfAngTolerance)<=vphi)
1650 &&((fSPhi+fDPhi+halfAngTolerance)>=vphi))
1655 else if ( yi*cosCPhi-xi*sinCPhi >=0 )
1662 if ( pDistS > -halfCarTolerance )
1680 sphi2 = pDistE/compE ;
1684 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1686 xi = p.
x() + sphi2*v.
x() ;
1687 yi = p.
y() + sphi2*v.
y() ;
1693 if( (fSPhi-halfAngTolerance > vphi)
1694 ||(fSPhi+fDPhi+halfAngTolerance < vphi) )
1697 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1698 else { sphi = 0.0 ; }
1703 if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
1708 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1709 else { sphi = 0.0 ; }
1724 if ( (fSPhi - halfAngTolerance <= vphi)
1725 && (vphi <= fSPhi + fDPhi + halfAngTolerance ) )
1755 xi = p.
x() + snxt*v.
x() ;
1756 yi = p.
y() + snxt*v.
y() ;
1762 *validNorm = false ;
1773 *validNorm = false ;
1785 *validNorm = false ;
1802 std::ostringstream message;
1803 G4long oldprc = message.precision(16);
1804 message <<
"Undefined side for valid surface normal to solid."
1807 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1808 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1811 <<
"v.x() = " << v.
x() <<
G4endl
1812 <<
"v.y() = " << v.
y() <<
G4endl
1815 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
1816 message.precision(oldprc) ;
1817 G4Exception(
"G4CutTubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1822 if ( snxt<halfCarTolerance ) { snxt=0 ; }
1832 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho;
1835 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1837 safRMin = rho - fRMin ;
1838 safRMax = fRMax - rho ;
1844 safZLow = std::fabs((p+vZ).dot(fLowNorm));
1848 safZHigh = std::fabs((p-vZ).dot(fHighNorm));
1849 safe = std::min(safZLow,safZHigh);
1851 if ( safRMin < safe ) { safe = safRMin; }
1852 if ( safRMax< safe ) { safe = safRMax; }
1856 if ( !fPhiFullCutTube )
1858 if ( p.
y()*cosCPhi-p.
x()*sinCPhi <= 0 )
1860 safePhi = -(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
1864 safePhi = (p.
x()*sinEPhi - p.
y()*cosEPhi) ;
1866 if (safePhi < safe) { safe = safePhi ; }
1868 if ( safe < 0 ) { safe = 0; }
1879 return {
"G4CutTubs"};
1897 G4long oldprc = os.precision(16);
1898 os <<
"-----------------------------------------------------------\n"
1899 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1900 <<
" ===================================================\n"
1901 <<
" Solid type: G4CutTubs\n"
1902 <<
" Parameters: \n"
1903 <<
" inner radius : " << fRMin/mm <<
" mm \n"
1904 <<
" outer radius : " << fRMax/mm <<
" mm \n"
1905 <<
" half length Z: " << fDz/mm <<
" mm \n"
1906 <<
" starting phi : " << fSPhi/degree <<
" degrees \n"
1907 <<
" delta phi : " << fDPhi/degree <<
" degrees \n"
1908 <<
" low Norm : " << fLowNorm <<
" \n"
1909 <<
" high Norm : " <<fHighNorm <<
" \n"
1910 <<
"-----------------------------------------------------------\n";
1911 os.precision(oldprc);
1923 if (fZMin == 0. && fZMax == 0.)
1946 G4double sbase = 0.5*dphi*(rrmax - rrmin);
1947 G4double sbot = sbase/std::abs(nbot.
z());
1948 G4double stop = sbase/std::abs(ntop.
z());
1949 G4double scut = (dphi == twopi) ? 0. : hmax*(rmax - rmin);
1950 G4double ssurf[6] = { scut, scut, sbot, stop, dphi*rmax*hmax, dphi*rmin*hmax };
1951 ssurf[1] += ssurf[0];
1952 ssurf[2] += ssurf[1];
1953 ssurf[3] += ssurf[2];
1954 ssurf[4] += ssurf[3];
1955 ssurf[5] += ssurf[4];
1957 constexpr G4int ntry = 100000;
1958 for (
G4int i=0; i<ntry; ++i)
1963 k -= (
G4int)(select <= ssurf[4]);
1964 k -= (
G4int)(select <= ssurf[3]);
1965 k -= (
G4int)(select <= ssurf[2]);
1966 k -= (
G4int)(select <= ssurf[1]);
1967 k -= (
G4int)(select <= ssurf[0]);
1991 G4double z = -fDz - (x*nbot.
x() + y*nbot.
y())/nbot.
z();
2000 G4double z = fDz - (x*ntop.
x() + y*ntop.
y())/ntop.
z();
2022 if ((ntop.
dot(p) - fDz*ntop.
z()) > 0.)
continue;
2023 if ((nbot.
dot(p) + fDz*nbot.
z()) > 0.)
continue;
2028 G4double x = rmax*std::cos(sphi + 0.5*dphi);
2029 G4double y = rmax*std::sin(sphi + 0.5*dphi);
2030 G4double z = fDz - (x*ntop.
x() + y*ntop.
y())/ntop.
z();
2046 typedef G4int G4int4[4];
2052 auto xyz =
new G4double3[nn];
2053 auto faces =
new G4int4[nf] ;
2055 for(
G4int i=0; i<nn; ++i)
2074 G4int* iEdge =
nullptr;
2076 for(
G4int i=0; i<nf ; ++i)
2079 for(
G4int k=0; k<n; ++k)
2081 faces[i][k]=iNodes[k];
2083 for(
G4int k=n; k<4; ++k)
2088 ph->createPolyhedron(nn,nf,xyz,faces);
2107 constexpr G4int npoints = 30;
2122 G4double cosdel = std::cos(delphi);
2123 G4double sindel = std::sin(delphi);
2125 for (
G4int i=0; i<npoints+1; ++i)
2127 G4double h = nx*cosphi + ny*sinphi + hzero;
2128 if (h < 0.)
return true;
2130 sinphi = sintmp*cosdel + cosphi*sindel;
2131 cosphi = cosphi*cosdel - sintmp*sindel;
2145 if(fLowNorm.
z()!=0.)
2147 newz = -fDz-(p.
x()*fLowNorm.
x()+p.
y()*fLowNorm.
y())/fLowNorm.
z();
2152 if(fHighNorm.
z()!=0.)
2154 newz = fDz-(p.
x()*fHighNorm.
x()+p.
y()*fHighNorm.
y())/fHighNorm.
z();
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
double dot(const Hep3Vector &) const
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 & operator=(const G4CSGSolid &rhs)
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4ThreeVector GetPointOnSurface() const override
G4ThreeVector GetHighNorm() const
G4double GetStartPhiAngle() const
G4double GetZHalfLength() const
G4double GetInnerRadius() const
G4ThreeVector GetLowNorm() const
G4VSolid * Clone() const override
G4double GetSurfaceArea() override
G4GeometryType GetEntityType() const override
G4double GetCutZ(const G4ThreeVector &p) const
G4double GetDeltaPhiAngle() const
G4double GetOuterRadius() const
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4bool IsCrossingCutPlanes() const
G4double GetSinStartPhi() const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4CutTubs & operator=(const G4CutTubs &rhs)
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
EInside Inside(const G4ThreeVector &p) const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4double GetSinEndPhi() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
G4double GetCosStartPhi() const
G4double GetCosEndPhi() const
std::ostream & StreamInfo(std::ostream &os) const override
G4CutTubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi, G4ThreeVector pLowNorm, G4ThreeVector pHighNorm)
G4double GetCubicVolume() override
G4Polyhedron * CreatePolyhedron() const override
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
virtual void AddSolid(const G4Box &)=0
G4Point3D GetVertex(G4int index) const
void GetFacet(G4int iFace, G4int &n, G4int *iNodes, G4int *edgeFlags=nullptr, G4int *iFaces=nullptr) const
G4int GetNoFacets() const
G4int GetNoVertices() const