Geant4 9.6.0
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 ()
 
G4double GetRmin () const
 
G4double GetRmax () const
 
G4double GetRtor () const
 
G4double GetSPhi () const
 
G4double GetDPhi () const
 
G4double GetCubicVolume ()
 
G4double GetSurfaceArea ()
 
EInside Inside (const G4ThreeVector &p) const
 
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
 
void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
 
G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const
 
G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const
 
G4double DistanceToIn (const G4ThreeVector &p) const
 
G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
 
G4double DistanceToOut (const G4ThreeVector &p) const
 
G4GeometryType GetEntityType () const
 
G4ThreeVector GetPointOnSurface () const
 
G4VSolidClone () const
 
std::ostream & StreamInfo (std::ostream &os) const
 
void DescribeYourselfTo (G4VGraphicsScene &scene) const
 
G4PolyhedronCreatePolyhedron () const
 
G4NURBSCreateNURBS () const
 
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 ()
 
virtual std::ostream & StreamInfo (std::ostream &os) const
 
virtual G4PolyhedronGetPolyhedron () const
 
 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
 
virtual G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const =0
 
virtual EInside Inside (const G4ThreeVector &p) const =0
 
virtual G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const =0
 
virtual G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const =0
 
virtual G4double DistanceToIn (const G4ThreeVector &p) const =0
 
virtual G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
 
virtual G4double DistanceToOut (const G4ThreeVector &p) const =0
 
virtual void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
 
virtual G4double GetCubicVolume ()
 
virtual G4double GetSurfaceArea ()
 
virtual G4GeometryType GetEntityType () const =0
 
virtual G4ThreeVector GetPointOnSurface () const
 
virtual G4VSolidClone () const
 
virtual std::ostream & StreamInfo (std::ostream &os) const =0
 
void DumpInfo () const
 
virtual void DescribeYourselfTo (G4VGraphicsScene &scene) const =0
 
virtual G4VisExtent GetExtent () const
 
virtual G4PolyhedronCreatePolyhedron () const
 
virtual G4NURBSCreateNURBS () const
 
virtual G4PolyhedronGetPolyhedron () 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)
 

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
 
G4double EstimateCubicVolume (G4int nStat, G4double epsilon) const
 
G4double EstimateSurfaceArea (G4int nStat, G4double ell) const
 
- Protected Attributes inherited from G4CSGSolid
G4double fCubicVolume
 
G4double fSurfaceArea
 
G4PolyhedronfpPolyhedron
 
- Protected Attributes inherited from G4VSolid
G4double kCarTolerance
 

Detailed Description

Definition at line 102 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 84 of file G4Torus.cc.

90 : G4CSGSolid(pName)
91{
92 SetAllParameters(pRmin, pRmax, pRtor, pSPhi, pDPhi);
93}
void SetAllParameters(G4double pRmin, G4double pRmax, G4double pRtor, G4double pSPhi, G4double pDPhi)
Definition: G4Torus.cc:100

◆ ~G4Torus()

G4Torus::~G4Torus ( )

Definition at line 193 of file G4Torus.cc.

194{}

◆ G4Torus() [2/3]

G4Torus::G4Torus ( __void__ &  a)

Definition at line 182 of file G4Torus.cc.

183 : G4CSGSolid(a), fRmin(0.), fRmax(0.), fRtor(0.), fSPhi(0.),
184 fDPhi(0.), fRminTolerance(0.), fRmaxTolerance(0. ),
185 kRadTolerance(0.), kAngTolerance(0.)
186{
187}

◆ G4Torus() [3/3]

G4Torus::G4Torus ( const G4Torus rhs)

Definition at line 200 of file G4Torus.cc.

201 : G4CSGSolid(rhs), fRmin(rhs.fRmin),fRmax(rhs.fRmax),
202 fRtor(rhs.fRtor),fSPhi(rhs.fSPhi),fDPhi(rhs.fDPhi),
203 fRminTolerance(rhs.fRminTolerance), fRmaxTolerance(rhs.fRmaxTolerance),
204 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance)
205{
206}

Member Function Documentation

◆ CalculateExtent()

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

Implements G4VSolid.

Definition at line 412 of file G4Torus.cc.

