Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Torus Class Reference

#include <G4Torus.hh>

+ Inheritance diagram for G4Torus:

Public Member Functions

 G4Torus (const G4String &pName, G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
 
 ~G4Torus () override
 
G4double GetRmin () const
 
G4double GetRmax () const
 
G4double GetRtor () const
 
G4double GetSPhi () const
 
G4double GetDPhi () const
 
G4double GetSinStartPhi () const
 
G4double GetCosStartPhi () const
 
G4double GetSinEndPhi () const
 
G4double GetCosEndPhi () const
 
G4double GetCubicVolume () override
 
G4double GetSurfaceArea () override
 
EInside Inside (const G4ThreeVector &p) const override
 
void BoundingLimits (G4ThreeVector &pMin, G4ThreeVector &pMax) const override
 
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
 
void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
 
G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const override
 
G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const override
 
G4double DistanceToIn (const G4ThreeVector &p) const override
 
G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
 
G4double DistanceToOut (const G4ThreeVector &p) const override
 
G4GeometryType GetEntityType () const override
 
G4ThreeVector GetPointOnSurface () const override
 
G4VSolidClone () const override
 
std::ostream & StreamInfo (std::ostream &os) const override
 
void DescribeYourselfTo (G4VGraphicsScene &scene) const override
 
G4PolyhedronCreatePolyhedron () const override
 
void SetAllParameters (G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
 
 G4Torus (__void__ &)
 
 G4Torus (const G4Torus &rhs)
 
G4Torusoperator= (const G4Torus &rhs)
 
- Public Member Functions inherited from G4CSGSolid
 G4CSGSolid (const G4String &pName)
 
virtual ~G4CSGSolid ()
 
G4PolyhedronGetPolyhedron () const override
 
 G4CSGSolid (__void__ &)
 
 G4CSGSolid (const G4CSGSolid &rhs)
 
G4CSGSolidoperator= (const G4CSGSolid &rhs)
 
- Public Member Functions inherited from G4VSolid
 G4VSolid (const G4String &name)
 
virtual ~G4VSolid ()
 
G4bool operator== (const G4VSolid &s) const
 
G4String GetName () const
 
void SetName (const G4String &name)
 
G4double GetTolerance () const
 
void DumpInfo () const
 
virtual G4VisExtent GetExtent () const
 
virtual const G4VSolidGetConstituentSolid (G4int no) const
 
virtual G4VSolidGetConstituentSolid (G4int no)
 
virtual const G4DisplacedSolidGetDisplacedSolidPtr () const
 
virtual G4DisplacedSolidGetDisplacedSolidPtr ()
 
 G4VSolid (__void__ &)
 
 G4VSolid (const G4VSolid &rhs)
 
G4VSolidoperator= (const G4VSolid &rhs)
 
G4double EstimateCubicVolume (G4int nStat, G4double epsilon) const
 
G4double EstimateSurfaceArea (G4int nStat, G4double ell) const
 

Additional Inherited Members

- Protected Member Functions inherited from G4CSGSolid
G4double GetRadiusInRing (G4double rmin, G4double rmax) const
 
- Protected Member Functions inherited from G4VSolid
void CalculateClippedPolygonExtent (G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
 
void ClipCrossSection (G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
 
void ClipBetweenSections (G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
 
void ClipPolygon (G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis) const
 
- Protected Attributes inherited from G4CSGSolid
G4double fCubicVolume = 0.0
 
G4double fSurfaceArea = 0.0
 
G4bool fRebuildPolyhedron = false
 
G4PolyhedronfpPolyhedron = nullptr
 
- Protected Attributes inherited from G4VSolid
G4double kCarTolerance
 

Detailed Description

Definition at line 91 of file G4Torus.hh.

Constructor & Destructor Documentation

◆ G4Torus() [1/3]

G4Torus::G4Torus ( const G4String & pName,
G4double pRmin,
G4double pRmax,
G4double pRtor,
G4double pSPhi,
G4double pDPhi )

Definition at line 65 of file G4Torus.cc.

71 : G4CSGSolid(pName)
72{
73 SetAllParameters(pRmin, pRmax, pRtor, pSPhi, pDPhi);
74}
G4CSGSolid(const G4String &pName)
Definition G4CSGSolid.cc:49
void SetAllParameters(G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
Definition G4Torus.cc:81

Referenced by Clone().

◆ ~G4Torus()

G4Torus::~G4Torus ( )
overridedefault

◆ G4Torus() [2/3]

G4Torus::G4Torus ( __void__ & a)

Definition at line 166 of file G4Torus.cc.

167 : G4CSGSolid(a)
168{
169}

◆ G4Torus() [3/3]

G4Torus::G4Torus ( const G4Torus & rhs)
default

Member Function Documentation

◆ BoundingLimits()

void G4Torus::BoundingLimits ( G4ThreeVector & pMin,
G4ThreeVector & pMax ) const
overridevirtual

Reimplemented from G4VSolid.

Definition at line 383 of file G4Torus.cc.

384{
385 G4double rmax = GetRmax();
386 G4double rtor = GetRtor();
387 G4double rint = rtor - rmax;
388 G4double rext = rtor + rmax;
389 G4double dz = rmax;
390
391 // Find bounding box
392 //
393 if (GetDPhi() >= twopi)
394 {
395 pMin.set(-rext,-rext,-dz);
396 pMax.set( rext, rext, dz);
397 }
398 else
399 {
400 G4TwoVector vmin,vmax;
401 G4GeomTools::DiskExtent(rint,rext,
404 vmin,vmax);
405 pMin.set(vmin.x(),vmin.y(),-dz);
406 pMax.set(vmax.x(),vmax.y(), dz);
407 }
408
409 // Check correctness of the bounding box
410 //
411 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
412 {
413 std::ostringstream message;
414 message << "Bad bounding box (min >= max) for solid: "
415 << GetName() << " !"
416 << "\npMin = " << pMin
417 << "\npMax = " << pMax;
418 G4Exception("G4Torus::BoundingLimits()", "GeomMgt0001",
419 JustWarning, message);
420 DumpInfo();
421 }
422}
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
double G4double
Definition G4Types.hh:83
double x() const
double y() const
double z() const
double x() const
double y() const
void set(double x, double y, double z)
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)
G4double GetSinEndPhi() const
G4double GetDPhi() const
G4double GetRtor() const
G4double GetRmax() const
G4double GetCosStartPhi() const
G4double GetCosEndPhi() const
G4double GetSinStartPhi() const
G4String GetName() const
void DumpInfo() const

Referenced by CalculateExtent().

◆ CalculateExtent()

G4bool G4Torus::CalculateExtent ( const EAxis pAxis,
const G4VoxelLimits & pVoxelLimit,
const G4AffineTransform & pTransform,
G4double & pmin,
G4double & pmax ) const
overridevirtual

Implements G4VSolid.

Definition at line 428 of file G4Torus.cc.

432{
433 G4ThreeVector bmin, bmax;
434 G4bool exist;
435
436 // Get bounding box
437 BoundingLimits(bmin,bmax);
438
439 // Check bounding box
440 G4BoundingEnvelope bbox(bmin,bmax);
441#ifdef G4BBOX_EXTENT
442 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
443#endif
444 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
445 {
446 return exist = pMin < pMax;
447 }
448
449 // Get parameters of the solid
450 G4double rmin = GetRmin();
451 G4double rmax = GetRmax();
452 G4double rtor = GetRtor();
453 G4double dphi = GetDPhi();
454 G4double sinStart = GetSinStartPhi();
455 G4double cosStart = GetCosStartPhi();
456 G4double sinEnd = GetSinEndPhi();
457 G4double cosEnd = GetCosEndPhi();
458 G4double rint = rtor - rmax;
459 G4double rext = rtor + rmax;
460
461 // Find bounding envelope and calculate extent
462 //
463 static const G4int NPHI = 24; // number of steps for whole torus
464 static const G4int NDISK = 16; // number of steps for disk
465 static const G4double sinHalfDisk = std::sin(pi/NDISK);
466 static const G4double cosHalfDisk = std::cos(pi/NDISK);
467 static const G4double sinStepDisk = 2.*sinHalfDisk*cosHalfDisk;
468 static const G4double cosStepDisk = 1. - 2.*sinHalfDisk*sinHalfDisk;
469
470 G4double astep = (360/NPHI)*deg; // max angle for one slice in phi
471 G4int kphi = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
472 G4double ang = dphi/kphi;
473
474 G4double sinHalf = std::sin(0.5*ang);
475 G4double cosHalf = std::cos(0.5*ang);
476 G4double sinStep = 2.*sinHalf*cosHalf;
477 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
478
479 // define vectors for bounding envelope
480 G4ThreeVectorList pols[NDISK+1];
481 for (auto & pol : pols) pol.resize(4);
482
483 std::vector<const G4ThreeVectorList *> polygons;
484 polygons.resize(NDISK+1);
485 for (G4int k=0; k<NDISK+1; ++k) polygons[k] = &pols[k];
486
487 // set internal and external reference circles
488 G4TwoVector rzmin[NDISK];
489 G4TwoVector rzmax[NDISK];
490
491 if ((rtor-rmin*sinHalfDisk)/cosHalf > (rtor+rmin*sinHalfDisk)) rmin = 0;
492 rmax /= cosHalfDisk;
493 G4double sinCurDisk = sinHalfDisk;
494 G4double cosCurDisk = cosHalfDisk;
495 for (G4int k=0; k<NDISK; ++k)
496 {
497 G4double rmincur = rtor + rmin*cosCurDisk;
498 if (cosCurDisk < 0 && rmin > 0) rmincur /= cosHalf;
499 rzmin[k].set(rmincur,rmin*sinCurDisk);
500
501 G4double rmaxcur = rtor + rmax*cosCurDisk;
502 if (cosCurDisk > 0) rmaxcur /= cosHalf;
503 rzmax[k].set(rmaxcur,rmax*sinCurDisk);
504
505 G4double sinTmpDisk = sinCurDisk;
506 sinCurDisk = sinCurDisk*cosStepDisk + cosCurDisk*sinStepDisk;
507 cosCurDisk = cosCurDisk*cosStepDisk - sinTmpDisk*sinStepDisk;
508 }
509
510 // Loop along slices in Phi. The extent is calculated as cumulative
511 // extent of the slices
512 pMin = kInfinity;
513 pMax = -kInfinity;
514 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
515 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
516 G4double sinCur1 = 0, cosCur1 = 0, sinCur2 = 0, cosCur2 = 0;
517 for (G4int i=0; i<kphi+1; ++i)
518 {
519 if (i == 0)
520 {
521 sinCur1 = sinStart;
522 cosCur1 = cosStart;
523 sinCur2 = sinCur1*cosHalf + cosCur1*sinHalf;
524 cosCur2 = cosCur1*cosHalf - sinCur1*sinHalf;
525 }
526 else
527 {
528 sinCur1 = sinCur2;
529 cosCur1 = cosCur2;
530 sinCur2 = (i == kphi) ? sinEnd : sinCur1*cosStep + cosCur1*sinStep;
531 cosCur2 = (i == kphi) ? cosEnd : cosCur1*cosStep - sinCur1*sinStep;
532 }
533 for (G4int k=0; k<NDISK; ++k)
534 {
535 G4double r1 = rzmin[k].x(), r2 = rzmax[k].x();
536 G4double z1 = rzmin[k].y(), z2 = rzmax[k].y();
537 pols[k][0].set(r1*cosCur1,r1*sinCur1,z1);
538 pols[k][1].set(r2*cosCur1,r2*sinCur1,z2);
539 pols[k][2].set(r2*cosCur2,r2*sinCur2,z2);
540 pols[k][3].set(r1*cosCur2,r1*sinCur2,z1);
541 }
542 pols[NDISK] = pols[0];
543
544 // get bounding box of current slice
545 G4TwoVector vmin,vmax;
547 DiskExtent(rint,rext,sinCur1,cosCur1,sinCur2,cosCur2,vmin,vmax);
548 bmin.setX(vmin.x()); bmin.setY(vmin.y());
549 bmax.setX(vmax.x()); bmax.setY(vmax.y());
550
551 // set bounding envelope for current slice and adjust extent
552 G4double emin,emax;
553 G4BoundingEnvelope benv(bmin,bmax,polygons);
554 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
555 if (emin < pMin) pMin = emin;
556 if (emax > pMax) pMax = emax;
557 if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
558 }
559 return (pMin < pMax);
560}
std::vector< G4ThreeVector > G4ThreeVectorList
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
void set(double x, double y)
void setY(double)
void setX(double)
G4double GetRmin() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
Definition G4Torus.cc:383
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const

◆ Clone()

G4VSolid * G4Torus::Clone ( ) const
overridevirtual

Reimplemented from G4VSolid.

Definition at line 1553 of file G4Torus.cc.

1554{
1555 return new G4Torus(*this);
1556}
G4Torus(const G4String &pName, G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
Definition G4Torus.cc:65

◆ ComputeDimensions()

void G4Torus::ComputeDimensions ( G4VPVParameterisation * p,
const G4int n,
const G4VPhysicalVolume * pRep )
overridevirtual

Reimplemented from G4VSolid.

Definition at line 214 of file G4Torus.cc.

217{
218 p->ComputeDimensions(*this,n,pRep);
219}
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const

◆ CreatePolyhedron()

G4Polyhedron * G4Torus::CreatePolyhedron ( ) const
overridevirtual

Reimplemented from G4VSolid.

Definition at line 1635 of file G4Torus.cc.

1636{
1637 return new G4PolyhedronTorus (fRmin, fRmax, fRtor, fSPhi, fDPhi);
1638}

◆ DescribeYourselfTo()

void G4Torus::DescribeYourselfTo ( G4VGraphicsScene & scene) const
overridevirtual

Implements G4VSolid.

Definition at line 1630 of file G4Torus.cc.

1631{
1632 scene.AddSolid (*this);
1633}
virtual void AddSolid(const G4Box &)=0

◆ DistanceToIn() [1/2]

G4double G4Torus::DistanceToIn ( const G4ThreeVector & p) const
overridevirtual

Implements G4VSolid.

Definition at line 1092 of file G4Torus.cc.

1093{
1094 G4double safe=0.0, safe1, safe2 ;
1095 G4double phiC, cosPhiC, sinPhiC, safePhi, ePhi, cosPsi ;
1096 G4double rho, pt ;
1097
1098 rho = std::hypot(p.x(),p.y());
1099 pt = std::hypot(p.z(),rho-fRtor);
1100 safe1 = fRmin - pt ;
1101 safe2 = pt - fRmax ;
1102
1103 if (safe1 > safe2) { safe = safe1; }
1104 else { safe = safe2; }
1105
1106 if ( fDPhi < twopi && (rho != 0.0) )
1107 {
1108 phiC = fSPhi + fDPhi*0.5 ;
1109 cosPhiC = std::cos(phiC) ;
1110 sinPhiC = std::sin(phiC) ;
1111 cosPsi = (p.x()*cosPhiC + p.y()*sinPhiC)/rho ;
1112
1113 if (cosPsi < std::cos(fDPhi*0.5) ) // Psi=angle from central phi to point
1114 { // Point lies outside phi range
1115 if ((p.y()*cosPhiC - p.x()*sinPhiC) <= 0 )
1116 {
1117 safePhi = std::fabs(p.x()*std::sin(fSPhi) - p.y()*std::cos(fSPhi)) ;
1118 }
1119 else
1120 {
1121 ePhi = fSPhi + fDPhi ;
1122 safePhi = std::fabs(p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1123 }
1124 if (safePhi > safe) { safe = safePhi ; }
1125 }
1126 }
1127 if (safe < 0 ) { safe = 0 ; }
1128 return safe;
1129}

◆ DistanceToIn() [2/2]

G4double G4Torus::DistanceToIn ( const G4ThreeVector & p,
const G4ThreeVector & v ) const
overridevirtual

Implements G4VSolid.

Definition at line 914 of file G4Torus.cc.

916{
917 // Get bounding box of full torus
918 //
919 G4double boxDx = fRtor + fRmax;
920 G4double boxDy = boxDx;
921 G4double boxDz = fRmax;
922 G4double boxMax = boxDx;
923 G4double boxMin = boxDz;
924
925 // Check if point is traveling away
926 //
927 G4double distX = std::abs(p.x()) - boxDx;
928 G4double distY = std::abs(p.y()) - boxDy;
929 G4double distZ = std::abs(p.z()) - boxDz;
930 if (distX >= -halfCarTolerance && p.x()*v.x() >= 0) return kInfinity;
931 if (distY >= -halfCarTolerance && p.y()*v.y() >= 0) return kInfinity;
932 if (distZ >= -halfCarTolerance && p.z()*v.z() >= 0) return kInfinity;
933
934 // Calculate safety distance to bounding box
935 // If point is too far, move it closer and calculate distance
936 //
937 G4double Dmax = 32*boxMax;
938 G4double safe = std::max(std::max(distX,distY),distZ);
939 if (safe > Dmax)
940 {
941 G4double dist = safe - 1.e-8*safe - boxMin; // stay outside after the move
942 dist += DistanceToIn(p + dist*v, v);
943 return (dist >= kInfinity) ? kInfinity : dist;
944 }
945
946 // Find intersection with torus
947 //
948 G4double snxt=kInfinity, sphi=kInfinity; // snxt = default return value
949
950 G4double sd[4] ;
951
952 // Precalculated trig for phi intersections - used by r,z intersections to
953 // check validity
954
955 G4bool seg; // true if segmented
956 G4double hDPhi; // half dphi
957 G4double cPhi,sinCPhi=0.,cosCPhi=0.; // central phi
958
959 G4double tolORMin2; // `generous' radii squared
960 G4double tolORMax2;
961
962 G4double Dist,xi,yi,zi,rhoi,it2; // Intersection point variables
963
964 G4double Comp;
965 G4double cosSPhi,sinSPhi; // Trig for phi start intersect
966 G4double ePhi,cosEPhi,sinEPhi; // for phi end intersect
967
968 // Set phi divided flag and precalcs
969 //
970 if ( fDPhi < twopi )
971 {
972 seg = true ;
973 hDPhi = 0.5*fDPhi ; // half delta phi
974 cPhi = fSPhi + hDPhi ;
975 sinCPhi = std::sin(cPhi) ;
976 cosCPhi = std::cos(cPhi) ;
977 }
978 else
979 {
980 seg = false ;
981 }
982
983 if (fRmin > fRminTolerance) // Calculate tolerant rmin and rmax
984 {
985 tolORMin2 = (fRmin - fRminTolerance)*(fRmin - fRminTolerance) ;
986 }
987 else
988 {
989 tolORMin2 = 0 ;
990 }
991 tolORMax2 = (fRmax + fRmaxTolerance)*(fRmax + fRmaxTolerance) ;
992
993 // Intersection with Rmax (possible return) and Rmin (must also check phi)
994
995 snxt = SolveNumericJT(p,v,fRmax,true);
996
997 if (fRmin != 0.0) // Possible Rmin intersection
998 {
999 sd[0] = SolveNumericJT(p,v,fRmin,true);
1000 if ( sd[0] < snxt ) { snxt = sd[0] ; }
1001 }
1002
1003 //
1004 // Phi segment intersection
1005 //
1006 // o Tolerant of points inside phi planes by up to kCarTolerance*0.5
1007 //
1008 // o NOTE: Large duplication of code between sphi & ephi checks
1009 // -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane
1010 // intersection check <=0 -> >=0
1011 // -> use some form of loop Construct ?
1012
1013 if (seg)
1014 {
1015 sinSPhi = std::sin(fSPhi) ; // First phi surface ('S'tarting phi)
1016 cosSPhi = std::cos(fSPhi) ;
1017 Comp = v.x()*sinSPhi - v.y()*cosSPhi ; // Component in outwards
1018 // normal direction
1019 if (Comp < 0 )
1020 {
1021 Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ;
1022
1023 if (Dist < halfCarTolerance)
1024 {
1025 sphi = Dist/Comp ;
1026 if (sphi < snxt)
1027 {
1028 if ( sphi < 0 ) { sphi = 0 ; }
1029
1030 xi = p.x() + sphi*v.x() ;
1031 yi = p.y() + sphi*v.y() ;
1032 zi = p.z() + sphi*v.z() ;
1033 rhoi = std::hypot(xi,yi);
1034 it2 = zi*zi + (rhoi-fRtor)*(rhoi-fRtor);
1035
1036 if ( it2 >= tolORMin2 && it2 <= tolORMax2 )
1037 {
1038 // r intersection is good - check intersecting
1039 // with correct half-plane
1040 //
1041 if ((yi*cosCPhi-xi*sinCPhi)<=0) { snxt=sphi; }
1042 }
1043 }
1044 }
1045 }
1046 ePhi=fSPhi+fDPhi; // Second phi surface ('E'nding phi)
1047 sinEPhi=std::sin(ePhi);
1048 cosEPhi=std::cos(ePhi);
1049 Comp=-(v.x()*sinEPhi-v.y()*cosEPhi);
1050
1051 if ( Comp < 0 ) // Component in outwards normal dirn
1052 {
1053 Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ;
1054
1055 if (Dist < halfCarTolerance )
1056 {
1057 sphi = Dist/Comp ;
1058
1059 if (sphi < snxt )
1060 {
1061 if (sphi < 0 ) { sphi = 0 ; }
1062
1063 xi = p.x() + sphi*v.x() ;
1064 yi = p.y() + sphi*v.y() ;
1065 zi = p.z() + sphi*v.z() ;
1066 rhoi = std::hypot(xi,yi);
1067 it2 = zi*zi + (rhoi-fRtor)*(rhoi-fRtor);
1068
1069 if (it2 >= tolORMin2 && it2 <= tolORMax2)
1070 {
1071 // z and r intersections good - check intersecting
1072 // with correct half-plane
1073 //
1074 if ((yi*cosCPhi-xi*sinCPhi)>=0) { snxt=sphi; }
1075 }
1076 }
1077 }
1078 }
1079 }
1080 if(snxt < halfCarTolerance) { snxt = 0.0 ; }
1081
1082 return snxt ;
1083}
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
Definition G4Torus.cc:914

Referenced by DistanceToIn(), and SurfaceNormal().

◆ DistanceToOut() [1/2]

G4double G4Torus::DistanceToOut ( const G4ThreeVector & p) const
overridevirtual

Implements G4VSolid.

Definition at line 1479 of file G4Torus.cc.

1480{
1481 G4double safe=0.0,safeR1,safeR2;
1482 G4double rho,pt ;
1483 G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi;
1484
1485 rho = std::hypot(p.x(),p.y());
1486 pt = std::hypot(p.z(),rho-fRtor);
1487
1488#ifdef G4CSGDEBUG
1489 if( Inside(p) == kOutside )
1490 {
1491 G4long oldprc = G4cout.precision(16) ;
1492 G4cout << G4endl ;
1493 DumpInfo();
1494 G4cout << "Position:" << G4endl << G4endl ;
1495 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ;
1496 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ;
1497 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ;
1498 G4cout.precision(oldprc);
1499 G4Exception("G4Torus::DistanceToOut(p)", "GeomSolids1002",
1500 JustWarning, "Point p is outside !?" );
1501 }
1502#endif
1503
1504 if (fRmin != 0.0)
1505 {
1506 safeR1 = pt - fRmin ;
1507 safeR2 = fRmax - pt ;
1508
1509 if (safeR1 < safeR2) { safe = safeR1 ; }
1510 else { safe = safeR2 ; }
1511 }
1512 else
1513 {
1514 safe = fRmax - pt ;
1515 }
1516
1517 // Check if phi divided, Calc distances closest phi plane
1518 //
1519 if (fDPhi < twopi) // Above/below central phi of Torus?
1520 {
1521 phiC = fSPhi + fDPhi*0.5 ;
1522 cosPhiC = std::cos(phiC) ;
1523 sinPhiC = std::sin(phiC) ;
1524
1525 if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
1526 {
1527 safePhi = -(p.x()*std::sin(fSPhi) - p.y()*std::cos(fSPhi)) ;
1528 }
1529 else
1530 {
1531 ePhi = fSPhi + fDPhi ;
1532 safePhi = (p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1533 }
1534 if (safePhi < safe) { safe = safePhi ; }
1535 }
1536 if (safe < 0) { safe = 0 ; }
1537 return safe ;
1538}
long G4long
Definition G4Types.hh:87
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
EInside Inside(const G4ThreeVector &p) const override
Definition G4Torus.cc:566
@ kOutside
Definition geomdefs.hh:68

◆ DistanceToOut() [2/2]

G4double G4Torus::DistanceToOut ( const G4ThreeVector & p,
const G4ThreeVector & v,
const G4bool calcNorm = false,
G4bool * validNorm = nullptr,
G4ThreeVector * n = nullptr ) const
overridevirtual

Implements G4VSolid.

Definition at line 1137 of file G4Torus.cc.

1142{
1143 ESide side = kNull, sidephi = kNull ;
1144 G4double snxt = kInfinity, sphi, sd[4] ;
1145
1146 // Vars for phi intersection
1147 //
1148 G4double sinSPhi, cosSPhi, ePhi, sinEPhi, cosEPhi;
1149 G4double cPhi, sinCPhi, cosCPhi ;
1150 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, zi, vphi ;
1151
1152 // Radial Intersections Defenitions & General Precals
1153
1154 //////////////////////// new calculation //////////////////////
1155
1156#if 1
1157
1158 // This is the version with the calculation of CalcNorm = true
1159 // To be done: Check the precision of this calculation.
1160 // If you want return always validNorm = false, then take the version below
1161
1162
1163 G4double rho = std::hypot(p.x(),p.y());
1164 G4double pt = hypot(p.z(),rho-fRtor);
1165
1166 G4double pDotV = p.x()*v.x() + p.y()*v.y() + p.z()*v.z() ;
1167
1168 G4double tolRMax = fRmax - fRmaxTolerance ;
1169
1170 G4double vDotNmax = pDotV - fRtor*(v.x()*p.x() + v.y()*p.y())/rho ;
1171 G4double pDotxyNmax = (1 - fRtor/rho) ;
1172
1173 if( (pt*pt > tolRMax*tolRMax) && (vDotNmax >= 0) )
1174 {
1175 // On tolerant boundary & heading outwards (or perpendicular to) outer
1176 // radial surface -> leaving immediately with *n for really convex part
1177 // only
1178
1179 if ( calcNorm && (pDotxyNmax >= -2.*fRmaxTolerance) )
1180 {
1181 *n = G4ThreeVector( p.x()*(1 - fRtor/rho)/pt,
1182 p.y()*(1 - fRtor/rho)/pt,
1183 p.z()/pt ) ;
1184 *validNorm = true ;
1185 }
1186
1187 return snxt = 0 ; // Leaving by Rmax immediately
1188 }
1189
1190 snxt = SolveNumericJT(p,v,fRmax,false);
1191 side = kRMax ;
1192
1193 // rmin
1194
1195 if ( fRmin != 0.0 )
1196 {
1197 G4double tolRMin = fRmin + fRminTolerance ;
1198
1199 if ( (pt*pt < tolRMin*tolRMin) && (vDotNmax < 0) )
1200 {
1201 if (calcNorm) { *validNorm = false ; } // Concave surface of the torus
1202 return snxt = 0 ; // Leaving by Rmin immediately
1203 }
1204
1205 sd[0] = SolveNumericJT(p,v,fRmin,false);
1206 if ( sd[0] < snxt )
1207 {
1208 snxt = sd[0] ;
1209 side = kRMin ;
1210 }
1211 }
1212
1213#else
1214
1215 // this is the "conservative" version which return always validnorm = false
1216 // NOTE: using this version the unit test testG4Torus will break
1217
1218 snxt = SolveNumericJT(p,v,fRmax,false);
1219 side = kRMax ;
1220
1221 if ( fRmin )
1222 {
1223 sd[0] = SolveNumericJT(p,v,fRmin,false);
1224 if ( sd[0] < snxt )
1225 {
1226 snxt = sd[0] ;
1227 side = kRMin ;
1228 }
1229 }
1230
1231 if ( calcNorm && (snxt == 0.0) )
1232 {
1233 *validNorm = false ; // Leaving solid, but possible re-intersection
1234 return snxt ;
1235 }
1236
1237#endif
1238
1239 if (fDPhi < twopi) // Phi Intersections
1240 {
1241 sinSPhi = std::sin(fSPhi) ;
1242 cosSPhi = std::cos(fSPhi) ;
1243 ePhi = fSPhi + fDPhi ;
1244 sinEPhi = std::sin(ePhi) ;
1245 cosEPhi = std::cos(ePhi) ;
1246 cPhi = fSPhi + fDPhi*0.5 ;
1247 sinCPhi = std::sin(cPhi) ;
1248 cosCPhi = std::cos(cPhi) ;
1249
1250 // angle calculation with correction
1251 // of difference in domain of atan2 and Sphi
1252 //
1253 vphi = std::atan2(v.y(),v.x()) ;
1254
1255 if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
1256 else if ( vphi > ePhi + halfAngTolerance ) { vphi -= twopi; }
1257
1258 if ( (p.x() != 0.0) || (p.y() != 0.0) ) // Check if on z axis (rho not needed later)
1259 {
1260 pDistS = p.x()*sinSPhi - p.y()*cosSPhi ; // pDist -ve when inside
1261 pDistE = -p.x()*sinEPhi + p.y()*cosEPhi ;
1262
1263 // Comp -ve when in direction of outwards normal
1264 //
1265 compS = -sinSPhi*v.x() + cosSPhi*v.y() ;
1266 compE = sinEPhi*v.x() - cosEPhi*v.y() ;
1267 sidephi = kNull ;
1268
1269 if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
1270 && (pDistE <= halfCarTolerance) ) )
1271 || ( (fDPhi > pi) && ((pDistS <= halfCarTolerance)
1272 || (pDistE <= halfCarTolerance) ) ) )
1273 {
1274 // Inside both phi *full* planes
1275
1276 if ( compS < 0 )
1277 {
1278 sphi = pDistS/compS ;
1279
1280 if (sphi >= -halfCarTolerance)
1281 {
1282 xi = p.x() + sphi*v.x() ;
1283 yi = p.y() + sphi*v.y() ;
1284
1285 // Check intersecting with correct half-plane
1286 // (if not -> no intersect)
1287 //
1288 if ( (std::fabs(xi)<=kCarTolerance)
1289 && (std::fabs(yi)<=kCarTolerance) )
1290 {
1291 sidephi = kSPhi;
1292 if ( ((fSPhi-halfAngTolerance)<=vphi)
1293 && ((ePhi+halfAngTolerance)>=vphi) )
1294 {
1295 sphi = kInfinity;
1296 }
1297 }
1298 else if ( yi*cosCPhi-xi*sinCPhi >=0 )
1299 {
1300 sphi = kInfinity ;
1301 }
1302 else
1303 {
1304 sidephi = kSPhi ;
1305 }
1306 }
1307 else
1308 {
1309 sphi = kInfinity ;
1310 }
1311 }
1312 else
1313 {
1314 sphi = kInfinity ;
1315 }
1316
1317 if ( compE < 0 )
1318 {
1319 sphi2 = pDistE/compE ;
1320
1321 // Only check further if < starting phi intersection
1322 //
1323 if ( (sphi2 > -kCarTolerance) && (sphi2 < sphi) )
1324 {
1325 xi = p.x() + sphi2*v.x() ;
1326 yi = p.y() + sphi2*v.y() ;
1327
1328 if ( (std::fabs(xi)<=kCarTolerance)
1329 && (std::fabs(yi)<=kCarTolerance) )
1330 {
1331 // Leaving via ending phi
1332 //
1333 if( (fSPhi-halfAngTolerance > vphi)
1334 || (ePhi+halfAngTolerance < vphi) )
1335 {
1336 sidephi = kEPhi ;
1337 sphi = sphi2;
1338 }
1339 }
1340 else // Check intersecting with correct half-plane
1341 {
1342 if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
1343 {
1344 // Leaving via ending phi
1345 //
1346 sidephi = kEPhi ;
1347 sphi = sphi2;
1348
1349 }
1350 }
1351 }
1352 }
1353 }
1354 else
1355 {
1356 sphi = kInfinity ;
1357 }
1358 }
1359 else
1360 {
1361 // On z axis + travel not || to z axis -> if phi of vector direction
1362 // within phi of shape, Step limited by rmax, else Step =0
1363
1364 vphi = std::atan2(v.y(),v.x());
1365
1366 if ( ( fSPhi-halfAngTolerance <= vphi ) &&
1367 ( vphi <= ( ePhi+halfAngTolerance ) ) )
1368 {
1369 sphi = kInfinity;
1370 }
1371 else
1372 {
1373 sidephi = kSPhi ; // arbitrary
1374 sphi=0;
1375 }
1376 }
1377
1378 // Order intersections
1379
1380 if (sphi<snxt)
1381 {
1382 snxt=sphi;
1383 side=sidephi;
1384 }
1385 }
1386
1387 G4double rhoi,it,iDotxyNmax ;
1388 // Note: by numerical computation we know where the ray hits the torus
1389 // So I propose to return the side where the ray hits
1390
1391 if (calcNorm)
1392 {
1393 switch(side)
1394 {
1395 case kRMax: // n is unit vector
1396 xi = p.x() + snxt*v.x() ;
1397 yi = p.y() + snxt*v.y() ;
1398 zi = p.z() + snxt*v.z() ;
1399 rhoi = std::hypot(xi,yi);
1400 it = hypot(zi,rhoi-fRtor);
1401
1402 iDotxyNmax = (1-fRtor/rhoi) ;
1403 if(iDotxyNmax >= -2.*fRmaxTolerance) // really convex part of Rmax
1404 {
1405 *n = G4ThreeVector( xi*(1-fRtor/rhoi)/it,
1406 yi*(1-fRtor/rhoi)/it,
1407 zi/it ) ;
1408 *validNorm = true ;
1409 }
1410 else
1411 {
1412 *validNorm = false ; // concave-convex part of Rmax
1413 }
1414 break ;
1415
1416 case kRMin:
1417 *validNorm = false ; // Rmin is concave or concave-convex
1418 break;
1419
1420 case kSPhi:
1421 if (fDPhi <= pi )
1422 {
1423 *n=G4ThreeVector(std::sin(fSPhi),-std::cos(fSPhi),0);
1424 *validNorm=true;
1425 }
1426 else
1427 {
1428 *validNorm = false ;
1429 }
1430 break ;
1431
1432 case kEPhi:
1433 if (fDPhi <= pi)
1434 {
1435 *n=G4ThreeVector(-std::sin(fSPhi+fDPhi),std::cos(fSPhi+fDPhi),0);
1436 *validNorm=true;
1437 }
1438 else
1439 {
1440 *validNorm = false ;
1441 }
1442 break;
1443
1444 default:
1445
1446 // It seems we go here from time to time ...
1447
1448 G4cout << G4endl;
1449 DumpInfo();
1450 std::ostringstream message;
1451 G4long oldprc = message.precision(16);
1452 message << "Undefined side for valid surface normal to solid."
1453 << G4endl
1454 << "Position:" << G4endl << G4endl
1455 << "p.x() = " << p.x()/mm << " mm" << G4endl
1456 << "p.y() = " << p.y()/mm << " mm" << G4endl
1457 << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl
1458 << "Direction:" << G4endl << G4endl
1459 << "v.x() = " << v.x() << G4endl
1460 << "v.y() = " << v.y() << G4endl
1461 << "v.z() = " << v.z() << G4endl << G4endl
1462 << "Proposed distance :" << G4endl << G4endl
1463 << "snxt = " << snxt/mm << " mm" << G4endl;
1464 message.precision(oldprc);
1465 G4Exception("G4Torus::DistanceToOut(p,v,..)",
1466 "GeomSolids1002",JustWarning, message);
1467 break;
1468 }
1469 }
1470 if ( snxt<halfCarTolerance ) { snxt=0 ; }
1471
1472 return snxt;
1473}
ESide
Definition G4Sphere.cc:61
CLHEP::Hep3Vector G4ThreeVector
G4double kCarTolerance
Definition G4VSolid.hh:299

Referenced by SurfaceNormal().

◆ GetCosEndPhi()

G4double G4Torus::GetCosEndPhi ( ) const
inline

Referenced by BoundingLimits(), and CalculateExtent().

◆ GetCosStartPhi()

G4double G4Torus::GetCosStartPhi ( ) const
inline

Referenced by BoundingLimits(), and CalculateExtent().

◆ GetCubicVolume()

G4double G4Torus::GetCubicVolume ( )
inlineoverridevirtual

Reimplemented from G4VSolid.

◆ GetDPhi()

◆ GetEntityType()

G4GeometryType G4Torus::GetEntityType ( ) const
overridevirtual

Implements G4VSolid.

Definition at line 1544 of file G4Torus.cc.

1545{
1546 return {"G4Torus"};
1547}

◆ GetPointOnSurface()

G4ThreeVector G4Torus::GetPointOnSurface ( ) const
overridevirtual

Reimplemented from G4VSolid.

Definition at line 1585 of file G4Torus.cc.

1586{
1587 G4double cosu, sinu,cosv, sinv, aOut, aIn, aSide, chose, phi, theta, rRand;
1588
1589 phi = G4RandFlat::shoot(fSPhi,fSPhi+fDPhi);
1590 theta = G4RandFlat::shoot(0.,twopi);
1591
1592 cosu = std::cos(phi); sinu = std::sin(phi);
1593 cosv = std::cos(theta); sinv = std::sin(theta);
1594
1595 // compute the areas
1596
1597 aOut = (fDPhi)*twopi*fRtor*fRmax;
1598 aIn = (fDPhi)*twopi*fRtor*fRmin;
1599 aSide = pi*(fRmax*fRmax-fRmin*fRmin);
1600
1601 if ((fSPhi == 0) && (fDPhi == twopi)){ aSide = 0; }
1602 chose = G4RandFlat::shoot(0.,aOut + aIn + 2.*aSide);
1603
1604 if(chose < aOut)
1605 {
1606 return { (fRtor+fRmax*cosv)*cosu, (fRtor+fRmax*cosv)*sinu, fRmax*sinv };
1607 }
1608 else if( (chose >= aOut) && (chose < aOut + aIn) )
1609 {
1610 return { (fRtor+fRmin*cosv)*cosu, (fRtor+fRmin*cosv)*sinu, fRmin*sinv };
1611 }
1612 else if( (chose >= aOut + aIn) && (chose < aOut + aIn + aSide) )
1613 {
1614 rRand = GetRadiusInRing(fRmin,fRmax);
1615 return { (fRtor+rRand*cosv)*std::cos(fSPhi),
1616 (fRtor+rRand*cosv)*std::sin(fSPhi), rRand*sinv };
1617 }
1618 else
1619 {
1620 rRand = GetRadiusInRing(fRmin,fRmax);
1621 return { (fRtor+rRand*cosv)*std::cos(fSPhi+fDPhi),
1622 (fRtor+rRand*cosv)*std::sin(fSPhi+fDPhi), rRand*sinv };
1623 }
1624}
G4double GetRadiusInRing(G4double rmin, G4double rmax) const

◆ GetRmax()

◆ GetRmin()

◆ GetRtor()

◆ GetSinEndPhi()

G4double G4Torus::GetSinEndPhi ( ) const
inline

Referenced by BoundingLimits(), and CalculateExtent().

◆ GetSinStartPhi()

G4double G4Torus::GetSinStartPhi ( ) const
inline

Referenced by BoundingLimits(), and CalculateExtent().

◆ GetSPhi()

◆ GetSurfaceArea()

G4double G4Torus::GetSurfaceArea ( )
inlineoverridevirtual

Reimplemented from G4VSolid.

◆ Inside()

EInside G4Torus::Inside ( const G4ThreeVector & p) const
overridevirtual

Implements G4VSolid.

Definition at line 566 of file G4Torus.cc.

567{
568 G4double r, pt2, pPhi, tolRMin, tolRMax ;
569
570 EInside in = kOutside ;
571
572 // General precals
573 //
574 r = std::hypot(p.x(),p.y());
575 pt2 = p.z()*p.z() + (r-fRtor)*(r-fRtor);
576
577 if (fRmin != 0.0) tolRMin = fRmin + fRminTolerance ;
578 else tolRMin = 0 ;
579
580 tolRMax = fRmax - fRmaxTolerance;
581
582 if (pt2 >= tolRMin*tolRMin && pt2 <= tolRMax*tolRMax )
583 {
584 if ( fDPhi == twopi || pt2 == 0 ) // on torus swept axis
585 {
586 in = kInside ;
587 }
588 else
589 {
590 // Try inner tolerant phi boundaries (=>inside)
591 // if not inside, try outer tolerant phi boundaries
592
593 pPhi = std::atan2(p.y(),p.x()) ;
594
595 if ( pPhi < -halfAngTolerance ) { pPhi += twopi ; } // 0<=pPhi<2pi
596 if ( fSPhi >= 0 )
597 {
598 if ( (std::fabs(pPhi) < halfAngTolerance)
599 && (std::fabs(fSPhi + fDPhi - twopi) < halfAngTolerance) )
600 {
601 pPhi += twopi ; // 0 <= pPhi < 2pi
602 }
603 if ( (pPhi >= fSPhi + halfAngTolerance)
604 && (pPhi <= fSPhi + fDPhi - halfAngTolerance) )
605 {
606 in = kInside ;
607 }
608 else if ( (pPhi >= fSPhi - halfAngTolerance)
609 && (pPhi <= fSPhi + fDPhi + halfAngTolerance) )
610 {
611 in = kSurface ;
612 }
613 }
614 else // fSPhi < 0
615 {
616 if ( (pPhi <= fSPhi + twopi - halfAngTolerance)
617 && (pPhi >= fSPhi + fDPhi + halfAngTolerance) ) {;}
618 else
619 {
620 in = kSurface ;
621 }
622 }
623 }
624 }
625 else // Try generous boundaries
626 {
627 tolRMin = fRmin - fRminTolerance ;
628 tolRMax = fRmax + fRmaxTolerance ;
629
630 if (tolRMin < 0 ) { tolRMin = 0 ; }
631
632 if ( (pt2 >= tolRMin*tolRMin) && (pt2 <= tolRMax*tolRMax) )
633 {
634 if ( (fDPhi == twopi) || (pt2 == 0) ) // Continuous in phi or on z-axis
635 {
636 in = kSurface ;
637 }
638 else // Try outer tolerant phi boundaries only
639 {
640 pPhi = std::atan2(p.y(),p.x()) ;
641
642 if ( pPhi < -halfAngTolerance ) { pPhi += twopi ; } // 0<=pPhi<2pi
643 if ( fSPhi >= 0 )
644 {
645 if ( (std::fabs(pPhi) < halfAngTolerance)
646 && (std::fabs(fSPhi + fDPhi - twopi) < halfAngTolerance) )
647 {
648 pPhi += twopi ; // 0 <= pPhi < 2pi
649 }
650 if ( (pPhi >= fSPhi - halfAngTolerance)
651 && (pPhi <= fSPhi + fDPhi + halfAngTolerance) )
652 {
653 in = kSurface;
654 }
655 }
656 else // fSPhi < 0
657 {
658 if ( (pPhi <= fSPhi + twopi - halfAngTolerance)
659 && (pPhi >= fSPhi + fDPhi + halfAngTolerance) ) {;}
660 else
661 {
662 in = kSurface ;
663 }
664 }
665 }
666 }
667 }
668 return in ;
669}
EInside
Definition geomdefs.hh:67
@ kInside
Definition geomdefs.hh:70
@ kSurface
Definition geomdefs.hh:69

Referenced by DistanceToOut(), and SurfaceNormal().

◆ operator=()

G4Torus & G4Torus::operator= ( const G4Torus & rhs)

Definition at line 187 of file G4Torus.cc.

188{
189 // Check assignment to self
190 //
191 if (this == &rhs) { return *this; }
192
193 // Copy base class data
194 //
196
197 // Copy data
198 //
199 fRmin = rhs.fRmin; fRmax = rhs.fRmax;
200 fRtor = rhs.fRtor; fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
201 fRminTolerance = rhs.fRminTolerance; fRmaxTolerance = rhs.fRmaxTolerance;
202 kRadTolerance = rhs.kRadTolerance; kAngTolerance = rhs.kAngTolerance;
203 halfCarTolerance = rhs.halfCarTolerance;
204 halfAngTolerance = rhs.halfAngTolerance;
205
206 return *this;
207}
G4CSGSolid & operator=(const G4CSGSolid &rhs)
Definition G4CSGSolid.cc:89

◆ SetAllParameters()

void G4Torus::SetAllParameters ( G4double pRmin,
G4double pRmax,
G4double pRtor,
G4double pSPhi,
G4double pDPhi )

Definition at line 81 of file G4Torus.cc.

86{
87 const G4double fEpsilon = 4.e-11; // relative tolerance of radii
88
89 fCubicVolume = 0.;
90 fSurfaceArea = 0.;
91 fRebuildPolyhedron = true;
92
95
96 halfCarTolerance = 0.5*kCarTolerance;
97 halfAngTolerance = 0.5*kAngTolerance;
98
99 if ( pRtor >= pRmax+1.e3*kCarTolerance ) // Check swept radius, as in G4Cons
100 {
101 fRtor = pRtor ;
102 }
103 else
104 {
105 std::ostringstream message;
106 message << "Invalid swept radius for Solid: " << GetName() << G4endl
107 << " pRtor = " << pRtor << ", pRmax = " << pRmax;
108 G4Exception("G4Torus::SetAllParameters()",
109 "GeomSolids0002", FatalException, message);
110 }
111
112 // Check radii, as in G4Cons
113 //
114 if ( pRmin < pRmax - 1.e2*kCarTolerance && pRmin >= 0 )
115 {
116 if (pRmin >= 1.e2*kCarTolerance) { fRmin = pRmin ; }
117 else { fRmin = 0.0 ; }
118 fRmax = pRmax ;
119 }
120 else
121 {
122 std::ostringstream message;
123 message << "Invalid values of radii for Solid: " << GetName() << G4endl
124 << " pRmin = " << pRmin << ", pRmax = " << pRmax;
125 G4Exception("G4Torus::SetAllParameters()",
126 "GeomSolids0002", FatalException, message);
127 }
128
129 // Relative tolerances
130 //
131 fRminTolerance = (fRmin) != 0.0
132 ? 0.5*std::max( kRadTolerance, fEpsilon*(fRtor-fRmin )) : 0;
133 fRmaxTolerance = 0.5*std::max( kRadTolerance, fEpsilon*(fRtor+fRmax) );
134
135 // Check angles
136 //
137 if ( pDPhi >= twopi ) { fDPhi = twopi ; }
138 else
139 {
140 if (pDPhi > 0) { fDPhi = pDPhi ; }
141 else
142 {
143 std::ostringstream message;
144 message << "Invalid Z delta-Phi for Solid: " << GetName() << G4endl
145 << " pDPhi = " << pDPhi;
146 G4Exception("G4Torus::SetAllParameters()",
147 "GeomSolids0002", FatalException, message);
148 }
149 }
150
151 // Ensure psphi in 0-2PI or -2PI-0 range if shape crosses 0
152 //
153 fSPhi = pSPhi;
154
155 if (fSPhi < 0) { fSPhi = twopi-std::fmod(std::fabs(fSPhi),twopi) ; }
156 else { fSPhi = std::fmod(fSPhi,twopi) ; }
157
158 if (fSPhi+fDPhi > twopi) { fSPhi-=twopi ; }
159}
@ FatalException
G4double fSurfaceArea
Definition G4CSGSolid.hh:69
G4double fCubicVolume
Definition G4CSGSolid.hh:68
G4bool fRebuildPolyhedron
Definition G4CSGSolid.hh:70
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const

Referenced by G4Torus().

◆ StreamInfo()

std::ostream & G4Torus::StreamInfo ( std::ostream & os) const
overridevirtual

Reimplemented from G4CSGSolid.

Definition at line 1562 of file G4Torus.cc.

1563{
1564 G4long oldprc = os.precision(16);
1565 os << "-----------------------------------------------------------\n"
1566 << " *** Dump for solid - " << GetName() << " ***\n"
1567 << " ===================================================\n"
1568 << " Solid type: G4Torus\n"
1569 << " Parameters: \n"
1570 << " inner radius: " << fRmin/mm << " mm \n"
1571 << " outer radius: " << fRmax/mm << " mm \n"
1572 << " swept radius: " << fRtor/mm << " mm \n"
1573 << " starting phi: " << fSPhi/degree << " degrees \n"
1574 << " delta phi : " << fDPhi/degree << " degrees \n"
1575 << "-----------------------------------------------------------\n";
1576 os.precision(oldprc);
1577
1578 return os;
1579}

◆ SurfaceNormal()

G4ThreeVector G4Torus::SurfaceNormal ( const G4ThreeVector & p) const
overridevirtual

Implements G4VSolid.

Definition at line 677 of file G4Torus.cc.

678{
679 G4int noSurfaces = 0;
680 G4double rho, pt, pPhi;
681 G4double distRMin = kInfinity;
682 G4double distSPhi = kInfinity, distEPhi = kInfinity;
683
684 // To cope with precision loss
685 //
686 const G4double delta = std::max(10.0*kCarTolerance,
687 1.0e-8*(fRtor+fRmax));
688 const G4double dAngle = 10.0*kAngTolerance;
689
690 G4ThreeVector nR, nPs, nPe;
691 G4ThreeVector norm, sumnorm(0.,0.,0.);
692
693 rho = std::hypot(p.x(),p.y());
694 pt = std::hypot(p.z(),rho-fRtor);
695
696 G4double distRMax = std::fabs(pt - fRmax);
697 if(fRmin != 0.0) distRMin = std::fabs(pt - fRmin);
698
699 if( rho > delta && pt != 0.0 )
700 {
701 G4double redFactor= (rho-fRtor)/rho;
702 nR = G4ThreeVector( p.x()*redFactor, // p.x()*(1.-fRtor/rho),
703 p.y()*redFactor, // p.y()*(1.-fRtor/rho),
704 p.z() );
705 nR *= 1.0/pt;
706 }
707
708 if ( fDPhi < twopi ) // && rho ) // old limitation against (0,0,z)
709 {
710 if ( rho != 0.0 )
711 {
712 pPhi = std::atan2(p.y(),p.x());
713
714 if(pPhi < fSPhi-delta) { pPhi += twopi; }
715 else if(pPhi > fSPhi+fDPhi+delta) { pPhi -= twopi; }
716
717 distSPhi = std::fabs( pPhi - fSPhi );
718 distEPhi = std::fabs(pPhi-fSPhi-fDPhi);
719 }
720 nPs = G4ThreeVector(std::sin(fSPhi),-std::cos(fSPhi),0);
721 nPe = G4ThreeVector(-std::sin(fSPhi+fDPhi),std::cos(fSPhi+fDPhi),0);
722 }
723 if( distRMax <= delta )
724 {
725 ++noSurfaces;
726 sumnorm += nR;
727 }
728 else if( (fRmin != 0.0) && (distRMin <= delta) ) // Must not be on both Outer and Inner
729 {
730 ++noSurfaces;
731 sumnorm -= nR;
732 }
733
734 // To be on one of the 'phi' surfaces,
735 // it must be within the 'tube' - with tolerance
736
737 if( (fDPhi < twopi) && (fRmin-delta <= pt) && (pt <= (fRmax+delta)) )
738 {
739 if (distSPhi <= dAngle)
740 {
741 ++noSurfaces;
742 sumnorm += nPs;
743 }
744 if (distEPhi <= dAngle)
745 {
746 ++noSurfaces;
747 sumnorm += nPe;
748 }
749 }
750 if ( noSurfaces == 0 )
751 {
752#ifdef G4CSGDEBUG
754 ed.precision(16);
755
756 EInside inIt= Inside( p );
757
758 if( inIt != kSurface )
759 {
760 ed << " ERROR> Surface Normal was called for Torus,"
761 << " with point not on surface." << G4endl;
762 }
763 else
764 {
765 ed << " ERROR> Surface Normal has not found a surface, "
766 << " despite the point being on the surface. " <<G4endl;
767 }
768
769 if( inIt != kInside)
770 {
771 ed << " Safety (Dist To In) = " << DistanceToIn(p) << G4endl;
772 }
773 if( inIt != kOutside)
774 {
775 ed << " Safety (Dist to Out) = " << DistanceToOut(p) << G4endl;
776 }
777 ed << " Coordinates of point : " << p << G4endl;
778 ed << " Parameters of solid : " << G4endl << *this << G4endl;
779
780 if( inIt == kSurface )
781 {
782 G4Exception("G4Torus::SurfaceNormal(p)", "GeomSolids1002",
783 JustWarning, ed,
784 "Failing to find normal, even though point is on surface!");
785 }
786 else
787 {
788 static const char* NameInside[3]= { "Inside", "Surface", "Outside" };
789 ed << " The point is " << NameInside[inIt] << " the solid. "<< G4endl;
790 G4Exception("G4Torus::SurfaceNormal(p)", "GeomSolids1002",
791 JustWarning, ed, "Point p is not on surface !?" );
792 }
793#endif
794 norm = ApproxSurfaceNormal(p);
795 }
796 else if ( noSurfaces == 1 ) { norm = sumnorm; }
797 else { norm = sumnorm.unit(); }
798
799 return norm ;
800}
std::ostringstream G4ExceptionDescription
Hep3Vector unit() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
Definition G4Torus.cc:1137

The documentation for this class was generated from the following files: