40 #if !(defined(G4GEOM_USE_UTORUS) && defined(G4GEOM_USE_SYS_USOLIDS))
58 using namespace CLHEP;
106 message <<
"Invalid swept radius for Solid: " <<
GetName() <<
G4endl
107 <<
" pRtor = " << pRtor <<
", pRmax = " << pRmax;
114 if ( pRmin < pRmax - 1.e2*kCarTolerance && pRmin >= 0 )
116 if (pRmin >= 1.
e2*kCarTolerance) {
fRmin = pRmin ; }
117 else {
fRmin = 0.0 ; }
123 message <<
"Invalid values of radii for Solid: " <<
GetName() <<
G4endl
124 <<
" pRmin = " << pRmin <<
", pRmax = " << pRmax;
140 if (pDPhi > 0) {
fDPhi = pDPhi ; }
144 message <<
"Invalid Z delta-Phi for Solid: " <<
GetName() <<
G4endl
145 <<
" pDPhi = " << pDPhi;
167 :
G4CSGSolid(a), fRmin(0.), fRmax(0.), fRtor(0.), fSPhi(0.),
168 fDPhi(0.), fRminTolerance(0.), fRmaxTolerance(0. ),
169 kRadTolerance(0.), kAngTolerance(0.),
170 halfCarTolerance(0.), halfAngTolerance(0.)
186 :
G4CSGSolid(rhs), fRmin(rhs.fRmin),fRmax(rhs.fRmax),
187 fRtor(rhs.fRtor), fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
188 fRminTolerance(rhs.fRminTolerance), fRmaxTolerance(rhs.fRmaxTolerance),
189 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
190 halfCarTolerance(rhs.halfCarTolerance),
191 halfAngTolerance(rhs.halfAngTolerance)
203 if (
this == &rhs) {
return *
this; }
243 std::vector<G4double>& roots )
const
257 c[2] = 2*( (d + 2*pDotV*pDotV -
r2) + 2*Rtor2*v.
z()*v.
z());
258 c[3] = 4*(pDotV*(d -
r2) + 2*Rtor2*p.
z()*v.
z()) ;
259 c[4] = (d-
r2)*(d-r2) +4*Rtor2*(p.
z()*p.
z()-
r2);
263 num = torusEq.
FindRoots( c, 4, srd, si );
265 for ( i = 0; i <
num; ++i )
267 if( si[i] == 0. ) { roots.push_back(srd[i]) ; }
270 std::sort(roots.begin() , roots.end() ) ;
283 G4bool IsDistanceToIn )
const
292 std::vector<G4double> roots ;
293 std::vector<G4double> rootsrefined ;
300 for (
size_t k = 0 ;
k<roots.size() ; ++
k )
310 if ( rootsrefined.size()==roots.size() )
312 t = t + rootsrefined[
k] ;
340 if ( IsDistanceToIn ==
true )
348 p.
y()*(1-
fRtor/std::hypot(p.
x(),p.
y())),
353 if ( r ==
GetRmin() ) { scal = -scal ; }
354 if ( scal < 0 ) {
return 0.0 ; }
361 if ( IsDistanceToIn ==
false )
368 p.
y()*(1-
fRtor/std::hypot(p.
x(),p.
y())),
373 if ( r ==
GetRmin() ) { scal = -scal ; }
374 if ( scal > 0 ) {
return 0.0 ; }
407 pMin.
set(-rext,-rext,-dz);
408 pMax.
set( rext, rext, dz);
417 pMin.
set(vmin.
x(),vmin.
y(),-
dz);
418 pMax.
set(vmax.
x(),vmax.
y(),
dz);
423 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
426 message <<
"Bad bounding box (min >= max) for solid: "
428 <<
"\npMin = " << pMin
429 <<
"\npMax = " <<
pMax;
430 G4Exception(
"G4Torus::BoundingLimits()",
"GeomMgt0001",
458 return exist = (pMin <
pMax) ?
true :
false;
475 static const G4int NPHI = 24;
476 static const G4int NDISK = 16;
477 static const G4double sinHalfDisk = std::sin(
pi/NDISK);
478 static const G4double cosHalfDisk = std::cos(
pi/NDISK);
479 static const G4double sinStepDisk = 2.*sinHalfDisk*cosHalfDisk;
480 static const G4double cosStepDisk = 1. - 2.*sinHalfDisk*sinHalfDisk;
483 G4int kphi = (dphi <= astep) ? 1 : (
G4int)((dphi-
deg)/astep) + 1;
486 G4double sinHalf = std::sin(0.5*ang);
487 G4double cosHalf = std::cos(0.5*ang);
488 G4double sinStep = 2.*sinHalf*cosHalf;
489 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
493 for (
G4int k=0;
k<NDISK+1; ++
k) pols[
k].resize(4);
495 std::vector<const G4ThreeVectorList *> polygons;
496 polygons.resize(NDISK+1);
497 for (
G4int k=0;
k<NDISK+1; ++
k) polygons[
k] = &pols[
k];
503 if ((rtor-rmin*sinHalfDisk)/cosHalf > (rtor+rmin*sinHalfDisk)) rmin = 0;
509 G4double rmincur = rtor + rmin*cosCurDisk;
510 if (cosCurDisk < 0 && rmin > 0) rmincur /= cosHalf;
511 rzmin[
k].
set(rmincur,rmin*sinCurDisk);
513 G4double rmaxcur = rtor + rmax*cosCurDisk;
514 if (cosCurDisk > 0) rmaxcur /= cosHalf;
515 rzmax[
k].
set(rmaxcur,rmax*sinCurDisk);
518 sinCurDisk = sinCurDisk*cosStepDisk + cosCurDisk*sinStepDisk;
519 cosCurDisk = cosCurDisk*cosStepDisk - sinTmpDisk*sinStepDisk;
528 G4double sinCur1 = 0, cosCur1 = 0, sinCur2 = 0, cosCur2 = 0;
529 for (
G4int i=0; i<kphi+1; ++i)
535 sinCur2 = sinCur1*cosHalf + cosCur1*sinHalf;
536 cosCur2 = cosCur1*cosHalf - sinCur1*sinHalf;
542 sinCur2 = (i == kphi) ? sinEnd : sinCur1*cosStep + cosCur1*sinStep;
543 cosCur2 = (i == kphi) ? cosEnd : cosCur1*cosStep - sinCur1*sinStep;
549 pols[
k][0].set(r1*cosCur1,r1*sinCur1,z1);
550 pols[
k][1].set(
r2*cosCur1,
r2*sinCur1,
z2);
551 pols[
k][2].set(
r2*cosCur2,
r2*sinCur2,
z2);
552 pols[
k][3].set(r1*cosCur2,r1*sinCur2,z1);
554 pols[NDISK] = pols[0];
559 DiskExtent(rint,rext,sinCur1,cosCur1,sinCur2,cosCur2,vmin,vmax);
566 if (!benv.
CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
continue;
567 if (emin < pMin) pMin =
emin;
568 if (emax > pMax) pMax =
emax;
569 if (eminlim > pMin && emaxlim < pMax)
break;
571 return (pMin < pMax);
586 r = std::hypot(p.
x(),p.
y());
594 if (pt2 >= tolRMin*tolRMin && pt2 <= tolRMax*tolRMax )
605 pPhi = std::atan2(p.
y(),p.
x()) ;
642 if (tolRMin < 0 ) { tolRMin = 0 ; }
644 if ( (pt2 >= tolRMin*tolRMin) && (pt2 <= tolRMax*tolRMax) )
652 pPhi = std::atan2(p.
y(),p.
x()) ;
691 G4int noSurfaces = 0;
705 rho = std::hypot(p.
x(),p.
y());
706 pt = std::hypot(p.
z(),rho-
fRtor);
711 if( rho > delta && pt != 0.0 )
724 pPhi = std::atan2(p.
y(),p.
x());
729 distSPhi = std::fabs( pPhi -
fSPhi );
735 if( distRMax <= delta )
740 else if(
fRmin && (distRMin <= delta) )
751 if (distSPhi <= dAngle)
756 if (distEPhi <= dAngle)
762 if ( noSurfaces == 0 )
772 ed <<
" ERROR> Surface Normal was called for Torus,"
773 <<
" with point not on surface." <<
G4endl;
777 ed <<
" ERROR> Surface Normal has not found a surface, "
778 <<
" despite the point being on the surface. " <<
G4endl;
789 ed <<
" Coordinates of point : " << p <<
G4endl;
790 ed <<
" Parameters of solid : " << G4endl << *
this <<
G4endl;
794 G4Exception(
"G4Torus::SurfaceNormal(p)",
"GeomSolids1002",
796 "Failing to find normal, even though point is on surface!");
800 static const char* NameInside[3]= {
"Inside",
"Surface",
"Outside" };
801 ed <<
" The point is " << NameInside[inIt] <<
" the solid. "<<
G4endl;
802 G4Exception(
"G4Torus::SurfaceNormal(p)",
"GeomSolids1002",
808 else if ( noSurfaces == 1 ) { norm = sumnorm; }
809 else { norm = sumnorm.
unit(); }
824 G4double distRMin,distRMax,distSPhi,distEPhi,distMin;
826 rho = std::hypot(p.
x(),p.
y());
827 pt = std::hypot(p.
z(),rho-
fRtor);
830 G4cout <<
" G4Torus::ApproximateSurfaceNormal called for point " << p
834 distRMax = std::fabs(pt -
fRmax) ;
838 distRMin = std::fabs(pt -
fRmin) ;
840 if (distRMin < distRMax)
858 phi = std::atan2(p.
y(),p.
x()) ;
860 if (phi < 0) { phi +=
twopi ; }
863 else { distSPhi = std::fabs(phi-
fSPhi)*rho ; }
865 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
867 if (distSPhi < distEPhi)
869 if (distSPhi<distMin) side =
kNSPhi ;
873 if (distEPhi < distMin) { side =
kNEPhi ; }
898 "Undefined side for valid surface normal to solid.");
953 G4double dist = safe - 1.e-8*safe - boxMin;
969 G4double cPhi,sinCPhi=0.,cosCPhi=0.;
986 cPhi =
fSPhi + hDPhi ;
987 sinCPhi = std::sin(cPhi) ;
988 cosCPhi = std::cos(cPhi) ;
1012 if ( sd[0] < snxt ) { snxt = sd[0] ; }
1027 sinSPhi = std::sin(
fSPhi) ;
1028 cosSPhi = std::cos(
fSPhi) ;
1029 Comp = v.
x()*sinSPhi - v.
y()*cosSPhi ;
1033 Dist = (p.
y()*cosSPhi - p.
x()*sinSPhi) ;
1040 if ( sphi < 0 ) { sphi = 0 ; }
1042 xi = p.
x() + sphi*v.
x() ;
1043 yi = p.
y() + sphi*v.
y() ;
1044 zi = p.
z() + sphi*v.
z() ;
1045 rhoi = std::hypot(xi,yi);
1048 if ( it2 >= tolORMin2 && it2 <= tolORMax2 )
1053 if ((yi*cosCPhi-xi*sinCPhi)<=0) { snxt=sphi; }
1059 sinEPhi=std::sin(ePhi);
1060 cosEPhi=std::cos(ePhi);
1061 Comp=-(v.
x()*sinEPhi-v.
y()*cosEPhi);
1065 Dist = -(p.
y()*cosEPhi - p.
x()*sinEPhi) ;
1073 if (sphi < 0 ) { sphi = 0 ; }
1075 xi = p.
x() + sphi*v.
x() ;
1076 yi = p.
y() + sphi*v.
y() ;
1077 zi = p.
z() + sphi*v.
z() ;
1078 rhoi = std::hypot(xi,yi);
1081 if (it2 >= tolORMin2 && it2 <= tolORMax2)
1086 if ((yi*cosCPhi-xi*sinCPhi)>=0) { snxt=sphi; }
1107 G4double phiC, cosPhiC, sinPhiC, safePhi, ePhi, cosPsi ;
1110 rho = std::hypot(p.
x(),p.
y());
1111 pt = std::hypot(p.
z(),rho-
fRtor);
1113 safe2 = pt -
fRmax ;
1115 if (safe1 > safe2) { safe = safe1; }
1116 else { safe = safe2; }
1121 cosPhiC = std::cos(phiC) ;
1122 sinPhiC = std::sin(phiC) ;
1123 cosPsi = (p.
x()*cosPhiC + p.
y()*sinPhiC)/rho ;
1125 if (cosPsi < std::cos(
fDPhi*0.5) )
1127 if ((p.
y()*cosPhiC - p.
x()*sinPhiC) <= 0 )
1129 safePhi = std::fabs(p.
x()*std::sin(
fSPhi) - p.
y()*std::cos(
fSPhi)) ;
1134 safePhi = std::fabs(p.
x()*std::sin(ePhi) - p.
y()*std::cos(ePhi)) ;
1136 if (safePhi > safe) { safe = safePhi ; }
1139 if (safe < 0 ) { safe = 0 ; }
1160 G4double sinSPhi, cosSPhi, ePhi, sinEPhi, cosEPhi;
1162 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, zi, vphi ;
1185 if( (pt*pt > tolRMax*tolRMax) && (vDotNmax >= 0) )
1191 if ( calcNorm && (pDotxyNmax >= -2.*fRmaxTolerance) )
1194 p.
y()*(1 -
fRtor/rho)/pt,
1211 if ( (pt*pt < tolRMin*tolRMin) && (vDotNmax < 0) )
1213 if (calcNorm) { *validNorm =
false ; }
1243 if ( calcNorm && (snxt == 0.0) )
1245 *validNorm =
false ;
1253 sinSPhi = std::sin(
fSPhi) ;
1254 cosSPhi = std::cos(
fSPhi) ;
1256 sinEPhi = std::sin(ePhi) ;
1257 cosEPhi = std::cos(ePhi) ;
1258 cPhi =
fSPhi + fDPhi*0.5 ;
1259 sinCPhi = std::sin(cPhi) ;
1260 cosCPhi = std::cos(cPhi) ;
1265 vphi = std::atan2(v.
y(),v.
x()) ;
1270 if ( p.
x() || p.
y() )
1272 pDistS = p.
x()*sinSPhi - p.
y()*cosSPhi ;
1273 pDistE = -p.
x()*sinEPhi + p.
y()*cosEPhi ;
1277 compS = -sinSPhi*v.
x() + cosSPhi*v.
y() ;
1278 compE = sinEPhi*v.
x() - cosEPhi*v.
y() ;
1290 sphi = pDistS/compS ;
1294 xi = p.
x() + sphi*v.
x() ;
1295 yi = p.
y() + sphi*v.
y() ;
1310 else if ( yi*cosCPhi-xi*sinCPhi >=0 )
1331 sphi2 = pDistE/compE ;
1337 xi = p.
x() + sphi2*v.
x() ;
1338 yi = p.
y() + sphi2*v.
y() ;
1354 if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
1376 vphi = std::atan2(v.
y(),v.
x());
1408 xi = p.
x() + snxt*v.
x() ;
1409 yi = p.
y() + snxt*v.
y() ;
1410 zi = p.
z() + snxt*v.
z() ;
1411 rhoi = std::hypot(xi,yi);
1412 it = hypot(zi,rhoi-
fRtor);
1414 iDotxyNmax = (1-
fRtor/rhoi) ;
1415 if(iDotxyNmax >= -2.*fRmaxTolerance)
1418 yi*(1-
fRtor/rhoi)/it,
1424 *validNorm =
false ;
1429 *validNorm =
false ;
1440 *validNorm =
false ;
1452 *validNorm =
false ;
1463 G4int oldprc = message.precision(16);
1464 message <<
"Undefined side for valid surface normal to solid."
1466 <<
"Position:" << G4endl << G4endl
1467 <<
"p.x() = " << p.
x()/
mm <<
" mm" << G4endl
1468 <<
"p.y() = " << p.
y()/
mm <<
" mm" << G4endl
1469 <<
"p.z() = " << p.
z()/
mm <<
" mm" << G4endl << G4endl
1470 <<
"Direction:" << G4endl << G4endl
1471 <<
"v.x() = " << v.
x() << G4endl
1472 <<
"v.y() = " << v.
y() << G4endl
1473 <<
"v.z() = " << v.
z() << G4endl << G4endl
1474 <<
"Proposed distance :" << G4endl << G4endl
1475 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl;
1476 message.precision(oldprc);
1495 G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi;
1497 rho = std::hypot(p.
x(),p.
y());
1498 pt = std::hypot(p.
z(),rho-
fRtor);
1510 G4cout.precision(oldprc);
1511 G4Exception(
"G4Torus::DistanceToOut(p)",
"GeomSolids1002",
1518 safeR1 = pt -
fRmin ;
1521 if (safeR1 < safeR2) { safe = safeR1 ; }
1522 else { safe = safeR2 ; }
1534 cosPhiC = std::cos(phiC) ;
1535 sinPhiC = std::sin(phiC) ;
1537 if ((p.
y()*cosPhiC-p.
x()*sinPhiC)<=0)
1539 safePhi = -(p.
x()*std::sin(
fSPhi) - p.
y()*std::cos(
fSPhi)) ;
1544 safePhi = (p.
x()*std::sin(ePhi) - p.
y()*std::cos(ePhi)) ;
1546 if (safePhi < safe) { safe = safePhi ; }
1548 if (safe < 0) { safe = 0 ; }
1576 G4int oldprc = os.precision(16);
1577 os <<
"-----------------------------------------------------------\n"
1578 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1579 <<
" ===================================================\n"
1580 <<
" Solid type: G4Torus\n"
1581 <<
" Parameters: \n"
1582 <<
" inner radius: " <<
fRmin/
mm <<
" mm \n"
1583 <<
" outer radius: " <<
fRmax/
mm <<
" mm \n"
1584 <<
" swept radius: " <<
fRtor/
mm <<
" mm \n"
1585 <<
" starting phi: " <<
fSPhi/
degree <<
" degrees \n"
1586 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1587 <<
"-----------------------------------------------------------\n";
1588 os.precision(oldprc);
1599 G4double cosu, sinu,cosv, sinv, aOut, aIn, aSide, chose,
phi,
theta, rRand;
1604 cosu = std::cos(phi); sinu = std::sin(phi);
1605 cosv = std::cos(theta); sinv = std::sin(theta);
1621 else if( (chose >= aOut) && (chose < aOut + aIn) )
1626 else if( (chose >= aOut + aIn) && (chose < aOut + aIn + aSide) )
1630 (
fRtor+rRand*cosv)*std::sin(
fSPhi), rRand*sinv);
1655 #endif // !defined(G4GEOM_USE_TORUS) || !defined(G4GEOM_USE_SYS_USOLIDS)