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",
181 if (
this == &rhs) {
return *
this; }
189 kRadTolerance = rhs.kRadTolerance; kAngTolerance = rhs.kAngTolerance;
190 fRMin = rhs.fRMin; fRMax = rhs.fRMax; fDz = rhs.fDz;
191 fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
192 fZMin = rhs.fZMin; fZMax = rhs.fZMax;
193 sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPhi;
194 cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = rhs.cosHDPhiIT;
195 sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPhi;
196 sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPhi;
197 fPhiFullCutTube = rhs.fPhiFullCutTube;
198 halfCarTolerance = rhs.halfCarTolerance;
199 halfRadTolerance = rhs.halfRadTolerance;
200 halfAngTolerance = rhs.halfAngTolerance;
201 fLowNorm = rhs.fLowNorm; fHighNorm = rhs.fHighNorm;
223 G4double mag, topx, topy, dists, diste;
230 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
231 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
232 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
233 dists = sinSphi*topx - cosSphi*topy;
234 diste = -sinEphi*topx + cosEphi*topy;
238 if (dists > 0 && diste > 0) { iftop =
false; }
243 if (dists <= 0 && diste <= 0) { iftop =
true; }
247 zmin = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() - dz;
251 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() - dz;
252 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() - dz;
253 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() - dz;
254 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() - dz;
255 zmin = std::min(std::min(std::min(z1,z2),z3),z4);
262 mag = std::sqrt(norm.
x()*norm.
x() + norm.
y()*norm.
y());
263 topx = (mag == 0) ? 0 : -rmax*norm.
x()/mag;
264 topy = (mag == 0) ? 0 : -rmax*norm.
y()/mag;
265 dists = sinSphi*topx - cosSphi*topy;
266 diste = -sinEphi*topx + cosEphi*topy;
270 if (dists > 0 && diste > 0) { iftop =
false; }
275 if (dists <= 0 && diste <= 0) { iftop =
true; }
279 zmax = -(norm.
x()*topx + norm.
y()*topy)/norm.
z() + dz;
283 G4double z1 = -rmin*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() + dz;
284 G4double z2 = -rmin*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() + dz;
285 G4double z3 = -rmax*(norm.
x()*cosSphi + norm.
y()*sinSphi)/norm.
z() + dz;
286 G4double z4 = -rmax*(norm.
x()*cosEphi + norm.
y()*sinEphi)/norm.
z() + dz;
287 zmax = std::max(std::max(std::max(z1,z2),z3),z4);
299 pMin.
set(vmin.
x(),vmin.
y(), zmin);
300 pMax.
set(vmax.
x(),vmax.
y(), zmax);
304 pMin.
set(-rmax,-rmax, zmin);
305 pMax.
set( rmax, rmax, zmax);
310 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
312 std::ostringstream message;
313 message <<
"Bad bounding box (min >= max) for solid: "
315 <<
"\npMin = " << pMin
316 <<
"\npMax = " << pMax;
317 G4Exception(
"G4CutTubs::BoundingLimits()",
"GeomMgt0001",
346 return exist = pMin < pMax;
358 const G4int NSTEPS = 24;
360 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
363 G4double sinHalf = std::sin(0.5*ang);
364 G4double cosHalf = std::cos(0.5*ang);
365 G4double sinStep = 2.*sinHalf*cosHalf;
366 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
371 if (rmin == 0 && dphi == twopi)
377 for (
G4int k=0; k<NSTEPS; ++k)
379 baseA[k].set(rext*cosCur,rext*sinCur,zmin);
380 baseB[k].set(rext*cosCur,rext*sinCur,zmax);
383 sinCur = sinCur*cosStep + cosCur*sinStep;
384 cosCur = cosCur*cosStep - sinTmp*sinStep;
386 std::vector<const G4ThreeVectorList *> polygons(2);
387 polygons[0] = &baseA;
388 polygons[1] = &baseB;
398 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
399 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
403 for (
G4int k=0; k<ksteps+2; ++k)
407 pols[0][0].set(rmin*cosStart,rmin*sinStart,zmax);
408 pols[0][1].set(rmin*cosStart,rmin*sinStart,zmin);
409 pols[0][2].set(rmax*cosStart,rmax*sinStart,zmin);
410 pols[0][3].set(rmax*cosStart,rmax*sinStart,zmax);
411 for (
G4int k=1; k<ksteps+1; ++k)
413 pols[k][0].set(rmin*cosCur,rmin*sinCur,zmax);
414 pols[k][1].set(rmin*cosCur,rmin*sinCur,zmin);
415 pols[k][2].set(rext*cosCur,rext*sinCur,zmin);
416 pols[k][3].set(rext*cosCur,rext*sinCur,zmax);
419 sinCur = sinCur*cosStep + cosCur*sinStep;
420 cosCur = cosCur*cosStep - sinTmp*sinStep;
422 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd,zmax);
423 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,zmin);
424 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,zmin);
425 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd,zmax);
428 std::vector<const G4ThreeVectorList *> polygons;
429 polygons.resize(ksteps+2);
430 for (
G4int k=0; k<ksteps+2; ++k) { polygons[k] = &pols[k]; }
448 G4double zinLow =(p+vZ).dot(fLowNorm);
449 if (zinLow > halfCarTolerance) {
return kOutside; }
453 G4double zinHigh = (p-vZ).dot(fHighNorm);
454 if (zinHigh > halfCarTolerance) {
return kOutside; }
460 G4double tolRMin = fRMin - halfRadTolerance;
461 G4double tolRMax = fRMax + halfRadTolerance;
462 if ( tolRMin < 0 ) { tolRMin = 0; }
464 if (r2 < tolRMin*tolRMin || r2 > tolRMax*tolRMax) {
return kOutside; }
470 if ((tolRMin == 0) && (std::fabs(p.
x()) <= halfCarTolerance)
471 && (std::fabs(p.
y()) <= halfCarTolerance))
481 G4double sphi = fSPhi - halfAngTolerance;
482 G4double ephi = sphi + fDPhi + kAngTolerance;
483 if ((phi0 >= sphi && phi0 <= ephi) ||
484 (phi1 >= sphi && phi1 <= ephi) ||
485 (phi2 >= sphi && phi2 <= ephi))
491 sphi += kAngTolerance;
492 ephi -= kAngTolerance;
493 if ((phi0 >= sphi && phi0 <= ephi) ||
494 (phi1 >= sphi && phi1 <= ephi) ||
495 (phi2 >= sphi && phi2 <= ephi)) { in =
kInside;
502 if ((zinLow >= -halfCarTolerance) || (zinHigh >= -halfCarTolerance))
509 if (fRMin != 0.0) { tolRMin = fRMin + halfRadTolerance; }
510 else { tolRMin = 0; }
511 tolRMax = fRMax - halfRadTolerance;
512 if (((r2 <= tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax)) &&
513 (r2 >= halfRadTolerance*halfRadTolerance))
529 G4int noSurfaces = 0;
531 G4double distZLow,distZHigh, distRMin, distRMax;
532 G4double distSPhi = kInfinity, distEPhi = kInfinity;
539 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
541 distRMin = std::fabs(rho - fRMin);
542 distRMax = std::fabs(rho - fRMax);
546 distZLow =std::fabs((p+vZ).dot(fLowNorm));
550 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
552 if (!fPhiFullCutTube)
554 if ( rho > halfCarTolerance )
556 pPhi = std::atan2(p.
y(),p.
x());
558 if(pPhi < fSPhi- halfCarTolerance) { pPhi += twopi; }
559 else if(pPhi > fSPhi+fDPhi+ halfCarTolerance) { pPhi -= twopi; }
561 distSPhi = std::fabs(pPhi - fSPhi);
562 distEPhi = std::fabs(pPhi - fSPhi - fDPhi);
564 else if( fRMin == 0.0 )
572 if ( rho > halfCarTolerance ) { nR =
G4ThreeVector(p.
x()/rho,p.
y()/rho,0); }
574 if( distRMax <= halfCarTolerance )
579 if( (fRMin != 0.0) && (distRMin <= halfCarTolerance) )
586 if (distSPhi <= halfAngTolerance)
591 if (distEPhi <= halfAngTolerance)
597 if (distZLow <= halfCarTolerance)
602 if (distZHigh <= halfCarTolerance)
605 sumnorm += fHighNorm;
607 if ( noSurfaces == 0 )
610 G4Exception(
"G4CutTubs::SurfaceNormal(p)",
"GeomSolids1002",
613 G4cout<<
"G4CutTubs::SN ( "<<p.
x()<<
", "<<p.
y()<<
", "<<p.
z()<<
" ); "
615 G4cout.precision(oldprc) ;
619 else if ( noSurfaces == 1 ) { norm = sumnorm; }
620 else { norm = sumnorm.
unit(); }
632 enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ};
638 G4double distRMin, distRMax, distSPhi, distEPhi, distMin ;
641 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
643 distRMin = std::fabs(rho - fRMin) ;
644 distRMax = std::fabs(rho - fRMax) ;
648 distZLow =std::fabs((p+vZ).dot(fLowNorm));
652 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
653 distZ=std::min(distZLow,distZHigh);
655 if (distRMin < distRMax)
657 if ( distZ < distRMin )
670 if ( distZ < distRMax )
681 if (!fPhiFullCutTube && (rho != 0.0) )
683 phi = std::atan2(p.
y(),p.
x()) ;
685 if ( phi < 0 ) { phi += twopi; }
689 distSPhi = std::fabs(phi - (fSPhi + twopi))*rho ;
693 distSPhi = std::fabs(phi - fSPhi)*rho ;
695 distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
697 if (distSPhi < distEPhi)
699 if ( distSPhi < distMin )
706 if ( distEPhi < distMin )
726 if ( distZHigh > distZLow ) { norm = fHighNorm ; }
727 else { norm = fLowNorm; }
745 "Undefined side for valid surface normal to solid.");
785 G4double Dist, sd=0, xi, yi, zi, rho2, inum, iden, cosPsi, Comp,calf ;
790 if (fRMin > kRadTolerance)
792 tolORMin2 = (fRMin - halfRadTolerance)*(fRMin - halfRadTolerance) ;
793 tolIRMin2 = (fRMin + halfRadTolerance)*(fRMin + halfRadTolerance) ;
800 tolORMax2 = (fRMax + halfRadTolerance)*(fRMax + halfRadTolerance) ;
801 tolIRMax2 = (fRMax - halfRadTolerance)*(fRMax - halfRadTolerance) ;
807 distZLow =(p+vZ).dot(fLowNorm);
811 distZHigh = (p-vZ).dot(fHighNorm);
813 if ( distZLow >= -halfCarTolerance )
815 calf = v.
dot(fLowNorm);
819 if(sd < 0.0) { sd = 0.0; }
821 xi = p.
x() + sd*v.
x() ;
822 yi = p.
y() + sd*v.
y() ;
823 rho2 = xi*xi + yi*yi ;
827 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
829 if (!fPhiFullCutTube && (rho2 != 0.0))
833 inum = xi*cosCPhi + yi*sinCPhi ;
834 iden = std::sqrt(rho2) ;
836 if (cosPsi >= cosHDPhiIT) {
return sd ; }
846 if ( sd<halfCarTolerance )
848 if(calf>=0) { sd=kInfinity; }
854 if(distZHigh >= -halfCarTolerance )
856 calf = v.
dot(fHighNorm);
859 sd = -distZHigh/calf;
861 if(sd < 0.0) { sd = 0.0; }
863 xi = p.
x() + sd*v.
x() ;
864 yi = p.
y() + sd*v.
y() ;
865 rho2 = xi*xi + yi*yi ;
869 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
871 if (!fPhiFullCutTube && (rho2 != 0.0))
875 inum = xi*cosCPhi + yi*sinCPhi ;
876 iden = std::sqrt(rho2) ;
878 if (cosPsi >= cosHDPhiIT) {
return sd ; }
888 if ( sd<halfCarTolerance )
890 if(calf>=0) { sd=kInfinity; }
907 t1 = 1.0 - v.
z()*v.
z() ;
908 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
909 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
913 c = t3 - fRMax*fRMax ;
915 if ((t3 >= tolORMax2) && (t2<0))
924 sd = c/(-b+std::sqrt(d));
929 G4double fTerm = sd-std::fmod(sd,dRmax);
934 zi = p.
z() + sd*v.
z() ;
935 xi = p.
x() + sd*v.
x() ;
936 yi = p.
y() + sd*v.
y() ;
937 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
938 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
940 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
941 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
950 xi = p.
x() + sd*v.
x() ;
951 yi = p.
y() + sd*v.
y() ;
952 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMax ;
953 if (cosPsi >= cosHDPhiIT) {
return sd ; }
963 if ((t3 > tolIRMin2) && (t2 < 0)
964 && (std::fabs(p.
z()) <= std::fabs(
GetCutZ(p))-halfCarTolerance ))
968 if (!fPhiFullCutTube)
970 inum = p.
x()*cosCPhi + p.
y()*sinCPhi ;
971 iden = std::sqrt(t3) ;
973 if (cosPsi >= cosHDPhiIT)
991 snxt = c/(-b+std::sqrt(d));
993 if ( snxt < halfCarTolerance ) { snxt=0; }
1008 c = t3 - fRMax*fRMax;
1018 snxt= c/(-b+std::sqrt(d));
1020 if ( snxt < halfCarTolerance ) { snxt=0; }
1031 c = (t3 - fRMin*fRMin)/t1 ;
1038 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1039 if (sd >= -10*halfCarTolerance)
1043 if (sd < 0.0) { sd = 0.0; }
1046 G4double fTerm = sd-std::fmod(sd,dRmax);
1049 zi = p.
z() + sd*v.
z() ;
1050 xi = p.
x() + sd*v.
x() ;
1051 yi = p.
y() + sd*v.
y() ;
1052 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
1053 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
1055 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
1056 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
1060 if ( fPhiFullCutTube )
1065 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMin ;
1066 if (cosPsi >= cosHDPhiIT)
1089 if ( !fPhiFullCutTube )
1093 Comp = v.
x()*sinSPhi - v.
y()*cosSPhi ;
1097 Dist = (p.
y()*cosSPhi - p.
x()*sinSPhi) ;
1099 if ( Dist < halfCarTolerance )
1105 if ( sd < 0 ) { sd = 0.0; }
1106 zi = p.
z() + sd*v.
z() ;
1107 xi = p.
x() + sd*v.
x() ;
1108 yi = p.
y() + sd*v.
y() ;
1109 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
1110 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
1112 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
1113 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
1115 rho2 = xi*xi + yi*yi ;
1116 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1117 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1118 && ( v.
y()*cosSPhi - v.
x()*sinSPhi > 0 )
1119 && ( v.
x()*cosSPhi + v.
y()*sinSPhi >= 0 ) )
1120 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1121 && (v.
y()*cosSPhi - v.
x()*sinSPhi > 0)
1122 && (v.
x()*cosSPhi + v.
y()*sinSPhi < 0) ) )
1127 if ((yi*cosCPhi-xi*sinCPhi) <= halfCarTolerance) { snxt = sd; }
1137 Comp = -(v.
x()*sinEPhi - v.
y()*cosEPhi) ;
1141 Dist = -(p.
y()*cosEPhi - p.
x()*sinEPhi) ;
1143 if ( Dist < halfCarTolerance )
1149 if ( sd < 0 ) { sd = 0; }
1150 zi = p.
z() + sd*v.
z() ;
1151 xi = p.
x() + sd*v.
x() ;
1152 yi = p.
y() + sd*v.
y() ;
1153 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
1154 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
1156 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
1157 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
1159 xi = p.
x() + sd*v.
x() ;
1160 yi = p.
y() + sd*v.
y() ;
1161 rho2 = xi*xi + yi*yi ;
1162 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1163 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1164 && (v.
x()*sinEPhi - v.
y()*cosEPhi > 0)
1165 && (v.
x()*cosEPhi + v.
y()*sinEPhi >= 0) )
1166 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1167 && (v.
x()*sinEPhi - v.
y()*cosEPhi > 0)
1168 && (v.
x()*cosEPhi + v.
y()*sinEPhi < 0) ) )
1173 if ( (yi*cosCPhi-xi*sinCPhi) >= -halfCarTolerance )
1184 if ( snxt<halfCarTolerance ) { snxt=0; }
1217 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho,cosPsi;
1222 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1224 safRMin = fRMin- rho ;
1225 safRMax = rho - fRMax ;
1231 safZLow = (p+vZ).dot(fLowNorm);
1235 safZHigh = (p-vZ).dot(fHighNorm);
1237 safe = std::max(safZLow,safZHigh);
1239 if ( safRMin > safe ) { safe = safRMin; }
1240 if ( safRMax> safe ) { safe = safRMax; }
1244 if ( (!fPhiFullCutTube) && ((rho) != 0.0) )
1248 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/rho ;
1250 if ( cosPsi < cosHDPhi )
1254 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0 )
1256 safePhi = std::fabs(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
1260 safePhi = std::fabs(p.
x()*sinEPhi - p.
y()*cosEPhi) ;
1262 if ( safePhi > safe ) { safe = safePhi; }
1265 if ( safe < 0 ) { safe = 0; }
1281 enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kPZ,kMZ};
1283 ESide side=kNull , sider=kNull, sidephi=kNull ;
1284 G4double snxt=kInfinity, srd=kInfinity,sz=kInfinity, sphi=kInfinity ;
1285 G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
1286 G4double distZLow,distZHigh,calfH,calfL;
1291 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1298 distZLow =(p+vZ).dot(fLowNorm);
1302 distZHigh = (p-vZ).dot(fHighNorm);
1304 calfH = v.
dot(fHighNorm);
1305 calfL = v.
dot(fLowNorm);
1309 if ( distZHigh < halfCarTolerance )
1311 snxt = -distZHigh/calfH ;
1327 if ( distZLow < halfCarTolerance )
1329 sz = -distZLow/calfL ;
1346 if((calfH<=0)&&(calfL<=0))
1362 t1 = 1.0 - v.
z()*v.
z() ;
1363 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1364 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1366 if ( snxt > 10*(fDz+fRMax) ) { roi2 = 2*fRMax*fRMax; }
1367 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1373 if ( (t2 >= 0.0) && (roi2 > fRMax*(fRMax + kRadTolerance)) )
1377 deltaR = t3 - fRMax*fRMax ;
1382 if ( deltaR < -kRadTolerance*fRMax )
1387 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1406 roMin2 = t3 - t2*t2/t1 ;
1408 if ( (fRMin != 0.0) && (roMin2 < fRMin*(fRMin - kRadTolerance)) )
1410 deltaR = t3 - fRMin*fRMin ;
1420 if (deltaR > kRadTolerance*fRMin)
1422 srd = c/(-b+std::sqrt(d2));
1427 if ( calcNorm ) { *validNorm =
false; }
1433 deltaR = t3 - fRMax*fRMax ;
1438 srd = -b + std::sqrt(d2) ;
1453 else if ( roi2 > fRMax*(fRMax + kRadTolerance) )
1456 deltaR = t3 - fRMax*fRMax ;
1462 srd = -b + std::sqrt(d2) ;
1479 if ( !fPhiFullCutTube )
1484 vphi = std::atan2(v.
y(),v.
x()) ;
1486 if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
1487 else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; }
1490 if ( (p.
x() != 0.0) || (p.
y() != 0.0) )
1494 pDistS = p.
x()*sinSPhi - p.
y()*cosSPhi ;
1495 pDistE = -p.
x()*sinEPhi + p.
y()*cosEPhi ;
1499 compS = -sinSPhi*v.
x() + cosSPhi*v.
y() ;
1500 compE = sinEPhi*v.
x() - cosEPhi*v.
y() ;
1504 if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
1505 && (pDistE <= halfCarTolerance) ) )
1506 || ( (fDPhi > pi) && ((pDistS <= halfCarTolerance)
1507 || (pDistE <= halfCarTolerance) ) ) )
1513 sphi = pDistS/compS ;
1515 if (sphi >= -halfCarTolerance)
1517 xi = p.
x() + sphi*v.
x() ;
1518 yi = p.
y() + sphi*v.
y() ;
1527 if (((fSPhi-halfAngTolerance)<=vphi)
1528 &&((fSPhi+fDPhi+halfAngTolerance)>=vphi))
1533 else if ( yi*cosCPhi-xi*sinCPhi >=0 )
1540 if ( pDistS > -halfCarTolerance )
1558 sphi2 = pDistE/compE ;
1562 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1564 xi = p.
x() + sphi2*v.
x() ;
1565 yi = p.
y() + sphi2*v.
y() ;
1571 if( (fSPhi-halfAngTolerance > vphi)
1572 ||(fSPhi+fDPhi+halfAngTolerance < vphi) )
1575 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1576 else { sphi = 0.0 ; }
1581 if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
1586 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1587 else { sphi = 0.0 ; }
1602 if ( (fSPhi - halfAngTolerance <= vphi)
1603 && (vphi <= fSPhi + fDPhi + halfAngTolerance ) )
1633 xi = p.
x() + snxt*v.
x() ;
1634 yi = p.
y() + snxt*v.
y() ;
1640 *validNorm = false ;
1651 *validNorm = false ;
1663 *validNorm = false ;
1680 std::ostringstream message;
1681 G4long oldprc = message.precision(16);
1682 message <<
"Undefined side for valid surface normal to solid."
1685 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1686 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1689 <<
"v.x() = " << v.
x() <<
G4endl
1690 <<
"v.y() = " << v.
y() <<
G4endl
1693 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
1694 message.precision(oldprc) ;
1695 G4Exception(
"G4CutTubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1700 if ( snxt<halfCarTolerance ) { snxt=0 ; }
1710 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho;
1713 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1715 safRMin = rho - fRMin ;
1716 safRMax = fRMax - rho ;
1722 safZLow = std::fabs((p+vZ).dot(fLowNorm));
1726 safZHigh = std::fabs((p-vZ).dot(fHighNorm));
1727 safe = std::min(safZLow,safZHigh);
1729 if ( safRMin < safe ) { safe = safRMin; }
1730 if ( safRMax< safe ) { safe = safRMax; }
1734 if ( !fPhiFullCutTube )
1736 if ( p.
y()*cosCPhi-p.
x()*sinCPhi <= 0 )
1738 safePhi = -(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
1742 safePhi = (p.
x()*sinEPhi - p.
y()*cosEPhi) ;
1744 if (safePhi < safe) { safe = safePhi ; }
1746 if ( safe < 0 ) { safe = 0; }
1757 return {
"G4CutTubs"};
1775 G4long oldprc = os.precision(16);
1776 os <<
"-----------------------------------------------------------\n"
1777 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1778 <<
" ===================================================\n"
1779 <<
" Solid type: G4CutTubs\n"
1780 <<
" Parameters: \n"
1781 <<
" inner radius : " << fRMin/mm <<
" mm \n"
1782 <<
" outer radius : " << fRMax/mm <<
" mm \n"
1783 <<
" half length Z: " << fDz/mm <<
" mm \n"
1784 <<
" starting phi : " << fSPhi/degree <<
" degrees \n"
1785 <<
" delta phi : " << fDPhi/degree <<
" degrees \n"
1786 <<
" low Norm : " << fLowNorm <<
" \n"
1787 <<
" high Norm : " <<fHighNorm <<
" \n"
1788 <<
"-----------------------------------------------------------\n";
1789 os.precision(oldprc);
1801 if (fZMin == 0. && fZMax == 0.)
1824 G4double sbase = 0.5*dphi*(rrmax - rrmin);
1825 G4double sbot = sbase/std::abs(nbot.
z());
1826 G4double stop = sbase/std::abs(ntop.
z());
1827 G4double scut = (dphi == twopi) ? 0. : hmax*(rmax - rmin);
1828 G4double ssurf[6] = { scut, scut, sbot, stop, dphi*rmax*hmax, dphi*rmin*hmax };
1829 ssurf[1] += ssurf[0];
1830 ssurf[2] += ssurf[1];
1831 ssurf[3] += ssurf[2];
1832 ssurf[4] += ssurf[3];
1833 ssurf[5] += ssurf[4];
1835 constexpr G4int ntry = 100000;
1836 for (
G4int i=0; i<ntry; ++i)
1841 k -= (
G4int)(select <= ssurf[4]);
1842 k -= (
G4int)(select <= ssurf[3]);
1843 k -= (
G4int)(select <= ssurf[2]);
1844 k -= (
G4int)(select <= ssurf[1]);
1845 k -= (
G4int)(select <= ssurf[0]);
1869 G4double z = -fDz - (x*nbot.
x() + y*nbot.
y())/nbot.
z();
1878 G4double z = fDz - (x*ntop.
x() + y*ntop.
y())/ntop.
z();
1900 if ((ntop.
dot(p) - fDz*ntop.
z()) > 0.) {
continue; }
1901 if ((nbot.
dot(p) + fDz*nbot.
z()) > 0.) {
continue; }
1906 G4double x = rmax*std::cos(sphi + 0.5*dphi);
1907 G4double y = rmax*std::sin(sphi + 0.5*dphi);
1908 G4double z = fDz - (x*ntop.
x() + y*ntop.
y())/ntop.
z();
1918 constexpr G4int nphi = 200, nrho = 100;
1931 G4double volume = dz*dphi*(rmax*rmax - rmin*rmin);
1942 G4double delrho = (rmax - rmin)/nrho;
1945 for (
G4int irho=0; irho<nrho; ++irho)
1948 G4double r2 = rmin + delrho*(irho + 1);
1950 G4double sector = 0.5*delphi*(r2*r2 - r1*r1);
1951 for (
G4int iphi=0; iphi<nphi; ++iphi)
1953 G4double phi = sphi + delphi*(iphi + 0.5);
1954 G4double h = nx*rho*std::cos(phi) + ny*rho*std::sin(phi) + 2.*dz;
1971 constexpr G4int nphi = 400;
1999 for (
G4int iphi=0; iphi<nphi; ++iphi)
2001 G4double phi = sphi + delphi*(iphi + 0.5);
2004 sinner += rmin*(nx*cosphi + ny*sinphi) + 2.*dz;
2005 souter += rmax*(nx*cosphi + ny*sinphi) + 2.*dz;
2007 sinner *= delphi*rmin;
2008 souter *= delphi*rmax;
2011 G4double scut = (dphi == twopi) ? 0. : 2.*dz*(rmax - rmin);
2012 G4double szero = 0.5*dphi*(rmax*rmax - rmin*rmin);
2013 G4double slow = szero/std::abs(nbot.
z());
2014 G4double shigh = szero/std::abs(ntop.
z());
2015 fSurfaceArea = sinner + souter + 2.*scut + slow + shigh;
2033 typedef G4int G4int4[4];
2039 auto xyz =
new G4double3[nn];
2040 auto faces =
new G4int4[nf] ;
2042 for(
G4int i=0; i<nn; ++i)
2061 G4int* iEdge =
nullptr;
2063 for(
G4int i=0; i<nf ; ++i)
2066 for(
G4int k=0; k<n; ++k)
2068 faces[i][k]=iNodes[k];
2070 for(
G4int k=n; k<4; ++k)
2075 ph->createPolyhedron(nn,nf,xyz,faces);
2094 constexpr G4int npoints = 30;
2109 G4double cosdel = std::cos(delphi);
2110 G4double sindel = std::sin(delphi);
2112 for (
G4int i=0; i<npoints+1; ++i)
2114 G4double h = nx*cosphi + ny*sinphi + hzero;
2115 if (h < 0.) {
return true; }
2117 sinphi = sintmp*cosdel + cosphi*sindel;
2118 cosphi = cosphi*cosdel - sintmp*sindel;
2132 if(fLowNorm.z()!=0.)
2134 newz = -fDz-(p.
x()*fLowNorm.x()+p.
y()*fLowNorm.y())/fLowNorm.z();
2139 if(fHighNorm.z()!=0.)
2141 newz = fDz-(p.
x()*fHighNorm.x()+p.
y()*fHighNorm.y())/fHighNorm.z();
G4TemplateAutoLock< G4Mutex > G4AutoLock
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
G4GLOB_DLL std::ostream G4cout
double dot(const Hep3Vector &) const
void set(double x, double y, double z)
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
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(const G4String &pName)
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
G4VSolid(const G4String &name)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
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