40#if !(defined(G4GEOM_USE_UTORUS) && defined(G4GEOM_USE_SYS_USOLIDS))
105 std::ostringstream message;
106 message <<
"Invalid swept radius for Solid: " <<
GetName() <<
G4endl
107 <<
" pRtor = " << pRtor <<
", pRmax = " << pRmax;
114 if ( pRmin < pRmax - 1.e2*kCarTolerance && pRmin >= 0 )
117 else {
fRmin = 0.0 ; }
122 std::ostringstream message;
123 message <<
"Invalid values of radii for Solid: " <<
GetName() <<
G4endl
124 <<
" pRmin = " << pRmin <<
", pRmax = " << pRmax;
140 if (pDPhi > 0) {
fDPhi = pDPhi ; }
143 std::ostringstream message;
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] ;
318 G4double theta = std::atan2(ptmp.
y(),ptmp.
x());
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);
425 std::ostringstream message;
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;
507 for (
G4int k=0; k<NDISK; ++k)
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;
545 for (
G4int k=0; k<NDISK; ++k)
547 G4double r1 = rzmin[k].
x(), r2 = rzmax[k].
x();
548 G4double z1 = rzmin[k].
y(), z2 = rzmax[k].
y();
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);
569 if (eminlim >
pMin && emaxlim <
pMax)
break;
580 G4double r, pt2, pPhi, tolRMin, tolRMax ;
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.");
939 G4double distX = std::abs(p.
x()) - boxDx;
940 G4double distY = std::abs(p.
y()) - boxDy;
941 G4double distZ = std::abs(p.
z()) - boxDz;
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);
1112 safe1 =
fRmin - pt ;
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) )
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) ;
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) ;
1418 yi*(1-
fRtor/rhoi)/it,
1424 *validNorm = false ;
1429 *validNorm = false ;
1440 *validNorm = false ;
1452 *validNorm = false ;
1462 std::ostringstream message;
1463 G4int oldprc = message.precision(16);
1464 message <<
"Undefined side for valid surface normal to solid."
1467 <<
"p.x() = " << p.
x()/
mm <<
" mm" <<
G4endl
1468 <<
"p.y() = " << p.
y()/
mm <<
" mm" <<
G4endl
1471 <<
"v.x() = " << v.
x() <<
G4endl
1472 <<
"v.y() = " << v.
y() <<
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 ;
1519 safeR2 =
fRmax - pt ;
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);
std::vector< G4ThreeVector > G4ThreeVectorList
static const G4double emax
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
static const G4double pMax
static const G4double pMin
static constexpr double twopi
static constexpr double mm
static constexpr double degree
static constexpr double pi
static constexpr double deg
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
void set(double x, double y)
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
G4bool fRebuildPolyhedron
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
G4int FindRoots(G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
EInside Inside(const G4ThreeVector &p) const
G4Torus & operator=(const G4Torus &rhs)
G4GeometryType GetEntityType() const
G4double halfCarTolerance
G4double GetSinEndPhi() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
void SetAllParameters(G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4double SolveNumericJT(const G4ThreeVector &p, const G4ThreeVector &v, G4double r, G4bool IsDistanceToIn) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double halfAngTolerance
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4ThreeVector GetPointOnSurface() const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
std::ostream & StreamInfo(std::ostream &os) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const
void TorusRootsJT(const G4ThreeVector &p, const G4ThreeVector &v, G4double r, std::vector< G4double > &roots) const
G4Torus(const G4String &pName, G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
G4double GetCosStartPhi() const
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4double GetCosEndPhi() const
G4Polyhedron * CreatePolyhedron() const
G4double GetSinStartPhi() const
virtual void AddSolid(const G4Box &)=0
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
static const G4double kInfinity
ThreeVector shoot(const G4int Ap, const G4int Af)
T max(const T t1, const T t2)
brief Return the largest of the two arguments