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

G4Torus represents a torus or torus segment with curved sides parallel to the z-axis. The torus has a specified swept radius about which it is centered, and a given minimum and maximum radius. A minimum radius of 0 signifies a filled torus. The torus segment is specified by starting and delta angles for phi, with 0 being the +x axis, PI/2 the +y axis. A delta angle of 2PI signifies a complete, unsegmented torus/cylinder. More...

#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=default
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
void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) 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
EInside Inside (const G4ThreeVector &p) const 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)=default
G4Torusoperator= (const G4Torus &rhs)
Public Member Functions inherited from G4CSGSolid
 G4CSGSolid (const G4String &pName)
 ~G4CSGSolid () override
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 ()
 G4VSolid (const G4VSolid &rhs)
G4VSolidoperator= (const G4VSolid &rhs)
G4bool operator== (const G4VSolid &s) const
G4String GetName () const
void SetName (const G4String &name)
G4double GetTolerance () const
virtual G4int GetNumOfConstituents () const
virtual G4bool IsFaceted () 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__ &)
G4double EstimateCubicVolume (G4int nStat, G4double epsilon) const
G4double EstimateSurfaceArea (G4int nStat, G4double epsilon) 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

G4Torus represents a torus or torus segment with curved sides parallel to the z-axis. The torus has a specified swept radius about which it is centered, and a given minimum and maximum radius. A minimum radius of 0 signifies a filled torus. The torus segment is specified by starting and delta angles for phi, with 0 being the +x axis, PI/2 the +y axis. A delta angle of 2PI signifies a complete, unsegmented torus/cylinder.

Definition at line 101 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 )

Constructs a torus or torus segment with the given name and dimensions.

Parameters
[in]pNameThe name of the solid.
[in]pRminInner radius.
[in]pRmaxOuter radius.
[in]pRtorSwept radius of torus.
[in]pSPhiStarting Phi angle in radians adjusted such that fSPhi+fDPhi<=2PI, fSPhi>-2PI.
[in]pDPhiDelta angle of the segment in radians.

Definition at line 78 of file G4Torus.cc.

