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()) && ( !pLowNorm.
y())
101 && ( !pHighNorm.
x()) && (!pHighNorm.
y()) )
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",
169 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
170 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.), fZMin(0.), fZMax(0.),
171 sinCPhi(0.), cosCPhi(0.), cosHDPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
172 sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
173 halfCarTolerance(0.), halfRadTolerance(0.), halfAngTolerance(0.),
192 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
193 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
194 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
195 fZMin(rhs.fZMin), fZMax(rhs.fZMax),
196 sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi), cosHDPhi(rhs.cosHDPhi),
197 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT),
198 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
199 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi),
200 fPhiFullCutTube(rhs.fPhiFullCutTube),
201 halfCarTolerance(rhs.halfCarTolerance),
202 halfRadTolerance(rhs.halfRadTolerance),
203 halfAngTolerance(rhs.halfAngTolerance),
204 fLowNorm(rhs.fLowNorm), fHighNorm(rhs.fHighNorm)
216 if (
this == &rhs) {
return *
this; }
224 kRadTolerance = rhs.kRadTolerance; kAngTolerance = rhs.kAngTolerance;
225 fRMin = rhs.fRMin; fRMax = rhs.fRMax; fDz = rhs.fDz;
226 fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
227 fZMin = rhs.fZMin; fZMax = rhs.fZMax;
228 sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPhi;
229 cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = rhs.cosHDPhiIT;
230 sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPhi;
231 sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPhi;
232 fPhiFullCutTube = rhs.fPhiFullCutTube;
233 halfCarTolerance = rhs.halfCarTolerance;
234 halfRadTolerance = rhs.halfRadTolerance;
235 halfAngTolerance = rhs.halfAngTolerance;
236 fLowNorm = rhs.fLowNorm; fHighNorm = rhs.fHighNorm;
247 constexpr G4int nphi = 200, nrho = 100;
259 G4double volume = dz*dphi*(rmax*rmax - rmin*rmin);
270 G4double delrho = (rmax - rmin)/nrho;
273 for (
G4int irho=0; irho<nrho; ++irho)
276 G4double r2 = rmin + delrho*(irho + 1);
278 G4double sector = 0.5*delphi*(r2*r2 - r1*r1);
279 for (
G4int iphi=0; iphi<nphi; ++iphi)
281 G4double phi = sphi + delphi*(iphi + 0.5);
282 G4double h = nx*rho*std::cos(phi) + ny*rho*std::sin(phi) + 2.*dz;
298 constexpr G4int nphi = 400;
325 for (
G4int iphi=0; iphi<nphi; ++iphi)
327 G4double phi = sphi + delphi*(iphi + 0.5);
330 sinner += rmin*(nx*cosphi + ny*sinphi) + 2.*dz;
331 souter += rmax*(nx*cosphi + ny*sinphi) + 2.*dz;
333 sinner *= delphi*rmin;
334 souter *= delphi*rmax;
337 G4double scut = (dphi == twopi) ? 0. : 2.*dz*(rmax - rmin);
338 G4double szero = 0.5*dphi*(rmax*rmax - rmin*rmin);
339 G4double slow = szero/std::abs(nbot.
z());
340 G4double shigh = szero/std::abs(ntop.
z());
341 fSurfaceArea = sinner + souter + 2.*scut + slow + shigh;
363 G4double mag, topx, topy, dists, diste;
370 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
371 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
372 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
373 dists = sinSphi*topx - cosSphi*topy;
374 diste = -sinEphi*topx + cosEphi*topy;
378 if (dists > 0 && diste > 0)iftop =
false;
383 if (dists <= 0 && diste <= 0) iftop =
true;
387 zmin = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() - dz;
391 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() - dz;
392 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() - dz;
393 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() - dz;
394 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() - dz;
395 zmin = std::min(std::min(std::min(z1,z2),z3),z4);
402 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
403 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
404 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
405 dists = sinSphi*topx - cosSphi*topy;
406 diste = -sinEphi*topx + cosEphi*topy;
410 if (dists > 0 && diste > 0) iftop =
false;
415 if (dists <= 0 && diste <= 0) iftop =
true;
419 zmax = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() + dz;
423 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() + dz;
424 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() + dz;
425 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() + dz;
426 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() + dz;
427 zmax = std::max(std::max(std::max(z1,z2),z3),z4);
439 pMin.
set(vmin.
x(),vmin.
y(), zmin);
440 pMax.
set(vmax.
x(),vmax.
y(), zmax);
444 pMin.
set(-rmax,-rmax, zmin);
445 pMax.
set( rmax, rmax, zmax);
450 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
452 std::ostringstream message;
453 message <<
"Bad bounding box (min >= max) for solid: "
455 <<
"\npMin = " << pMin
456 <<
"\npMax = " << pMax;
457 G4Exception(
"G4CutTubs::BoundingLimits()",
"GeomMgt0001",
486 return exist = (pMin < pMax) ?
true :
false;
498 const G4int NSTEPS = 24;
500 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
503 G4double sinHalf = std::sin(0.5*ang);
504 G4double cosHalf = std::cos(0.5*ang);
505 G4double sinStep = 2.*sinHalf*cosHalf;
506 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
511 if (rmin == 0 && dphi == twopi)
517 for (
G4int k=0; k<NSTEPS; ++k)
519 baseA[k].set(rext*cosCur,rext*sinCur,zmin);
520 baseB[k].set(rext*cosCur,rext*sinCur,zmax);
523 sinCur = sinCur*cosStep + cosCur*sinStep;
524 cosCur = cosCur*cosStep - sinTmp*sinStep;
526 std::vector<const G4ThreeVectorList *> polygons(2);
527 polygons[0] = &baseA;
528 polygons[1] = &baseB;
538 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
539 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
543 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
544 pols[0][0].set(rmin*cosStart,rmin*sinStart,zmax);
545 pols[0][1].set(rmin*cosStart,rmin*sinStart,zmin);
546 pols[0][2].set(rmax*cosStart,rmax*sinStart,zmin);
547 pols[0][3].set(rmax*cosStart,rmax*sinStart,zmax);
548 for (
G4int k=1; k<ksteps+1; ++k)
550 pols[k][0].set(rmin*cosCur,rmin*sinCur,zmax);
551 pols[k][1].set(rmin*cosCur,rmin*sinCur,zmin);
552 pols[k][2].set(rext*cosCur,rext*sinCur,zmin);
553 pols[k][3].set(rext*cosCur,rext*sinCur,zmax);
556 sinCur = sinCur*cosStep + cosCur*sinStep;
557 cosCur = cosCur*cosStep - sinTmp*sinStep;
559 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd,zmax);
560 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,zmin);
561 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,zmin);
562 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd,zmax);
565 std::vector<const G4ThreeVectorList *> polygons;
566 polygons.resize(ksteps+2);
567 for (
G4int k=0; k<ksteps+2; ++k) { polygons[k] = &pols[k]; }
585 G4double zinLow =(p+vZ).dot(fLowNorm);
586 if (zinLow > halfCarTolerance) {
return kOutside; }
590 G4double zinHigh = (p-vZ).dot(fHighNorm);
591 if (zinHigh > halfCarTolerance) {
return kOutside; }
597 G4double tolRMin = fRMin - halfRadTolerance;
598 G4double tolRMax = fRMax + halfRadTolerance;
599 if ( tolRMin < 0 ) { tolRMin = 0; }
601 if (r2 < tolRMin*tolRMin || r2 > tolRMax*tolRMax) {
return kOutside; }
607 if ((tolRMin == 0) && (std::fabs(p.
x()) <= halfCarTolerance)
608 && (std::fabs(p.
y()) <= halfCarTolerance))
618 G4double sphi = fSPhi - halfAngTolerance;
619 G4double ephi = sphi + fDPhi + kAngTolerance;
620 if ((phi0 >= sphi && phi0 <= ephi) ||
621 (phi1 >= sphi && phi1 <= ephi) ||
622 (phi2 >= sphi && phi2 <= ephi)) in =
kSurface;
625 sphi += kAngTolerance;
626 ephi -= kAngTolerance;
627 if ((phi0 >= sphi && phi0 <= ephi) ||
628 (phi1 >= sphi && phi1 <= ephi) ||
629 (phi2 >= sphi && phi2 <= ephi)) in =
kInside;
635 if ((zinLow >= -halfCarTolerance) || (zinHigh >= -halfCarTolerance))
642 if (fRMin) { tolRMin = fRMin + halfRadTolerance; }
643 else { tolRMin = 0; }
644 tolRMax = fRMax - halfRadTolerance;
645 if (((r2 <= tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax)) &&
646 (r2 >= halfRadTolerance*halfRadTolerance))
662 G4int noSurfaces = 0;
664 G4double distZLow,distZHigh, distRMin, distRMax;
665 G4double distSPhi = kInfinity, distEPhi = kInfinity;
672 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
674 distRMin = std::fabs(rho - fRMin);
675 distRMax = std::fabs(rho - fRMax);
679 distZLow =std::fabs((p+vZ).dot(fLowNorm));
683 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
685 if (!fPhiFullCutTube)
687 if ( rho > halfCarTolerance )
689 pPhi = std::atan2(p.
y(),p.
x());
691 if(pPhi < fSPhi- halfCarTolerance) { pPhi += twopi; }
692 else if(pPhi > fSPhi+fDPhi+ halfCarTolerance) { pPhi -= twopi; }
694 distSPhi = std::fabs(pPhi - fSPhi);
695 distEPhi = std::fabs(pPhi - fSPhi - fDPhi);
705 if ( rho > halfCarTolerance ) { nR =
G4ThreeVector(p.
x()/rho,p.
y()/rho,0); }
707 if( distRMax <= halfCarTolerance )
712 if( fRMin && (distRMin <= halfCarTolerance) )
719 if (distSPhi <= halfAngTolerance)
724 if (distEPhi <= halfAngTolerance)
730 if (distZLow <= halfCarTolerance)
735 if (distZHigh <= halfCarTolerance)
738 sumnorm += fHighNorm;
740 if ( noSurfaces == 0 )
743 G4Exception(
"G4CutTubs::SurfaceNormal(p)",
"GeomSolids1002",
746 G4cout<<
"G4CutTubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
748 G4cout.precision(oldprc) ;
752 else if ( noSurfaces == 1 ) { norm = sumnorm; }
753 else { norm = sumnorm.
unit(); }
771 G4double distRMin, distRMax, distSPhi, distEPhi, distMin ;
774 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
776 distRMin = std::fabs(rho - fRMin) ;
777 distRMax = std::fabs(rho - fRMax) ;
781 distZLow =std::fabs((p+vZ).dot(fLowNorm));
785 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
786 distZ=std::min(distZLow,distZHigh);
788 if (distRMin < distRMax)
790 if ( distZ < distRMin )
803 if ( distZ < distRMax )
814 if (!fPhiFullCutTube && rho )
816 phi = std::atan2(p.
y(),p.
x()) ;
818 if ( phi < 0 ) { phi += twopi; }
822 distSPhi = std::fabs(phi - (fSPhi + twopi))*rho ;
826 distSPhi = std::fabs(phi - fSPhi)*rho ;
828 distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
830 if (distSPhi < distEPhi)
832 if ( distSPhi < distMin )
839 if ( distEPhi < distMin )
859 if ( distZHigh > distZLow ) { norm = fHighNorm ; }
860 else { norm = fLowNorm; }
878 "Undefined side for valid surface normal to solid.");
918 G4double Dist, sd=0, xi, yi, zi, rho2, inum, iden, cosPsi, Comp,calf ;
923 if (fRMin > kRadTolerance)
925 tolORMin2 = (fRMin - halfRadTolerance)*(fRMin - halfRadTolerance) ;
926 tolIRMin2 = (fRMin + halfRadTolerance)*(fRMin + halfRadTolerance) ;
933 tolORMax2 = (fRMax + halfRadTolerance)*(fRMax + halfRadTolerance) ;
934 tolIRMax2 = (fRMax - halfRadTolerance)*(fRMax - halfRadTolerance) ;
940 distZLow =(p+vZ).dot(fLowNorm);
944 distZHigh = (p-vZ).dot(fHighNorm);
946 if ( distZLow >= -halfCarTolerance )
948 calf = v.
dot(fLowNorm);
952 if(sd < 0.0) { sd = 0.0; }
954 xi = p.
x() + sd*v.
x() ;
955 yi = p.
y() + sd*v.
y() ;
956 rho2 = xi*xi + yi*yi ;
960 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
962 if (!fPhiFullCutTube && rho2)
966 inum = xi*cosCPhi + yi*sinCPhi ;
967 iden = std::sqrt(rho2) ;
969 if (cosPsi >= cosHDPhiIT) {
return sd ; }
979 if ( sd<halfCarTolerance )
981 if(calf>=0) { sd=kInfinity; }
987 if(distZHigh >= -halfCarTolerance )
989 calf = v.
dot(fHighNorm);
992 sd = -distZHigh/calf;
994 if(sd < 0.0) { sd = 0.0; }
996 xi = p.
x() + sd*v.
x() ;
997 yi = p.
y() + sd*v.
y() ;
998 rho2 = xi*xi + yi*yi ;
1002 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
1004 if (!fPhiFullCutTube && rho2)
1008 inum = xi*cosCPhi + yi*sinCPhi ;
1009 iden = std::sqrt(rho2) ;
1010 cosPsi = inum/iden ;
1011 if (cosPsi >= cosHDPhiIT) {
return sd ; }
1021 if ( sd<halfCarTolerance )
1023 if(calf>=0) { sd=kInfinity; }
1040 t1 = 1.0 - v.
z()*v.
z() ;
1041 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1042 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1046 c = t3 - fRMax*fRMax ;
1048 if ((t3 >= tolORMax2) && (t2<0))
1057 sd = c/(-b+std::sqrt(d));
1062 G4double fTerm = sd-std::fmod(sd,dRmax);
1067 zi = p.
z() + sd*v.
z() ;
1068 xi = p.
x() + sd*v.
x() ;
1069 yi = p.
y() + sd*v.
y() ;
1070 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1071 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1073 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1074 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1078 if (fPhiFullCutTube)
1084 xi = p.
x() + sd*v.
x() ;
1085 yi = p.
y() + sd*v.
y() ;
1086 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMax ;
1087 if (cosPsi >= cosHDPhiIT) {
return sd ; }
1098 if ((t3 > tolIRMin2) && (t2 < 0)
1099 && (std::fabs(p.
z()) <= std::fabs(
GetCutZ(p))-halfCarTolerance ))
1103 if (!fPhiFullCutTube)
1105 inum = p.
x()*cosCPhi + p.
y()*sinCPhi ;
1106 iden = std::sqrt(t3) ;
1107 cosPsi = inum/iden ;
1108 if (cosPsi >= cosHDPhiIT)
1127 snxt = c/(-b+std::sqrt(d));
1129 if ( snxt < halfCarTolerance ) { snxt=0; }
1147 c = t3 - fRMax*fRMax;
1158 snxt= c/(-b+std::sqrt(d));
1160 if ( snxt < halfCarTolerance ) { snxt=0; }
1174 c = (t3 - fRMin*fRMin)/t1 ;
1181 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1182 if (sd >= -10*halfCarTolerance)
1186 if (sd < 0.0) { sd = 0.0; }
1189 G4double fTerm = sd-std::fmod(sd,dRmax);
1192 zi = p.
z() + sd*v.
z() ;
1193 xi = p.
x() + sd*v.
x() ;
1194 yi = p.
y() + sd*v.
y() ;
1195 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1196 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1198 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1199 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1203 if ( fPhiFullCutTube )
1209 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMin ;
1210 if (cosPsi >= cosHDPhiIT)
1234 if ( !fPhiFullCutTube )
1238 Comp = v.
x()*sinSPhi - v.
y()*cosSPhi ;
1242 Dist = (p.
y()*cosSPhi - p.
x()*sinSPhi) ;
1244 if ( Dist < halfCarTolerance )
1250 if ( sd < 0 ) { sd = 0.0; }
1251 zi = p.
z() + sd*v.
z() ;
1252 xi = p.
x() + sd*v.
x() ;
1253 yi = p.
y() + sd*v.
y() ;
1254 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1255 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1257 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1258 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1260 rho2 = xi*xi + yi*yi ;
1261 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1262 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1263 && ( v.
y()*cosSPhi - v.
x()*sinSPhi > 0 )
1264 && ( v.
x()*cosSPhi + v.
y()*sinSPhi >= 0 ) )
1265 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1266 && (v.
y()*cosSPhi - v.
x()*sinSPhi > 0)
1267 && (v.
x()*cosSPhi + v.
y()*sinSPhi < 0) ) )
1272 if ((yi*cosCPhi-xi*sinCPhi) <= halfCarTolerance) { snxt = sd; }
1282 Comp = -(v.
x()*sinEPhi - v.
y()*cosEPhi) ;
1286 Dist = -(p.
y()*cosEPhi - p.
x()*sinEPhi) ;
1288 if ( Dist < halfCarTolerance )
1294 if ( sd < 0 ) { sd = 0; }
1295 zi = p.
z() + sd*v.
z() ;
1296 xi = p.
x() + sd*v.
x() ;
1297 yi = p.
y() + sd*v.
y() ;
1298 if ((-xi*fLowNorm.
x()-yi*fLowNorm.
y()
1299 -(zi+fDz)*fLowNorm.
z())>-halfCarTolerance)
1301 if ((-xi*fHighNorm.
x()-yi*fHighNorm.
y()
1302 +(fDz-zi)*fHighNorm.
z())>-halfCarTolerance)
1304 xi = p.
x() + sd*v.
x() ;
1305 yi = p.
y() + sd*v.
y() ;
1306 rho2 = xi*xi + yi*yi ;
1307 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1308 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1309 && (v.
x()*sinEPhi - v.
y()*cosEPhi > 0)
1310 && (v.
x()*cosEPhi + v.
y()*sinEPhi >= 0) )
1311 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1312 && (v.
x()*sinEPhi - v.
y()*cosEPhi > 0)
1313 && (v.
x()*cosEPhi + v.
y()*sinEPhi < 0) ) )
1318 if ( (yi*cosCPhi-xi*sinCPhi) >= -halfCarTolerance )
1329 if ( snxt<halfCarTolerance ) { snxt=0; }
1362 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho,cosPsi;
1367 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1369 safRMin = fRMin- rho ;
1370 safRMax = rho - fRMax ;
1376 safZLow = (p+vZ).dot(fLowNorm);
1380 safZHigh = (p-vZ).dot(fHighNorm);
1382 safe = std::max(safZLow,safZHigh);
1384 if ( safRMin > safe ) { safe = safRMin; }
1385 if ( safRMax> safe ) { safe = safRMax; }
1389 if ( (!fPhiFullCutTube) && (rho) )
1393 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/rho ;
1395 if ( cosPsi < cosHDPhi )
1399 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0 )
1401 safePhi = std::fabs(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
1405 safePhi = std::fabs(p.
x()*sinEPhi - p.
y()*cosEPhi) ;
1407 if ( safePhi > safe ) { safe = safePhi; }
1410 if ( safe < 0 ) { safe = 0; }
1429 G4double snxt=kInfinity, srd=kInfinity,sz=kInfinity, sphi=kInfinity ;
1430 G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
1431 G4double distZLow,distZHigh,calfH,calfL;
1436 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1443 distZLow =(p+vZ).dot(fLowNorm);
1447 distZHigh = (p-vZ).dot(fHighNorm);
1449 calfH = v.
dot(fHighNorm);
1450 calfL = v.
dot(fLowNorm);
1454 if ( distZHigh < halfCarTolerance )
1456 snxt = -distZHigh/calfH ;
1472 if ( distZLow < halfCarTolerance )
1474 sz = -distZLow/calfL ;
1491 if((calfH<=0)&&(calfL<=0))
1507 t1 = 1.0 - v.
z()*v.
z() ;
1508 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1509 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1511 if ( snxt > 10*(fDz+fRMax) ) { roi2 = 2*fRMax*fRMax; }
1512 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1518 if ( (t2 >= 0.0) && (roi2 > fRMax*(fRMax + kRadTolerance)) )
1522 deltaR = t3 - fRMax*fRMax ;
1527 if ( deltaR < -kRadTolerance*fRMax )
1532 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1551 roMin2 = t3 - t2*t2/t1 ;
1553 if ( fRMin && (roMin2 < fRMin*(fRMin - kRadTolerance)) )
1555 deltaR = t3 - fRMin*fRMin ;
1565 if (deltaR > kRadTolerance*fRMin)
1567 srd = c/(-b+std::sqrt(d2));
1572 if ( calcNorm ) { *validNorm =
false; }
1578 deltaR = t3 - fRMax*fRMax ;
1583 srd = -b + std::sqrt(d2) ;
1598 else if ( roi2 > fRMax*(fRMax + kRadTolerance) )
1601 deltaR = t3 - fRMax*fRMax ;
1607 srd = -b + std::sqrt(d2) ;
1624 if ( !fPhiFullCutTube )
1629 vphi = std::atan2(v.
y(),v.
x()) ;
1631 if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
1632 else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; }
1635 if ( p.
x() || p.
y() )
1639 pDistS = p.
x()*sinSPhi - p.
y()*cosSPhi ;
1640 pDistE = -p.
x()*sinEPhi + p.
y()*cosEPhi ;
1644 compS = -sinSPhi*v.
x() + cosSPhi*v.
y() ;
1645 compE = sinEPhi*v.
x() - cosEPhi*v.
y() ;
1649 if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
1650 && (pDistE <= halfCarTolerance) ) )
1651 || ( (fDPhi > pi) && !((pDistS > halfCarTolerance)
1652 && (pDistE > halfCarTolerance) ) ) )
1658 sphi = pDistS/compS ;
1660 if (sphi >= -halfCarTolerance)
1662 xi = p.
x() + sphi*v.
x() ;
1663 yi = p.
y() + sphi*v.
y() ;
1672 if (((fSPhi-halfAngTolerance)<=vphi)
1673 &&((fSPhi+fDPhi+halfAngTolerance)>=vphi))
1678 else if ( yi*cosCPhi-xi*sinCPhi >=0 )
1685 if ( pDistS > -halfCarTolerance )
1703 sphi2 = pDistE/compE ;
1707 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1709 xi = p.
x() + sphi2*v.
x() ;
1710 yi = p.
y() + sphi2*v.
y() ;
1716 if( !((fSPhi-halfAngTolerance <= vphi)
1717 &&(fSPhi+fDPhi+halfAngTolerance >= vphi)) )
1720 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1721 else { sphi = 0.0 ; }
1726 if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
1731 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1732 else { sphi = 0.0 ; }
1747 if ( (fSPhi - halfAngTolerance <= vphi)
1748 && (vphi <= fSPhi + fDPhi + halfAngTolerance ) )
1778 xi = p.
x() + snxt*v.
x() ;
1779 yi = p.
y() + snxt*v.
y() ;
1785 *validNorm = false ;
1796 *validNorm = false ;
1808 *validNorm = false ;
1825 std::ostringstream message;
1826 G4long oldprc = message.precision(16);
1827 message <<
"Undefined side for valid surface normal to solid."
1830 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1831 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1834 <<
"v.x() = " << v.
x() <<
G4endl
1835 <<
"v.y() = " << v.
y() <<
G4endl
1838 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
1839 message.precision(oldprc) ;
1840 G4Exception(
"G4CutTubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1845 if ( snxt<halfCarTolerance ) { snxt=0 ; }
1855 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho;
1858 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1860 safRMin = rho - fRMin ;
1861 safRMax = fRMax - rho ;
1867 safZLow = std::fabs((p+vZ).dot(fLowNorm));
1871 safZHigh = std::fabs((p-vZ).dot(fHighNorm));
1872 safe = std::min(safZLow,safZHigh);
1874 if ( safRMin < safe ) { safe = safRMin; }
1875 if ( safRMax< safe ) { safe = safRMax; }
1879 if ( !fPhiFullCutTube )
1881 if ( p.
y()*cosCPhi-p.
x()*sinCPhi <= 0 )
1883 safePhi = -(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
1887 safePhi = (p.
x()*sinEPhi - p.
y()*cosEPhi) ;
1889 if (safePhi < safe) { safe = safePhi ; }
1891 if ( safe < 0 ) { safe = 0; }
1920 G4long oldprc = os.precision(16);
1921 os <<
"-----------------------------------------------------------\n"
1922 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1923 <<
" ===================================================\n"
1924 <<
" Solid type: G4CutTubs\n"
1925 <<
" Parameters: \n"
1926 <<
" inner radius : " << fRMin/mm <<
" mm \n"
1927 <<
" outer radius : " << fRMax/mm <<
" mm \n"
1928 <<
" half length Z: " << fDz/mm <<
" mm \n"
1929 <<
" starting phi : " << fSPhi/degree <<
" degrees \n"
1930 <<
" delta phi : " << fDPhi/degree <<
" degrees \n"
1931 <<
" low Norm : " << fLowNorm <<
" \n"
1932 <<
" high Norm : " <<fHighNorm <<
" \n"
1933 <<
"-----------------------------------------------------------\n";
1934 os.precision(oldprc);
1946 if (fZMin == 0. && fZMax == 0.)
1969 G4double sbase = 0.5*dphi*(rrmax - rrmin);
1970 G4double sbot = sbase/std::abs(nbot.
z());
1971 G4double stop = sbase/std::abs(ntop.
z());
1972 G4double scut = (dphi == twopi) ? 0. : hmax*(rmax - rmin);
1973 G4double ssurf[6] = { scut, scut, sbot, stop, dphi*rmax*hmax, dphi*rmin*hmax };
1974 ssurf[1] += ssurf[0];
1975 ssurf[2] += ssurf[1];
1976 ssurf[3] += ssurf[2];
1977 ssurf[4] += ssurf[3];
1978 ssurf[5] += ssurf[4];
1980 constexpr G4int ntry = 100000;
1981 for (
G4int i=0; i<ntry; ++i)
1986 k -= (select <= ssurf[4]);
1987 k -= (select <= ssurf[3]);
1988 k -= (select <= ssurf[2]);
1989 k -= (select <= ssurf[1]);
1990 k -= (select <= ssurf[0]);
2014 G4double z = -fDz - (x*nbot.
x() + y*nbot.
y())/nbot.
z();
2023 G4double z = fDz - (x*ntop.
x() + y*ntop.
y())/ntop.
z();
2045 if ((ntop.
dot(p) - fDz*ntop.
z()) > 0.)
continue;
2046 if ((nbot.
dot(p) + fDz*nbot.
z()) > 0.)
continue;
2051 G4double x = rmax*std::cos(sphi + 0.5*dphi);
2052 G4double y = rmax*std::sin(sphi + 0.5*dphi);
2053 G4double z = fDz - (x*ntop.
x() + y*ntop.
y())/ntop.
z();
2069 typedef G4int G4int4[4];
2075 G4double3* xyz =
new G4double3[nn];
2076 G4int4* faces =
new G4int4[nf] ;
2078 for(
G4int i=0; i<nn; ++i)
2099 for(
G4int i=0; i<nf ; ++i)
2102 for(
G4int k=0; k<n; ++k)
2104 faces[i][k]=iNodes[k];
2106 for(
G4int k=n; k<4; ++k)
2130 constexpr G4int npoints = 30;
2145 G4double cosdel = std::cos(delphi);
2146 G4double sindel = std::sin(delphi);
2148 for (
G4int i=0; i<npoints+1; ++i)
2150 G4double h = nx*cosphi + ny*sinphi + hzero;
2151 if (h < 0.)
return true;
2153 sinphi = sintmp*cosdel + cosphi*sindel;
2154 cosphi = cosphi*cosdel - sintmp*sindel;
2168 if(fLowNorm.
z()!=0.)
2170 newz = -fDz-(p.
x()*fLowNorm.
x()+p.
y()*fLowNorm.
y())/fLowNorm.
z();
2175 if(fHighNorm.
z()!=0.)
2177 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)
G4ThreeVector GetHighNorm() const
G4double GetCubicVolume()
G4double GetStartPhiAngle() const
G4double GetZHalfLength() const
G4double GetInnerRadius() const
EInside Inside(const G4ThreeVector &p) const
G4ThreeVector GetLowNorm() const
G4double GetCutZ(const G4ThreeVector &p) const
G4Polyhedron * CreatePolyhedron() const
G4double GetDeltaPhiAngle() const
G4double GetOuterRadius() const
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4bool IsCrossingCutPlanes() const
G4double GetSinStartPhi() const
G4GeometryType GetEntityType() const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4CutTubs & operator=(const G4CutTubs &rhs)
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const
G4double GetSurfaceArea()
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4ThreeVector GetPointOnSurface() const
G4double GetSinEndPhi() const
std::ostream & StreamInfo(std::ostream &os) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double GetCosStartPhi() const
G4double GetCosEndPhi() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4CutTubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi, G4ThreeVector pLowNorm, G4ThreeVector pHighNorm)
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 createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])
G4int GetNoFacets() const
G4int GetNoVertices() const