39#if !defined(G4GEOM_USE_UCONS)
77 :
G4CSGSolid(pName), fRmin1(pRmin1), fRmin2(pRmin2),
78 fRmax1(pRmax1), fRmax2(pRmax2), fDz(pDz), fSPhi(0.), fDPhi(0.)
84 halfRadTolerance=kRadTolerance*0.5;
85 halfAngTolerance=kAngTolerance*0.5;
91 std::ostringstream message;
92 message <<
"Invalid Z half-length for Solid: " <<
GetName() <<
G4endl
100 if (((pRmin1>=pRmax1) || (pRmin2>=pRmax2) || (pRmin1<0)) && (pRmin2<0))
102 std::ostringstream message;
103 message <<
"Invalid values of radii for Solid: " <<
GetName() <<
G4endl
104 <<
" pRmin1 = " << pRmin1 <<
", pRmin2 = " << pRmin2
105 <<
", pRmax1 = " << pRmax1 <<
", pRmax2 = " << pRmax2;
109 if( (pRmin1 == 0.0) && (pRmin2 > 0.0) ) { fRmin1 = 1e3*kRadTolerance ; }
110 if( (pRmin2 == 0.0) && (pRmin1 > 0.0) ) { fRmin2 = 1e3*kRadTolerance ; }
114 CheckPhiAngles(pSPhi, pDPhi);
123 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
124 fRmin1(0.), fRmin2(0.), fRmax1(0.), fRmax2(0.), fDz(0.),
125 fSPhi(0.), fDPhi(0.), sinCPhi(0.), cosCPhi(0.), cosHDPhi(0.),
126 cosHDPhiOT(0.), cosHDPhiIT(0.), sinSPhi(0.), cosSPhi(0.),
127 sinEPhi(0.), cosEPhi(0.),
128 halfCarTolerance(0.), halfRadTolerance(0.), halfAngTolerance(0.)
145 :
G4CSGSolid(rhs), kRadTolerance(rhs.kRadTolerance),
146 kAngTolerance(rhs.kAngTolerance), fRmin1(rhs.fRmin1), fRmin2(rhs.fRmin2),
147 fRmax1(rhs.fRmax1), fRmax2(rhs.fRmax2), fDz(rhs.fDz), fSPhi(rhs.fSPhi),
148 fDPhi(rhs.fDPhi), sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi),
149 cosHDPhi(rhs.cosHDPhi), cosHDPhiOT(rhs.cosHDPhiOT),
150 cosHDPhiIT(rhs.cosHDPhiIT), sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi),
151 sinEPhi(rhs.sinEPhi), cosEPhi(rhs.cosEPhi), fPhiFullCone(rhs.fPhiFullCone),
152 halfCarTolerance(rhs.halfCarTolerance),
153 halfRadTolerance(rhs.halfRadTolerance),
154 halfAngTolerance(rhs.halfAngTolerance)
166 if (
this == &rhs) {
return *
this; }
174 kRadTolerance = rhs.kRadTolerance;
175 kAngTolerance = rhs.kAngTolerance;
176 fRmin1 = rhs.fRmin1; fRmin2 = rhs.fRmin2;
177 fRmax1 = rhs.fRmax1; fRmax2 = rhs.fRmax2;
178 fDz = rhs.fDz; fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
179 sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPhi; cosHDPhi = rhs.cosHDPhi;
180 cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = rhs.cosHDPhiIT;
181 sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPhi;
182 sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPhi;
183 fPhiFullCone = rhs.fPhiFullCone;
184 halfCarTolerance = rhs.halfCarTolerance;
185 halfRadTolerance = rhs.halfRadTolerance;
186 halfAngTolerance = rhs.halfAngTolerance;
197 G4double r2, rl, rh, pPhi, tolRMin, tolRMax;
200 if (std::fabs(p.
z()) > fDz + halfCarTolerance ) {
return in =
kOutside; }
201 else if(std::fabs(p.
z()) >= fDz - halfCarTolerance ) { in =
kSurface; }
204 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
205 rl = 0.5*(fRmin2*(p.
z() + fDz) + fRmin1*(fDz - p.
z()))/fDz ;
206 rh = 0.5*(fRmax2*(p.
z()+fDz)+fRmax1*(fDz-p.
z()))/fDz;
210 tolRMin = rl - halfRadTolerance;
211 if ( tolRMin < 0 ) { tolRMin = 0; }
212 tolRMax = rh + halfRadTolerance;
214 if ( (r2<tolRMin*tolRMin) || (r2>tolRMax*tolRMax) ) {
return in =
kOutside; }
216 if (rl) { tolRMin = rl + halfRadTolerance; }
217 else { tolRMin = 0.0; }
218 tolRMax = rh - halfRadTolerance;
222 if ( (r2 < tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax) ) { in =
kSurface; }
224 if ( !fPhiFullCone && ((p.
x() != 0.0) || (p.
y() != 0.0)) )
226 pPhi = std::atan2(p.
y(),p.
x()) ;
228 if ( pPhi < fSPhi - halfAngTolerance ) { pPhi += twopi; }
229 else if ( pPhi > fSPhi + fDPhi + halfAngTolerance ) { pPhi -= twopi; }
231 if ( (pPhi < fSPhi - halfAngTolerance) ||
232 (pPhi > fSPhi + fDPhi + halfAngTolerance) ) {
return in =
kOutside; }
236 if ( (pPhi < fSPhi + halfAngTolerance) ||
237 (pPhi > fSPhi + fDPhi - halfAngTolerance) ) { in =
kSurface; }
240 else if ( !fPhiFullCone ) { in =
kSurface; }
276 pMin.
set(vmin.
x(),vmin.
y(),-dz);
277 pMax.
set(vmax.
x(),vmax.
y(), dz);
281 pMin.
set(-rmax,-rmax,-dz);
282 pMax.
set( rmax, rmax, dz);
287 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
289 std::ostringstream message;
290 message <<
"Bad bounding box (min >= max) for solid: "
292 <<
"\npMin = " << pMin
293 <<
"\npMax = " << pMax;
294 G4Exception(
"G4Cons::BoundingLimits()",
"GeomMgt0001",
319 if (
true)
return bbox.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
323 return exist = (pMin < pMax) ?
true :
false;
336 const G4int NSTEPS = 24;
338 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
341 G4double sinHalf = std::sin(0.5*ang);
342 G4double cosHalf = std::cos(0.5*ang);
343 G4double sinStep = 2.*sinHalf*cosHalf;
344 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
350 if (rmin1 == 0 && rmin2 == 0 && dphi == twopi)
356 for (
G4int k=0; k<NSTEPS; ++k)
358 baseA[k].set(rext1*cosCur,rext1*sinCur,-dz);
359 baseB[k].set(rext2*cosCur,rext2*sinCur, dz);
362 sinCur = sinCur*cosStep + cosCur*sinStep;
363 cosCur = cosCur*cosStep - sinTmp*sinStep;
365 std::vector<const G4ThreeVectorList *> polygons(2);
366 polygons[0] = &baseA;
367 polygons[1] = &baseB;
377 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
378 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
382 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
383 pols[0][0].set(rmin2*cosStart,rmin2*sinStart, dz);
384 pols[0][1].set(rmin1*cosStart,rmin1*sinStart,-dz);
385 pols[0][2].set(rmax1*cosStart,rmax1*sinStart,-dz);
386 pols[0][3].set(rmax2*cosStart,rmax2*sinStart, dz);
387 for (
G4int k=1; k<ksteps+1; ++k)
389 pols[k][0].set(rmin2*cosCur,rmin2*sinCur, dz);
390 pols[k][1].set(rmin1*cosCur,rmin1*sinCur,-dz);
391 pols[k][2].set(rext1*cosCur,rext1*sinCur,-dz);
392 pols[k][3].set(rext2*cosCur,rext2*sinCur, dz);
395 sinCur = sinCur*cosStep + cosCur*sinStep;
396 cosCur = cosCur*cosStep - sinTmp*sinStep;
398 pols[ksteps+1][0].set(rmin2*cosEnd,rmin2*sinEnd, dz);
399 pols[ksteps+1][1].set(rmin1*cosEnd,rmin1*sinEnd,-dz);
400 pols[ksteps+1][2].set(rmax1*cosEnd,rmax1*sinEnd,-dz);
401 pols[ksteps+1][3].set(rmax2*cosEnd,rmax2*sinEnd, dz);
404 std::vector<const G4ThreeVectorList *> polygons;
405 polygons.resize(ksteps+2);
406 for (
G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
421 G4int noSurfaces = 0;
424 G4double distSPhi = kInfinity, distEPhi = kInfinity;
425 G4double tanRMin, secRMin, pRMin, widRMin;
426 G4double tanRMax, secRMax, pRMax, widRMax;
431 distZ = std::fabs(std::fabs(p.
z()) - fDz);
432 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
434 tanRMin = (fRmin2 - fRmin1)*0.5/fDz;
435 secRMin = std::sqrt(1 + tanRMin*tanRMin);
436 pRMin = rho - p.
z()*tanRMin;
437 widRMin = fRmin2 - fDz*tanRMin;
438 distRMin = std::fabs(pRMin - widRMin)/secRMin;
440 tanRMax = (fRmax2 - fRmax1)*0.5/fDz;
441 secRMax = std::sqrt(1+tanRMax*tanRMax);
442 pRMax = rho - p.
z()*tanRMax;
443 widRMax = fRmax2 - fDz*tanRMax;
444 distRMax = std::fabs(pRMax - widRMax)/secRMax;
450 pPhi = std::atan2(p.
y(),p.
x());
452 if (pPhi < fSPhi-halfCarTolerance) { pPhi += twopi; }
453 else if (pPhi > fSPhi+fDPhi+halfCarTolerance) { pPhi -= twopi; }
455 distSPhi = std::fabs( pPhi - fSPhi );
456 distEPhi = std::fabs( pPhi - fSPhi - fDPhi );
458 else if( !(fRmin1) || !(fRmin2) )
466 if ( rho > halfCarTolerance )
468 nR =
G4ThreeVector(p.
x()/rho/secRMax, p.
y()/rho/secRMax, -tanRMax/secRMax);
469 if (fRmin1 || fRmin2)
471 nr =
G4ThreeVector(-p.
x()/rho/secRMin,-p.
y()/rho/secRMin,tanRMin/secRMin);
475 if( distRMax <= halfCarTolerance )
480 if( (fRmin1 || fRmin2) && (distRMin <= halfCarTolerance) )
487 if (distSPhi <= halfAngTolerance)
492 if (distEPhi <= halfAngTolerance)
498 if (distZ <= halfCarTolerance)
501 if ( p.
z() >= 0.) { sumnorm += nZ; }
502 else { sumnorm -= nZ; }
504 if ( noSurfaces == 0 )
507 G4Exception(
"G4Cons::SurfaceNormal(p)",
"GeomSolids1002",
510 norm = ApproxSurfaceNormal(p);
512 else if ( noSurfaces == 1 ) { norm = sumnorm; }
513 else { norm = sumnorm.
unit(); }
528 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
529 G4double tanRMin, secRMin, pRMin, widRMin ;
530 G4double tanRMax, secRMax, pRMax, widRMax ;
532 distZ = std::fabs(std::fabs(p.
z()) - fDz) ;
533 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
535 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
536 secRMin = std::sqrt(1 + tanRMin*tanRMin) ;
537 pRMin = rho - p.
z()*tanRMin ;
538 widRMin = fRmin2 - fDz*tanRMin ;
539 distRMin = std::fabs(pRMin - widRMin)/secRMin ;
541 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
542 secRMax = std::sqrt(1+tanRMax*tanRMax) ;
543 pRMax = rho - p.
z()*tanRMax ;
544 widRMax = fRmax2 - fDz*tanRMax ;
545 distRMax = std::fabs(pRMax - widRMax)/secRMax ;
547 if (distRMin < distRMax)
549 if (distZ < distRMin)
562 if (distZ < distRMax)
573 if ( !fPhiFullCone && rho )
575 phi = std::atan2(p.
y(),p.
x()) ;
577 if (phi < 0) { phi += twopi; }
579 if (fSPhi < 0) { distSPhi = std::fabs(phi - (fSPhi + twopi))*rho; }
580 else { distSPhi = std::fabs(phi - fSPhi)*rho; }
582 distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
586 if (distSPhi < distEPhi)
588 if (distSPhi < distMin) { side = kNSPhi; }
592 if (distEPhi < distMin) { side = kNEPhi; }
630 "Undefined side for valid surface normal to solid.");
665 const G4double dRmax = 50*(fRmax1+fRmax2);
667 G4double tanRMax,secRMax,rMaxAv,rMaxOAv ;
668 G4double tanRMin,secRMin,rMinAv,rMinOAv ;
671 G4double tolORMin,tolORMin2,tolIRMin,tolIRMin2 ;
672 G4double tolORMax2,tolIRMax,tolIRMax2 ;
675 G4double Dist,sd,xi,yi,zi,ri=0.,risec,rhoi2,cosPsi ;
685 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
686 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
687 rMinAv = (fRmin1 + fRmin2)*0.5 ;
689 if (rMinAv > halfRadTolerance)
691 rMinOAv = rMinAv - halfRadTolerance ;
697 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
698 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
699 rMaxAv = (fRmax1 + fRmax2)*0.5 ;
700 rMaxOAv = rMaxAv + halfRadTolerance ;
704 tolIDz = fDz - halfCarTolerance ;
705 tolODz = fDz + halfCarTolerance ;
707 if (std::fabs(p.
z()) >= tolIDz)
709 if ( p.
z()*v.
z() < 0 )
711 sd = (std::fabs(p.
z()) - fDz)/std::fabs(v.
z()) ;
713 if( sd < 0.0 ) { sd = 0.0; }
715 xi = p.
x() + sd*v.
x() ;
716 yi = p.
y() + sd*v.
y() ;
717 rhoi2 = xi*xi + yi*yi ;
724 tolORMin = fRmin1 - halfRadTolerance*secRMin ;
725 tolIRMin = fRmin1 + halfRadTolerance*secRMin ;
726 tolIRMax = fRmax1 - halfRadTolerance*secRMin ;
732 tolORMin = fRmin2 - halfRadTolerance*secRMin ;
733 tolIRMin = fRmin2 + halfRadTolerance*secRMin ;
734 tolIRMax = fRmax2 - halfRadTolerance*secRMin ;
741 tolIRMin2 = tolIRMin*tolIRMin ;
748 if ( tolIRMax > 0 ) { tolIRMax2 = tolIRMax*tolIRMax; }
749 else { tolIRMax2 = 0.0; }
751 if ( (tolIRMin2 <= rhoi2) && (rhoi2 <= tolIRMax2) )
753 if ( !fPhiFullCone && rhoi2 )
757 cosPsi = (xi*cosCPhi + yi*sinCPhi)/std::sqrt(rhoi2) ;
759 if (cosPsi >= cosHDPhiIT) {
return sd; }
792 t1 = 1.0 - v.
z()*v.
z() ;
793 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
794 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
795 rin = tanRMin*p.
z() + rMinAv ;
796 rout = tanRMax*p.
z() + rMaxAv ;
801 nt1 = t1 - (tanRMax*v.
z())*(tanRMax*v.
z()) ;
802 nt2 = t2 - tanRMax*v.
z()*rout ;
803 nt3 = t3 - rout*rout ;
805 if (std::fabs(nt1) > kRadTolerance)
810 if ( (nt3 > rout*rout*kRadTolerance*kRadTolerance*secRMax*secRMax)
819 if ((rout < 0) && (nt3 <= 0))
824 if (b>0) { sd = c/(-b-std::sqrt(d)); }
825 else { sd = -b + std::sqrt(d); }
829 if ((b <= 0) && (c >= 0))
831 sd=c/(-b+std::sqrt(d));
837 sd = -b + std::sqrt(d) ;
838 if((sd<0) & (sd>-halfRadTolerance)) sd=0;
850 G4double fTerm = sd-std::fmod(sd,dRmax);
853 zi = p.
z() + sd*v.
z() ;
855 if (std::fabs(zi) <= tolODz)
859 if ( fPhiFullCone ) {
return sd; }
862 xi = p.
x() + sd*v.
x() ;
863 yi = p.
y() + sd*v.
y() ;
864 ri = rMaxAv + zi*tanRMax ;
865 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
867 if ( cosPsi >= cosHDPhiIT ) {
return sd; }
878 if ( ( t3 > (rin + halfRadTolerance*secRMin)*
879 (rin + halfRadTolerance*secRMin) )
880 && (nt2 < 0) && (d >= 0) && (std::fabs(p.
z()) <= tolIDz) )
887 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
891 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/std::sqrt(t3) ;
892 if ( cosPsi >= cosHDPhiIT )
894 if ( Normal.
dot(v) <= 0 ) {
return 0.0; }
899 if ( Normal.
dot(v) <= 0 ) {
return 0.0; }
906 if ( std::fabs(nt2) > kRadTolerance )
910 if ( sd < 0 ) {
return kInfinity; }
913 zi = p.
z() + sd*v.
z() ;
915 if ((std::fabs(zi) <= tolODz) && (nt2 < 0))
919 if ( fPhiFullCone ) {
return sd; }
922 xi = p.
x() + sd*v.
x() ;
923 yi = p.
y() + sd*v.
y() ;
924 ri = rMaxAv + zi*tanRMax ;
925 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
927 if (cosPsi >= cosHDPhiIT) {
return sd; }
949 nt1 = t1 - (tanRMin*v.
z())*(tanRMin*v.
z()) ;
950 nt2 = t2 - tanRMin*v.
z()*rin ;
955 if ( nt3 > rin*kRadTolerance*secRMin )
965 if(b>0){sd = c/( -b-std::sqrt(d));}
966 else {sd = -b + std::sqrt(d) ;}
972 G4double fTerm = sd-std::fmod(sd,dRmax);
975 zi = p.
z() + sd*v.
z() ;
977 if ( std::fabs(zi) <= tolODz )
981 xi = p.
x() + sd*v.
x() ;
982 yi = p.
y() + sd*v.
y() ;
983 ri = rMinAv + zi*tanRMin ;
984 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
986 if (cosPsi >= cosHDPhiIT)
988 if ( sd > halfRadTolerance ) { snxt=sd; }
993 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
995 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1001 if ( sd > halfRadTolerance ) {
return sd; }
1006 xi = p.
x() + sd*v.
x() ;
1007 yi = p.
y() + sd*v.
y() ;
1008 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1009 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1010 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1017 else if ( nt3 < -rin*kRadTolerance*secRMin )
1030 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1031 else { sd = -b + std::sqrt(d); }
1032 zi = p.
z() + sd*v.
z() ;
1033 ri = rMinAv + zi*tanRMin ;
1037 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1041 G4double fTerm = sd-std::fmod(sd,dRmax);
1044 if ( !fPhiFullCone )
1046 xi = p.
x() + sd*v.
x() ;
1047 yi = p.
y() + sd*v.
y() ;
1048 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1050 if (cosPsi >= cosHDPhiOT)
1052 if ( sd > halfRadTolerance ) { snxt=sd; }
1057 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1058 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin);
1059 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1065 if( sd > halfRadTolerance ) {
return sd; }
1070 xi = p.
x() + sd*v.
x() ;
1071 yi = p.
y() + sd*v.
y() ;
1072 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1073 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1074 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1081 if (b>0) { sd = -b - std::sqrt(d); }
1082 else { sd = c/(-b+std::sqrt(d)); }
1083 zi = p.
z() + sd*v.
z() ;
1084 ri = rMinAv + zi*tanRMin ;
1086 if ( (sd >= 0) && (ri > 0) && (std::fabs(zi) <= tolODz) )
1090 G4double fTerm = sd-std::fmod(sd,dRmax);
1093 if ( !fPhiFullCone )
1095 xi = p.
x() + sd*v.
x() ;
1096 yi = p.
y() + sd*v.
y() ;
1097 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1099 if (cosPsi >= cosHDPhiIT)
1101 if ( sd > halfRadTolerance ) { snxt=sd; }
1106 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1107 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin);
1108 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1114 if ( sd > halfRadTolerance ) {
return sd; }
1119 xi = p.
x() + sd*v.
x() ;
1120 yi = p.
y() + sd*v.
y() ;
1121 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1122 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1123 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1137 if ( std::fabs(p.
z()) <= tolODz )
1143 if ( !fPhiFullCone )
1145 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/std::sqrt(t3) ;
1147 if (cosPsi >= cosHDPhiIT) {
return 0.0; }
1149 else {
return 0.0; }
1162 if (b>0) { sd = -b - std::sqrt(d); }
1163 else { sd = c/(-b+std::sqrt(d)); }
1164 zi = p.
z() + sd*v.
z() ;
1165 ri = rMinAv + zi*tanRMin ;
1169 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1170 else { sd = -b + std::sqrt(d); }
1172 zi = p.
z() + sd*v.
z() ;
1174 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1178 G4double fTerm = sd-std::fmod(sd,dRmax);
1181 if ( !fPhiFullCone )
1183 xi = p.
x() + sd*v.
x() ;
1184 yi = p.
y() + sd*v.
y() ;
1185 ri = rMinAv + zi*tanRMin ;
1186 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1188 if ( cosPsi >= cosHDPhiIT ) { snxt = sd; }
1193 else {
return kInfinity; }
1205 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1206 else { sd = -b + std::sqrt(d) ; }
1207 zi = p.
z() + sd*v.
z() ;
1209 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1213 G4double fTerm = sd-std::fmod(sd,dRmax);
1216 if ( !fPhiFullCone )
1218 xi = p.
x() + sd*v.
x();
1219 yi = p.
y() + sd*v.
y();
1220 ri = rMinAv + zi*tanRMin ;
1221 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri;
1223 if (cosPsi >= cosHDPhiIT) { snxt = sd; }
1242 if ( !fPhiFullCone )
1246 Comp = v.
x()*sinSPhi - v.
y()*cosSPhi ;
1250 Dist = (p.
y()*cosSPhi - p.
x()*sinSPhi) ;
1252 if (Dist < halfCarTolerance)
1258 if ( sd < 0 ) { sd = 0.0; }
1260 zi = p.
z() + sd*v.
z() ;
1262 if ( std::fabs(zi) <= tolODz )
1264 xi = p.
x() + sd*v.
x() ;
1265 yi = p.
y() + sd*v.
y() ;
1266 rhoi2 = xi*xi + yi*yi ;
1267 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ;
1268 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ;
1270 if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) )
1275 if ((yi*cosCPhi - xi*sinCPhi) <= 0 ) { snxt = sd; }
1284 Comp = -(v.
x()*sinEPhi - v.
y()*cosEPhi) ;
1288 Dist = -(p.
y()*cosEPhi - p.
x()*sinEPhi) ;
1289 if (Dist < halfCarTolerance)
1295 if ( sd < 0 ) { sd = 0.0; }
1297 zi = p.
z() + sd*v.
z() ;
1299 if (std::fabs(zi) <= tolODz)
1301 xi = p.
x() + sd*v.
x() ;
1302 yi = p.
y() + sd*v.
y() ;
1303 rhoi2 = xi*xi + yi*yi ;
1304 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ;
1305 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ;
1307 if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) )
1312 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) { snxt = sd; }
1319 if (snxt < halfCarTolerance) { snxt = 0.; }
1333 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi, cosPsi ;
1337 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1338 safeZ = std::fabs(p.
z()) - fDz ;
1340 if ( fRmin1 || fRmin2 )
1342 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
1343 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
1344 pRMin = tanRMin*p.
z() + (fRmin1 + fRmin2)*0.5 ;
1345 safeR1 = (pRMin - rho)/secRMin ;
1347 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1348 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1349 pRMax = tanRMax*p.
z() + (fRmax1 + fRmax2)*0.5 ;
1350 safeR2 = (rho - pRMax)/secRMax ;
1352 if ( safeR1 > safeR2) { safe = safeR1; }
1353 else { safe = safeR2; }
1357 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1358 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1359 pRMax = tanRMax*p.
z() + (fRmax1 + fRmax2)*0.5 ;
1360 safe = (rho - pRMax)/secRMax ;
1362 if ( safeZ > safe ) { safe = safeZ; }
1364 if ( !fPhiFullCone && rho )
1368 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/rho ;
1370 if ( cosPsi < cosHDPhi )
1372 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0.0 )
1374 safePhi = std::fabs(p.
x()*sinSPhi-p.
y()*cosSPhi);
1378 safePhi = std::fabs(p.
x()*sinEPhi-p.
y()*cosEPhi);
1380 if ( safePhi > safe ) { safe = safePhi; }
1383 if ( safe < 0.0 ) { safe = 0.0; }
1399 ESide side = kNull, sider = kNull, sidephi = kNull;
1403 G4double tanRMax, secRMax, rMaxAv ;
1404 G4double tanRMin, secRMin, rMinAv ;
1406 G4double t1, t2, t3, rout, rin, nt1, nt2, nt3 ;
1411 ESide sidetol = kNull ;
1416 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, risec, vphi ;
1423 pdist = fDz - p.
z() ;
1425 if (pdist > halfCarTolerance)
1427 snxt = pdist/v.
z() ;
1440 else if ( v.
z() < 0.0 )
1442 pdist = fDz + p.
z() ;
1444 if ( pdist > halfCarTolerance)
1446 snxt = -pdist/v.
z() ;
1482 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1483 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1484 rMaxAv = (fRmax1 + fRmax2)*0.5 ;
1487 t1 = 1.0 - v.
z()*v.
z() ;
1488 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1489 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1490 rout = tanRMax*p.
z() + rMaxAv ;
1492 nt1 = t1 - (tanRMax*v.
z())*(tanRMax*v.
z()) ;
1493 nt2 = t2 - tanRMax*v.
z()*rout ;
1494 nt3 = t3 - rout*rout ;
1498 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3
1499 - fRmax2*(fRmax2 + kRadTolerance*secRMax);
1501 else if (v.
z() < 0.0)
1503 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3
1504 - fRmax1*(fRmax1 + kRadTolerance*secRMax);
1511 if ( nt1 && (deltaRoi2 > 0.0) )
1524 if (nt3 > -halfRadTolerance && nt2 >= 0 )
1528 risec = std::sqrt(t3)*secRMax ;
1537 if (b>0) { srd = -b - std::sqrt(d); }
1538 else { srd = c/(-b+std::sqrt(d)) ; }
1540 zi = p.
z() + srd*v.
z() ;
1541 ri = tanRMax*zi + rMaxAv ;
1543 if ((ri >= 0) && (-halfRadTolerance <= srd) && (srd <= halfRadTolerance))
1551 if ( (ri < 0) || (srd < halfRadTolerance) )
1556 if (b>0) { sr2 = c/(-b-std::sqrt(d)); }
1557 else { sr2 = -b + std::sqrt(d); }
1558 zi = p.
z() + sr2*v.
z() ;
1559 ri = tanRMax*zi + rMaxAv ;
1561 if ((ri >= 0) && (sr2 > halfRadTolerance))
1569 if( (-halfRadTolerance <= sr2) && ( sr2 <= halfRadTolerance) )
1588 risec = std::sqrt(t3)*secRMax;
1595 else if ( nt2 && (deltaRoi2 > 0.0) )
1601 risec = std::sqrt(t3)*secRMax;
1617 if ( slentol <= halfCarTolerance )
1628 xi = p.
x() + slentol*v.
x();
1629 yi = p.
y() + slentol*v.
y();
1630 risec = std::sqrt(xi*xi + yi*yi)*secRMax;
1633 if ( Normal.
dot(v) > 0 )
1637 *n = Normal.
unit() ;
1644 slentol = kInfinity ;
1650 if ( fRmin1 || fRmin2 )
1652 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
1653 nt1 = t1 - (tanRMin*v.
z())*(tanRMin*v.
z()) ;
1657 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
1658 rMinAv = (fRmin1 + fRmin2)*0.5 ;
1659 rin = tanRMin*p.
z() + rMinAv ;
1660 nt2 = t2 - tanRMin*v.
z()*rin ;
1661 nt3 = t3 - rin*rin ;
1674 if (nt3 < kRadTolerance*(rin + kRadTolerance*0.25))
1678 if (calcNorm) { *validNorm =
false; }
1684 if (b>0) { sr2 = -b - std::sqrt(d); }
1685 else { sr2 = c/(-b+std::sqrt(d)); }
1686 zi = p.
z() + sr2*v.
z() ;
1687 ri = tanRMin*zi + rMinAv ;
1689 if( (ri>=0.0)&&(-halfRadTolerance<=sr2)&&(sr2<=halfRadTolerance) )
1697 if( (ri<0) || (sr2 < halfRadTolerance) )
1699 if (b>0) { sr3 = c/(-b-std::sqrt(d)); }
1700 else { sr3 = -b + std::sqrt(d) ; }
1705 if ( sr3 > halfRadTolerance )
1709 zi = p.
z() + sr3*v.
z() ;
1710 ri = tanRMin*zi + rMinAv ;
1719 else if ( sr3 > -halfRadTolerance )
1727 else if ( (sr2 < srd) && (sr2 > halfCarTolerance) )
1732 else if (sr2 > -halfCarTolerance)
1739 if( slentol <= halfCarTolerance )
1748 xi = p.
x() + slentol*v.
x() ;
1749 yi = p.
y() + slentol*v.
y() ;
1750 if( sidetol==kRMax )
1752 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
1753 Normal =
G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ;
1757 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1758 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1760 if( Normal.
dot(v) > 0 )
1766 *n = Normal.
unit() ;
1776 slentol = kInfinity ;
1788 if ( !fPhiFullCone )
1793 vphi = std::atan2(v.
y(),v.
x()) ;
1795 if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
1796 else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; }
1798 if ( p.
x() || p.
y() )
1802 pDistS = p.
x()*sinSPhi - p.
y()*cosSPhi ;
1803 pDistE = -p.
x()*sinEPhi + p.
y()*cosEPhi ;
1807 compS = -sinSPhi*v.
x() + cosSPhi*v.
y() ;
1808 compE = sinEPhi*v.
x() - cosEPhi*v.
y() ;
1812 if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
1813 && (pDistE <= halfCarTolerance) ) )
1814 || ( (fDPhi > pi) && !((pDistS > halfCarTolerance)
1815 && (pDistE > halfCarTolerance) ) ) )
1820 sphi = pDistS/compS ;
1821 if (sphi >= -halfCarTolerance)
1823 xi = p.
x() + sphi*v.
x() ;
1824 yi = p.
y() + sphi*v.
y() ;
1833 if ( ( fSPhi-halfAngTolerance <= vphi )
1834 && ( fSPhi+fDPhi+halfAngTolerance >=vphi ) )
1840 if ( (yi*cosCPhi-xi*sinCPhi)>=0 )
1847 if ( pDistS > -halfCarTolerance )
1865 sphi2 = pDistE/compE ;
1869 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1871 xi = p.
x() + sphi2*v.
x() ;
1872 yi = p.
y() + sphi2*v.
y() ;
1881 if(!( (fSPhi-halfAngTolerance <= vphi)
1882 && (fSPhi+fDPhi+halfAngTolerance >= vphi) ) )
1885 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; }
1886 else { sphi = 0.0; }
1890 if ( yi*cosCPhi-xi*sinCPhi >= 0 )
1895 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; }
1896 else { sphi = 0.0; }
1911 if ( (fSPhi-halfAngTolerance <= vphi)
1912 && (vphi <= fSPhi+fDPhi+halfAngTolerance) )
1938 xi = p.
x() + snxt*v.
x() ;
1939 yi = p.
y() + snxt*v.
y() ;
1940 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
1945 *validNorm = false ;
1955 *validNorm = false ;
1966 *validNorm = false ;
1980 std::ostringstream message;
1981 G4int oldprc = message.precision(16) ;
1982 message <<
"Undefined side for valid surface normal to solid."
1985 <<
"p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1986 <<
"p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1988 <<
"pho at z = " << std::sqrt( p.
x()*p.
x()+p.
y()*p.
y() )/mm
1990 if( p.
x() != 0. || p.
y() != 0.)
1992 message <<
"point phi = " << std::atan2(p.
y(),p.
x())/degree
1996 <<
"v.x() = " << v.
x() <<
G4endl
1997 <<
"v.y() = " << v.
y() <<
G4endl
2000 <<
"snxt = " << snxt/mm <<
" mm" <<
G4endl ;
2001 message.precision(oldprc) ;
2002 G4Exception(
"G4Cons::DistanceToOut(p,v,..)",
"GeomSolids1002",
2007 if (snxt < halfCarTolerance) { snxt = 0.; }
2018 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi;
2032 G4cout <<
"pho at z = " << std::sqrt( p.
x()*p.
x()+p.
y()*p.
y() )/mm
2034 if( (p.
x() != 0.) || (p.
x() != 0.) )
2036 G4cout <<
"point phi = " << std::atan2(p.
y(),p.
x())/degree
2039 G4cout.precision(oldprc) ;
2040 G4Exception(
"G4Cons::DistanceToOut(p)",
"GeomSolids1002",
2045 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
2046 safeZ = fDz - std::fabs(p.
z()) ;
2048 if (fRmin1 || fRmin2)
2050 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
2051 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
2052 pRMin = tanRMin*p.
z() + (fRmin1 + fRmin2)*0.5 ;
2053 safeR1 = (rho - pRMin)/secRMin ;
2057 safeR1 = kInfinity ;
2060 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
2061 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
2062 pRMax = tanRMax*p.
z() + (fRmax1+fRmax2)*0.5 ;
2063 safeR2 = (pRMax - rho)/secRMax ;
2065 if (safeR1 < safeR2) { safe = safeR1; }
2066 else { safe = safeR2; }
2067 if (safeZ < safe) { safe = safeZ ; }
2075 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0 )
2077 safePhi = -(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
2081 safePhi = (p.
x()*sinEPhi - p.
y()*cosEPhi) ;
2083 if (safePhi < safe) { safe = safePhi; }
2085 if ( safe < 0 ) { safe = 0; }
2105 return new G4Cons(*
this);
2114 G4int oldprc = os.precision(16);
2115 os <<
"-----------------------------------------------------------\n"
2116 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
2117 <<
" ===================================================\n"
2118 <<
" Solid type: G4Cons\n"
2119 <<
" Parameters: \n"
2120 <<
" inside -fDz radius: " << fRmin1/mm <<
" mm \n"
2121 <<
" outside -fDz radius: " << fRmax1/mm <<
" mm \n"
2122 <<
" inside +fDz radius: " << fRmin2/mm <<
" mm \n"
2123 <<
" outside +fDz radius: " << fRmax2/mm <<
" mm \n"
2124 <<
" half length in Z : " << fDz/mm <<
" mm \n"
2125 <<
" starting angle of segment: " << fSPhi/degree <<
" degrees \n"
2126 <<
" delta angle of segment : " << fDPhi/degree <<
" degrees \n"
2127 <<
"-----------------------------------------------------------\n";
2128 os.precision(oldprc);
2143 G4double rone = (fRmax1-fRmax2)/(2.*fDz);
2144 G4double rtwo = (fRmin1-fRmin2)/(2.*fDz);
2145 G4double qone = (fRmax1 == fRmax2) ? 0. : fDz*(fRmax1+fRmax2)/(fRmax1-fRmax2);
2146 G4double qtwo = (fRmin1 == fRmin2) ? 0. : fDz*(fRmin1+fRmin2)/(fRmin1-fRmin2);
2148 G4double slin = std::hypot(fRmin1-fRmin2, 2.*fDz);
2149 G4double slout = std::hypot(fRmax1-fRmax2, 2.*fDz);
2150 G4double Aone = 0.5*fDPhi*(fRmax2 + fRmax1)*slout;
2151 G4double Atwo = 0.5*fDPhi*(fRmin2 + fRmin1)*slin;
2152 G4double Athree = 0.5*fDPhi*(fRmax1*fRmax1-fRmin1*fRmin1);
2153 G4double Afour = 0.5*fDPhi*(fRmax2*fRmax2-fRmin2*fRmin2);
2154 G4double Afive = fDz*(fRmax1-fRmin1+fRmax2-fRmin2);
2156 G4double phi = G4RandFlat::shoot(fSPhi,fSPhi+fDPhi);
2162 if ( (fSPhi == 0.) && fPhiFullCone ) { Afive = 0.; }
2163 G4double chose = G4RandFlat::shoot(0.,Aone+Atwo+Athree+Afour+2.*Afive);
2165 if( (chose >= 0.) && (chose < Aone) )
2167 if(fRmax1 != fRmax2)
2169 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2171 rone*sinu*(qone-zRand), zRand);
2176 G4RandFlat::shoot(-1.*fDz,fDz));
2179 else if( (chose >= Aone) && (chose < Aone + Atwo) )
2181 if(fRmin1 != fRmin2)
2183 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2185 rtwo*sinu*(qtwo-zRand), zRand);
2190 G4RandFlat::shoot(-1.*fDz,fDz));
2193 else if( (chose >= Aone + Atwo) && (chose < Aone + Atwo + Athree) )
2197 else if( (chose >= Aone + Atwo + Athree)
2198 && (chose < Aone + Atwo + Athree + Afour) )
2202 else if( (chose >= Aone + Atwo + Athree + Afour)
2203 && (chose < Aone + Atwo + Athree + Afour + Afive) )
2205 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2206 rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
2207 fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
2209 rRand1*sinSPhi, zRand);
2213 G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz);
2214 rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
2215 fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
2217 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