84 : G4CSGSolid(pName)
85{
86 SetAllParameters(pRmin, pRmax, pRtor, pSPhi, pDPhi);
87}
G4CSGSolid(const G4String &pName)
Definition G4CSGSolid.cc:49
void SetAllParameters(G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
Definition G4Torus.cc:94

Referenced by Clone(), G4Torus(), and operator=().

◆ ~G4Torus()

G4Torus::~G4Torus ( )
overridedefault

Default destructor.

◆ G4Torus() [2/3]

G4Torus::G4Torus ( __void__ & a)

Fake default constructor for usage restricted to direct object persistency for clients requiring preallocation of memory for persistifiable objects.

Definition at line 179 of file G4Torus.cc.

180 : G4CSGSolid(a)
181{
182}

◆ G4Torus() [3/3]

G4Torus::G4Torus ( const G4Torus & rhs)
default

Copy constructor and assignment operator.

Member Function Documentation

◆ BoundingLimits()

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

Computes the bounding limits of the solid.

Parameters
[out]pMinThe minimum bounding limit point.
[out]pMaxThe maximum bounding limit point.

Reimplemented from G4VSolid.

Definition at line 384 of file G4Torus.cc.

385{
386 G4double rmax = GetRmax();
387 G4double rtor = GetRtor();
388 G4double rint = rtor - rmax;
389 G4double rext = rtor + rmax;
390 G4double dz = rmax;
391
392 // Find bounding box
393 //
394 if (GetDPhi() >= twopi)
395 {
396 pMin.set(-rext,-rext,-dz);
397 pMax.set( rext, rext, dz);
398 }
399 else
400 {
401 G4TwoVector vmin,vmax;
402 G4GeomTools::DiskExtent(rint,rext,
405 vmin,vmax);
406 pMin.set(vmin.x(),vmin.y(),-dz);
407 pMax.set(vmax.x(),vmax.y(), dz);
408 }
409
410 // Check correctness of the bounding box
411 //
412 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
413 {
414 std::ostringstream message;
415 message << "Bad bounding box (min >= max) for solid: "
416 << GetName() << " !"
417 << "\npMin = " << pMin
418 << "\npMax = " << pMax;
419 G4Exception("G4Torus::BoundingLimits()", "GeomMgt0001",
420 JustWarning, message);
421 DumpInfo();
422 }
423}
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep2Vector G4TwoVector
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

Calculates the minimum and maximum extent of the solid, when under the specified transform, and within the specified limits.

Parameters
[in]pAxisThe axis along which compute the extent.
[in]pVoxelLimitThe limiting space dictated by voxels.
[in]pTransformThe internal transformation applied to the solid.
[out]pMinThe minimum extent value.
[out]pMaxThe maximum extent value.
Returns
True if the solid is intersected by the extent region.

Implements G4VSolid.

Definition at line 429 of file G4Torus.cc.

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

◆ Clone()

G4VSolid * G4Torus::Clone ( ) const
overridevirtual

Makes a clone of the object for use in multi-treading.

Returns
A pointer to the new cloned allocated solid.

Reimplemented from G4VSolid.

Definition at line 1556 of file G4Torus.cc.

1557{
1558 return new G4Torus(*this);
1559}
G4Torus(const G4String &pName, G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
Definition G4Torus.cc:78

◆ ComputeDimensions()

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

Dispatch method for parameterisation replication mechanism and dimension computation.

Reimplemented from G4VSolid.

Definition at line 215 of file G4Torus.cc.

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

◆ CreatePolyhedron()

G4Polyhedron * G4Torus::CreatePolyhedron ( ) const
overridevirtual

Creates a Polyhedron used for Visualisation. It is the caller's responsibility to delete it. A null pointer means "not created".

Reimplemented from G4VSolid.

Definition at line 1666 of file G4Torus.cc.

1667{
1668 return new G4PolyhedronTorus (fRmin, fRmax, fRtor, fSPhi, fDPhi);
1669}

◆ DescribeYourselfTo()

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

Methods for creating graphical representations (i.e. for visualisation).

Implements G4VSolid.

Definition at line 1661 of file G4Torus.cc.

1662{
1663 scene.AddSolid (*this);
1664}
virtual void AddSolid(const G4Box &)=0

◆ DistanceToIn() [1/2]

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

Calculates the distance to the nearest surface of a shape from an outside point. The distance can be an underestimate.

Parameters
[in]pThe point at offset p.
Returns
The safety distance to enter the shape.

Implements G4VSolid.

Definition at line 1095 of file G4Torus.cc.

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

◆ DistanceToIn() [2/2]

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

Returns the distance along the normalised vector 'v' to the shape, from the point at offset 'p'. If there is no intersection, returns kInfinity. The first intersection resulting from 'leaving' a surface/volume is discarded. Hence, it is tolerant of points on the surface of the shape.

Parameters
[in]pThe point at offset p.
[in]vThe normalised direction vector.
Returns
The distance to enter the shape.

Implements G4VSolid.

Definition at line 917 of file G4Torus.cc.

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

Referenced by DistanceToIn(), and SurfaceNormal().

◆ DistanceToOut() [1/2]

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

Calculates the distance to the nearest surface of a shape from an inside point 'p'. The distance can be an underestimate.

Parameters
[in]pThe point at offset p.
Returns
The safety distance to exit the shape.

Implements G4VSolid.

Definition at line 1482 of file G4Torus.cc.

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

Returns the distance along the normalised vector 'v' to the shape, from a point at an offset 'p' inside or on the surface of the shape. Intersections with surfaces, when the point is less than Tolerance/2 from a surface must be ignored.

Parameters
[in]pThe point at offset p.
[in]vThe normalised direction vector.
[in]calcNormFlag to indicate if to calculate the normal or not.
[out]validNormFlag set to true if the solid lies entirely behind or on the exiting surface. It is set false if the solid does not lie entirely behind or on the exiting surface. 'calcNorm' must be true, otherwise it is unused.
[out]nThe exiting outwards normal vector (undefined Magnitude). 'calcNorm' must be true, otherwise it is unused.
Returns
The distance to exit the shape.

Implements G4VSolid.

Definition at line 1140 of file G4Torus.cc.

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

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 ( )
overridevirtual

Returning an estimation of the solid volume (capacity) and surface area, in internal units.

Reimplemented from G4VSolid.

Definition at line 1627 of file G4Torus.cc.

1628{
1629 if (fCubicVolume == 0)
1630 {
1631 G4AutoLock l(&torusMutex);
1632 fCubicVolume = fDPhi*CLHEP::pi*fRtor*(fRmax*fRmax-fRmin*fRmin);
1633 l.unlock();
1634 }
1635 return fCubicVolume;
1636}
G4TemplateAutoLock< G4Mutex > G4AutoLock
G4double fCubicVolume
Definition G4CSGSolid.hh:92

◆ GetDPhi()

◆ GetEntityType()

G4GeometryType G4Torus::GetEntityType ( ) const
overridevirtual

Returns the type ID, "G4Torus" of the solid.

Implements G4VSolid.

Definition at line 1547 of file G4Torus.cc.

1548{
1549 return {"G4Torus"};
1550}

◆ GetPointOnSurface()

G4ThreeVector G4Torus::GetPointOnSurface ( ) const
overridevirtual

Returns a random point located and uniformly distributed on the surface of the solid.

Reimplemented from G4VSolid.

Definition at line 1588 of file G4Torus.cc.

1589{
1590 G4double rrmin = fRmin*fRmin;
1591 G4double rrmax = fRmax*fRmax;
1592 G4double smax = twopi*fRtor*fDPhi*fRmax;
1593 G4double smin = twopi*fRtor*fDPhi*fRmin;
1594 G4double sphi = (fDPhi >= twopi) ? 0. : pi*(rrmax - rrmin);
1595
1596 G4double u = G4QuickRand();
1597 G4double v = twopi*G4QuickRand();;
1598 G4double select = (smax + smin + 2.*sphi)*G4QuickRand();
1599 G4double phi, r, ds;
1600 if (select < 2.*sphi)
1601 {
1602 // phi cut
1603 phi = fSPhi + fDPhi*(G4double)(select < sphi);
1604 r = std::sqrt(rrmin + (rrmax - rrmin)*u);
1605 ds = fRtor + r*std::cos(v);
1606 }
1607 else
1608 {
1609 // toroidal surface (rejection sampling)
1610 phi = fSPhi + fDPhi*u;
1611 r = (select < 2.*sphi + smax) ? fRmax : fRmin;
1612 ds = fRtor + r*std::cos(v);
1613 for (auto i = 0; i < 10; ++i)
1614 {
1615 if ((fRtor + r)*G4QuickRand() < ds) { break; }
1616 v = twopi*G4QuickRand();
1617 ds = fRtor + r*std::cos(v);
1618 }
1619 }
1620 return { ds*std::cos(phi), ds*std::sin(phi), r*std::sin(v) };
1621}
G4double G4QuickRand(uint32_t seed=0)
const G4double pi

◆ 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 ( )
overridevirtual

Returns an estimation of the solid surface area in internal units. This method may be overloaded by derived classes to compute the exact geometrical quantity for solids where this is possible, or anyway to cache the computed value. Note: the computed value is NOT cached.

Reimplemented from G4VSolid.

Definition at line 1642 of file G4Torus.cc.

1643{
1644 if (fSurfaceArea == 0)
1645 {
1646 G4AutoLock l(&torusMutex);
1647 fSurfaceArea = fDPhi*CLHEP::twopi*fRtor*(fRmax+fRmin);
1648 if(fDPhi < CLHEP::twopi)
1649 {
1650 fSurfaceArea = fSurfaceArea + CLHEP::twopi*(fRmax*fRmax-fRmin*fRmin);
1651 }
1652 l.unlock();
1653 }
1654 return fSurfaceArea;
1655}
G4double fSurfaceArea
Definition G4CSGSolid.hh:93

◆ Inside()

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

Concrete implementations of the expected query interfaces for solids, as defined in the base class G4VSolid.

Implements G4VSolid.

Definition at line 570 of file G4Torus.cc.

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

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

◆ SetAllParameters()

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

Checks and sets all the parameters given in input. Used in constructor.

Definition at line 94 of file G4Torus.cc.

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

Referenced by G4Torus().

◆ StreamInfo()

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

Streams the object contents to an output stream.

Reimplemented from G4CSGSolid.

Definition at line 1565 of file G4Torus.cc.

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

◆ SurfaceNormal()

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

Returns the outwards pointing unit normal of the shape for the surface closest to the point at offset 'p'.

Parameters
[in]pThe point at offset p.
Returns
The outwards pointing unit normal.

Implements G4VSolid.

Definition at line 680 of file G4Torus.cc.

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

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