39#if !defined(G4GEOM_USE_UCONS)
82 :
G4CSGSolid(pName), fRmin1(pRmin1), fRmin2(pRmin2),
83 fRmax1(pRmax1), fRmax2(pRmax2), fDz(pDz), fSPhi(0.), fDPhi(0.)
89 halfRadTolerance=kRadTolerance*0.5;
90 halfAngTolerance=kAngTolerance*0.5;
96 std::ostringstream message;
97 message <<
"Invalid Z half-length for Solid: " <<
GetName() <<
G4endl
105 if (((pRmin1>=pRmax1) || (pRmin2>=pRmax2) || (pRmin1<0)) && (pRmin2<0))
107 std::ostringstream message;
108 message <<
"Invalid values of radii for Solid: " <<
GetName() <<
G4endl
109 <<
" pRmin1 = " << pRmin1 <<
", pRmin2 = " << pRmin2
110 <<
", pRmax1 = " << pRmax1 <<
", pRmax2 = " << pRmax2;
114 if( (pRmin1 == 0.0) && (pRmin2 > 0.0) ) { fRmin1 = 1e3*kRadTolerance ; }
115 if( (pRmin2 == 0.0) && (pRmin1 > 0.0) ) { fRmin2 = 1e3*kRadTolerance ; }
119 CheckPhiAngles(pSPhi, pDPhi);
128 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
129 fRmin1(0.), fRmin2(0.), fRmax1(0.), fRmax2(0.), fDz(0.),
130 fSPhi(0.), fDPhi(0.), sinCPhi(0.), cosCPhi(0.), cosHDPhi(0.),
131 cosHDPhiOT(0.), cosHDPhiIT(0.), sinSPhi(0.), cosSPhi(0.),
132 sinEPhi(0.), cosEPhi(0.),
133 halfCarTolerance(0.), halfRadTolerance(0.), halfAngTolerance(0.)
150 :
G4CSGSolid(rhs), kRadTolerance(rhs.kRadTolerance),
151 kAngTolerance(rhs.kAngTolerance), fRmin1(rhs.fRmin1), fRmin2(rhs.fRmin2),
152 fRmax1(rhs.fRmax1), fRmax2(rhs.fRmax2), fDz(rhs.fDz), fSPhi(rhs.fSPhi),
153 fDPhi(rhs.fDPhi), sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi),
154 cosHDPhi(rhs.cosHDPhi), cosHDPhiOT(rhs.cosHDPhiOT),
155 cosHDPhiIT(rhs.cosHDPhiIT), sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
156 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullCone(rhs.fPhiFullCone),
157 halfCarTolerance(rhs.halfCarTolerance),
158 halfRadTolerance(rhs.halfRadTolerance),
159 halfAngTolerance(rhs.halfAngTolerance)
171 if (
this == &rhs) {
return *
this; }
179 kRadTolerance = rhs.kRadTolerance;
180 kAngTolerance = rhs.kAngTolerance;
181 fRmin1 = rhs.fRmin1; fRmin2 = rhs.fRmin2;
182 fRmax1 = rhs.fRmax1; fRmax2 = rhs.fRmax2;
183 fDz = rhs.fDz; 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 fPhiFullCone = rhs.fPhiFullCone;
189 halfCarTolerance = rhs.halfCarTolerance;
190 halfRadTolerance = rhs.halfRadTolerance;
191 halfAngTolerance = rhs.halfAngTolerance;
202 G4double r2, rl, rh, pPhi, tolRMin, tolRMax;
205 if (std::fabs(p.
z()) > fDz + halfCarTolerance ) {
return in =
kOutside; }
206 else if(std::fabs(p.
z()) >= fDz - halfCarTolerance ) { in =
kSurface; }
209 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
210 rl = 0.5*(fRmin2*(p.
z() + fDz) + fRmin1*(fDz - p.
z()))/fDz ;
211 rh = 0.5*(fRmax2*(p.
z()+fDz)+fRmax1*(fDz-p.
z()))/fDz;
215 tolRMin = rl - halfRadTolerance;
216 if ( tolRMin < 0 ) { tolRMin = 0; }
217 tolRMax = rh + halfRadTolerance;
219 if ( (r2<tolRMin*tolRMin) || (r2>tolRMax*tolRMax) ) {
return in =
kOutside; }
221 if (rl) { tolRMin = rl + halfRadTolerance; }
222 else { tolRMin = 0.0; }
223 tolRMax = rh - halfRadTolerance;
227 if ( (r2 < tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax) ) { in =
kSurface; }
229 if ( !fPhiFullCone && ((p.
x() != 0.0) || (p.
y() != 0.0)) )
231 pPhi = std::atan2(p.
y(),p.
x()) ;
233 if ( pPhi < fSPhi - halfAngTolerance ) { pPhi += twopi; }
234 else if ( pPhi > fSPhi + fDPhi + halfAngTolerance ) { pPhi -= twopi; }
236 if ( (pPhi < fSPhi - halfAngTolerance) ||
237 (pPhi > fSPhi + fDPhi + halfAngTolerance) ) {
return in =
kOutside; }
241 if ( (pPhi < fSPhi + halfAngTolerance) ||
242 (pPhi > fSPhi + fDPhi - halfAngTolerance) ) { in =
kSurface; }
245 else if ( !fPhiFullCone ) { in =
kSurface; }
281 pMin.
set(vmin.
x(),vmin.
y(),-dz);
282 pMax.
set(vmax.
x(),vmax.
y(), dz);
286 pMin.
set(-rmax,-rmax,-dz);
287 pMax.
set( rmax, rmax, dz);
292 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
294 std::ostringstream message;
295 message <<
"Bad bounding box (min >= max) for solid: "
297 <<
"\npMin = " << pMin
298 <<
"\npMax = " << pMax;
299 G4Exception(
"G4Cons::BoundingLimits()",
"GeomMgt0001",
324 if (
true)
return bbox.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
328 return exist = (pMin < pMax) ?
true :
false;
341 const G4int NSTEPS = 24;
343 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
346 G4double sinHalf = std::sin(0.5*ang);
347 G4double cosHalf = std::cos(0.5*ang);
348 G4double sinStep = 2.*sinHalf*cosHalf;
349 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
355 if (rmin1 == 0 && rmin2 == 0 && dphi == twopi)
361 for (
G4int k=0; k<NSTEPS; ++k)
363 baseA[k].set(rext1*cosCur,rext1*sinCur,-dz);
364 baseB[k].set(rext2*cosCur,rext2*sinCur, dz);
367 sinCur = sinCur*cosStep + cosCur*sinStep;
368 cosCur = cosCur*cosStep - sinTmp*sinStep;
370 std::vector<const G4ThreeVectorList *> polygons(2);
371 polygons[0] = &baseA;
372 polygons[1] = &baseB;
382 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
383 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
387 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
388 pols[0][0].set(rmin2*cosStart,rmin2*sinStart, dz);
389 pols[0][1].set(rmin1*cosStart,rmin1*sinStart,-dz);
390 pols[0][2].set(rmax1*cosStart,rmax1*sinStart,-dz);
391 pols[0][3].set(rmax2*cosStart,rmax2*sinStart, dz);
392 for (
G4int k=1; k<ksteps+1; ++k)
394 pols[k][0].set(rmin2*cosCur,rmin2*sinCur, dz);
395 pols[k][1].set(rmin1*cosCur,rmin1*sinCur,-dz);
396 pols[k][2].set(rext1*cosCur,rext1*sinCur,-dz);
397 pols[k][3].set(rext2*cosCur,rext2*sinCur, dz);
400 sinCur = sinCur*cosStep + cosCur*sinStep;
401 cosCur = cosCur*cosStep - sinTmp*sinStep;
403 pols[ksteps+1][0].set(rmin2*cosEnd,rmin2*sinEnd, dz);
404 pols[ksteps+1][1].set(rmin1*cosEnd,rmin1*sinEnd,-dz);
405 pols[ksteps+1][2].set(rmax1*cosEnd,rmax1*sinEnd,-dz);
406 pols[ksteps+1][3].set(rmax2*cosEnd,rmax2*sinEnd, dz);
409 std::vector<const G4ThreeVectorList *> polygons;
410 polygons.resize(ksteps+2);
411 for (
G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
426 G4int noSurfaces = 0;
429 G4double distSPhi = kInfinity, distEPhi = kInfinity;
430 G4double tanRMin, secRMin, pRMin, widRMin;
431 G4double tanRMax, secRMax, pRMax, widRMax;
436 distZ = std::fabs(std::fabs(p.
z()) - fDz);
437 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
439 tanRMin = (fRmin2 - fRmin1)*0.5/fDz;
440 secRMin = std::sqrt(1 + tanRMin*tanRMin);
441 pRMin = rho - p.
z()*tanRMin;
442 widRMin = fRmin2 - fDz*tanRMin;
443 distRMin = std::fabs(pRMin - widRMin)/secRMin;
445 tanRMax = (fRmax2 - fRmax1)*0.5/fDz;
446 secRMax = std::sqrt(1+tanRMax*tanRMax);
447 pRMax = rho - p.
z()*tanRMax;
448 widRMax = fRmax2 - fDz*tanRMax;
449 distRMax = std::fabs(pRMax - widRMax)/secRMax;
455 pPhi = std::atan2(p.
y(),p.
x());
457 if (pPhi < fSPhi-halfCarTolerance) { pPhi += twopi; }
458 else if (pPhi > fSPhi+fDPhi+halfCarTolerance) { pPhi -= twopi; }
460 distSPhi = std::fabs( pPhi - fSPhi );
461 distEPhi = std::fabs( pPhi - fSPhi - fDPhi );
463 else if( !(fRmin1) || !(fRmin2) )
471 if ( rho > halfCarTolerance )
473 nR =
G4ThreeVector(p.
x()/rho/secRMax, p.
y()/rho/secRMax, -tanRMax/secRMax);
474 if (fRmin1 || fRmin2)
476 nr =
G4ThreeVector(-p.
x()/rho/secRMin,-p.
y()/rho/secRMin,tanRMin/secRMin);
480 if( distRMax <= halfCarTolerance )
485 if( (fRmin1 || fRmin2) && (distRMin <= halfCarTolerance) )
492 if (distSPhi <= halfAngTolerance)
497 if (distEPhi <= halfAngTolerance)
503 if (distZ <= halfCarTolerance)
506 if ( p.
z() >= 0.) { sumnorm += nZ; }
507 else { sumnorm -= nZ; }
509 if ( noSurfaces == 0 )
512 G4Exception(
"G4Cons::SurfaceNormal(p)",
"GeomSolids1002",
515 norm = ApproxSurfaceNormal(p);
517 else if ( noSurfaces == 1 ) { norm = sumnorm; }
518 else { norm = sumnorm.
unit(); }
533 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
534 G4double tanRMin, secRMin, pRMin, widRMin ;
535 G4double tanRMax, secRMax, pRMax, widRMax ;
537 distZ = std::fabs(std::fabs(p.
z()) - fDz) ;
538 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
540 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
541 secRMin = std::sqrt(1 + tanRMin*tanRMin) ;
542 pRMin = rho - p.
z()*tanRMin ;
543 widRMin = fRmin2 - fDz*tanRMin ;
544 distRMin = std::fabs(pRMin - widRMin)/secRMin ;
546 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
547 secRMax = std::sqrt(1+tanRMax*tanRMax) ;
548 pRMax = rho - p.
z()*tanRMax ;
549 widRMax = fRmax2 - fDz*tanRMax ;
550 distRMax = std::fabs(pRMax - widRMax)/secRMax ;
552 if (distRMin < distRMax)
554 if (distZ < distRMin)
567 if (distZ < distRMax)
578 if ( !fPhiFullCone && rho )
580 phi = std::atan2(p.
y(),p.
x()) ;
582 if (phi < 0) { phi += twopi; }
584 if (fSPhi < 0) { distSPhi = std::fabs(phi - (fSPhi + twopi))*rho; }
585 else { distSPhi = std::fabs(phi - fSPhi)*rho; }
587 distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
591 if (distSPhi < distEPhi)
593 if (distSPhi < distMin) { side = kNSPhi; }
597 if (distEPhi < distMin) { side = kNEPhi; }
635 "Undefined side for valid surface normal to solid.");
670 const G4double dRmax = 50*(fRmax1+fRmax2);
672 G4double tanRMax,secRMax,rMaxAv,rMaxOAv ;
673 G4double tanRMin,secRMin,rMinAv,rMinOAv ;
676 G4double tolORMin,tolORMin2,tolIRMin,tolIRMin2 ;
677 G4double tolORMax2,tolIRMax,tolIRMax2 ;
680 G4double Dist,sd,xi,yi,zi,ri=0.,risec,rhoi2,cosPsi ;
690 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
691 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
692 rMinAv = (fRmin1 + fRmin2)*0.5 ;
694 if (rMinAv > halfRadTolerance)
696 rMinOAv = rMinAv - halfRadTolerance ;
702 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
703 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
704 rMaxAv = (fRmax1 + fRmax2)*0.5 ;
705 rMaxOAv = rMaxAv + halfRadTolerance ;
709 tolIDz = fDz - halfCarTolerance ;
710 tolODz = fDz + halfCarTolerance ;
712 if (std::fabs(p.
z()) >= tolIDz)
714 if ( p.
z()*v.
z() < 0 )
716 sd = (std::fabs(p.
z()) - fDz)/std::fabs(v.
z()) ;
718 if( sd < 0.0 ) { sd = 0.0; }
720 xi = p.
x() + sd*v.
x() ;
721 yi = p.
y() + sd*v.
y() ;
722 rhoi2 = xi*xi + yi*yi ;
729 tolORMin = fRmin1 - halfRadTolerance*secRMin ;
730 tolIRMin = fRmin1 + halfRadTolerance*secRMin ;
731 tolIRMax = fRmax1 - halfRadTolerance*secRMin ;
737 tolORMin = fRmin2 - halfRadTolerance*secRMin ;
738 tolIRMin = fRmin2 + halfRadTolerance*secRMin ;
739 tolIRMax = fRmax2 - halfRadTolerance*secRMin ;
746 tolIRMin2 = tolIRMin*tolIRMin ;
753 if ( tolIRMax > 0 ) { tolIRMax2 = tolIRMax*tolIRMax; }
754 else { tolIRMax2 = 0.0; }
756 if ( (tolIRMin2 <= rhoi2) && (rhoi2 <= tolIRMax2) )
758 if ( !fPhiFullCone && rhoi2 )
762 cosPsi = (xi*cosCPhi + yi*sinCPhi)/std::sqrt(rhoi2) ;
764 if (cosPsi >= cosHDPhiIT) {
return sd; }
797 t1 = 1.0 - v.
z()*v.
z() ;
798 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
799 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
800 rin = tanRMin*p.
z() + rMinAv ;
801 rout = tanRMax*p.
z() + rMaxAv ;
806 nt1 = t1 - (tanRMax*v.
z())*(tanRMax*v.
z()) ;
807 nt2 = t2 - tanRMax*v.
z()*rout ;
808 nt3 = t3 - rout*rout ;
810 if (std::fabs(nt1) > kRadTolerance)
815 if ( (nt3 > rout*rout*kRadTolerance*kRadTolerance*secRMax*secRMax)
824 if ((rout < 0) && (nt3 <= 0))
829 if (b>0) { sd = c/(-b-std::sqrt(d)); }
830 else { sd = -b + std::sqrt(d); }
834 if ((b <= 0) && (c >= 0))
836 sd=c/(-b+std::sqrt(d));
842 sd = -b + std::sqrt(d) ;
843 if((sd<0) & (sd>-halfRadTolerance)) sd=0;
855 G4double fTerm = sd-std::fmod(sd,dRmax);
858 zi = p.
z() + sd*v.
z() ;
860 if (std::fabs(zi) <= tolODz)
864 if ( fPhiFullCone ) {
return sd; }
867 xi = p.
x() + sd*v.
x() ;
868 yi = p.
y() + sd*v.
y() ;
869 ri = rMaxAv + zi*tanRMax ;
870 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
872 if ( cosPsi >= cosHDPhiIT ) {
return sd; }
883 if ( ( t3 > (rin + halfRadTolerance*secRMin)*
884 (rin + halfRadTolerance*secRMin) )
885 && (nt2 < 0) && (d >= 0) && (std::fabs(p.
z()) <= tolIDz) )
892 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
896 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/std::sqrt(t3) ;
897 if ( cosPsi >= cosHDPhiIT )
899 if ( Normal.
dot(v) <= 0 ) {
return 0.0; }
904 if ( Normal.
dot(v) <= 0 ) {
return 0.0; }
911 if ( std::fabs(nt2) > kRadTolerance )
915 if ( sd < 0 ) {
return kInfinity; }
918 zi = p.
z() + sd*v.
z() ;
920 if ((std::fabs(zi) <= tolODz) && (nt2 < 0))
924 if ( fPhiFullCone ) {
return sd; }
927 xi = p.
x() + sd*v.
x() ;
928 yi = p.
y() + sd*v.
y() ;
929 ri = rMaxAv + zi*tanRMax ;
930 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
932 if (cosPsi >= cosHDPhiIT) {
return sd; }
954 nt1 = t1 - (tanRMin*v.
z())*(tanRMin*v.
z()) ;
955 nt2 = t2 - tanRMin*v.
z()*rin ;
960 if ( nt3 > rin*kRadTolerance*secRMin )
970 if(b>0){sd = c/( -b-std::sqrt(d));}
971 else {sd = -b + std::sqrt(d) ;}
977 G4double fTerm = sd-std::fmod(sd,dRmax);
980 zi = p.
z() + sd*v.
z() ;
982 if ( std::fabs(zi) <= tolODz )
986 xi = p.
x() + sd*v.
x() ;
987 yi = p.
y() + sd*v.
y() ;
988 ri = rMinAv + zi*tanRMin ;
989 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
991 if (cosPsi >= cosHDPhiIT)
993 if ( sd > halfRadTolerance ) { snxt=sd; }
998 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1000 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1006 if ( sd > halfRadTolerance ) {
return sd; }
1011 xi = p.
x() + sd*v.
x() ;
1012 yi = p.
y() + sd*v.
y() ;
1013 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1014 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1015 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1022 else if ( nt3 < -rin*kRadTolerance*secRMin )
1035 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1036 else { sd = -b + std::sqrt(d); }
1037 zi = p.
z() + sd*v.
z() ;
1038 ri = rMinAv + zi*tanRMin ;
1042 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1046 G4double fTerm = sd-std::fmod(sd,dRmax);
1049 if ( !fPhiFullCone )
1051 xi = p.
x() + sd*v.
x() ;
1052 yi = p.
y() + sd*v.
y() ;
1053 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1055 if (cosPsi >= cosHDPhiOT)
1057 if ( sd > halfRadTolerance ) { snxt=sd; }
1062 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1063 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin);
1064 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1070 if( sd > halfRadTolerance ) {
return sd; }
1075 xi = p.
x() + sd*v.
x() ;
1076 yi = p.
y() + sd*v.
y() ;
1077 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1078 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1079 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1086 if (b>0) { sd = -b - std::sqrt(d); }
1087 else { sd = c/(-b+std::sqrt(d)); }
1088 zi = p.
z() + sd*v.
z() ;
1089 ri = rMinAv + zi*tanRMin ;
1091 if ( (sd >= 0) && (ri > 0) && (std::fabs(zi) <= tolODz) )
1095 G4double fTerm = sd-std::fmod(sd,dRmax);
1098 if ( !fPhiFullCone )
1100 xi = p.
x() + sd*v.
x() ;
1101 yi = p.
y() + sd*v.
y() ;
1102 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1104 if (cosPsi >= cosHDPhiIT)
1106 if ( sd > halfRadTolerance ) { snxt=sd; }
1111 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1112 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin);
1113 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1119 if ( sd > halfRadTolerance ) {
return sd; }
1124 xi = p.
x() + sd*v.
x() ;
1125 yi = p.
y() + sd*v.
y() ;
1126 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1127 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1128 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1142 if ( std::fabs(p.
z()) <= tolODz )
1148 if ( !fPhiFullCone )
1150 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/std::sqrt(t3) ;
1152 if (cosPsi >= cosHDPhiIT) {
return 0.0; }
1154 else {
return 0.0; }
1167 if (b>0) { sd = -b - std::sqrt(d); }
1168 else { sd = c/(-b+std::sqrt(d)); }
1169 zi = p.
z() + sd*v.
z() ;
1170 ri = rMinAv + zi*tanRMin ;
1174 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1175 else { sd = -b + std::sqrt(d); }
1177 zi = p.
z() + sd*v.
z() ;
1179 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1183 G4double fTerm = sd-std::fmod(sd,dRmax);
1186 if ( !fPhiFullCone )
1188 xi = p.
x() + sd*v.
x() ;
1189 yi = p.
y() + sd*v.
y() ;
1190 ri = rMinAv + zi*tanRMin ;
1191 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1193 if ( cosPsi >= cosHDPhiIT ) { snxt = sd; }
1198 else {
return kInfinity; }
1210 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1211 else { sd = -b + std::sqrt(d) ; }
1212 zi = p.
z() + sd*v.
z() ;
1214 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1218 G4double fTerm = sd-std::fmod(sd,dRmax);
1221 if ( !fPhiFullCone )
1223 xi = p.
x() + sd*v.
x();
1224 yi = p.
y() + sd*v.
y();
1225 ri = rMinAv + zi*tanRMin ;
1226 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri;
1228 if (cosPsi >= cosHDPhiIT) { snxt = sd; }
1247 if ( !fPhiFullCone )
1251 Comp = v.
x()*sinSPhi - v.
y()*cosSPhi ;
1255 Dist = (p.
y()*cosSPhi - p.
x()*sinSPhi) ;
1257 if (Dist < halfCarTolerance)
1263 if ( sd < 0 ) { sd = 0.0; }
1265 zi = p.
z() + sd*v.
z() ;
1267 if ( std::fabs(zi) <= tolODz )
1269 xi = p.
x() + sd*v.
x() ;
1270 yi = p.
y() + sd*v.
y() ;
1271 rhoi2 = xi*xi + yi*yi ;
1272 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ;
1273 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ;
1275 if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) )
1280 if ((yi*cosCPhi - xi*sinCPhi) <= 0 ) { snxt = sd; }
1289 Comp = -(v.
x()*sinEPhi - v.
y()*cosEPhi) ;
1293 Dist = -(p.
y()*cosEPhi - p.
x()*sinEPhi) ;
1294 if (Dist < halfCarTolerance)
1300 if ( sd < 0 ) { sd = 0.0; }
1302 zi = p.
z() + sd*v.
z() ;
1304 if (std::fabs(zi) <= tolODz)
1306 xi = p.
x() + sd*v.
x() ;
1307 yi = p.
y() + sd*v.
y() ;
1308 rhoi2 = xi*xi + yi*yi ;
1309 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ;
1310 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ;
1312 if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) )
1317 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) { snxt = sd; }
1324 if (snxt < halfCarTolerance) { snxt = 0.; }
1338 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi, cosPsi ;
1342 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1343 safeZ = std::fabs(p.
z()) - fDz ;
1345 if ( fRmin1 || fRmin2 )
1347 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
1348 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
1349 pRMin = tanRMin*p.
z() + (fRmin1 + fRmin2)*0.5 ;
1350 safeR1 = (pRMin - rho)/secRMin ;
1352 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1353 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1354 pRMax = tanRMax*p.
z() + (fRmax1 + fRmax2)*0.5 ;
1355 safeR2 = (rho - pRMax)/secRMax ;
1357 if ( safeR1 > safeR2) { safe = safeR1; }
1358 else { safe = safeR2; }
1362 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1363 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1364 pRMax = tanRMax*p.
z() + (fRmax1 + fRmax2)*0.5 ;
1365 safe = (rho - pRMax)/secRMax ;
1367 if ( safeZ > safe ) { safe = safeZ; }
1369 if ( !fPhiFullCone && rho )
1373 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/rho ;
1375 if ( cosPsi < cosHDPhi )
1377 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0.0 )
1379 safePhi = std::fabs(p.
x()*sinSPhi-p.
y()*cosSPhi);
1383 safePhi = std::fabs(p.
x()*sinEPhi-p.
y()*cosEPhi);
1385 if ( safePhi > safe ) { safe = safePhi; }
1388 if ( safe < 0.0 ) { safe = 0.0; }
1404 ESide side = kNull, sider = kNull, sidephi = kNull;
1408 G4double tanRMax, secRMax, rMaxAv ;
1409 G4double tanRMin, secRMin, rMinAv ;
1411 G4double t1, t2, t3, rout, rin, nt1, nt2, nt3 ;
1416 ESide sidetol = kNull ;
1421 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, risec, vphi ;
1428 pdist = fDz - p.
z() ;
1430 if (pdist > halfCarTolerance)
1432 snxt = pdist/v.
z() ;
1445 else if ( v.
z() < 0.0 )
1447 pdist = fDz + p.
z() ;
1449 if ( pdist > halfCarTolerance)
1451 snxt = -pdist/v.
z() ;
1487 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1488 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1489 rMaxAv = (fRmax1 + fRmax2)*0.5 ;
1492 t1 = 1.0 - v.
z()*v.
z() ;
1493 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1494 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1495 rout = tanRMax*p.
z() + rMaxAv ;
1497 nt1 = t1 - (tanRMax*v.
z())*(tanRMax*v.
z()) ;
1498 nt2 = t2 - tanRMax*v.
z()*rout ;
1499 nt3 = t3 - rout*rout ;
1503 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3
1504 - fRmax2*(fRmax2 + kRadTolerance*secRMax);
1506 else if (v.
z() < 0.0)
1508 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3
1509 - fRmax1*(fRmax1 + kRadTolerance*secRMax);
1516 if ( nt1 && (deltaRoi2 > 0.0) )
1529 if (nt3 > -halfRadTolerance && nt2 >= 0 )
1533 risec = std::sqrt(t3)*secRMax ;
1542 if (b>0) { srd = -b - std::sqrt(d); }
1543 else { srd = c/(-b+std::sqrt(d)) ; }
1545 zi = p.
z() + srd*v.
z() ;
1546 ri = tanRMax*zi + rMaxAv ;
1548 if ((ri >= 0) && (-halfRadTolerance <= srd) && (srd <= halfRadTolerance))
1556 if ( (ri < 0) || (srd < halfRadTolerance) )
1561 if (b>0) { sr2 = c/(-b-std::sqrt(d)); }
1562 else { sr2 = -b + std::sqrt(d); }
1563 zi = p.
z() + sr2*v.
z() ;
1564 ri = tanRMax*zi + rMaxAv ;
1566 if ((ri >= 0) && (sr2 > halfRadTolerance))
1574 if( (-halfRadTolerance <= sr2) && ( sr2 <= halfRadTolerance) )
1593 risec = std::sqrt(t3)*secRMax;
1600 else if ( nt2 && (deltaRoi2 > 0.0) )
1606 risec = std::sqrt(t3)*secRMax;
1622 if ( slentol <= halfCarTolerance )
1633 xi = p.
x() + slentol*v.
x();
1634 yi = p.
y() + slentol*v.
y();
1635 risec = std::sqrt(xi*xi + yi*yi)*secRMax;
1638 if ( Normal.
dot(v) > 0 )
1642 *n = Normal.
unit() ;
1649 slentol = kInfinity ;
1655 if ( fRmin1 || fRmin2 )
1657 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
1658 nt1 = t1 - (tanRMin*v.
z())*(tanRMin*v.
z()) ;
1662 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
1663 rMinAv = (fRmin1 + fRmin2)*0.5 ;
1664 rin = tanRMin*p.
z() + rMinAv ;
1665 nt2 = t2 - tanRMin*v.
z()*rin ;
1666 nt3 = t3 - rin*rin ;
1679 if (nt3 < kRadTolerance*(rin + kRadTolerance*0.25))
1683 if (calcNorm) { *validNorm =
false; }
1689 if (b>0) { sr2 = -b - std::sqrt(d); }
1690 else { sr2 = c/(-b+std::sqrt(d)); }
1691 zi = p.
z() + sr2*v.
z() ;
1692 ri = tanRMin*zi + rMinAv ;
1694 if( (ri>=0.0)&&(-halfRadTolerance<=sr2)&&(sr2<=halfRadTolerance) )
1702 if( (ri<0) || (sr2 < halfRadTolerance) )
1704 if (b>0) { sr3 = c/(-b-std::sqrt(d)); }
1705 else { sr3 = -b + std::sqrt(d) ; }
1710 if ( sr3 > halfRadTolerance )
1714 zi = p.
z() + sr3*v.
z() ;
1715 ri = tanRMin*zi + rMinAv ;
1724 else if ( sr3 > -halfRadTolerance )
1732 else if ( (sr2 < srd) && (sr2 > halfCarTolerance) )
1737 else if (sr2 > -halfCarTolerance)
1744 if( slentol <= halfCarTolerance )
1753 xi = p.
x() + slentol*v.
x() ;
1754 yi = p.
y() + slentol*v.
y() ;
1755 if( sidetol==kRMax )
1757 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
1758 Normal =
G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ;
1762 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1763 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1765 if( Normal.
dot(v) > 0 )
1771 *n = Normal.
unit() ;
1781 slentol = kInfinity ;
1793 if ( !fPhiFullCone )
1798 vphi = std::atan2(v.
y(),v.
x()) ;
1800 if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
1801 else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; }
1803 if ( p.
x() || p.
y() )
1807 pDistS = p.
x()*sinSPhi - p.
y()*cosSPhi ;
1808 pDistE = -p.
x()*sinEPhi + p.
y()*cosEPhi ;
1812 compS = -sinSPhi*v.
x() + cosSPhi*v.
y() ;
1813 compE = sinEPhi*v.
x() - cosEPhi*v.
y() ;
1817 if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
1818 && (pDistE <= halfCarTolerance) ) )
1819 || ( (fDPhi > pi) && !((pDistS > halfCarTolerance)
1820 && (pDistE > halfCarTolerance) ) ) )
1825 sphi = pDistS/compS ;
1826 if (sphi >= -halfCarTolerance)
1828 xi = p.
x() + sphi*v.
x() ;
1829 yi = p.
y() + sphi*v.
y() ;
1838 if ( ( fSPhi-halfAngTolerance <= vphi )
1839 && ( fSPhi+fDPhi+halfAngTolerance >=vphi ) )
1845 if ( (yi*cosCPhi-xi*sinCPhi)>=0 )
1852 if ( pDistS > -halfCarTolerance )
1870 sphi2 = pDistE/compE ;
1874 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1876 xi = p.
x() + sphi2*v.
x() ;
1877 yi = p.
y() + sphi2*v.
y() ;
1886 if(!( (fSPhi-halfAngTolerance <= vphi)
1887 && (fSPhi+fDPhi+halfAngTolerance >= vphi) ) )
1890 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; }
1891 else { sphi = 0.0; }
1895 if ( yi*cosCPhi-xi*sinCPhi >= 0 )
1900 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; }
1901 else { sphi = 0.0; }
1916 if ( (fSPhi-halfAngTolerance <= vphi)
1917 && (vphi <= fSPhi+fDPhi+halfAngTolerance) )
1943 xi = p.
x() + snxt*v.
x() ;
1944 yi = p.
y() + snxt*v.
y() ;
1945 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
1950 *validNorm = false ;
1960 *validNorm = false ;
1971 *validNorm = false ;
1985 std::ostringstream message;
1986 G4long oldprc = message.precision(16) ;
1987 message <<
"Undefined side for valid surface normal to solid."
1990 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1991 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1993 <<
"pho at z = " << std::sqrt( p.
x()*p.
x()+p.
y()*p.
y() )/mm
1995 if( p.
x() != 0. || p.
y() != 0.)
1997 message <<
"point phi = " << std::atan2(p.
y(),p.
x())/degree
2001 <<
"v.x() = " << v.
x() <<
G4endl
2002 <<
"v.y() = " << v.
y() <<
G4endl
2005 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
2006 message.precision(oldprc) ;
2007 G4Exception(
"G4Cons::DistanceToOut(p,v,..)",
"GeomSolids1002",
2012 if (snxt < halfCarTolerance) { snxt = 0.; }
2023 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi;
2037 G4cout <<
"pho at z = " << std::sqrt( p.
x()*p.
x()+p.
y()*p.
y() )/mm
2039 if( (p.
x() != 0.) || (p.
x() != 0.) )
2041 G4cout <<
"point phi = " << std::atan2(p.
y(),p.
x())/degree
2044 G4cout.precision(oldprc) ;
2045 G4Exception(
"G4Cons::DistanceToOut(p)",
"GeomSolids1002",
2050 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
2051 safeZ = fDz - std::fabs(p.
z()) ;
2053 if (fRmin1 || fRmin2)
2055 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
2056 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
2057 pRMin = tanRMin*p.
z() + (fRmin1 + fRmin2)*0.5 ;
2058 safeR1 = (rho - pRMin)/secRMin ;
2062 safeR1 = kInfinity ;
2065 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
2066 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
2067 pRMax = tanRMax*p.
z() + (fRmax1+fRmax2)*0.5 ;
2068 safeR2 = (pRMax - rho)/secRMax ;
2070 if (safeR1 < safeR2) { safe = safeR1; }
2071 else { safe = safeR2; }
2072 if (safeZ < safe) { safe = safeZ ; }
2080 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0 )
2082 safePhi = -(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
2086 safePhi = (p.
x()*sinEPhi - p.
y()*cosEPhi) ;
2088 if (safePhi < safe) { safe = safePhi; }
2090 if ( safe < 0 ) { safe = 0; }
2110 return new G4Cons(*
this);
2119 G4long oldprc = os.precision(16);
2120 os <<
"-----------------------------------------------------------\n"
2121 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
2122 <<
" ===================================================\n"
2123 <<
" Solid type: G4Cons\n"
2124 <<
" Parameters: \n"
2125 <<
" inside -fDz radius: " << fRmin1/mm <<
" mm \n"
2126 <<
" outside -fDz radius: " << fRmax1/mm <<
" mm \n"
2127 <<
" inside +fDz radius: " << fRmin2/mm <<
" mm \n"
2128 <<
" outside +fDz radius: " << fRmax2/mm <<
" mm \n"
2129 <<
" half length in Z : " << fDz/mm <<
" mm \n"
2130 <<
" starting angle of segment: " << fSPhi/degree <<
" degrees \n"
2131 <<
" delta angle of segment : " << fDPhi/degree <<
" degrees \n"
2132 <<
"-----------------------------------------------------------\n";
2133 os.precision(oldprc);
2148 G4double rone = (fRmax1-fRmax2)/(2.*fDz);
2149 G4double rtwo = (fRmin1-fRmin2)/(2.*fDz);
2150 G4double qone = (fRmax1 == fRmax2) ? 0. : fDz*(fRmax1+fRmax2)/(fRmax1-fRmax2);
2151 G4double qtwo = (fRmin1 == fRmin2) ? 0. : fDz*(fRmin1+fRmin2)/(fRmin1-fRmin2);
2153 G4double slin = std::hypot(fRmin1-fRmin2, 2.*fDz);
2154 G4double slout = std::hypot(fRmax1-fRmax2, 2.*fDz);
2155 G4double Aone = 0.5*fDPhi*(fRmax2 + fRmax1)*slout;
2156 G4double Atwo = 0.5*fDPhi*(fRmin2 + fRmin1)*slin;
2157 G4double Athree = 0.5*fDPhi*(fRmax1*fRmax1-fRmin1*fRmin1);
2158 G4double Afour = 0.5*fDPhi*(fRmax2*fRmax2-fRmin2*fRmin2);
2159 G4double Afive = fDz*(fRmax1-fRmin1+fRmax2-fRmin2);
2161 G4double phi = G4RandFlat::shoot(fSPhi,fSPhi+fDPhi);
2167 if ( (fSPhi == 0.) && fPhiFullCone ) { Afive = 0.; }
2168 G4double chose = G4RandFlat::shoot(0.,Aone+Atwo+Athree+Afour+2.*Afive);
2170 if( (chose >= 0.) && (chose < Aone) )
2172 if(fRmax1 != fRmax2)
2174 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2176 rone*sinu*(qone-zRand), zRand);
2181 G4RandFlat::shoot(-1.*fDz,fDz));
2184 else if( (chose >= Aone) && (chose < Aone + Atwo) )
2186 if(fRmin1 != fRmin2)
2188 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2190 rtwo*sinu*(qtwo-zRand), zRand);
2195 G4RandFlat::shoot(-1.*fDz,fDz));
2198 else if( (chose >= Aone + Atwo) && (chose < Aone + Atwo + Athree) )
2202 else if( (chose >= Aone + Atwo + Athree)
2203 && (chose < Aone + Atwo + Athree + Afour) )
2207 else if( (chose >= Aone + Atwo + Athree + Afour)
2208 && (chose < Aone + Atwo + Athree + Afour + Afive) )
2210 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2211 rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
2212 fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
2214 rRand1*sinSPhi, zRand);
2218 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2219 rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
2220 fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
2222 rRand1*sinEPhi, zRand);
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
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
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4double GetOuterRadiusPlusZ() const
G4double GetCosStartPhi() const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4double GetDeltaPhiAngle() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4double GetInnerRadiusMinusZ() const
G4double GetInnerRadiusPlusZ() const
G4GeometryType GetEntityType() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4double GetCosEndPhi() const
G4Polyhedron * CreatePolyhedron() const
G4Cons(const G4String &pName, G4double pRmin1, G4double pRmax1, G4double pRmin2, G4double pRmax2, G4double pDz, G4double pSPhi, G4double pDPhi)
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double GetOuterRadiusMinusZ() const
G4double GetSinEndPhi() const
G4Cons & operator=(const G4Cons &rhs)
G4double GetSinStartPhi() const
EInside Inside(const G4ThreeVector &p) const
G4ThreeVector GetPointOnSurface() const
G4double GetZHalfLength() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const
std::ostream & StreamInfo(std::ostream &os) const
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
virtual void AddSolid(const G4Box &)=0
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const