62 using namespace CLHEP;
84 :
G4CSGSolid(pName), fRmin1(pRmin1), fRmin2(pRmin2),
85 fRmax1(pRmax1), fRmax2(pRmax2), fDz(pDz), fSPhi(0.), fDPhi(0.)
94 std::ostringstream message;
95 message <<
"Invalid Z half-length for Solid: " <<
GetName() <<
G4endl
103 if (((pRmin1>=pRmax1) || (pRmin2>=pRmax2) || (pRmin1<0)) && (pRmin2<0))
105 std::ostringstream message;
106 message <<
"Invalid values of radii for Solid: " <<
GetName() <<
G4endl
107 <<
" pRmin1 = " << pRmin1 <<
", pRmin2 = " << pRmin2
108 <<
", pRmax1 = " << pRmax1 <<
", pRmax2 = " << pRmax2;
112 if( (pRmin1 == 0.0) && (pRmin2 > 0.0) ) { fRmin1 = 1e3*kRadTolerance ; }
113 if( (pRmin2 == 0.0) && (pRmin1 > 0.0) ) { fRmin2 = 1e3*kRadTolerance ; }
117 CheckPhiAngles(pSPhi, pDPhi);
126 :
G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.),
127 fRmin1(0.), fRmin2(0.), fRmax1(0.), fRmax2(0.), fDz(0.),
128 fSPhi(0.), fDPhi(0.), sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.),
129 cosHDPhiIT(0.), sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
147 :
G4CSGSolid(rhs), kRadTolerance(rhs.kRadTolerance),
148 kAngTolerance(rhs.kAngTolerance), fRmin1(rhs.fRmin1), fRmin2(rhs.fRmin2),
149 fRmax1(rhs.fRmax1), fRmax2(rhs.fRmax2), fDz(rhs.fDz), fSPhi(rhs.fSPhi),
150 fDPhi(rhs.fDPhi), sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi),
151 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT),
152 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi), sinEPhi(rhs.sinEPhi),
153 cosEPhi(rhs.cosEPhi), fPhiFullCone(rhs.fPhiFullCone)
165 if (
this == &rhs) {
return *
this; }
173 kRadTolerance = rhs.kRadTolerance;
174 kAngTolerance = rhs.kAngTolerance;
175 fRmin1 = rhs.fRmin1; fRmin2 = rhs.fRmin2;
176 fRmax1 = rhs.fRmax1; fRmax2 = rhs.fRmax2;
177 fDz = rhs.fDz; fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
178 sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPhi;
179 cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = rhs.cosHDPhiIT;
180 sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPhi;
181 sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPhi;
182 fPhiFullCone = rhs.fPhiFullCone;
193 G4double r2, rl, rh, pPhi, tolRMin, tolRMax;
196 static const G4double halfRadTolerance=kRadTolerance*0.5;
197 static const G4double halfAngTolerance=kAngTolerance*0.5;
199 if (std::fabs(p.
z()) > fDz + halfCarTolerance ) {
return in =
kOutside; }
200 else if(std::fabs(p.
z()) >= fDz - halfCarTolerance ) { in =
kSurface; }
203 r2 = p.
x()*p.
x() + p.
y()*p.
y() ;
204 rl = 0.5*(fRmin2*(p.
z() + fDz) + fRmin1*(fDz - p.
z()))/fDz ;
205 rh = 0.5*(fRmax2*(p.
z()+fDz)+fRmax1*(fDz-p.
z()))/fDz;
209 tolRMin = rl - halfRadTolerance;
210 if ( tolRMin < 0 ) { tolRMin = 0; }
211 tolRMax = rh + halfRadTolerance;
213 if ( (r2<tolRMin*tolRMin) || (r2>tolRMax*tolRMax) ) {
return in =
kOutside; }
215 if (rl) { tolRMin = rl + halfRadTolerance; }
216 else { tolRMin = 0.0; }
217 tolRMax = rh - halfRadTolerance;
221 if ( (r2 < tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax) ) { in =
kSurface; }
223 if ( !fPhiFullCone && ((p.
x() != 0.0) || (p.
y() != 0.0)) )
225 pPhi = std::atan2(p.
y(),p.
x()) ;
227 if ( pPhi < fSPhi - halfAngTolerance ) { pPhi +=
twopi; }
228 else if ( pPhi > fSPhi + fDPhi + halfAngTolerance ) { pPhi -=
twopi; }
230 if ( (pPhi < fSPhi - halfAngTolerance) ||
231 (pPhi > fSPhi + fDPhi + halfAngTolerance) ) {
return in =
kOutside; }
235 if ( (pPhi < fSPhi + halfAngTolerance) ||
236 (pPhi > fSPhi + fDPhi - halfAngTolerance) ) { in =
kSurface; }
239 else if ( !fPhiFullCone ) { in =
kSurface; }
268 && (fRmin1 == 0) && (fRmin2 == 0) )
279 G4double diff1, diff2, delta, maxDiff, newMin, newMax, RMax ;
280 G4double xoff1, xoff2, yoff1, yoff2 ;
283 zMin = zoffset - fDz ;
284 zMax = zoffset + fDz ;
306 RMax = (fRmax2 >= fRmax1) ? zMax : zMin ;
307 xMax = xoffset + (fRmax1 + fRmax2)*0.5 +
308 (RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ;
309 xMin = 2*xoffset-xMax ;
331 yMax = yoffset + (fRmax1 + fRmax2)*0.5 +
332 (RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ;
333 yMin = 2*yoffset-yMax ;
334 RMax = yMax - yoffset ;
358 yoff1 = yoffset - yMin ;
359 yoff2 = yMax - yoffset ;
361 if ((yoff1 >= 0) && (yoff2 >= 0))
370 delta=RMax*RMax-yoff1*yoff1;
371 diff1=(delta>0.) ? std::sqrt(delta) : 0.;
372 delta=RMax*RMax-yoff2*yoff2;
373 diff2=(delta>0.) ? std::sqrt(delta) : 0.;
374 maxDiff = (diff1>diff2) ? diff1:diff2 ;
375 newMin = xoffset - maxDiff ;
376 newMax = xoffset + maxDiff ;
377 pMin = ( newMin < xMin ) ? xMin : newMin ;
378 pMax = ( newMax > xMax) ? xMax : newMax ;
383 xoff1 = xoffset - xMin ;
384 xoff2 = xMax - xoffset ;
386 if ((xoff1 >= 0) && (xoff2 >= 0) )
395 delta=RMax*RMax-xoff1*xoff1;
396 diff1=(delta>0.) ? std::sqrt(delta) : 0.;
397 delta=RMax*RMax-xoff2*xoff2;
398 diff2=(delta>0.) ? std::sqrt(delta) : 0.;
399 maxDiff = (diff1 > diff2) ? diff1:diff2 ;
400 newMin = yoffset - maxDiff ;
401 newMax = yoffset + maxDiff ;
402 pMin = (newMin < yMin) ? yMin : newMin ;
403 pMax = (newMax > yMax) ? yMax : newMax ;
422 G4int i, noEntries, noBetweenSections4 ;
423 G4bool existsAfterClip = false ;
429 noEntries = vertices->size() ;
430 noBetweenSections4 = noEntries-4 ;
432 for ( i = 0 ; i < noEntries ; i += 4 )
436 for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
440 if ( (pMin != kInfinity) || (pMax != -kInfinity) )
442 existsAfterClip = true ;
463 existsAfterClip = true ;
469 return existsAfterClip ;
481 G4int noSurfaces = 0;
484 G4double distSPhi = kInfinity, distEPhi = kInfinity;
485 G4double tanRMin, secRMin, pRMin, widRMin;
486 G4double tanRMax, secRMax, pRMax, widRMax;
489 static const G4double dAngle = 0.5*kAngTolerance;
494 distZ = std::fabs(std::fabs(p.
z()) - fDz);
495 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y());
497 tanRMin = (fRmin2 - fRmin1)*0.5/fDz;
498 secRMin = std::sqrt(1 + tanRMin*tanRMin);
499 pRMin = rho - p.
z()*tanRMin;
500 widRMin = fRmin2 - fDz*tanRMin;
501 distRMin = std::fabs(pRMin - widRMin)/secRMin;
503 tanRMax = (fRmax2 - fRmax1)*0.5/fDz;
504 secRMax = std::sqrt(1+tanRMax*tanRMax);
505 pRMax = rho - p.
z()*tanRMax;
506 widRMax = fRmax2 - fDz*tanRMax;
507 distRMax = std::fabs(pRMax - widRMax)/secRMax;
513 pPhi = std::atan2(p.
y(),p.
x());
515 if (pPhi < fSPhi-delta) { pPhi +=
twopi; }
516 else if (pPhi > fSPhi+fDPhi+delta) { pPhi -=
twopi; }
518 distSPhi = std::fabs( pPhi - fSPhi );
519 distEPhi = std::fabs( pPhi - fSPhi - fDPhi );
521 else if( !(fRmin1) || !(fRmin2) )
527 nPe =
G4ThreeVector(-std::sin(fSPhi+fDPhi), std::cos(fSPhi+fDPhi), 0);
531 nR =
G4ThreeVector(p.
x()/rho/secRMax, p.
y()/rho/secRMax, -tanRMax/secRMax);
532 if (fRmin1 || fRmin2)
534 nr =
G4ThreeVector(-p.
x()/rho/secRMin,-p.
y()/rho/secRMin,tanRMin/secRMin);
538 if( distRMax <= delta )
543 if( (fRmin1 || fRmin2) && (distRMin <= delta) )
550 if (distSPhi <= dAngle)
555 if (distEPhi <= dAngle)
564 if ( p.
z() >= 0.) { sumnorm += nZ; }
565 else { sumnorm -= nZ; }
567 if ( noSurfaces == 0 )
570 G4Exception(
"G4Cons::SurfaceNormal(p)",
"GeomSolids1002",
573 norm = ApproxSurfaceNormal(p);
575 else if ( noSurfaces == 1 ) { norm = sumnorm; }
576 else { norm = sumnorm.
unit(); }
591 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ;
592 G4double tanRMin, secRMin, pRMin, widRMin ;
593 G4double tanRMax, secRMax, pRMax, widRMax ;
595 distZ = std::fabs(std::fabs(p.
z()) - fDz) ;
596 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
598 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
599 secRMin = std::sqrt(1 + tanRMin*tanRMin) ;
600 pRMin = rho - p.
z()*tanRMin ;
601 widRMin = fRmin2 - fDz*tanRMin ;
602 distRMin = std::fabs(pRMin - widRMin)/secRMin ;
604 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
605 secRMax = std::sqrt(1+tanRMax*tanRMax) ;
606 pRMax = rho - p.
z()*tanRMax ;
607 widRMax = fRmax2 - fDz*tanRMax ;
608 distRMax = std::fabs(pRMax - widRMax)/secRMax ;
610 if (distRMin < distRMax)
612 if (distZ < distRMin)
625 if (distZ < distRMax)
636 if ( !fPhiFullCone && rho )
638 phi = std::atan2(p.
y(),p.
x()) ;
640 if (phi < 0) { phi +=
twopi; }
642 if (fSPhi < 0) { distSPhi = std::fabs(phi - (fSPhi +
twopi))*rho; }
643 else { distSPhi = std::fabs(phi - fSPhi)*rho; }
645 distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
649 if (distSPhi < distEPhi)
651 if (distSPhi < distMin) { side = kNSPhi; }
655 if (distEPhi < distMin) { side = kNEPhi; }
676 norm=
G4ThreeVector(-std::sin(fSPhi+fDPhi), std::cos(fSPhi+fDPhi), 0) ;
682 "Undefined side for valid surface normal to solid.");
716 const G4double dRmax = 50*(fRmax1+fRmax2);
718 static const G4double halfRadTolerance=kRadTolerance*0.5;
720 G4double tanRMax,secRMax,rMaxAv,rMaxOAv ;
721 G4double tanRMin,secRMin,rMinAv,rMinOAv ;
724 G4double tolORMin,tolORMin2,tolIRMin,tolIRMin2 ;
725 G4double tolORMax2,tolIRMax,tolIRMax2 ;
728 G4double Dist,sd,xi,yi,zi,ri=0.,risec,rhoi2,cosPsi ;
738 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
739 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
740 rMinAv = (fRmin1 + fRmin2)*0.5 ;
742 if (rMinAv > halfRadTolerance)
744 rMinOAv = rMinAv - halfRadTolerance ;
750 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
751 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
752 rMaxAv = (fRmax1 + fRmax2)*0.5 ;
753 rMaxOAv = rMaxAv + halfRadTolerance ;
757 tolIDz = fDz - halfCarTolerance ;
758 tolODz = fDz + halfCarTolerance ;
760 if (std::fabs(p.
z()) >= tolIDz)
762 if ( p.
z()*v.
z() < 0 )
764 sd = (std::fabs(p.
z()) - fDz)/std::fabs(v.
z()) ;
766 if( sd < 0.0 ) { sd = 0.0; }
768 xi = p.
x() + sd*v.
x() ;
769 yi = p.
y() + sd*v.
y() ;
770 rhoi2 = xi*xi + yi*yi ;
777 tolORMin = fRmin1 - halfRadTolerance*secRMin ;
778 tolIRMin = fRmin1 + halfRadTolerance*secRMin ;
779 tolIRMax = fRmax1 - halfRadTolerance*secRMin ;
780 tolORMax2 = (fRmax1 + halfRadTolerance*secRMax)*
781 (fRmax1 + halfRadTolerance*secRMax) ;
785 tolORMin = fRmin2 - halfRadTolerance*secRMin ;
786 tolIRMin = fRmin2 + halfRadTolerance*secRMin ;
787 tolIRMax = fRmax2 - halfRadTolerance*secRMin ;
788 tolORMax2 = (fRmax2 + halfRadTolerance*secRMax)*
789 (fRmax2 + halfRadTolerance*secRMax) ;
793 tolORMin2 = tolORMin*tolORMin ;
794 tolIRMin2 = tolIRMin*tolIRMin ;
801 if ( tolIRMax > 0 ) { tolIRMax2 = tolIRMax*tolIRMax; }
802 else { tolIRMax2 = 0.0; }
804 if ( (tolIRMin2 <= rhoi2) && (rhoi2 <= tolIRMax2) )
806 if ( !fPhiFullCone && rhoi2 )
810 cosPsi = (xi*cosCPhi + yi*sinCPhi)/std::sqrt(rhoi2) ;
812 if (cosPsi >= cosHDPhiIT) {
return sd; }
845 t1 = 1.0 - v.
z()*v.
z() ;
846 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
847 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
848 rin = tanRMin*p.
z() + rMinAv ;
849 rout = tanRMax*p.
z() + rMaxAv ;
854 nt1 = t1 - (tanRMax*v.
z())*(tanRMax*v.
z()) ;
855 nt2 = t2 - tanRMax*v.
z()*rout ;
856 nt3 = t3 - rout*rout ;
858 if (std::fabs(nt1) > kRadTolerance)
863 if ( (nt3 > rout*rout*kRadTolerance*kRadTolerance*secRMax*secRMax)
872 if ((rout < 0) && (nt3 <= 0))
877 if (b>0) { sd = c/(-b-std::sqrt(d)); }
878 else { sd = -b + std::sqrt(d); }
882 if ((b <= 0) && (c >= 0))
884 sd=c/(-b+std::sqrt(d));
890 sd = -b + std::sqrt(d) ;
891 if((sd<0) & (sd>-halfRadTolerance)) sd=0;
903 G4double fTerm = sd-std::fmod(sd,dRmax);
906 zi = p.
z() + sd*v.
z() ;
908 if (std::fabs(zi) <= tolODz)
912 if ( fPhiFullCone ) {
return sd; }
915 xi = p.
x() + sd*v.
x() ;
916 yi = p.
y() + sd*v.
y() ;
917 ri = rMaxAv + zi*tanRMax ;
918 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
920 if ( cosPsi >= cosHDPhiIT ) {
return sd; }
931 if ( ( t3 > (rin + halfRadTolerance*secRMin)*
932 (rin + halfRadTolerance*secRMin) )
933 && (nt2 < 0) && (d >= 0) && (std::fabs(p.
z()) <= tolIDz) )
940 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
944 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/std::sqrt(t3) ;
945 if ( cosPsi >= cosHDPhiIT )
947 if ( Normal.
dot(v) <= 0 ) {
return 0.0; }
952 if ( Normal.
dot(v) <= 0 ) {
return 0.0; }
959 if ( std::fabs(nt2) > kRadTolerance )
963 if ( sd < 0 ) {
return kInfinity; }
966 zi = p.
z() + sd*v.
z() ;
968 if ((std::fabs(zi) <= tolODz) && (nt2 < 0))
972 if ( fPhiFullCone ) {
return sd; }
975 xi = p.
x() + sd*v.
x() ;
976 yi = p.
y() + sd*v.
y() ;
977 ri = rMaxAv + zi*tanRMax ;
978 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
980 if (cosPsi >= cosHDPhiIT) {
return sd; }
1002 nt1 = t1 - (tanRMin*v.
z())*(tanRMin*v.
z()) ;
1003 nt2 = t2 - tanRMin*v.
z()*rin ;
1004 nt3 = t3 - rin*rin ;
1008 if ( nt3 > rin*kRadTolerance*secRMin )
1018 if(b>0){sd = c/( -b-std::sqrt(d));}
1019 else {sd = -b + std::sqrt(d) ;}
1025 G4double fTerm = sd-std::fmod(sd,dRmax);
1028 zi = p.
z() + sd*v.
z() ;
1030 if ( std::fabs(zi) <= tolODz )
1032 if ( !fPhiFullCone )
1034 xi = p.
x() + sd*v.
x() ;
1035 yi = p.
y() + sd*v.
y() ;
1036 ri = rMinAv + zi*tanRMin ;
1037 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1039 if (cosPsi >= cosHDPhiIT)
1041 if ( sd > halfRadTolerance ) { snxt=sd; }
1046 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1047 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin);
1048 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1054 if ( sd > halfRadTolerance ) {
return sd; }
1059 xi = p.
x() + sd*v.
x() ;
1060 yi = p.
y() + sd*v.
y() ;
1061 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1062 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1063 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1070 else if ( nt3 < -rin*kRadTolerance*secRMin )
1083 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1084 else { sd = -b + std::sqrt(d); }
1085 zi = p.
z() + sd*v.
z() ;
1086 ri = rMinAv + zi*tanRMin ;
1090 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1094 G4double fTerm = sd-std::fmod(sd,dRmax);
1097 if ( !fPhiFullCone )
1099 xi = p.
x() + sd*v.
x() ;
1100 yi = p.
y() + sd*v.
y() ;
1101 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1103 if (cosPsi >= cosHDPhiOT)
1105 if ( sd > halfRadTolerance ) { snxt=sd; }
1110 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1111 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin);
1112 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1118 if( sd > halfRadTolerance ) {
return sd; }
1123 xi = p.
x() + sd*v.
x() ;
1124 yi = p.
y() + sd*v.
y() ;
1125 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1126 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1127 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1134 if (b>0) { sd = -b - std::sqrt(d); }
1135 else { sd = c/(-b+std::sqrt(d)); }
1136 zi = p.
z() + sd*v.
z() ;
1137 ri = rMinAv + zi*tanRMin ;
1139 if ( (sd >= 0) && (ri > 0) && (std::fabs(zi) <= tolODz) )
1143 G4double fTerm = sd-std::fmod(sd,dRmax);
1146 if ( !fPhiFullCone )
1148 xi = p.
x() + sd*v.
x() ;
1149 yi = p.
y() + sd*v.
y() ;
1150 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1152 if (cosPsi >= cosHDPhiIT)
1154 if ( sd > halfRadTolerance ) { snxt=sd; }
1159 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1160 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin);
1161 if ( Normal.
dot(v) <= 0 ) { snxt = sd; }
1167 if ( sd > halfRadTolerance ) {
return sd; }
1172 xi = p.
x() + sd*v.
x() ;
1173 yi = p.
y() + sd*v.
y() ;
1174 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1175 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1176 if ( Normal.
dot(v) <= 0 ) {
return sd; }
1190 if ( std::fabs(p.
z()) <= tolODz )
1196 if ( !fPhiFullCone )
1198 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/std::sqrt(t3) ;
1200 if (cosPsi >= cosHDPhiIT) {
return 0.0; }
1202 else {
return 0.0; }
1215 if (b>0) { sd = -b - std::sqrt(d); }
1216 else { sd = c/(-b+std::sqrt(d)); }
1217 zi = p.
z() + sd*v.
z() ;
1218 ri = rMinAv + zi*tanRMin ;
1222 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1223 else { sd = -b + std::sqrt(d); }
1225 zi = p.
z() + sd*v.
z() ;
1227 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1231 G4double fTerm = sd-std::fmod(sd,dRmax);
1234 if ( !fPhiFullCone )
1236 xi = p.
x() + sd*v.
x() ;
1237 yi = p.
y() + sd*v.
y() ;
1238 ri = rMinAv + zi*tanRMin ;
1239 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ;
1241 if ( cosPsi >= cosHDPhiIT ) { snxt = sd; }
1246 else {
return kInfinity; }
1258 if (b>0) { sd = c/(-b-std::sqrt(d)); }
1259 else { sd = -b + std::sqrt(d) ; }
1260 zi = p.
z() + sd*v.
z() ;
1262 if ( (sd >= 0) && (std::fabs(zi) <= tolODz) )
1266 G4double fTerm = sd-std::fmod(sd,dRmax);
1269 if ( !fPhiFullCone )
1271 xi = p.
x() + sd*v.
x();
1272 yi = p.
y() + sd*v.
y();
1273 ri = rMinAv + zi*tanRMin ;
1274 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri;
1276 if (cosPsi >= cosHDPhiIT) { snxt = sd; }
1295 if ( !fPhiFullCone )
1299 Comp = v.
x()*sinSPhi - v.
y()*cosSPhi ;
1303 Dist = (p.
y()*cosSPhi - p.
x()*sinSPhi) ;
1305 if (Dist < halfCarTolerance)
1311 if ( sd < 0 ) { sd = 0.0; }
1313 zi = p.
z() + sd*v.
z() ;
1315 if ( std::fabs(zi) <= tolODz )
1317 xi = p.
x() + sd*v.
x() ;
1318 yi = p.
y() + sd*v.
y() ;
1319 rhoi2 = xi*xi + yi*yi ;
1320 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ;
1321 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ;
1323 if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) )
1328 if ((yi*cosCPhi - xi*sinCPhi) <= 0 ) { snxt = sd; }
1337 Comp = -(v.
x()*sinEPhi - v.
y()*cosEPhi) ;
1341 Dist = -(p.
y()*cosEPhi - p.
x()*sinEPhi) ;
1342 if (Dist < halfCarTolerance)
1348 if ( sd < 0 ) { sd = 0.0; }
1350 zi = p.
z() + sd*v.
z() ;
1352 if (std::fabs(zi) <= tolODz)
1354 xi = p.
x() + sd*v.
x() ;
1355 yi = p.
y() + sd*v.
y() ;
1356 rhoi2 = xi*xi + yi*yi ;
1357 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ;
1358 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ;
1360 if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) )
1365 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) { snxt = sd; }
1372 if (snxt < halfCarTolerance) { snxt = 0.; }
1386 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi, cosPsi ;
1390 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
1391 safeZ = std::fabs(p.
z()) - fDz ;
1393 if ( fRmin1 || fRmin2 )
1395 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
1396 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
1397 pRMin = tanRMin*p.
z() + (fRmin1 + fRmin2)*0.5 ;
1398 safeR1 = (pRMin - rho)/secRMin ;
1400 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1401 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1402 pRMax = tanRMax*p.
z() + (fRmax1 + fRmax2)*0.5 ;
1403 safeR2 = (rho - pRMax)/secRMax ;
1405 if ( safeR1 > safeR2) { safe = safeR1; }
1406 else { safe = safeR2; }
1410 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1411 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1412 pRMax = tanRMax*p.
z() + (fRmax1 + fRmax2)*0.5 ;
1413 safe = (rho - pRMax)/secRMax ;
1415 if ( safeZ > safe ) { safe = safeZ; }
1417 if ( !fPhiFullCone && rho )
1421 cosPsi = (p.
x()*cosCPhi + p.
y()*sinCPhi)/rho ;
1423 if ( cosPsi < std::cos(fDPhi*0.5) )
1425 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0.0 )
1427 safePhi = std::fabs(p.
x()*std::sin(fSPhi)-p.
y()*std::cos(fSPhi));
1431 safePhi = std::fabs(p.
x()*sinEPhi-p.
y()*cosEPhi);
1433 if ( safePhi > safe ) { safe = safePhi; }
1436 if ( safe < 0.0 ) { safe = 0.0; }
1452 ESide side = kNull, sider = kNull, sidephi = kNull;
1455 static const G4double halfRadTolerance=kRadTolerance*0.5;
1456 static const G4double halfAngTolerance=kAngTolerance*0.5;
1460 G4double tanRMax, secRMax, rMaxAv ;
1461 G4double tanRMin, secRMin, rMinAv ;
1468 ESide sidetol = kNull ;
1473 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, risec, vphi ;
1480 pdist = fDz - p.
z() ;
1482 if (pdist > halfCarTolerance)
1484 snxt = pdist/v.
z() ;
1497 else if ( v.
z() < 0.0 )
1499 pdist = fDz + p.
z() ;
1501 if ( pdist > halfCarTolerance)
1503 snxt = -pdist/v.
z() ;
1539 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
1540 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
1541 rMaxAv = (fRmax1 + fRmax2)*0.5 ;
1544 t1 = 1.0 - v.
z()*v.
z() ;
1545 t2 = p.
x()*v.
x() + p.
y()*v.
y() ;
1546 t3 = p.
x()*p.
x() + p.
y()*p.
y() ;
1547 rout = tanRMax*p.
z() + rMaxAv ;
1549 nt1 = t1 - (tanRMax*v.
z())*(tanRMax*v.
z()) ;
1550 nt2 = t2 - tanRMax*v.
z()*rout ;
1551 nt3 = t3 - rout*rout ;
1555 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3
1556 - fRmax2*(fRmax2 + kRadTolerance*secRMax);
1558 else if ( v.
z() < 0.0 )
1560 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3
1561 - fRmax1*(fRmax1 + kRadTolerance*secRMax);
1568 if ( nt1 && (deltaRoi2 > 0.0) )
1581 if (nt3 > -halfRadTolerance && nt2 >= 0 )
1585 risec = std::sqrt(t3)*secRMax ;
1594 if (b>0) { srd = -b - std::sqrt(d); }
1595 else { srd = c/(-b+std::sqrt(d)) ; }
1597 zi = p.
z() + srd*v.
z() ;
1598 ri = tanRMax*zi + rMaxAv ;
1600 if ((ri >= 0) && (-halfRadTolerance <= srd) && (srd <= halfRadTolerance))
1608 if ( (ri < 0) || (srd < halfRadTolerance) )
1613 if (b>0) { sr2 = c/(-b-std::sqrt(d)); }
1614 else { sr2 = -b + std::sqrt(d); }
1615 zi = p.
z() + sr2*v.
z() ;
1616 ri = tanRMax*zi + rMaxAv ;
1618 if ((ri >= 0) && (sr2 > halfRadTolerance))
1626 if( (-halfRadTolerance <= sr2) && ( sr2 <= halfRadTolerance) )
1645 risec = std::sqrt(t3)*secRMax;
1652 else if ( nt2 && (deltaRoi2 > 0.0) )
1658 risec = std::sqrt(t3)*secRMax;
1674 if ( slentol <= halfCarTolerance )
1685 xi = p.
x() + slentol*v.
x();
1686 yi = p.
y() + slentol*v.
y();
1687 risec = std::sqrt(xi*xi + yi*yi)*secRMax;
1690 if ( Normal.
dot(v) > 0 )
1694 *n = Normal.
unit() ;
1701 slentol = kInfinity ;
1707 if ( fRmin1 || fRmin2 )
1709 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
1710 nt1 = t1 - (tanRMin*v.
z())*(tanRMin*v.
z()) ;
1714 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
1715 rMinAv = (fRmin1 + fRmin2)*0.5 ;
1716 rin = tanRMin*p.
z() + rMinAv ;
1717 nt2 = t2 - tanRMin*v.
z()*rin ;
1718 nt3 = t3 - rin*rin ;
1731 if (nt3 < kRadTolerance*(rin + kRadTolerance*0.25))
1735 if (calcNorm) { *validNorm =
false; }
1741 if (b>0) { sr2 = -b - std::sqrt(d); }
1742 else { sr2 = c/(-b+std::sqrt(d)); }
1743 zi = p.
z() + sr2*v.
z() ;
1744 ri = tanRMin*zi + rMinAv ;
1746 if( (ri>=0.0)&&(-halfRadTolerance<=sr2)&&(sr2<=halfRadTolerance) )
1754 if( (ri<0) || (sr2 < halfRadTolerance) )
1756 if (b>0) { sr3 = c/(-b-std::sqrt(d)); }
1757 else { sr3 = -b + std::sqrt(d) ; }
1762 if ( sr3 > halfRadTolerance )
1766 zi = p.
z() + sr3*v.
z() ;
1767 ri = tanRMin*zi + rMinAv ;
1776 else if ( sr3 > -halfRadTolerance )
1784 else if ( (sr2 < srd) && (sr2 > halfCarTolerance) )
1789 else if (sr2 > -halfCarTolerance)
1796 if( slentol <= halfCarTolerance )
1805 xi = p.
x() + slentol*v.
x() ;
1806 yi = p.
y() + slentol*v.
y() ;
1807 if( sidetol==kRMax )
1809 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
1810 Normal =
G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ;
1814 risec = std::sqrt(xi*xi + yi*yi)*secRMin ;
1815 Normal =
G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ;
1817 if( Normal.
dot(v) > 0 )
1823 *n = Normal.
unit() ;
1833 slentol = kInfinity ;
1845 if ( !fPhiFullCone )
1850 vphi = std::atan2(v.
y(),v.
x()) ;
1852 if ( vphi < fSPhi - halfAngTolerance ) { vphi +=
twopi; }
1853 else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -=
twopi; }
1855 if ( p.
x() || p.
y() )
1859 pDistS = p.
x()*sinSPhi - p.
y()*cosSPhi ;
1860 pDistE = -p.
x()*sinEPhi + p.
y()*cosEPhi ;
1864 compS = -sinSPhi*v.
x() + cosSPhi*v.
y() ;
1865 compE = sinEPhi*v.
x() - cosEPhi*v.
y() ;
1869 if( ( (fDPhi <=
pi) && ( (pDistS <= halfCarTolerance)
1870 && (pDistE <= halfCarTolerance) ) )
1871 || ( (fDPhi >
pi) && !((pDistS > halfCarTolerance)
1872 && (pDistE > halfCarTolerance) ) ) )
1877 sphi = pDistS/compS ;
1878 if (sphi >= -halfCarTolerance)
1880 xi = p.
x() + sphi*v.
x() ;
1881 yi = p.
y() + sphi*v.
y() ;
1890 if ( ( fSPhi-halfAngTolerance <= vphi )
1891 && ( fSPhi+fDPhi+halfAngTolerance >=vphi ) )
1897 if ( (yi*cosCPhi-xi*sinCPhi)>=0 )
1904 if ( pDistS > -halfCarTolerance )
1922 sphi2 = pDistE/compE ;
1926 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1928 xi = p.
x() + sphi2*v.
x() ;
1929 yi = p.
y() + sphi2*v.
y() ;
1938 if(!( (fSPhi-halfAngTolerance <= vphi)
1939 && (fSPhi+fDPhi+halfAngTolerance >= vphi) ) )
1942 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; }
1943 else { sphi = 0.0; }
1947 if ( yi*cosCPhi-xi*sinCPhi >= 0 )
1952 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; }
1953 else { sphi = 0.0; }
1968 if ( (fSPhi-halfAngTolerance <= vphi)
1969 && (vphi <= fSPhi+fDPhi+halfAngTolerance) )
1995 xi = p.
x() + snxt*v.
x() ;
1996 yi = p.
y() + snxt*v.
y() ;
1997 risec = std::sqrt(xi*xi + yi*yi)*secRMax ;
2002 *validNorm = false ;
2012 *validNorm = false ;
2023 *validNorm = false ;
2037 std::ostringstream message;
2038 G4int oldprc = message.precision(16) ;
2039 message <<
"Undefined side for valid surface normal to solid."
2041 <<
"Position:" << G4endl << G4endl
2042 <<
"p.x() = " << p.
x()/
mm <<
" mm" << G4endl
2043 <<
"p.y() = " << p.
y()/
mm <<
" mm" << G4endl
2044 <<
"p.z() = " << p.
z()/
mm <<
" mm" << G4endl << G4endl
2045 <<
"pho at z = " << std::sqrt( p.
x()*p.
x()+p.
y()*p.
y() )/
mm
2046 <<
" mm" << G4endl << G4endl ;
2047 if( p.
x() != 0. || p.
x() != 0.)
2049 message <<
"point phi = " << std::atan2(p.
y(),p.
x())/
degree
2050 <<
" degree" << G4endl << G4endl ;
2052 message <<
"Direction:" << G4endl << G4endl
2053 <<
"v.x() = " << v.
x() << G4endl
2054 <<
"v.y() = " << v.
y() << G4endl
2055 <<
"v.z() = " << v.
z() << G4endl<< G4endl
2056 <<
"Proposed distance :" << G4endl<< G4endl
2057 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
2058 message.precision(oldprc) ;
2059 G4Exception(
"G4Cons::DistanceToOut(p,v,..)",
"GeomSolids1002",
2064 if (snxt < halfCarTolerance) { snxt = 0.; }
2075 G4double safe=0.0, rho, safeR1, safeR2, safeZ, safePhi;
2089 G4cout <<
"pho at z = " << std::sqrt( p.
x()*p.
x()+p.
y()*p.
y() )/
mm
2090 <<
" mm" << G4endl << G4endl ;
2091 if( (p.
x() != 0.) || (p.
x() != 0.) )
2094 <<
" degree" << G4endl << G4endl ;
2096 G4cout.precision(oldprc) ;
2097 G4Exception(
"G4Cons::DistanceToOut(p)",
"GeomSolids1002",
2102 rho = std::sqrt(p.
x()*p.
x() + p.
y()*p.
y()) ;
2103 safeZ = fDz - std::fabs(p.
z()) ;
2105 if (fRmin1 || fRmin2)
2107 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;
2108 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ;
2109 pRMin = tanRMin*p.
z() + (fRmin1 + fRmin2)*0.5 ;
2110 safeR1 = (rho - pRMin)/secRMin ;
2114 safeR1 = kInfinity ;
2117 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;
2118 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
2119 pRMax = tanRMax*p.
z() + (fRmax1+fRmax2)*0.5 ;
2120 safeR2 = (pRMax - rho)/secRMax ;
2122 if (safeR1 < safeR2) { safe = safeR1; }
2123 else { safe = safeR2; }
2124 if (safeZ < safe) { safe = safeZ ; }
2132 if ( (p.
y()*cosCPhi - p.
x()*sinCPhi) <= 0 )
2134 safePhi = -(p.
x()*sinSPhi - p.
y()*cosSPhi) ;
2138 safePhi = (p.
x()*sinEPhi - p.
y()*cosEPhi) ;
2140 if (safePhi < safe) { safe = safePhi; }
2142 if ( safe < 0 ) { safe = 0; }
2163 G4double meshAngle, meshRMax1, meshRMax2, crossAngle;
2164 G4double cosCrossAngle, sinCrossAngle, sAngle ;
2165 G4double rMaxX1, rMaxX2, rMaxY1, rMaxY2, rMinX1, rMinX2, rMinY1, rMinY2 ;
2166 G4int crossSection, noCrossSections ;
2180 meshAngle = fDPhi/(noCrossSections - 1) ;
2182 meshRMax1 = fRmax1/std::cos(meshAngle*0.5) ;
2183 meshRMax2 = fRmax2/std::cos(meshAngle*0.5) ;
2188 if ( fPhiFullCone && (fSPhi == 0.0) )
2190 sAngle = -meshAngle*0.5 ;
2200 vertices->reserve(noCrossSections*4) ;
2201 for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++)
2205 crossAngle = sAngle + crossSection*meshAngle ;
2206 cosCrossAngle = std::cos(crossAngle) ;
2207 sinCrossAngle = std::sin(crossAngle) ;
2209 rMaxX1 = meshRMax1*cosCrossAngle ;
2210 rMaxY1 = meshRMax1*sinCrossAngle ;
2211 rMaxX2 = meshRMax2*cosCrossAngle ;
2212 rMaxY2 = meshRMax2*sinCrossAngle ;
2214 rMinX1 = fRmin1*cosCrossAngle ;
2215 rMinY1 = fRmin1*sinCrossAngle ;
2216 rMinX2 = fRmin2*cosCrossAngle ;
2217 rMinY2 = fRmin2*sinCrossAngle ;
2235 "Error in allocation of vertices. Out of memory !");
2256 return new G4Cons(*
this);
2265 G4int oldprc = os.precision(16);
2266 os <<
"-----------------------------------------------------------\n"
2267 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
2268 <<
" ===================================================\n"
2269 <<
" Solid type: G4Cons\n"
2270 <<
" Parameters: \n"
2271 <<
" inside -fDz radius: " << fRmin1/
mm <<
" mm \n"
2272 <<
" outside -fDz radius: " << fRmax1/
mm <<
" mm \n"
2273 <<
" inside +fDz radius: " << fRmin2/
mm <<
" mm \n"
2274 <<
" outside +fDz radius: " << fRmax2/
mm <<
" mm \n"
2275 <<
" half length in Z : " << fDz/
mm <<
" mm \n"
2276 <<
" starting angle of segment: " << fSPhi/
degree <<
" degrees \n"
2277 <<
" delta angle of segment : " << fDPhi/
degree <<
" degrees \n"
2278 <<
"-----------------------------------------------------------\n";
2279 os.precision(oldprc);
2294 G4double Aone, Atwo, Athree, Afour, Afive, slin, slout, phi;
2295 G4double zRand, cosu, sinu, rRand1, rRand2, chose, rone, rtwo, qone, qtwo;
2296 rone = (fRmax1-fRmax2)/(2.*fDz);
2297 rtwo = (fRmin1-fRmin2)/(2.*fDz);
2299 if(fRmax1!=fRmax2) { qone = fDz*(fRmax1+fRmax2)/(fRmax1-fRmax2); }
2300 if(fRmin1!=fRmin2) { qtwo = fDz*(fRmin1+fRmin2)/(fRmin1-fRmin2); }
2301 slin = std::sqrt(
sqr(fRmin1-fRmin2)+
sqr(2.*fDz));
2302 slout = std::sqrt(
sqr(fRmax1-fRmax2)+
sqr(2.*fDz));
2303 Aone = 0.5*fDPhi*(fRmax2 + fRmax1)*slout;
2304 Atwo = 0.5*fDPhi*(fRmin2 + fRmin1)*slin;
2305 Athree = 0.5*fDPhi*(fRmax1*fRmax1-fRmin1*fRmin1);
2306 Afour = 0.5*fDPhi*(fRmax2*fRmax2-fRmin2*fRmin2);
2307 Afive = fDz*(fRmax1-fRmin1+fRmax2-fRmin2);
2309 phi = RandFlat::shoot(fSPhi,fSPhi+fDPhi);
2310 cosu = std::cos(phi); sinu = std::sin(phi);
2314 if ( (fSPhi == 0.) && fPhiFullCone ) { Afive = 0.; }
2315 chose = RandFlat::shoot(0.,Aone+Atwo+Athree+Afour+2.*Afive);
2317 if( (chose >= 0.) && (chose < Aone) )
2319 if(fRmin1 != fRmin2)
2321 zRand = RandFlat::shoot(-1.*fDz,fDz);
2323 rtwo*sinu*(qtwo-zRand), zRand);
2328 RandFlat::shoot(-1.*fDz,fDz));
2331 else if( (chose >= Aone) && (chose <= Aone + Atwo) )
2333 if(fRmax1 != fRmax2)
2335 zRand = RandFlat::shoot(-1.*fDz,fDz);
2337 rone*sinu*(qone-zRand), zRand);
2342 RandFlat::shoot(-1.*fDz,fDz));
2345 else if( (chose >= Aone + Atwo) && (chose < Aone + Atwo + Athree) )
2349 else if( (chose >= Aone + Atwo + Athree)
2350 && (chose < Aone + Atwo + Athree + Afour) )
2354 else if( (chose >= Aone + Atwo + Athree + Afour)
2355 && (chose < Aone + Atwo + Athree + Afour + Afive) )
2357 zRand = RandFlat::shoot(-1.*fDz,fDz);
2358 rRand1 = RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
2359 fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
2361 rRand1*std::sin(fSPhi), zRand);
2365 zRand = RandFlat::shoot(-1.*fDz,fDz);
2366 rRand1 = RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
2367 fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
2369 rRand1*std::sin(fSPhi+fDPhi), zRand);
2389 G4double RMax = (fRmax2 >= fRmax1) ? fRmax2 : fRmax1 ;