416{
417 if ((!pTransform.IsRotated()) && (fDPhi==twopi) && (fRmin==0))
418 {
419 // Special case handling for unrotated solid torus
420 // Compute x/y/z mins and maxs for bounding box respecting limits,
421 // with early returns if outside limits. Then switch() on pAxis,
422 // and compute exact x and y limit for x/y case
423
424 G4double xoffset,xMin,xMax;
425 G4double yoffset,yMin,yMax;
426 G4double zoffset,zMin,zMax;
427
428 G4double RTorus,delta,diff1,diff2,maxDiff,newMin,newMax;
429 G4double xoff1,xoff2,yoff1,yoff2;
430
431 xoffset = pTransform.NetTranslation().x();
432 xMin = xoffset - fRmax - fRtor ;
433 xMax = xoffset + fRmax + fRtor ;
434
435 if (pVoxelLimit.IsXLimited())
436 {
437 if ( (xMin > pVoxelLimit.GetMaxXExtent()+kCarTolerance)
438 || (xMax < pVoxelLimit.GetMinXExtent()-kCarTolerance) )
439 return false ;
440 else
441 {
442 if (xMin < pVoxelLimit.GetMinXExtent())
443 {
444 xMin = pVoxelLimit.GetMinXExtent() ;
445 }
446 if (xMax > pVoxelLimit.GetMaxXExtent())
447 {
448 xMax = pVoxelLimit.GetMaxXExtent() ;
449 }
450 }
451 }
452 yoffset = pTransform.NetTranslation().y();
453 yMin = yoffset - fRmax - fRtor ;
454 yMax = yoffset + fRmax + fRtor ;
455
456 if (pVoxelLimit.IsYLimited())
457 {
458 if ( (yMin > pVoxelLimit.GetMaxYExtent()+kCarTolerance)
459 || (yMax < pVoxelLimit.GetMinYExtent()-kCarTolerance) )
460 {
461 return false ;
462 }
463 else
464 {
465 if (yMin < pVoxelLimit.GetMinYExtent() )
466 {
467 yMin = pVoxelLimit.GetMinYExtent() ;
468 }
469 if (yMax > pVoxelLimit.GetMaxYExtent() )
470 {
471 yMax = pVoxelLimit.GetMaxYExtent() ;
472 }
473 }
474 }
475 zoffset = pTransform.NetTranslation().z() ;
476 zMin = zoffset - fRmax ;
477 zMax = zoffset + fRmax ;
478
479 if (pVoxelLimit.IsZLimited())
480 {
481 if ( (zMin > pVoxelLimit.GetMaxZExtent()+kCarTolerance)
482 || (zMax < pVoxelLimit.GetMinZExtent()-kCarTolerance) )
483 {
484 return false ;
485 }
486 else
487 {
488 if (zMin < pVoxelLimit.GetMinZExtent() )
489 {
490 zMin = pVoxelLimit.GetMinZExtent() ;
491 }
492 if (zMax > pVoxelLimit.GetMaxZExtent() )
493 {
494 zMax = pVoxelLimit.GetMaxZExtent() ;
495 }
496 }
497 }
498
499 // Known to cut cylinder
500
501 switch (pAxis)
502 {
503 case kXAxis:
504 yoff1=yoffset-yMin;
505 yoff2=yMax-yoffset;
506 if ( yoff1 >= 0 && yoff2 >= 0 )
507 {
508 // Y limits cross max/min x => no change
509 //
510 pMin = xMin ;
511 pMax = xMax ;
512 }
513 else
514 {
515 // Y limits don't cross max/min x => compute max delta x,
516 // hence new mins/maxs
517 //
518
519 RTorus=fRmax+fRtor;
520 delta = RTorus*RTorus - yoff1*yoff1;
521 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
522 delta = RTorus*RTorus - yoff2*yoff2;
523 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
524 maxDiff = (diff1 > diff2) ? diff1:diff2 ;
525 newMin = xoffset - maxDiff ;
526 newMax = xoffset + maxDiff ;
527 pMin = (newMin < xMin) ? xMin : newMin ;
528 pMax = (newMax > xMax) ? xMax : newMax ;
529 }
530 break;
531
532 case kYAxis:
533 xoff1 = xoffset - xMin ;
534 xoff2 = xMax - xoffset ;
535 if (xoff1 >= 0 && xoff2 >= 0 )
536 {
537 // X limits cross max/min y => no change
538 //
539 pMin = yMin ;
540 pMax = yMax ;
541 }
542 else
543 {
544 // X limits don't cross max/min y => compute max delta y,
545 // hence new mins/maxs
546 //
547 RTorus=fRmax+fRtor;
548 delta = RTorus*RTorus - xoff1*xoff1;
549 diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
550 delta = RTorus*RTorus - xoff2*xoff2;
551 diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
552 maxDiff = (diff1 > diff2) ? diff1 : diff2 ;
553 newMin = yoffset - maxDiff ;
554 newMax = yoffset + maxDiff ;
555 pMin = (newMin < yMin) ? yMin : newMin ;
556 pMax = (newMax > yMax) ? yMax : newMax ;
557 }
558 break;
559
560 case kZAxis:
561 pMin=zMin;
562 pMax=zMax;
563 break;
564
565 default:
566 break;
567 }
568 pMin -= kCarTolerance ;
569 pMax += kCarTolerance ;
570
571 return true;
572 }
573 else
574 {
575 G4int i, noEntries, noBetweenSections4 ;
576 G4bool existsAfterClip = false ;
577
578 // Calculate rotated vertex coordinates
579
580 G4ThreeVectorList *vertices ;
581 G4int noPolygonVertices ; // will be 4
582 vertices = CreateRotatedVertices(pTransform,noPolygonVertices) ;
583
584 pMin = +kInfinity ;
585 pMax = -kInfinity ;
586
587 noEntries = vertices->size() ;
588 noBetweenSections4 = noEntries - noPolygonVertices ;
589
590 for (i=0;i<noEntries;i+=noPolygonVertices)
591 {
592 ClipCrossSection(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
593 }
594 for (i=0;i<noBetweenSections4;i+=noPolygonVertices)
595 {
596 ClipBetweenSections(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
597 }
598 if (pMin!=kInfinity||pMax!=-kInfinity)
599 {
600 existsAfterClip = true ; // Add 2*tolerance to avoid precision troubles
601 pMin -= kCarTolerance ;
602 pMax += kCarTolerance ;
603 }
604 else
605 {
606 // Check for case where completely enveloping clipping volume
607 // If point inside then we are confident that the solid completely
608 // envelopes the clipping volume. Hence set min/max extents according
609 // to clipping volume extents along the specified axis.
610
611 G4ThreeVector clipCentre(
612 (pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
613 (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
614 (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5 ) ;
615
616 if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside )
617 {
618 existsAfterClip = true ;
619 pMin = pVoxelLimit.GetMinExtent(pAxis) ;
620 pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
621 }
622 }
623 delete vertices;
624 return existsAfterClip;
625 }
626}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
std::vector< G4ThreeVector > G4ThreeVectorList
Definition: G4VSolid.hh:85
double z() const
double x() const
double y() const
G4bool IsRotated() const
G4AffineTransform Inverse() const
G4ThreeVector NetTranslation() const
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
EInside Inside(const G4ThreeVector &p) const
Definition: G4Torus.cc:632
void ClipBetweenSections(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
Definition: G4VSolid.cc:376
G4double kCarTolerance
Definition: G4VSolid.hh:307
void ClipCrossSection(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
Definition: G4VSolid.cc:345
G4double GetMinExtent(const EAxis pAxis) const
G4bool IsYLimited() const
G4double GetMinZExtent() const
G4bool IsXLimited() const
G4double GetMaxExtent(const EAxis pAxis) const
G4double GetMaxYExtent() const
G4double GetMaxZExtent() const
G4double GetMinYExtent() const
G4double GetMinXExtent() const
G4bool IsZLimited() const
G4double GetMaxXExtent() const
@ kYAxis
Definition: geomdefs.hh:54
@ kXAxis
Definition: geomdefs.hh:54
@ kZAxis
Definition: geomdefs.hh:54
@ kOutside
Definition: geomdefs.hh:58

◆ Clone()

G4VSolid * G4Torus::Clone ( ) const
virtual

Reimplemented from G4VSolid.

Definition at line 1703 of file G4Torus.cc.

1704{
1705 return new G4Torus(*this);
1706}

◆ ComputeDimensions()

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

Reimplemented from G4VSolid.

Definition at line 237 of file G4Torus.cc.

240{
241 p->ComputeDimensions(*this,n,pRep);
242}
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const

◆ CreateNURBS()

G4NURBS * G4Torus::CreateNURBS ( ) const
virtual

Reimplemented from G4VSolid.

Definition at line 1793 of file G4Torus.cc.

1794{
1795 G4NURBS* pNURBS;
1796 if (fRmin != 0)
1797 {
1798 if (fDPhi >= twopi)
1799 {
1800 pNURBS = new G4NURBStube(fRmin, fRmax, fRtor);
1801 }
1802 else
1803 {
1804 pNURBS = new G4NURBStubesector(fRmin, fRmax, fRtor, fSPhi, fSPhi + fDPhi);
1805 }
1806 }
1807 else
1808 {
1809 if (fDPhi >= twopi)
1810 {
1811 pNURBS = new G4NURBScylinder (fRmax, fRtor);
1812 }
1813 else
1814 {
1815 const G4double epsilon = 1.e-4; // Cylinder sector not yet available!
1816 pNURBS = new G4NURBStubesector (epsilon, fRmax, fRtor,
1817 fSPhi, fSPhi + fDPhi);
1818 }
1819 }
1820 return pNURBS;
1821}

◆ CreatePolyhedron()

G4Polyhedron * G4Torus::CreatePolyhedron ( ) const
virtual

Reimplemented from G4VSolid.

Definition at line 1788 of file G4Torus.cc.

1789{
1790 return new G4PolyhedronTorus (fRmin, fRmax, fRtor, fSPhi, fDPhi);
1791}

◆ DescribeYourselfTo()

void G4Torus::DescribeYourselfTo ( G4VGraphicsScene scene) const
virtual

Implements G4VSolid.

Definition at line 1783 of file G4Torus.cc.

1784{
1785 scene.AddSolid (*this);
1786}
virtual void AddSolid(const G4Box &)=0

◆ DistanceToIn() [1/2]

G4double G4Torus::DistanceToIn ( const G4ThreeVector p) const
virtual

Implements G4VSolid.

Definition at line 1139 of file G4Torus.cc.

1140{
1141 G4double safe=0.0, safe1, safe2 ;
1142 G4double phiC, cosPhiC, sinPhiC, safePhi, ePhi, cosPsi ;
1143 G4double rho2, rho, pt2, pt ;
1144
1145 rho2 = p.x()*p.x() + p.y()*p.y() ;
1146 rho = std::sqrt(rho2) ;
1147 pt2 = std::fabs(rho2 + p.z()*p.z() + fRtor*fRtor - 2*fRtor*rho) ;
1148 pt = std::sqrt(pt2) ;
1149
1150 safe1 = fRmin - pt ;
1151 safe2 = pt - fRmax ;
1152
1153 if (safe1 > safe2) { safe = safe1; }
1154 else { safe = safe2; }
1155
1156 if ( fDPhi < twopi && rho )
1157 {
1158 phiC = fSPhi + fDPhi*0.5 ;
1159 cosPhiC = std::cos(phiC) ;
1160 sinPhiC = std::sin(phiC) ;
1161 cosPsi = (p.x()*cosPhiC + p.y()*sinPhiC)/rho ;
1162
1163 if (cosPsi < std::cos(fDPhi*0.5) ) // Psi=angle from central phi to point
1164 { // Point lies outside phi range
1165 if ((p.y()*cosPhiC - p.x()*sinPhiC) <= 0 )
1166 {
1167 safePhi = std::fabs(p.x()*std::sin(fSPhi) - p.y()*std::cos(fSPhi)) ;
1168 }
1169 else
1170 {
1171 ePhi = fSPhi + fDPhi ;
1172 safePhi = std::fabs(p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1173 }
1174 if (safePhi > safe) { safe = safePhi ; }
1175 }
1176 }
1177 if (safe < 0 ) { safe = 0 ; }
1178 return safe;
1179}

◆ DistanceToIn() [2/2]

G4double G4Torus::DistanceToIn ( const G4ThreeVector p,
const G4ThreeVector v 
) const
virtual

Implements G4VSolid.

Definition at line 987 of file G4Torus.cc.

989{
990
991 G4double snxt=kInfinity, sphi=kInfinity; // snxt = default return value
992
993 G4double sd[4] ;
994
995 // Precalculated trig for phi intersections - used by r,z intersections to
996 // check validity
997
998 G4bool seg; // true if segmented
999 G4double hDPhi; // half dphi
1000 G4double cPhi,sinCPhi=0.,cosCPhi=0.; // central phi
1001
1002 G4double tolORMin2; // `generous' radii squared
1003 G4double tolORMax2;
1004
1005 static const G4double halfCarTolerance = 0.5*kCarTolerance;
1006
1007 G4double Dist,xi,yi,zi,rhoi2,it2; // Intersection point variables
1008
1009 G4double Comp;
1010 G4double cosSPhi,sinSPhi; // Trig for phi start intersect
1011 G4double ePhi,cosEPhi,sinEPhi; // for phi end intersect
1012
1013 // Set phi divided flag and precalcs
1014 //
1015 if ( fDPhi < twopi )
1016 {
1017 seg = true ;
1018 hDPhi = 0.5*fDPhi ; // half delta phi
1019 cPhi = fSPhi + hDPhi ;
1020 sinCPhi = std::sin(cPhi) ;
1021 cosCPhi = std::cos(cPhi) ;
1022 }
1023 else
1024 {
1025 seg = false ;
1026 }
1027
1028 if (fRmin > fRminTolerance) // Calculate tolerant rmin and rmax
1029 {
1030 tolORMin2 = (fRmin - fRminTolerance)*(fRmin - fRminTolerance) ;
1031 }
1032 else
1033 {
1034 tolORMin2 = 0 ;
1035 }
1036 tolORMax2 = (fRmax + fRmaxTolerance)*(fRmax + fRmaxTolerance) ;
1037
1038 // Intersection with Rmax (possible return) and Rmin (must also check phi)
1039
1040 G4double Rtor2 = fRtor*fRtor ;
1041
1042 snxt = SolveNumericJT(p,v,fRmax,true);
1043
1044 if (fRmin) // Possible Rmin intersection
1045 {
1046 sd[0] = SolveNumericJT(p,v,fRmin,true);
1047 if ( sd[0] < snxt ) { snxt = sd[0] ; }
1048 }
1049
1050 //
1051 // Phi segment intersection
1052 //
1053 // o Tolerant of points inside phi planes by up to kCarTolerance*0.5
1054 //
1055 // o NOTE: Large duplication of code between sphi & ephi checks
1056 // -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane
1057 // intersection check <=0 -> >=0
1058 // -> use some form of loop Construct ?
1059
1060 if (seg)
1061 {
1062 sinSPhi = std::sin(fSPhi) ; // First phi surface ('S'tarting phi)
1063 cosSPhi = std::cos(fSPhi) ;
1064 Comp = v.x()*sinSPhi - v.y()*cosSPhi ; // Component in outwards
1065 // normal direction
1066 if (Comp < 0 )
1067 {
1068 Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ;
1069
1070 if (Dist < halfCarTolerance)
1071 {
1072 sphi = Dist/Comp ;
1073 if (sphi < snxt)
1074 {
1075 if ( sphi < 0 ) { sphi = 0 ; }
1076
1077 xi = p.x() + sphi*v.x() ;
1078 yi = p.y() + sphi*v.y() ;
1079 zi = p.z() + sphi*v.z() ;
1080 rhoi2 = xi*xi + yi*yi ;
1081 it2 = std::fabs(rhoi2 + zi*zi + Rtor2 - 2*fRtor*std::sqrt(rhoi2)) ;
1082
1083 if ( it2 >= tolORMin2 && it2 <= tolORMax2 )
1084 {
1085 // r intersection is good - check intersecting
1086 // with correct half-plane
1087 //
1088 if ((yi*cosCPhi-xi*sinCPhi)<=0) { snxt=sphi; }
1089 }
1090 }
1091 }
1092 }
1093 ePhi=fSPhi+fDPhi; // Second phi surface ('E'nding phi)
1094 sinEPhi=std::sin(ePhi);
1095 cosEPhi=std::cos(ePhi);
1096 Comp=-(v.x()*sinEPhi-v.y()*cosEPhi);
1097
1098 if ( Comp < 0 ) // Component in outwards normal dirn
1099 {
1100 Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ;
1101
1102 if (Dist < halfCarTolerance )
1103 {
1104 sphi = Dist/Comp ;
1105
1106 if (sphi < snxt )
1107 {
1108 if (sphi < 0 ) { sphi = 0 ; }
1109
1110 xi = p.x() + sphi*v.x() ;
1111 yi = p.y() + sphi*v.y() ;
1112 zi = p.z() + sphi*v.z() ;
1113 rhoi2 = xi*xi + yi*yi ;
1114 it2 = std::fabs(rhoi2 + zi*zi + Rtor2 - 2*fRtor*std::sqrt(rhoi2)) ;
1115
1116 if (it2 >= tolORMin2 && it2 <= tolORMax2)
1117 {
1118 // z and r intersections good - check intersecting
1119 // with correct half-plane
1120 //
1121 if ((yi*cosCPhi-xi*sinCPhi)>=0) { snxt=sphi; }
1122 }
1123 }
1124 }
1125 }
1126 }
1127 if(snxt < halfCarTolerance) { snxt = 0.0 ; }
1128
1129 return snxt ;
1130}

Referenced by SurfaceNormal().

◆ DistanceToOut() [1/2]

G4double G4Torus::DistanceToOut ( const G4ThreeVector p) const
virtual

Implements G4VSolid.

Definition at line 1542 of file G4Torus.cc.

1543{
1544 G4double safe=0.0,safeR1,safeR2;
1545 G4double rho2,rho,pt2,pt ;
1546 G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi;
1547 rho2 = p.x()*p.x() + p.y()*p.y() ;
1548 rho = std::sqrt(rho2) ;
1549 pt2 = std::fabs(rho2 + p.z()*p.z() + fRtor*fRtor - 2*fRtor*rho) ;
1550 pt = std::sqrt(pt2) ;
1551
1552#ifdef G4CSGDEBUG
1553 if( Inside(p) == kOutside )
1554 {
1555 G4int oldprc = G4cout.precision(16) ;
1556 G4cout << G4endl ;
1557 DumpInfo();
1558 G4cout << "Position:" << G4endl << G4endl ;
1559 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ;
1560 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ;
1561 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ;
1562 G4cout.precision(oldprc);
1563 G4Exception("G4Torus::DistanceToOut(p)", "GeomSolids1002",
1564 JustWarning, "Point p is outside !?" );
1565 }
1566#endif
1567
1568 if (fRmin)
1569 {
1570 safeR1 = pt - fRmin ;
1571 safeR2 = fRmax - pt ;
1572
1573 if (safeR1 < safeR2) { safe = safeR1 ; }
1574 else { safe = safeR2 ; }
1575 }
1576 else
1577 {
1578 safe = fRmax - pt ;
1579 }
1580
1581 // Check if phi divided, Calc distances closest phi plane
1582 //
1583 if (fDPhi<twopi) // Above/below central phi of Torus?
1584 {
1585 phiC = fSPhi + fDPhi*0.5 ;
1586 cosPhiC = std::cos(phiC) ;
1587 sinPhiC = std::sin(phiC) ;
1588
1589 if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
1590 {
1591 safePhi = -(p.x()*std::sin(fSPhi) - p.y()*std::cos(fSPhi)) ;
1592 }
1593 else
1594 {
1595 ePhi = fSPhi + fDPhi ;
1596 safePhi = (p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1597 }
1598 if (safePhi < safe) { safe = safePhi ; }
1599 }
1600 if (safe < 0) { safe = 0 ; }
1601 return safe ;
1602}
@ JustWarning
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
void DumpInfo() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41

◆ DistanceToOut() [2/2]

G4double G4Torus::DistanceToOut ( const G4ThreeVector p,
const G4ThreeVector v,
const G4bool  calcNorm = G4bool(false),
G4bool validNorm = 0,
G4ThreeVector n = 0 
) const
virtual

Implements G4VSolid.

Definition at line 1187 of file G4Torus.cc.

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

Referenced by SurfaceNormal().

◆ GetCubicVolume()

G4double G4Torus::GetCubicVolume ( )
inlinevirtual

Reimplemented from G4VSolid.

◆ GetDPhi()

◆ GetEntityType()

G4GeometryType G4Torus::GetEntityType ( ) const
virtual

Implements G4VSolid.

Definition at line 1694 of file G4Torus.cc.

1695{
1696 return G4String("G4Torus");
1697}

◆ GetPointOnSurface()

G4ThreeVector G4Torus::GetPointOnSurface ( ) const
virtual

Reimplemented from G4VSolid.

Definition at line 1735 of file G4Torus.cc.

1736{
1737 G4double cosu, sinu,cosv, sinv, aOut, aIn, aSide, chose, phi, theta, rRand;
1738
1739 phi = RandFlat::shoot(fSPhi,fSPhi+fDPhi);
1740 theta = RandFlat::shoot(0.,twopi);
1741
1742 cosu = std::cos(phi); sinu = std::sin(phi);
1743 cosv = std::cos(theta); sinv = std::sin(theta);
1744
1745 // compute the areas
1746
1747 aOut = (fDPhi)*twopi*fRtor*fRmax;
1748 aIn = (fDPhi)*twopi*fRtor*fRmin;
1749 aSide = pi*(fRmax*fRmax-fRmin*fRmin);
1750
1751 if ((fSPhi == 0) && (fDPhi == twopi)){ aSide = 0; }
1752 chose = RandFlat::shoot(0.,aOut + aIn + 2.*aSide);
1753
1754 if(chose < aOut)
1755 {
1756 return G4ThreeVector ((fRtor+fRmax*cosv)*cosu,
1757 (fRtor+fRmax*cosv)*sinu, fRmax*sinv);
1758 }
1759 else if( (chose >= aOut) && (chose < aOut + aIn) )
1760 {
1761 return G4ThreeVector ((fRtor+fRmin*cosv)*cosu,
1762 (fRtor+fRmin*cosv)*sinu, fRmin*sinv);
1763 }
1764 else if( (chose >= aOut + aIn) && (chose < aOut + aIn + aSide) )
1765 {
1766 rRand = GetRadiusInRing(fRmin,fRmax);
1767 return G4ThreeVector ((fRtor+rRand*cosv)*std::cos(fSPhi),
1768 (fRtor+rRand*cosv)*std::sin(fSPhi), rRand*sinv);
1769 }
1770 else
1771 {
1772 rRand = GetRadiusInRing(fRmin,fRmax);
1773 return G4ThreeVector ((fRtor+rRand*cosv)*std::cos(fSPhi+fDPhi),
1774 (fRtor+rRand*cosv)*std::sin(fSPhi+fDPhi),
1775 rRand*sinv);
1776 }
1777}
static double shoot()
Definition: RandFlat.cc:59
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
Definition: G4CSGSolid.cc:101
const G4double pi

◆ GetRmax()

◆ GetRmin()

◆ GetRtor()

◆ GetSPhi()

◆ GetSurfaceArea()

G4double G4Torus::GetSurfaceArea ( )
inlinevirtual

Reimplemented from G4VSolid.

◆ Inside()

EInside G4Torus::Inside ( const G4ThreeVector p) const
virtual

Implements G4VSolid.

Definition at line 632 of file G4Torus.cc.

633{
634 G4double r2, pt2, pPhi, tolRMin, tolRMax ;
635
636 EInside in = kOutside ;
637 static const G4double halfAngTolerance = 0.5*kAngTolerance;
638
639 // General precals
640 r2 = p.x()*p.x() + p.y()*p.y() ;
641 pt2 = r2 + p.z()*p.z() + fRtor*fRtor - 2*fRtor*std::sqrt(r2) ;
642
643 if (fRmin) tolRMin = fRmin + fRminTolerance ;
644 else tolRMin = 0 ;
645
646 tolRMax = fRmax - fRmaxTolerance;
647
648 if (pt2 >= tolRMin*tolRMin && pt2 <= tolRMax*tolRMax )
649 {
650 if ( fDPhi == twopi || pt2 == 0 ) // on torus swept axis
651 {
652 in = kInside ;
653 }
654 else
655 {
656 // Try inner tolerant phi boundaries (=>inside)
657 // if not inside, try outer tolerant phi boundaries
658
659 pPhi = std::atan2(p.y(),p.x()) ;
660
661 if ( pPhi < -halfAngTolerance ) { pPhi += twopi ; } // 0<=pPhi<2pi
662 if ( fSPhi >= 0 )
663 {
664 if ( (std::fabs(pPhi) < halfAngTolerance)
665 && (std::fabs(fSPhi + fDPhi - twopi) < halfAngTolerance) )
666 {
667 pPhi += twopi ; // 0 <= pPhi < 2pi
668 }
669 if ( (pPhi >= fSPhi + halfAngTolerance)
670 && (pPhi <= fSPhi + fDPhi - halfAngTolerance) )
671 {
672 in = kInside ;
673 }
674 else if ( (pPhi >= fSPhi - halfAngTolerance)
675 && (pPhi <= fSPhi + fDPhi + halfAngTolerance) )
676 {
677 in = kSurface ;
678 }
679 }
680 else // fSPhi < 0
681 {
682 if ( (pPhi <= fSPhi + twopi - halfAngTolerance)
683 && (pPhi >= fSPhi + fDPhi + halfAngTolerance) ) {;}
684 else
685 {
686 in = kSurface ;
687 }
688 }
689 }
690 }
691 else // Try generous boundaries
692 {
693 tolRMin = fRmin - fRminTolerance ;
694 tolRMax = fRmax + fRmaxTolerance ;
695
696 if (tolRMin < 0 ) { tolRMin = 0 ; }
697
698 if ( (pt2 >= tolRMin*tolRMin) && (pt2 <= tolRMax*tolRMax) )
699 {
700 if ( (fDPhi == twopi) || (pt2 == 0) ) // Continuous in phi or on z-axis
701 {
702 in = kSurface ;
703 }
704 else // Try outer tolerant phi boundaries only
705 {
706 pPhi = std::atan2(p.y(),p.x()) ;
707
708 if ( pPhi < -halfAngTolerance ) { pPhi += twopi ; } // 0<=pPhi<2pi
709 if ( fSPhi >= 0 )
710 {
711 if ( (std::fabs(pPhi) < halfAngTolerance)
712 && (std::fabs(fSPhi + fDPhi - twopi) < halfAngTolerance) )
713 {
714 pPhi += twopi ; // 0 <= pPhi < 2pi
715 }
716 if ( (pPhi >= fSPhi - halfAngTolerance)
717 && (pPhi <= fSPhi + fDPhi + halfAngTolerance) )
718 {
719 in = kSurface;
720 }
721 }
722 else // fSPhi < 0
723 {
724 if ( (pPhi <= fSPhi + twopi - halfAngTolerance)
725 && (pPhi >= fSPhi + fDPhi + halfAngTolerance) ) {;}
726 else
727 {
728 in = kSurface ;
729 }
730 }
731 }
732 }
733 }
734 return in ;
735}
EInside
Definition: geomdefs.hh:58
@ kInside
Definition: geomdefs.hh:58
@ kSurface
Definition: geomdefs.hh:58

Referenced by CalculateExtent(), DistanceToOut(), and SurfaceNormal().

◆ operator=()

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

Definition at line 212 of file G4Torus.cc.

213{
214 // Check assignment to self
215 //
216 if (this == &rhs) { return *this; }
217
218 // Copy base class data
219 //
221
222 // Copy data
223 //
224 fRmin = rhs.fRmin; fRmax = rhs.fRmax;
225 fRtor = rhs.fRtor; fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
226 fRminTolerance = rhs.fRminTolerance; fRmaxTolerance = rhs.fRmaxTolerance;
227 kRadTolerance = rhs.kRadTolerance; kAngTolerance = rhs.kAngTolerance;
228
229 return *this;
230}
G4CSGSolid & operator=(const G4CSGSolid &rhs)
Definition: G4CSGSolid.cc:82

◆ SetAllParameters()

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

Definition at line 100 of file G4Torus.cc.

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

Referenced by G4Torus().

◆ StreamInfo()

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

Reimplemented from G4CSGSolid.

Definition at line 1712 of file G4Torus.cc.

1713{
1714 G4int oldprc = os.precision(16);
1715 os << "-----------------------------------------------------------\n"
1716 << " *** Dump for solid - " << GetName() << " ***\n"
1717 << " ===================================================\n"
1718 << " Solid type: G4Torus\n"
1719 << " Parameters: \n"
1720 << " inner radius: " << fRmin/mm << " mm \n"
1721 << " outer radius: " << fRmax/mm << " mm \n"
1722 << " swept radius: " << fRtor/mm << " mm \n"
1723 << " starting phi: " << fSPhi/degree << " degrees \n"
1724 << " delta phi : " << fDPhi/degree << " degrees \n"
1725 << "-----------------------------------------------------------\n";
1726 os.precision(oldprc);
1727
1728 return os;
1729}

◆ SurfaceNormal()

G4ThreeVector G4Torus::SurfaceNormal ( const G4ThreeVector p) const
virtual

Implements G4VSolid.

Definition at line 743 of file G4Torus.cc.

744{
745 G4int noSurfaces = 0;
746 G4double rho2, rho, pt2, pt, pPhi;
747 G4double distRMin = kInfinity;
748 G4double distSPhi = kInfinity, distEPhi = kInfinity;
749
750 // To cope with precision loss
751 //
752 const G4double delta = std::max(10.0*kCarTolerance,
753 1.0e-8*(fRtor+fRmax));
754 const G4double dAngle = 10.0*kAngTolerance;
755
756 G4ThreeVector nR, nPs, nPe;
757 G4ThreeVector norm, sumnorm(0.,0.,0.);
758
759 rho2 = p.x()*p.x() + p.y()*p.y();
760 rho = std::sqrt(rho2);
761 pt2 = rho2+p.z()*p.z() +fRtor * (fRtor-2*rho);
762 pt2 = std::max(pt2, 0.0); // std::fabs(pt2);
763 pt = std::sqrt(pt2) ;
764
765 G4double distRMax = std::fabs(pt - fRmax);
766 if(fRmin) distRMin = std::fabs(pt - fRmin);
767
768 if( rho > delta && pt != 0.0 )
769 {
770 G4double redFactor= (rho-fRtor)/rho;
771 nR = G4ThreeVector( p.x()*redFactor, // p.x()*(1.-fRtor/rho),
772 p.y()*redFactor, // p.y()*(1.-fRtor/rho),
773 p.z() );
774 nR *= 1.0/pt;
775 }
776
777 if ( fDPhi < twopi ) // && rho ) // old limitation against (0,0,z)
778 {
779 if ( rho )
780 {
781 pPhi = std::atan2(p.y(),p.x());
782
783 if(pPhi < fSPhi-delta) { pPhi += twopi; }
784 else if(pPhi > fSPhi+fDPhi+delta) { pPhi -= twopi; }
785
786 distSPhi = std::fabs( pPhi - fSPhi );
787 distEPhi = std::fabs(pPhi-fSPhi-fDPhi);
788 }
789 nPs = G4ThreeVector(std::sin(fSPhi),-std::cos(fSPhi),0);
790 nPe = G4ThreeVector(-std::sin(fSPhi+fDPhi),std::cos(fSPhi+fDPhi),0);
791 }
792 if( distRMax <= delta )
793 {
794 noSurfaces ++;
795 sumnorm += nR;
796 }
797 else if( fRmin && (distRMin <= delta) ) // Must not be on both Outer and Inner
798 {
799 noSurfaces ++;
800 sumnorm -= nR;
801 }
802
803 // To be on one of the 'phi' surfaces,
804 // it must be within the 'tube' - with tolerance
805
806 if( (fDPhi < twopi) && (fRmin-delta <= pt) && (pt <= (fRmax+delta)) )
807 {
808 if (distSPhi <= dAngle)
809 {
810 noSurfaces ++;
811 sumnorm += nPs;
812 }
813 if (distEPhi <= dAngle)
814 {
815 noSurfaces ++;
816 sumnorm += nPe;
817 }
818 }
819 if ( noSurfaces == 0 )
820 {
821#ifdef G4CSGDEBUG
823 ed.precision(16);
824
825 EInside inIt= Inside( p );
826
827 if( inIt != kSurface )
828 {
829 ed << " ERROR> Surface Normal was called for Torus,"
830 << " with point not on surface." << G4endl;
831 }
832 else
833 {
834 ed << " ERROR> Surface Normal has not found a surface, "
835 << " despite the point being on the surface. " <<G4endl;
836 }
837
838 if( inIt != kInside)
839 {
840 ed << " Safety (Dist To In) = " << DistanceToIn(p) << G4endl;
841 }
842 if( inIt != kOutside)
843 {
844 ed << " Safety (Dist to Out) = " << DistanceToOut(p) << G4endl;
845 }
846 ed << " Coordinates of point : " << p << G4endl;
847 ed << " Parameters of solid : " << G4endl << *this << G4endl;
848
849 if( inIt == kSurface )
850 {
851 G4Exception("G4Torus::SurfaceNormal(p)", "GeomSolids1002",
852 JustWarning, ed,
853 "Failing to find normal, even though point is on surface!" );
854 }
855 else
856 {
857 static const char* NameInside[3]= { "Inside", "Surface", "Outside" };
858 ed << " The point is " << NameInside[inIt] << " the solid. "<< G4endl;
859 G4Exception("G4Torus::SurfaceNormal(p)", "GeomSolids1002",
860 JustWarning, ed, "Point p is not on surface !?" );
861 }
862#endif
863 norm = ApproxSurfaceNormal(p);
864 }
865 else if ( noSurfaces == 1 ) { norm = sumnorm; }
866 else { norm = sumnorm.unit(); }
867
868 // G4cout << "G4Torus::SurfaceNormal p= " << p << " returns norm= " << norm << G4endl;
869
870 return norm ;
871}
Hep3Vector unit() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
Definition: G4Torus.cc:1187
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
Definition: G4Torus.cc:987
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76

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