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

#include <G4CutTubs.hh>

+ Inheritance diagram for G4CutTubs:

Public Member Functions

 G4CutTubs (const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi, G4ThreeVector pLowNorm, G4ThreeVector pHighNorm)
 
 ~G4CutTubs () override
 
G4double GetInnerRadius () const
 
G4double GetOuterRadius () const
 
G4double GetZHalfLength () const
 
G4double GetStartPhiAngle () const
 
G4double GetDeltaPhiAngle () const
 
G4double GetSinStartPhi () const
 
G4double GetCosStartPhi () const
 
G4double GetSinEndPhi () const
 
G4double GetCosEndPhi () const
 
G4ThreeVector GetLowNorm () const
 
G4ThreeVector GetHighNorm () const
 
void SetInnerRadius (G4double newRMin)
 
void SetOuterRadius (G4double newRMax)
 
void SetZHalfLength (G4double newDz)
 
void SetStartPhiAngle (G4double newSPhi, G4bool trig=true)
 
void SetDeltaPhiAngle (G4double newDPhi)
 
G4double GetCubicVolume () override
 
G4double GetSurfaceArea () 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
 
 G4CutTubs (__void__ &)
 
 G4CutTubs (const G4CutTubs &rhs)
 
G4CutTubsoperator= (const G4CutTubs &rhs)
 
- Public Member Functions inherited from G4CSGSolid
 G4CSGSolid (const G4String &pName)
 
virtual ~G4CSGSolid ()
 
G4PolyhedronGetPolyhedron () const override
 
 G4CSGSolid (__void__ &)
 
 G4CSGSolid (const G4CSGSolid &rhs)
 
G4CSGSolidoperator= (const G4CSGSolid &rhs)
 
- Public Member Functions inherited from G4VSolid
 G4VSolid (const G4String &name)
 
virtual ~G4VSolid ()
 
G4bool operator== (const G4VSolid &s) const
 
G4String GetName () const
 
void SetName (const G4String &name)
 
G4double GetTolerance () const
 
virtual void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
 
void DumpInfo () const
 
virtual G4VisExtent GetExtent () const
 
virtual const G4VSolidGetConstituentSolid (G4int no) const
 
virtual G4VSolidGetConstituentSolid (G4int no)
 
virtual const G4DisplacedSolidGetDisplacedSolidPtr () const
 
virtual G4DisplacedSolidGetDisplacedSolidPtr ()
 
 G4VSolid (__void__ &)
 
 G4VSolid (const G4VSolid &rhs)
 
G4VSolidoperator= (const G4VSolid &rhs)
 
G4double EstimateCubicVolume (G4int nStat, G4double epsilon) const
 
G4double EstimateSurfaceArea (G4int nStat, G4double ell) const
 

Protected Member Functions

void Initialize ()
 
void CheckSPhiAngle (G4double sPhi)
 
void CheckDPhiAngle (G4double dPhi)
 
void CheckPhiAngles (G4double sPhi, G4double dPhi)
 
void InitializeTrigonometry ()
 
G4ThreeVector ApproxSurfaceNormal (const G4ThreeVector &p) const
 
G4bool IsCrossingCutPlanes () const
 
G4double GetCutZ (const G4ThreeVector &p) const
 
- 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
 

Additional Inherited Members

- Protected Attributes inherited from G4CSGSolid
G4double fCubicVolume = 0.0
 
G4double fSurfaceArea = 0.0
 
G4bool fRebuildPolyhedron = false
 
G4PolyhedronfpPolyhedron = nullptr
 
- Protected Attributes inherited from G4VSolid
G4double kCarTolerance
 

Detailed Description

Definition at line 59 of file G4CutTubs.hh.

Constructor & Destructor Documentation

◆ G4CutTubs() [1/3]

G4CutTubs::G4CutTubs ( const G4String & pName,
G4double pRMin,
G4double pRMax,
G4double pDz,
G4double pSPhi,
G4double pDPhi,
G4ThreeVector pLowNorm,
G4ThreeVector pHighNorm )

Definition at line 63 of file G4CutTubs.cc.

68 : G4CSGSolid(pName), fRMin(pRMin), fRMax(pRMax), fDz(pDz),
69 fSPhi(0.), fDPhi(0.), fZMin(0.), fZMax(0.)
70{
73
74 halfCarTolerance = kCarTolerance*0.5;
75 halfRadTolerance = kRadTolerance*0.5;
76 halfAngTolerance = kAngTolerance*0.5;
77
78 if (pDz<=0) // Check z-len
79 {
80 std::ostringstream message;
81 message << "Negative Z half-length (" << pDz << ") in solid: " << GetName();
82 G4Exception("G4CutTubs::G4CutTubs()", "GeomSolids0002", FatalException, message);
83 }
84 if ( (pRMin >= pRMax) || (pRMin < 0) ) // Check radii
85 {
86 std::ostringstream message;
87 message << "Invalid values for radii in solid: " << GetName()
88 << G4endl
89 << " pRMin = " << pRMin << ", pRMax = " << pRMax;
90 G4Exception("G4CutTubs::G4CutTubs()", "GeomSolids0002", FatalException, message);
91 }
92
93 // Check angles
94 //
95 CheckPhiAngles(pSPhi, pDPhi);
96
97 // Check on Cutted Planes Normals
98 // If there is NO CUT, propose to use G4Tubs instead
99 //
100 if ( ( pLowNorm.x() == 0.0) && ( pLowNorm.y() == 0.0)
101 && ( pHighNorm.x() == 0.0) && (pHighNorm.y() == 0.0) )
102 {
103 std::ostringstream message;
104 message << "Inexisting Low/High Normal to Z plane or Parallel to Z."
105 << G4endl
106 << "Normals to Z plane are " << pLowNorm << " and "
107 << pHighNorm << " in solid: " << GetName() << " \n";
108 G4Exception("G4CutTubs::G4CutTubs()", "GeomSolids1001",
109 JustWarning, message, "Should use G4Tubs!");
110 }
111
112 // If Normal is (0,0,0),means parallel to R, give it value of (0,0,+/-1)
113 //
114 if (pLowNorm.mag2() == 0.) { pLowNorm.setZ(-1.); }
115 if (pHighNorm.mag2()== 0.) { pHighNorm.setZ(1.); }
116
117 // Given Normals to Cut Planes have to be an unit vectors.
118 // Normalize if it is needed.
119 //
120 if (pLowNorm.mag2() != 1.) { pLowNorm = pLowNorm.unit(); }
121 if (pHighNorm.mag2()!= 1.) { pHighNorm = pHighNorm.unit(); }
122
123 // Normals to cutted planes have to point outside Solid
124 //
125 if( (pLowNorm.mag2() != 0.) && (pHighNorm.mag2()!= 0. ) )
126 {
127 if( ( pLowNorm.z()>= 0. ) || ( pHighNorm.z() <= 0.))
128 {
129 std::ostringstream message;
130 message << "Invalid Low or High Normal to Z plane; "
131 "has to point outside Solid." << G4endl
132 << "Invalid Norm to Z plane (" << pLowNorm << " or "
133 << pHighNorm << ") in solid: " << GetName();
134 G4Exception("G4CutTubs::G4CutTubs()", "GeomSolids0002",
135 FatalException, message);
136 }
137 }
138 fLowNorm = pLowNorm;
139 fHighNorm = pHighNorm;
140
141 // Check intersection of cut planes, they MUST NOT intersect
142 // each other inside the lateral surface
143 //
145 {
146 std::ostringstream message;
147 message << "Invalid normals to Z plane in solid : " << GetName() << G4endl
148 << "Cut planes are crossing inside lateral surface !!!\n"
149 << " Solid type: G4CutTubs\n"
150 << " Parameters: \n"
151 << " inner radius : " << fRMin/mm << " mm \n"
152 << " outer radius : " << fRMax/mm << " mm \n"
153 << " half length Z: " << fDz/mm << " mm \n"
154 << " starting phi : " << fSPhi/degree << " degrees \n"
155 << " delta phi : " << fDPhi/degree << " degrees \n"
156 << " low Norm : " << fLowNorm << " \n"
157 << " high Norm : " << fHighNorm;
158 G4Exception("G4CutTubs::G4CutTubs()", "GeomSolids0002",
159 FatalException, message);
160 }
161}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4endl
Definition G4ios.hh:67
double z() const
Hep3Vector unit() const
double x() const
double mag2() const
double y() const
void setZ(double)
G4CSGSolid(const G4String &pName)
Definition G4CSGSolid.cc:49
G4bool IsCrossingCutPlanes() const
void CheckPhiAngles(G4double sPhi, G4double dPhi)
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
G4String GetName() const
G4double kCarTolerance
Definition G4VSolid.hh:299

Referenced by Clone().

◆ ~G4CutTubs()

G4CutTubs::~G4CutTubs ( )
overridedefault

◆ G4CutTubs() [2/3]

G4CutTubs::G4CutTubs ( __void__ & a)

Definition at line 168 of file G4CutTubs.cc.

169 : G4CSGSolid(a)
170{
171}

◆ G4CutTubs() [3/3]

G4CutTubs::G4CutTubs ( const G4CutTubs & rhs)
default

Member Function Documentation

◆ ApproxSurfaceNormal()

G4ThreeVector G4CutTubs::ApproxSurfaceNormal ( const G4ThreeVector & p) const
protected

Definition at line 740 of file G4CutTubs.cc.

741{
742 enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ};
743
744 ENorm side ;
745 G4ThreeVector norm ;
746 G4double rho, phi ;
747 G4double distZLow,distZHigh,distZ;
748 G4double distRMin, distRMax, distSPhi, distEPhi, distMin ;
749 G4ThreeVector vZ=G4ThreeVector(0,0,fDz);
750
751 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
752
753 distRMin = std::fabs(rho - fRMin) ;
754 distRMax = std::fabs(rho - fRMax) ;
755
756 //dist to Low Cut
757 //
758 distZLow =std::fabs((p+vZ).dot(fLowNorm));
759
760 //dist to High Cut
761 //
762 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
763 distZ=std::min(distZLow,distZHigh);
764
765 if (distRMin < distRMax) // First minimum
766 {
767 if ( distZ < distRMin )
768 {
769 distMin = distZ ;
770 side = kNZ ;
771 }
772 else
773 {
774 distMin = distRMin ;
775 side = kNRMin ;
776 }
777 }
778 else
779 {
780 if ( distZ < distRMax )
781 {
782 distMin = distZ ;
783 side = kNZ ;
784 }
785 else
786 {
787 distMin = distRMax ;
788 side = kNRMax ;
789 }
790 }
791 if (!fPhiFullCutTube && (rho != 0.0) ) // Protected against (0,0,z)
792 {
793 phi = std::atan2(p.y(),p.x()) ;
794
795 if ( phi < 0 ) { phi += twopi; }
796
797 if ( fSPhi < 0 )
798 {
799 distSPhi = std::fabs(phi - (fSPhi + twopi))*rho ;
800 }
801 else
802 {
803 distSPhi = std::fabs(phi - fSPhi)*rho ;
804 }
805 distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
806
807 if (distSPhi < distEPhi) // Find new minimum
808 {
809 if ( distSPhi < distMin )
810 {
811 side = kNSPhi ;
812 }
813 }
814 else
815 {
816 if ( distEPhi < distMin )
817 {
818 side = kNEPhi ;
819 }
820 }
821 }
822 switch ( side )
823 {
824 case kNRMin : // Inner radius
825 {
826 norm = G4ThreeVector(-p.x()/rho, -p.y()/rho, 0) ;
827 break ;
828 }
829 case kNRMax : // Outer radius
830 {
831 norm = G4ThreeVector(p.x()/rho, p.y()/rho, 0) ;
832 break ;
833 }
834 case kNZ : // + or - dz
835 {
836 if ( distZHigh > distZLow ) { norm = fHighNorm ; }
837 else { norm = fLowNorm; }
838 break ;
839 }
840 case kNSPhi:
841 {
842 norm = G4ThreeVector(sinSPhi, -cosSPhi, 0) ;
843 break ;
844 }
845 case kNEPhi:
846 {
847 norm = G4ThreeVector(-sinEPhi, cosEPhi, 0) ;
848 break;
849 }
850 default: // Should never reach this case ...
851 {
852 DumpInfo();
853 G4Exception("G4CutTubs::ApproxSurfaceNormal()",
854 "GeomSolids1002", JustWarning,
855 "Undefined side for valid surface normal to solid.");
856 break ;
857 }
858 }
859 return norm;
860}
ENorm
Definition G4Sphere.cc:65
@ kNRMax
Definition G4Sphere.cc:65
@ kNEPhi
Definition G4Sphere.cc:65
@ kNSPhi
Definition G4Sphere.cc:65
@ kNRMin
Definition G4Sphere.cc:65
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
void DumpInfo() const

Referenced by SurfaceNormal().

◆ BoundingLimits()

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

Reimplemented from G4VSolid.

Definition at line 327 of file G4CutTubs.cc.

328{
329 G4double rmin = GetInnerRadius();
330 G4double rmax = GetOuterRadius();
332 G4double dphi = GetDeltaPhiAngle();
333
334 G4double sinSphi = GetSinStartPhi();
335 G4double cosSphi = GetCosStartPhi();
336 G4double sinEphi = GetSinEndPhi();
337 G4double cosEphi = GetCosEndPhi();
338
339 G4ThreeVector norm;
340 G4double mag, topx, topy, dists, diste;
341 G4bool iftop;
342
343 // Find Zmin
344 //
345 G4double zmin;
346 norm = GetLowNorm();
347 mag = std::sqrt(norm.x()*norm.x() + norm.y()*norm.y());
348 topx = (mag == 0) ? 0 : -rmax*norm.x()/mag;
349 topy = (mag == 0) ? 0 : -rmax*norm.y()/mag;
350 dists = sinSphi*topx - cosSphi*topy;
351 diste = -sinEphi*topx + cosEphi*topy;
352 if (dphi > pi)
353 {
354 iftop = true;
355 if (dists > 0 && diste > 0)iftop = false;
356 }
357 else
358 {
359 iftop = false;
360 if (dists <= 0 && diste <= 0) iftop = true;
361 }
362 if (iftop)
363 {
364 zmin = -(norm.x()*topx + norm.y()*topy)/norm.z() - dz;
365 }
366 else
367 {
368 G4double z1 = -rmin*(norm.x()*cosSphi + norm.y()*sinSphi)/norm.z() - dz;
369 G4double z2 = -rmin*(norm.x()*cosEphi + norm.y()*sinEphi)/norm.z() - dz;
370 G4double z3 = -rmax*(norm.x()*cosSphi + norm.y()*sinSphi)/norm.z() - dz;
371 G4double z4 = -rmax*(norm.x()*cosEphi + norm.y()*sinEphi)/norm.z() - dz;
372 zmin = std::min(std::min(std::min(z1,z2),z3),z4);
373 }
374
375 // Find Zmax
376 //
377 G4double zmax;
378 norm = GetHighNorm();
379 mag = std::sqrt(norm.x()*norm.x() + norm.y()*norm.y());
380 topx = (mag == 0) ? 0 : -rmax*norm.x()/mag;
381 topy = (mag == 0) ? 0 : -rmax*norm.y()/mag;
382 dists = sinSphi*topx - cosSphi*topy;
383 diste = -sinEphi*topx + cosEphi*topy;
384 if (dphi > pi)
385 {
386 iftop = true;
387 if (dists > 0 && diste > 0) iftop = false;
388 }
389 else
390 {
391 iftop = false;
392 if (dists <= 0 && diste <= 0) iftop = true;
393 }
394 if (iftop)
395 {
396 zmax = -(norm.x()*topx + norm.y()*topy)/norm.z() + dz;
397 }
398 else
399 {
400 G4double z1 = -rmin*(norm.x()*cosSphi + norm.y()*sinSphi)/norm.z() + dz;
401 G4double z2 = -rmin*(norm.x()*cosEphi + norm.y()*sinEphi)/norm.z() + dz;
402 G4double z3 = -rmax*(norm.x()*cosSphi + norm.y()*sinSphi)/norm.z() + dz;
403 G4double z4 = -rmax*(norm.x()*cosEphi + norm.y()*sinEphi)/norm.z() + dz;
404 zmax = std::max(std::max(std::max(z1,z2),z3),z4);
405 }
406
407 // Find bounding box
408 //
409 if (dphi < twopi)
410 {
411 G4TwoVector vmin,vmax;
412 G4GeomTools::DiskExtent(rmin,rmax,
415 vmin,vmax);
416 pMin.set(vmin.x(),vmin.y(), zmin);
417 pMax.set(vmax.x(),vmax.y(), zmax);
418 }
419 else
420 {
421 pMin.set(-rmax,-rmax, zmin);
422 pMax.set( rmax, rmax, zmax);
423 }
424
425 // Check correctness of the bounding box
426 //
427 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
428 {
429 std::ostringstream message;
430 message << "Bad bounding box (min >= max) for solid: "
431 << GetName() << " !"
432 << "\npMin = " << pMin
433 << "\npMax = " << pMax;
434 G4Exception("G4CutTubs::BoundingLimits()", "GeomMgt0001",
435 JustWarning, message);
436 DumpInfo();
437 }
438}
bool G4bool
Definition G4Types.hh:86
double x() const
double y() const
void set(double x, double y, double z)
G4ThreeVector GetHighNorm() const
G4double GetZHalfLength() const
G4double GetInnerRadius() const
G4ThreeVector GetLowNorm() const
G4double GetDeltaPhiAngle() const
G4double GetOuterRadius() const
G4double GetSinStartPhi() const
G4double GetSinEndPhi() const
G4double GetCosStartPhi() const
G4double GetCosEndPhi() const
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)

Referenced by CalculateExtent(), and GetPointOnSurface().

◆ CalculateExtent()

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

Implements G4VSolid.

Definition at line 444 of file G4CutTubs.cc.

449{
450 G4ThreeVector bmin, bmax;
451 G4bool exist;
452
453 // Get bounding box
454 BoundingLimits(bmin,bmax);
455
456 // Check bounding box
457 G4BoundingEnvelope bbox(bmin,bmax);
458#ifdef G4BBOX_EXTENT
459 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
460#endif
461 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
462 {
463 return exist = pMin < pMax;
464 }
465
466 // Get parameters of the solid
467 G4double rmin = GetInnerRadius();
468 G4double rmax = GetOuterRadius();
469 G4double dphi = GetDeltaPhiAngle();
470 G4double zmin = bmin.z();
471 G4double zmax = bmax.z();
472
473 // Find bounding envelope and calculate extent
474 //
475 const G4int NSTEPS = 24; // number of steps for whole circle
476 G4double astep = twopi/NSTEPS; // max angle for one step
477 G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
478 G4double ang = dphi/ksteps;
479
480 G4double sinHalf = std::sin(0.5*ang);
481 G4double cosHalf = std::cos(0.5*ang);
482 G4double sinStep = 2.*sinHalf*cosHalf;
483 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
484 G4double rext = rmax/cosHalf;
485
486 // bounding envelope for full cylinder consists of two polygons,
487 // in other cases it is a sequence of quadrilaterals
488 if (rmin == 0 && dphi == twopi)
489 {
490 G4double sinCur = sinHalf;
491 G4double cosCur = cosHalf;
492
493 G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
494 for (G4int k=0; k<NSTEPS; ++k)
495 {
496 baseA[k].set(rext*cosCur,rext*sinCur,zmin);
497 baseB[k].set(rext*cosCur,rext*sinCur,zmax);
498
499 G4double sinTmp = sinCur;
500 sinCur = sinCur*cosStep + cosCur*sinStep;
501 cosCur = cosCur*cosStep - sinTmp*sinStep;
502 }
503 std::vector<const G4ThreeVectorList *> polygons(2);
504 polygons[0] = &baseA;
505 polygons[1] = &baseB;
506 G4BoundingEnvelope benv(bmin,bmax,polygons);
507 exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
508 }
509 else
510 {
511 G4double sinStart = GetSinStartPhi();
512 G4double cosStart = GetCosStartPhi();
513 G4double sinEnd = GetSinEndPhi();
514 G4double cosEnd = GetCosEndPhi();
515 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
516 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
517
518 // set quadrilaterals
519 G4ThreeVectorList pols[NSTEPS+2];
520 for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
521 pols[0][0].set(rmin*cosStart,rmin*sinStart,zmax);
522 pols[0][1].set(rmin*cosStart,rmin*sinStart,zmin);
523 pols[0][2].set(rmax*cosStart,rmax*sinStart,zmin);
524 pols[0][3].set(rmax*cosStart,rmax*sinStart,zmax);
525 for (G4int k=1; k<ksteps+1; ++k)
526 {
527 pols[k][0].set(rmin*cosCur,rmin*sinCur,zmax);
528 pols[k][1].set(rmin*cosCur,rmin*sinCur,zmin);
529 pols[k][2].set(rext*cosCur,rext*sinCur,zmin);
530 pols[k][3].set(rext*cosCur,rext*sinCur,zmax);
531
532 G4double sinTmp = sinCur;
533 sinCur = sinCur*cosStep + cosCur*sinStep;
534 cosCur = cosCur*cosStep - sinTmp*sinStep;
535 }
536 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd,zmax);
537 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,zmin);
538 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,zmin);
539 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd,zmax);
540
541 // set envelope and calculate extent
542 std::vector<const G4ThreeVectorList *> polygons;
543 polygons.resize(ksteps+2);
544 for (G4int k=0; k<ksteps+2; ++k) { polygons[k] = &pols[k]; }
545 G4BoundingEnvelope benv(bmin,bmax,polygons);
546 exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
547 }
548 return exist;
549}
std::vector< G4ThreeVector > G4ThreeVectorList
int G4int
Definition G4Types.hh:85
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
Definition G4CutTubs.cc:327

◆ CheckDPhiAngle()

void G4CutTubs::CheckDPhiAngle ( G4double dPhi)
inlineprotected

◆ CheckPhiAngles()

void G4CutTubs::CheckPhiAngles ( G4double sPhi,
G4double dPhi )
inlineprotected

Referenced by G4CutTubs().

◆ CheckSPhiAngle()

void G4CutTubs::CheckSPhiAngle ( G4double sPhi)
inlineprotected

◆ Clone()

G4VSolid * G4CutTubs::Clone ( ) const
overridevirtual

Reimplemented from G4VSolid.

Definition at line 1886 of file G4CutTubs.cc.

1887{
1888 return new G4CutTubs(*this);
1889}
G4CutTubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi, G4ThreeVector pLowNorm, G4ThreeVector pHighNorm)
Definition G4CutTubs.cc:63

◆ CreatePolyhedron()

G4Polyhedron * G4CutTubs::CreatePolyhedron ( ) const
overridevirtual

Reimplemented from G4VSolid.

Definition at line 2043 of file G4CutTubs.cc.

2044{
2045 typedef G4double G4double3[3];
2046 typedef G4int G4int4[4];
2047
2048 auto ph = new G4Polyhedron;
2049 G4Polyhedron *ph1 = new G4PolyhedronTubs (fRMin, fRMax, fDz, fSPhi, fDPhi);
2050 G4int nn=ph1->GetNoVertices();
2051 G4int nf=ph1->GetNoFacets();
2052 auto xyz = new G4double3[nn]; // number of nodes
2053 auto faces = new G4int4[nf] ; // number of faces
2054
2055 for(G4int i=0; i<nn; ++i)
2056 {
2057 xyz[i][0]=ph1->GetVertex(i+1).x();
2058 xyz[i][1]=ph1->GetVertex(i+1).y();
2059 G4double tmpZ=ph1->GetVertex(i+1).z();
2060 if(tmpZ>=fDz-kCarTolerance)
2061 {
2062 xyz[i][2]=GetCutZ(G4ThreeVector(xyz[i][0],xyz[i][1],fDz));
2063 }
2064 else if(tmpZ<=-fDz+kCarTolerance)
2065 {
2066 xyz[i][2]=GetCutZ(G4ThreeVector(xyz[i][0],xyz[i][1],-fDz));
2067 }
2068 else
2069 {
2070 xyz[i][2]=tmpZ;
2071 }
2072 }
2073 G4int iNodes[4];
2074 G4int* iEdge = nullptr;
2075 G4int n;
2076 for(G4int i=0; i<nf ; ++i)
2077 {
2078 ph1->GetFacet(i+1,n,iNodes,iEdge);
2079 for(G4int k=0; k<n; ++k)
2080 {
2081 faces[i][k]=iNodes[k];
2082 }
2083 for(G4int k=n; k<4; ++k)
2084 {
2085 faces[i][k]=0;
2086 }
2087 }
2088 ph->createPolyhedron(nn,nf,xyz,faces);
2089
2090 delete [] xyz;
2091 delete [] faces;
2092 delete ph1;
2093
2094 return ph;
2095}
G4double GetCutZ(const G4ThreeVector &p) const
G4Point3D GetVertex(G4int index) const
void GetFacet(G4int iFace, G4int &n, G4int *iNodes, G4int *edgeFlags=nullptr, G4int *iFaces=nullptr) const
G4int GetNoFacets() const
G4int GetNoVertices() const

◆ DescribeYourselfTo()

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

Implements G4VSolid.

Definition at line 2038 of file G4CutTubs.cc.

2039{
2040 scene.AddSolid (*this) ;
2041}
virtual void AddSolid(const G4Box &)=0

◆ DistanceToIn() [1/2]

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

Implements G4VSolid.

Definition at line 1337 of file G4CutTubs.cc.

1338{
1339 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho,cosPsi;
1340 G4ThreeVector vZ=G4ThreeVector(0,0,fDz);
1341
1342 // Distance to R
1343 //
1344 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1345
1346 safRMin = fRMin- rho ;
1347 safRMax = rho - fRMax ;
1348
1349 // Distances to ZCut(Low/High)
1350
1351 // Dist to Low Cut
1352 //
1353 safZLow = (p+vZ).dot(fLowNorm);
1354
1355 // Dist to High Cut
1356 //
1357 safZHigh = (p-vZ).dot(fHighNorm);
1358
1359 safe = std::max(safZLow,safZHigh);
1360
1361 if ( safRMin > safe ) { safe = safRMin; }
1362 if ( safRMax> safe ) { safe = safRMax; }
1363
1364 // Distance to Phi
1365 //
1366 if ( (!fPhiFullCutTube) && ((rho) != 0.0) )
1367 {
1368 // Psi=angle from central phi to point
1369 //
1370 cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/rho ;
1371
1372 if ( cosPsi < cosHDPhi )
1373 {
1374 // Point lies outside phi range
1375
1376 if ( (p.y()*cosCPhi - p.x()*sinCPhi) <= 0 )
1377 {
1378 safePhi = std::fabs(p.x()*sinSPhi - p.y()*cosSPhi) ;
1379 }
1380 else
1381 {
1382 safePhi = std::fabs(p.x()*sinEPhi - p.y()*cosEPhi) ;
1383 }
1384 if ( safePhi > safe ) { safe = safePhi; }
1385 }
1386 }
1387 if ( safe < 0 ) { safe = 0; }
1388
1389 return safe ;
1390}

◆ DistanceToIn() [2/2]

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

Implements G4VSolid.

Definition at line 884 of file G4CutTubs.cc.

886{
887 G4double snxt = kInfinity ; // snxt = default return value
888 G4double tolORMin2, tolIRMax2 ; // 'generous' radii squared
889 G4double tolORMax2, tolIRMin2;
890 const G4double dRmax = 100.*fRMax;
891 G4ThreeVector vZ=G4ThreeVector(0,0,fDz);
892
893 // Intersection point variables
894 //
895 G4double Dist, sd=0, xi, yi, zi, rho2, inum, iden, cosPsi, Comp,calf ;
896 G4double t1, t2, t3, b, c, d ; // Quadratic solver variables
897 G4double distZLow,distZHigh;
898 // Calculate tolerant rmin and rmax
899
900 if (fRMin > kRadTolerance)
901 {
902 tolORMin2 = (fRMin - halfRadTolerance)*(fRMin - halfRadTolerance) ;
903 tolIRMin2 = (fRMin + halfRadTolerance)*(fRMin + halfRadTolerance) ;
904 }
905 else
906 {
907 tolORMin2 = 0.0 ;
908 tolIRMin2 = 0.0 ;
909 }
910 tolORMax2 = (fRMax + halfRadTolerance)*(fRMax + halfRadTolerance) ;
911 tolIRMax2 = (fRMax - halfRadTolerance)*(fRMax - halfRadTolerance) ;
912
913 // Intersection with ZCut surfaces
914
915 // dist to Low Cut
916 //
917 distZLow =(p+vZ).dot(fLowNorm);
918
919 // dist to High Cut
920 //
921 distZHigh = (p-vZ).dot(fHighNorm);
922
923 if ( distZLow >= -halfCarTolerance )
924 {
925 calf = v.dot(fLowNorm);
926 if (calf<0)
927 {
928 sd = -distZLow/calf;
929 if(sd < 0.0) { sd = 0.0; }
930
931 xi = p.x() + sd*v.x() ; // Intersection coords
932 yi = p.y() + sd*v.y() ;
933 rho2 = xi*xi + yi*yi ;
934
935 // Check validity of intersection
936
937 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
938 {
939 if (!fPhiFullCutTube && (rho2 != 0.0))
940 {
941 // Psi = angle made with central (average) phi of shape
942 //
943 inum = xi*cosCPhi + yi*sinCPhi ;
944 iden = std::sqrt(rho2) ;
945 cosPsi = inum/iden ;
946 if (cosPsi >= cosHDPhiIT) { return sd ; }
947 }
948 else
949 {
950 return sd ;
951 }
952 }
953 }
954 else
955 {
956 if ( sd<halfCarTolerance )
957 {
958 if(calf>=0) { sd=kInfinity; }
959 return sd ; // On/outside extent, and heading away
960 } // -> cannot intersect
961 }
962 }
963
964 if(distZHigh >= -halfCarTolerance )
965 {
966 calf = v.dot(fHighNorm);
967 if (calf<0)
968 {
969 sd = -distZHigh/calf;
970
971 if(sd < 0.0) { sd = 0.0; }
972
973 xi = p.x() + sd*v.x() ; // Intersection coords
974 yi = p.y() + sd*v.y() ;
975 rho2 = xi*xi + yi*yi ;
976
977 // Check validity of intersection
978
979 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
980 {
981 if (!fPhiFullCutTube && (rho2 != 0.0))
982 {
983 // Psi = angle made with central (average) phi of shape
984 //
985 inum = xi*cosCPhi + yi*sinCPhi ;
986 iden = std::sqrt(rho2) ;
987 cosPsi = inum/iden ;
988 if (cosPsi >= cosHDPhiIT) { return sd ; }
989 }
990 else
991 {
992 return sd ;
993 }
994 }
995 }
996 else
997 {
998 if ( sd<halfCarTolerance )
999 {
1000 if(calf>=0) { sd=kInfinity; }
1001 return sd ; // On/outside extent, and heading away
1002 } // -> cannot intersect
1003 }
1004 }
1005
1006 // -> Can not intersect z surfaces
1007 //
1008 // Intersection with rmax (possible return) and rmin (must also check phi)
1009 //
1010 // Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc.
1011 //
1012 // Intersects with x^2+y^2=R^2
1013 //
1014 // Hence (v.x^2+v.y^2)t^2+ 2t(p.x*v.x+p.y*v.y)+p.x^2+p.y^2-R^2=0
1015 // t1 t2 t3
1016
1017 t1 = 1.0 - v.z()*v.z() ;
1018 t2 = p.x()*v.x() + p.y()*v.y() ;
1019 t3 = p.x()*p.x() + p.y()*p.y() ;
1020 if ( t1 > 0 ) // Check not || to z axis
1021 {
1022 b = t2/t1 ;
1023 c = t3 - fRMax*fRMax ;
1024
1025 if ((t3 >= tolORMax2) && (t2<0)) // This also handles the tangent case
1026 {
1027 // Try outer cylinder intersection, c=(t3-fRMax*fRMax)/t1;
1028
1029 c /= t1 ;
1030 d = b*b - c ;
1031
1032 if (d >= 0) // If real root
1033 {
1034 sd = c/(-b+std::sqrt(d));
1035 if (sd >= 0) // If 'forwards'
1036 {
1037 if ( sd>dRmax ) // Avoid rounding errors due to precision issues on
1038 { // 64 bits systems. Split long distances and recompute
1039 G4double fTerm = sd-std::fmod(sd,dRmax);
1040 sd = fTerm + DistanceToIn(p+fTerm*v,v);
1041 }
1042 // Check z intersection
1043 //
1044 zi = p.z() + sd*v.z() ;
1045 xi = p.x() + sd*v.x() ;
1046 yi = p.y() + sd*v.y() ;
1047 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
1048 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
1049 {
1050 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
1051 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
1052 {
1053 // Z ok. Check phi intersection if reqd
1054 //
1055 if (fPhiFullCutTube)
1056 {
1057 return sd ;
1058 }
1059 else
1060 {
1061 xi = p.x() + sd*v.x() ;
1062 yi = p.y() + sd*v.y() ;
1063 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMax ;
1064 if (cosPsi >= cosHDPhiIT) { return sd ; }
1065 }
1066 } // end if std::fabs(zi)
1067 }
1068 } // end if (sd>=0)
1069 } // end if (d>=0)
1070 } // end if (r>=fRMax)
1071 else
1072 {
1073 // Inside outer radius :
1074 // check not inside, and heading through tubs (-> 0 to in)
1075 if ((t3 > tolIRMin2) && (t2 < 0)
1076 && (std::fabs(p.z()) <= std::fabs(GetCutZ(p))-halfCarTolerance ))
1077 {
1078 // Inside both radii, delta r -ve, inside z extent
1079
1080 if (!fPhiFullCutTube)
1081 {
1082 inum = p.x()*cosCPhi + p.y()*sinCPhi ;
1083 iden = std::sqrt(t3) ;
1084 cosPsi = inum/iden ;
1085 if (cosPsi >= cosHDPhiIT)
1086 {
1087 // In the old version, the small negative tangent for the point
1088 // on surface was not taken in account, and returning 0.0 ...
1089 // New version: check the tangent for the point on surface and
1090 // if no intersection, return kInfinity, if intersection instead
1091 // return sd.
1092 //
1093 c = t3-fRMax*fRMax;
1094 if ( c<=0.0 )
1095 {
1096 return 0.0;
1097 }
1098 else
1099 {
1100 c = c/t1 ;
1101 d = b*b-c;
1102 if ( d>=0.0 )
1103 {
1104 snxt = c/(-b+std::sqrt(d)); // using safe solution
1105 // for quadratic equation
1106 if ( snxt < halfCarTolerance ) { snxt=0; }
1107 return snxt ;
1108 }
1109 else
1110 {
1111 return kInfinity;
1112 }
1113 }
1114 }
1115 }
1116 else
1117 {
1118 // In the old version, the small negative tangent for the point
1119 // on surface was not taken in account, and returning 0.0 ...
1120 // New version: check the tangent for the point on surface and
1121 // if no intersection, return kInfinity, if intersection instead
1122 // return sd.
1123 //
1124 c = t3 - fRMax*fRMax;
1125 if ( c<=0.0 )
1126 {
1127 return 0.0;
1128 }
1129 else
1130 {
1131 c = c/t1 ;
1132 d = b*b-c;
1133 if ( d>=0.0 )
1134 {
1135 snxt= c/(-b+std::sqrt(d)); // using safe solution
1136 // for quadratic equation
1137 if ( snxt < halfCarTolerance ) { snxt=0; }
1138 return snxt ;
1139 }
1140 else
1141 {
1142 return kInfinity;
1143 }
1144 }
1145 } // end if (!fPhiFullCutTube)
1146 } // end if (t3>tolIRMin2)
1147 } // end if (Inside Outer Radius)
1148
1149 if ( fRMin != 0.0 ) // Try inner cylinder intersection
1150 {
1151 c = (t3 - fRMin*fRMin)/t1 ;
1152 d = b*b - c ;
1153 if ( d >= 0.0 ) // If real root
1154 {
1155 // Always want 2nd root - we are outside and know rmax Hit was bad
1156 // - If on surface of rmin also need farthest root
1157
1158 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1159 if (sd >= -10*halfCarTolerance) // check forwards
1160 {
1161 // Check z intersection
1162 //
1163 if (sd < 0.0) { sd = 0.0; }
1164 if (sd>dRmax) // Avoid rounding errors due to precision issues seen
1165 { // 64 bits systems. Split long distances and recompute
1166 G4double fTerm = sd-std::fmod(sd,dRmax);
1167 sd = fTerm + DistanceToIn(p+fTerm*v,v);
1168 }
1169 zi = p.z() + sd*v.z() ;
1170 xi = p.x() + sd*v.x() ;
1171 yi = p.y() + sd*v.y() ;
1172 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
1173 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
1174 {
1175 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
1176 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
1177 {
1178 // Z ok. Check phi
1179 //
1180 if ( fPhiFullCutTube )
1181 {
1182 return sd ;
1183 }
1184 else
1185 {
1186 cosPsi = (xi*cosCPhi + yi*sinCPhi)/fRMin ;
1187 if (cosPsi >= cosHDPhiIT)
1188 {
1189 // Good inner radius isect
1190 // - but earlier phi isect still possible
1191 //
1192 snxt = sd ;
1193 }
1194 }
1195 } // end if std::fabs(zi)
1196 }
1197 } // end if (sd>=0)
1198 } // end if (d>=0)
1199 } // end if (fRMin)
1200 }
1201
1202 // Phi segment intersection
1203 //
1204 // o Tolerant of points inside phi planes by up to kCarTolerance*0.5
1205 //
1206 // o NOTE: Large duplication of code between sphi & ephi checks
1207 // -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane
1208 // intersection check <=0 -> >=0
1209 // -> use some form of loop Construct ?
1210 //
1211 if ( !fPhiFullCutTube )
1212 {
1213 // First phi surface (Starting phi)
1214 //
1215 Comp = v.x()*sinSPhi - v.y()*cosSPhi ;
1216
1217 if ( Comp < 0 ) // Component in outwards normal dirn
1218 {
1219 Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ;
1220
1221 if ( Dist < halfCarTolerance )
1222 {
1223 sd = Dist/Comp ;
1224
1225 if (sd < snxt)
1226 {
1227 if ( sd < 0 ) { sd = 0.0; }
1228 zi = p.z() + sd*v.z() ;
1229 xi = p.x() + sd*v.x() ;
1230 yi = p.y() + sd*v.y() ;
1231 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
1232 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
1233 {
1234 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
1235 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
1236 {
1237 rho2 = xi*xi + yi*yi ;
1238 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1239 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1240 && ( v.y()*cosSPhi - v.x()*sinSPhi > 0 )
1241 && ( v.x()*cosSPhi + v.y()*sinSPhi >= 0 ) )
1242 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1243 && (v.y()*cosSPhi - v.x()*sinSPhi > 0)
1244 && (v.x()*cosSPhi + v.y()*sinSPhi < 0) ) )
1245 {
1246 // z and r intersections good
1247 // - check intersecting with correct half-plane
1248 //
1249 if ((yi*cosCPhi-xi*sinCPhi) <= halfCarTolerance) { snxt = sd; }
1250 }
1251 } //two Z conditions
1252 }
1253 }
1254 }
1255 }
1256
1257 // Second phi surface (Ending phi)
1258 //
1259 Comp = -(v.x()*sinEPhi - v.y()*cosEPhi) ;
1260
1261 if (Comp < 0 ) // Component in outwards normal dirn
1262 {
1263 Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ;
1264
1265 if ( Dist < halfCarTolerance )
1266 {
1267 sd = Dist/Comp ;
1268
1269 if (sd < snxt)
1270 {
1271 if ( sd < 0 ) { sd = 0; }
1272 zi = p.z() + sd*v.z() ;
1273 xi = p.x() + sd*v.x() ;
1274 yi = p.y() + sd*v.y() ;
1275 if ((-xi*fLowNorm.x()-yi*fLowNorm.y()
1276 -(zi+fDz)*fLowNorm.z())>-halfCarTolerance)
1277 {
1278 if ((-xi*fHighNorm.x()-yi*fHighNorm.y()
1279 +(fDz-zi)*fHighNorm.z())>-halfCarTolerance)
1280 {
1281 xi = p.x() + sd*v.x() ;
1282 yi = p.y() + sd*v.y() ;
1283 rho2 = xi*xi + yi*yi ;
1284 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1285 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1286 && (v.x()*sinEPhi - v.y()*cosEPhi > 0)
1287 && (v.x()*cosEPhi + v.y()*sinEPhi >= 0) )
1288 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1289 && (v.x()*sinEPhi - v.y()*cosEPhi > 0)
1290 && (v.x()*cosEPhi + v.y()*sinEPhi < 0) ) )
1291 {
1292 // z and r intersections good
1293 // - check intersecting with correct half-plane
1294 //
1295 if ( (yi*cosCPhi-xi*sinCPhi) >= -halfCarTolerance )
1296 {
1297 snxt = sd;
1298 }
1299 } //?? >=-halfCarTolerance
1300 }
1301 } // two Z conditions
1302 }
1303 }
1304 } // Comp < 0
1305 } // !fPhiFullTube
1306 if ( snxt<halfCarTolerance ) { snxt=0; }
1307
1308 return snxt ;
1309}
double dot(const Hep3Vector &) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
Definition G4CutTubs.cc:884

Referenced by DistanceToIn().

◆ DistanceToOut() [1/2]

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

Implements G4VSolid.

Definition at line 1830 of file G4CutTubs.cc.

1831{
1832 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho;
1833 G4ThreeVector vZ=G4ThreeVector(0,0,fDz);
1834
1835 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ; // Distance to R
1836
1837 safRMin = rho - fRMin ;
1838 safRMax = fRMax - rho ;
1839
1840 // Distances to ZCut(Low/High)
1841
1842 // Dist to Low Cut
1843 //
1844 safZLow = std::fabs((p+vZ).dot(fLowNorm));
1845
1846 // Dist to High Cut
1847 //
1848 safZHigh = std::fabs((p-vZ).dot(fHighNorm));
1849 safe = std::min(safZLow,safZHigh);
1850
1851 if ( safRMin < safe ) { safe = safRMin; }
1852 if ( safRMax< safe ) { safe = safRMax; }
1853
1854 // Check if phi divided, Calc distances closest phi plane
1855 //
1856 if ( !fPhiFullCutTube )
1857 {
1858 if ( p.y()*cosCPhi-p.x()*sinCPhi <= 0 )
1859 {
1860 safePhi = -(p.x()*sinSPhi - p.y()*cosSPhi) ;
1861 }
1862 else
1863 {
1864 safePhi = (p.x()*sinEPhi - p.y()*cosEPhi) ;
1865 }
1866 if (safePhi < safe) { safe = safePhi ; }
1867 }
1868 if ( safe < 0 ) { safe = 0; }
1869
1870 return safe ;
1871}

◆ DistanceToOut() [2/2]

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

Implements G4VSolid.

Definition at line 1397 of file G4CutTubs.cc.

1402{
1403 enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kPZ,kMZ};
1404
1405 ESide side=kNull , sider=kNull, sidephi=kNull ;
1406 G4double snxt=kInfinity, srd=kInfinity,sz=kInfinity, sphi=kInfinity ;
1407 G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
1408 G4double distZLow,distZHigh,calfH,calfL;
1409 G4ThreeVector vZ=G4ThreeVector(0,0,fDz);
1410
1411 // Vars for phi intersection:
1412 //
1413 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1414
1415 // Z plane intersection
1416 // Distances to ZCut(Low/High)
1417
1418 // dist to Low Cut
1419 //
1420 distZLow =(p+vZ).dot(fLowNorm);
1421
1422 // dist to High Cut
1423 //
1424 distZHigh = (p-vZ).dot(fHighNorm);
1425
1426 calfH = v.dot(fHighNorm);
1427 calfL = v.dot(fLowNorm);
1428
1429 if (calfH > 0 )
1430 {
1431 if ( distZHigh < halfCarTolerance )
1432 {
1433 snxt = -distZHigh/calfH ;
1434 side = kPZ ;
1435 }
1436 else
1437 {
1438 if (calcNorm)
1439 {
1440 *n = G4ThreeVector(0,0,1) ;
1441 *validNorm = true ;
1442 }
1443 return snxt = 0 ;
1444 }
1445 }
1446 if ( calfL>0)
1447 {
1448
1449 if ( distZLow < halfCarTolerance )
1450 {
1451 sz = -distZLow/calfL ;
1452 if(sz<snxt){
1453 snxt=sz;
1454 side = kMZ ;
1455 }
1456
1457 }
1458 else
1459 {
1460 if (calcNorm)
1461 {
1462 *n = G4ThreeVector(0,0,-1) ;
1463 *validNorm = true ;
1464 }
1465 return snxt = 0.0 ;
1466 }
1467 }
1468 if((calfH<=0)&&(calfL<=0))
1469 {
1470 snxt = kInfinity ; // Travel perpendicular to z axis
1471 side = kNull;
1472 }
1473 // Radial Intersections
1474 //
1475 // Find intersection with cylinders at rmax/rmin
1476 // Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc.
1477 //
1478 // Intersects with x^2+y^2=R^2
1479 //
1480 // Hence (v.x^2+v.y^2)t^2+ 2t(p.x*v.x+p.y*v.y)+p.x^2+p.y^2-R^2=0
1481 //
1482 // t1 t2 t3
1483
1484 t1 = 1.0 - v.z()*v.z() ; // since v normalised
1485 t2 = p.x()*v.x() + p.y()*v.y() ;
1486 t3 = p.x()*p.x() + p.y()*p.y() ;
1487
1488 if ( snxt > 10*(fDz+fRMax) ) { roi2 = 2*fRMax*fRMax; }
1489 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; } // radius^2 on +-fDz
1490
1491 if ( t1 > 0 ) // Check not parallel
1492 {
1493 // Calculate srd, r exit distance
1494
1495 if ( (t2 >= 0.0) && (roi2 > fRMax*(fRMax + kRadTolerance)) )
1496 {
1497 // Delta r not negative => leaving via rmax
1498
1499 deltaR = t3 - fRMax*fRMax ;
1500
1501 // NOTE: Should use rho-fRMax<-kRadTolerance*0.5
1502 // - avoid sqrt for efficiency
1503
1504 if ( deltaR < -kRadTolerance*fRMax )
1505 {
1506 b = t2/t1 ;
1507 c = deltaR/t1 ;
1508 d2 = b*b-c;
1509 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1510 else { srd = 0.; }
1511 sider = kRMax ;
1512 }
1513 else
1514 {
1515 // On tolerant boundary & heading outwards (or perpendicular to)
1516 // outer radial surface -> leaving immediately
1517
1518 if ( calcNorm )
1519 {
1520 *n = G4ThreeVector(p.x()/fRMax,p.y()/fRMax,0) ;
1521 *validNorm = true ;
1522 }
1523 return snxt = 0 ; // Leaving by rmax immediately
1524 }
1525 }
1526 else if ( t2 < 0. ) // i.e. t2 < 0; Possible rmin intersection
1527 {
1528 roMin2 = t3 - t2*t2/t1 ; // min ro2 of the plane of movement
1529
1530 if ( (fRMin != 0.0) && (roMin2 < fRMin*(fRMin - kRadTolerance)) )
1531 {
1532 deltaR = t3 - fRMin*fRMin ;
1533 b = t2/t1 ;
1534 c = deltaR/t1 ;
1535 d2 = b*b - c ;
1536
1537 if ( d2 >= 0 ) // Leaving via rmin
1538 {
1539 // NOTE: SHould use rho-rmin>kRadTolerance*0.5
1540 // - avoid sqrt for efficiency
1541
1542 if (deltaR > kRadTolerance*fRMin)
1543 {
1544 srd = c/(-b+std::sqrt(d2));
1545 sider = kRMin ;
1546 }
1547 else
1548 {
1549 if ( calcNorm ) { *validNorm = false; } // Concave side
1550 return snxt = 0.0;
1551 }
1552 }
1553 else // No rmin intersect -> must be rmax intersect
1554 {
1555 deltaR = t3 - fRMax*fRMax ;
1556 c = deltaR/t1 ;
1557 d2 = b*b-c;
1558 if( d2 >=0. )
1559 {
1560 srd = -b + std::sqrt(d2) ;
1561 sider = kRMax ;
1562 }
1563 else // Case: On the border+t2<kRadTolerance
1564 // (v is perpendicular to the surface)
1565 {
1566 if (calcNorm)
1567 {
1568 *n = G4ThreeVector(p.x()/fRMax,p.y()/fRMax,0) ;
1569 *validNorm = true ;
1570 }
1571 return snxt = 0.0;
1572 }
1573 }
1574 }
1575 else if ( roi2 > fRMax*(fRMax + kRadTolerance) )
1576 // No rmin intersect -> must be rmax intersect
1577 {
1578 deltaR = t3 - fRMax*fRMax ;
1579 b = t2/t1 ;
1580 c = deltaR/t1;
1581 d2 = b*b-c;
1582 if( d2 >= 0 )
1583 {
1584 srd = -b + std::sqrt(d2) ;
1585 sider = kRMax ;
1586 }
1587 else // Case: On the border+t2<kRadTolerance
1588 // (v is perpendicular to the surface)
1589 {
1590 if (calcNorm)
1591 {
1592 *n = G4ThreeVector(p.x()/fRMax,p.y()/fRMax,0) ;
1593 *validNorm = true ;
1594 }
1595 return snxt = 0.0;
1596 }
1597 }
1598 }
1599 // Phi Intersection
1600
1601 if ( !fPhiFullCutTube )
1602 {
1603 // add angle calculation with correction
1604 // of the difference in domain of atan2 and Sphi
1605 //
1606 vphi = std::atan2(v.y(),v.x()) ;
1607
1608 if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
1609 else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; }
1610
1611
1612 if ( (p.x() != 0.0) || (p.y() != 0.0) ) // Check if on z axis (rho not needed later)
1613 {
1614 // pDist -ve when inside
1615
1616 pDistS = p.x()*sinSPhi - p.y()*cosSPhi ;
1617 pDistE = -p.x()*sinEPhi + p.y()*cosEPhi ;
1618
1619 // Comp -ve when in direction of outwards normal
1620
1621 compS = -sinSPhi*v.x() + cosSPhi*v.y() ;
1622 compE = sinEPhi*v.x() - cosEPhi*v.y() ;
1623
1624 sidephi = kNull;
1625
1626 if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
1627 && (pDistE <= halfCarTolerance) ) )
1628 || ( (fDPhi > pi) && ((pDistS <= halfCarTolerance)
1629 || (pDistE <= halfCarTolerance) ) ) )
1630 {
1631 // Inside both phi *full* planes
1632
1633 if ( compS < 0 )
1634 {
1635 sphi = pDistS/compS ;
1636
1637 if (sphi >= -halfCarTolerance)
1638 {
1639 xi = p.x() + sphi*v.x() ;
1640 yi = p.y() + sphi*v.y() ;
1641
1642 // Check intersecting with correct half-plane
1643 // (if not -> no intersect)
1644 //
1645 if( (std::fabs(xi)<=kCarTolerance)
1646 && (std::fabs(yi)<=kCarTolerance) )
1647 {
1648 sidephi = kSPhi;
1649 if (((fSPhi-halfAngTolerance)<=vphi)
1650 &&((fSPhi+fDPhi+halfAngTolerance)>=vphi))
1651 {
1652 sphi = kInfinity;
1653 }
1654 }
1655 else if ( yi*cosCPhi-xi*sinCPhi >=0 )
1656 {
1657 sphi = kInfinity ;
1658 }
1659 else
1660 {
1661 sidephi = kSPhi ;
1662 if ( pDistS > -halfCarTolerance )
1663 {
1664 sphi = 0.0 ; // Leave by sphi immediately
1665 }
1666 }
1667 }
1668 else
1669 {
1670 sphi = kInfinity ;
1671 }
1672 }
1673 else
1674 {
1675 sphi = kInfinity ;
1676 }
1677
1678 if ( compE < 0 )
1679 {
1680 sphi2 = pDistE/compE ;
1681
1682 // Only check further if < starting phi intersection
1683 //
1684 if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
1685 {
1686 xi = p.x() + sphi2*v.x() ;
1687 yi = p.y() + sphi2*v.y() ;
1688
1689 if ((std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance))
1690 {
1691 // Leaving via ending phi
1692 //
1693 if( (fSPhi-halfAngTolerance > vphi)
1694 ||(fSPhi+fDPhi+halfAngTolerance < vphi) )
1695 {
1696 sidephi = kEPhi ;
1697 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1698 else { sphi = 0.0 ; }
1699 }
1700 }
1701 else // Check intersecting with correct half-plane
1702
1703 if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
1704 {
1705 // Leaving via ending phi
1706 //
1707 sidephi = kEPhi ;
1708 if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
1709 else { sphi = 0.0 ; }
1710 }
1711 }
1712 }
1713 }
1714 else
1715 {
1716 sphi = kInfinity ;
1717 }
1718 }
1719 else
1720 {
1721 // On z axis + travel not || to z axis -> if phi of vector direction
1722 // within phi of shape, Step limited by rmax, else Step =0
1723
1724 if ( (fSPhi - halfAngTolerance <= vphi)
1725 && (vphi <= fSPhi + fDPhi + halfAngTolerance ) )
1726 {
1727 sphi = kInfinity ;
1728 }
1729 else
1730 {
1731 sidephi = kSPhi ; // arbitrary
1732 sphi = 0.0 ;
1733 }
1734 }
1735 if (sphi < snxt) // Order intersecttions
1736 {
1737 snxt = sphi ;
1738 side = sidephi ;
1739 }
1740 }
1741 if (srd < snxt) // Order intersections
1742 {
1743 snxt = srd ;
1744 side = sider ;
1745 }
1746 }
1747 if (calcNorm)
1748 {
1749 switch(side)
1750 {
1751 case kRMax:
1752 // Note: returned vector not normalised
1753 // (divide by fRMax for unit vector)
1754 //
1755 xi = p.x() + snxt*v.x() ;
1756 yi = p.y() + snxt*v.y() ;
1757 *n = G4ThreeVector(xi/fRMax,yi/fRMax,0) ;
1758 *validNorm = true ;
1759 break ;
1760
1761 case kRMin:
1762 *validNorm = false ; // Rmin is inconvex
1763 break ;
1764
1765 case kSPhi:
1766 if ( fDPhi <= pi )
1767 {
1768 *n = G4ThreeVector(sinSPhi,-cosSPhi,0) ;
1769 *validNorm = true ;
1770 }
1771 else
1772 {
1773 *validNorm = false ;
1774 }
1775 break ;
1776
1777 case kEPhi:
1778 if (fDPhi <= pi)
1779 {
1780 *n = G4ThreeVector(-sinEPhi,cosEPhi,0) ;
1781 *validNorm = true ;
1782 }
1783 else
1784 {
1785 *validNorm = false ;
1786 }
1787 break ;
1788
1789 case kPZ:
1790 *n = fHighNorm ;
1791 *validNorm = true ;
1792 break ;
1793
1794 case kMZ:
1795 *n = fLowNorm ;
1796 *validNorm = true ;
1797 break ;
1798
1799 default:
1800 G4cout << G4endl ;
1801 DumpInfo();
1802 std::ostringstream message;
1803 G4long oldprc = message.precision(16);
1804 message << "Undefined side for valid surface normal to solid."
1805 << G4endl
1806 << "Position:" << G4endl << G4endl
1807 << "p.x() = " << p.x()/mm << " mm" << G4endl
1808 << "p.y() = " << p.y()/mm << " mm" << G4endl
1809 << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl
1810 << "Direction:" << G4endl << G4endl
1811 << "v.x() = " << v.x() << G4endl
1812 << "v.y() = " << v.y() << G4endl
1813 << "v.z() = " << v.z() << G4endl << G4endl
1814 << "Proposed distance :" << G4endl << G4endl
1815 << "snxt = " << snxt/mm << " mm" << G4endl ;
1816 message.precision(oldprc) ;
1817 G4Exception("G4CutTubs::DistanceToOut(p,v,..)", "GeomSolids1002",
1818 JustWarning, message);
1819 break ;
1820 }
1821 }
1822 if ( snxt<halfCarTolerance ) { snxt=0 ; }
1823 return snxt ;
1824}
ESide
Definition G4Sphere.cc:61
@ kRMax
Definition G4Sphere.cc:61
@ kNull
Definition G4Sphere.cc:61
@ kSPhi
Definition G4Sphere.cc:61
@ kRMin
Definition G4Sphere.cc:61
@ kEPhi
Definition G4Sphere.cc:61
long G4long
Definition G4Types.hh:87
G4GLOB_DLL std::ostream G4cout

◆ GetCosEndPhi()

G4double G4CutTubs::GetCosEndPhi ( ) const
inline

Referenced by BoundingLimits(), and CalculateExtent().

◆ GetCosStartPhi()

G4double G4CutTubs::GetCosStartPhi ( ) const
inline

◆ GetCubicVolume()

G4double G4CutTubs::GetCubicVolume ( )
overridevirtual

Reimplemented from G4VSolid.

Definition at line 222 of file G4CutTubs.cc.

223{
224 constexpr G4int nphi = 200, nrho = 100;
225
226 if (fCubicVolume == 0.)
227 {
228 // get parameters
229 G4double rmin = GetInnerRadius();
230 G4double rmax = GetOuterRadius();
232 G4double sphi = GetStartPhiAngle();
233 G4double dphi = GetDeltaPhiAngle();
234
235 // calculate volume
236 G4double volume = dz*dphi*(rmax*rmax - rmin*rmin);
237 if (dphi < twopi) // make recalculation
238 {
239 // set values for calculation of h - distance between
240 // opposite points on bases
241 G4ThreeVector nbot = GetLowNorm();
242 G4ThreeVector ntop = GetHighNorm();
243 G4double nx = nbot.x()/nbot.z() - ntop.x()/ntop.z();
244 G4double ny = nbot.y()/nbot.z() - ntop.y()/ntop.z();
245
246 // compute volume by integration
247 G4double delrho = (rmax - rmin)/nrho;
248 G4double delphi = dphi/nphi;
249 volume = 0.;
250 for (G4int irho=0; irho<nrho; ++irho)
251 {
252 G4double r1 = rmin + delrho*irho;
253 G4double r2 = rmin + delrho*(irho + 1);
254 G4double rho = 0.5*(r1 + r2);
255 G4double sector = 0.5*delphi*(r2*r2 - r1*r1);
256 for (G4int iphi=0; iphi<nphi; ++iphi)
257 {
258 G4double phi = sphi + delphi*(iphi + 0.5);
259 G4double h = nx*rho*std::cos(phi) + ny*rho*std::sin(phi) + 2.*dz;
260 volume += sector*h;
261 }
262 }
263 }
264 fCubicVolume = volume;
265 }
266 return fCubicVolume;
267}
G4double fCubicVolume
Definition G4CSGSolid.hh:68
G4double GetStartPhiAngle() const

◆ GetCutZ()

G4double G4CutTubs::GetCutZ ( const G4ThreeVector & p) const
protected

Definition at line 2140 of file G4CutTubs.cc.

2141{
2142 G4double newz = p.z(); // p.z() should be either +fDz or -fDz
2143 if (p.z()<0)
2144 {
2145 if(fLowNorm.z()!=0.)
2146 {
2147 newz = -fDz-(p.x()*fLowNorm.x()+p.y()*fLowNorm.y())/fLowNorm.z();
2148 }
2149 }
2150 else
2151 {
2152 if(fHighNorm.z()!=0.)
2153 {
2154 newz = fDz-(p.x()*fHighNorm.x()+p.y()*fHighNorm.y())/fHighNorm.z();
2155 }
2156 }
2157 return newz;
2158}

Referenced by CreatePolyhedron(), and DistanceToIn().

◆ GetDeltaPhiAngle()

◆ GetEntityType()

G4GeometryType G4CutTubs::GetEntityType ( ) const
overridevirtual

Implements G4VSolid.

Definition at line 1877 of file G4CutTubs.cc.

1878{
1879 return {"G4CutTubs"};
1880}

◆ GetHighNorm()

◆ GetInnerRadius()

G4double G4CutTubs::GetInnerRadius ( ) const
inline

◆ GetLowNorm()

◆ GetOuterRadius()

◆ GetPointOnSurface()

G4ThreeVector G4CutTubs::GetPointOnSurface ( ) const
overridevirtual

Reimplemented from G4VSolid.

Definition at line 1920 of file G4CutTubs.cc.

1921{
1922 // Set min and max z
1923 if (fZMin == 0. && fZMax == 0.)
1924 {
1925 G4AutoLock l(&zminmaxMutex);
1926 G4ThreeVector bmin, bmax;
1927 BoundingLimits(bmin,bmax);
1928 fZMin = bmin.z();
1929 fZMax = bmax.z();
1930 l.unlock();
1931 }
1932
1933 // Set parameters
1934 G4double hmax = fZMax - fZMin;
1935 G4double sphi = fSPhi;
1936 G4double dphi = fDPhi;
1937 G4double rmin = fRMin;
1938 G4double rmax = fRMax;
1939 G4double rrmax = rmax*rmax;
1940 G4double rrmin = rmin*rmin;
1941
1942 G4ThreeVector nbot = GetLowNorm();
1943 G4ThreeVector ntop = GetHighNorm();
1944
1945 // Set array of surface areas
1946 G4double sbase = 0.5*dphi*(rrmax - rrmin);
1947 G4double sbot = sbase/std::abs(nbot.z());
1948 G4double stop = sbase/std::abs(ntop.z());
1949 G4double scut = (dphi == twopi) ? 0. : hmax*(rmax - rmin);
1950 G4double ssurf[6] = { scut, scut, sbot, stop, dphi*rmax*hmax, dphi*rmin*hmax };
1951 ssurf[1] += ssurf[0];
1952 ssurf[2] += ssurf[1];
1953 ssurf[3] += ssurf[2];
1954 ssurf[4] += ssurf[3];
1955 ssurf[5] += ssurf[4];
1956
1957 constexpr G4int ntry = 100000;
1958 for (G4int i=0; i<ntry; ++i)
1959 {
1960 // Select surface
1961 G4double select = ssurf[5]*G4QuickRand();
1962 G4int k = 5;
1963 k -= (G4int)(select <= ssurf[4]);
1964 k -= (G4int)(select <= ssurf[3]);
1965 k -= (G4int)(select <= ssurf[2]);
1966 k -= (G4int)(select <= ssurf[1]);
1967 k -= (G4int)(select <= ssurf[0]);
1968
1969 // Generate point on selected surface (rejection sampling)
1970 G4ThreeVector p(0,0,0);
1971 switch(k)
1972 {
1973 case 0: // cut at start phi
1974 {
1975 G4double r = rmin + (rmax - rmin)*G4QuickRand();
1976 p.set(r*cosSPhi, r*sinSPhi, fZMin + hmax*G4QuickRand());
1977 break;
1978 }
1979 case 1: // cut at end phi
1980 {
1981 G4double r = rmin + (rmax - rmin)*G4QuickRand();
1982 p.set(r*cosEPhi, r*sinEPhi, fZMin + hmax*G4QuickRand());
1983 break;
1984 }
1985 case 2: // base at low z
1986 {
1987 G4double r = std::sqrt(rrmin + (rrmax - rrmin)*G4QuickRand());
1988 G4double phi = sphi + dphi*G4QuickRand();
1989 G4double x = r*std::cos(phi);
1990 G4double y = r*std::sin(phi);
1991 G4double z = -fDz - (x*nbot.x() + y*nbot.y())/nbot.z();
1992 return {x, y, z};
1993 }
1994 case 3: // base at high z
1995 {
1996 G4double r = std::sqrt(rrmin + (rrmax - rrmin)*G4QuickRand());
1997 G4double phi = sphi + dphi*G4QuickRand();
1998 G4double x = r*std::cos(phi);
1999 G4double y = r*std::sin(phi);
2000 G4double z = fDz - (x*ntop.x() + y*ntop.y())/ntop.z();
2001 return {x, y, z};
2002 }
2003 case 4: // external lateral surface
2004 {
2005 G4double phi = sphi + dphi*G4QuickRand();
2006 G4double z = fZMin + hmax*G4QuickRand();
2007 G4double x = rmax*std::cos(phi);
2008 G4double y = rmax*std::sin(phi);
2009 p.set(x, y, z);
2010 break;
2011 }
2012 case 5: // internal lateral surface
2013 {
2014 G4double phi = sphi + dphi*G4QuickRand();
2015 G4double z = fZMin + hmax*G4QuickRand();
2016 G4double x = rmin*std::cos(phi);
2017 G4double y = rmin*std::sin(phi);
2018 p.set(x, y, z);
2019 break;
2020 }
2021 }
2022 if ((ntop.dot(p) - fDz*ntop.z()) > 0.) continue;
2023 if ((nbot.dot(p) + fDz*nbot.z()) > 0.) continue;
2024 return p;
2025 }
2026 // Just in case, if all attempts to generate a point have failed
2027 // Normally should never happen
2028 G4double x = rmax*std::cos(sphi + 0.5*dphi);
2029 G4double y = rmax*std::sin(sphi + 0.5*dphi);
2030 G4double z = fDz - (x*ntop.x() + y*ntop.y())/ntop.z();
2031 return {x, y, z};
2032}
G4double G4QuickRand()

◆ GetSinEndPhi()

G4double G4CutTubs::GetSinEndPhi ( ) const
inline

Referenced by BoundingLimits(), and CalculateExtent().

◆ GetSinStartPhi()

G4double G4CutTubs::GetSinStartPhi ( ) const
inline

◆ GetStartPhiAngle()

G4double G4CutTubs::GetStartPhiAngle ( ) const
inline

◆ GetSurfaceArea()

G4double G4CutTubs::GetSurfaceArea ( )
overridevirtual

Reimplemented from G4VSolid.

Definition at line 273 of file G4CutTubs.cc.

274{
275 constexpr G4int nphi = 400;
276
277 if (fSurfaceArea == 0.)
278 {
279 // get parameters
280 G4double rmin = GetInnerRadius();
281 G4double rmax = GetOuterRadius();
283 G4double sphi = GetStartPhiAngle();
284 G4double dphi = GetDeltaPhiAngle();
285 G4ThreeVector nbot = GetLowNorm();
286 G4ThreeVector ntop = GetHighNorm();
287
288 // calculate lateral surface area
289 G4double sinner = 2.*dz*dphi*rmin;
290 G4double souter = 2.*dz*dphi*rmax;
291 if (dphi < twopi) // make recalculation
292 {
293 // set values for calculation of h - distance between
294 // opposite points on bases
295 G4double nx = nbot.x()/nbot.z() - ntop.x()/ntop.z();
296 G4double ny = nbot.y()/nbot.z() - ntop.y()/ntop.z();
297
298 // compute lateral surface area by integration
299 G4double delphi = dphi/nphi;
300 sinner = 0.;
301 souter = 0.;
302 for (G4int iphi=0; iphi<nphi; ++iphi)
303 {
304 G4double phi = sphi + delphi*(iphi + 0.5);
305 G4double cosphi = std::cos(phi);
306 G4double sinphi = std::sin(phi);
307 sinner += rmin*(nx*cosphi + ny*sinphi) + 2.*dz;
308 souter += rmax*(nx*cosphi + ny*sinphi) + 2.*dz;
309 }
310 sinner *= delphi*rmin;
311 souter *= delphi*rmax;
312 }
313 // set surface area
314 G4double scut = (dphi == twopi) ? 0. : 2.*dz*(rmax - rmin);
315 G4double szero = 0.5*dphi*(rmax*rmax - rmin*rmin);
316 G4double slow = szero/std::abs(nbot.z());
317 G4double shigh = szero/std::abs(ntop.z());
318 fSurfaceArea = sinner + souter + 2.*scut + slow + shigh;
319 }
320 return fSurfaceArea;
321}
G4double fSurfaceArea
Definition G4CSGSolid.hh:69

◆ GetZHalfLength()

◆ Initialize()

void G4CutTubs::Initialize ( )
inlineprotected

◆ InitializeTrigonometry()

void G4CutTubs::InitializeTrigonometry ( )
inlineprotected

◆ Inside()

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

Implements G4VSolid.

Definition at line 555 of file G4CutTubs.cc.

556{
557 G4ThreeVector vZ = G4ThreeVector(0,0,fDz);
558 EInside in = kInside;
559
560 // Check the lower cut plane
561 //
562 G4double zinLow =(p+vZ).dot(fLowNorm);
563 if (zinLow > halfCarTolerance) { return kOutside; }
564
565 // Check the higher cut plane
566 //
567 G4double zinHigh = (p-vZ).dot(fHighNorm);
568 if (zinHigh > halfCarTolerance) { return kOutside; }
569
570 // Check radius
571 //
572 G4double r2 = p.x()*p.x() + p.y()*p.y() ;
573
574 G4double tolRMin = fRMin - halfRadTolerance;
575 G4double tolRMax = fRMax + halfRadTolerance;
576 if ( tolRMin < 0 ) { tolRMin = 0; }
577
578 if (r2 < tolRMin*tolRMin || r2 > tolRMax*tolRMax) { return kOutside; }
579
580 // Check Phi cut
581 //
582 if(!fPhiFullCutTube)
583 {
584 if ((tolRMin == 0) && (std::fabs(p.x()) <= halfCarTolerance)
585 && (std::fabs(p.y()) <= halfCarTolerance))
586 {
587 return kSurface;
588 }
589
590 G4double phi0 = std::atan2(p.y(),p.x());
591 G4double phi1 = phi0 - twopi;
592 G4double phi2 = phi0 + twopi;
593
594 in = kOutside;
595 G4double sphi = fSPhi - halfAngTolerance;
596 G4double ephi = sphi + fDPhi + kAngTolerance;
597 if ((phi0 >= sphi && phi0 <= ephi) ||
598 (phi1 >= sphi && phi1 <= ephi) ||
599 (phi2 >= sphi && phi2 <= ephi)) in = kSurface;
600 if (in == kOutside) { return kOutside; }
601
602 sphi += kAngTolerance;
603 ephi -= kAngTolerance;
604 if ((phi0 >= sphi && phi0 <= ephi) ||
605 (phi1 >= sphi && phi1 <= ephi) ||
606 (phi2 >= sphi && phi2 <= ephi)) in = kInside;
607 if (in == kSurface) { return kSurface; }
608 }
609
610 // Check on the Surface for Z
611 //
612 if ((zinLow >= -halfCarTolerance) || (zinHigh >= -halfCarTolerance))
613 {
614 return kSurface;
615 }
616
617 // Check on the Surface for R
618 //
619 if (fRMin != 0.0) { tolRMin = fRMin + halfRadTolerance; }
620 else { tolRMin = 0; }
621 tolRMax = fRMax - halfRadTolerance;
622 if (((r2 <= tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax)) &&
623 (r2 >= halfRadTolerance*halfRadTolerance))
624 {
625 return kSurface;
626 }
627
628 return in;
629}
EInside
Definition geomdefs.hh:67
@ kInside
Definition geomdefs.hh:70
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69

◆ IsCrossingCutPlanes()

G4bool G4CutTubs::IsCrossingCutPlanes ( ) const
protected

Definition at line 2105 of file G4CutTubs.cc.

2106{
2107 constexpr G4int npoints = 30;
2108
2109 // set values for calculation of h - distance between
2110 // opposite points on bases
2111 G4ThreeVector nbot = GetLowNorm();
2112 G4ThreeVector ntop = GetHighNorm();
2113 if (std::abs(nbot.z()) < kCarTolerance) return true;
2114 if (std::abs(ntop.z()) < kCarTolerance) return true;
2115 G4double nx = nbot.x()/nbot.z() - ntop.x()/ntop.z();
2116 G4double ny = nbot.y()/nbot.z() - ntop.y()/ntop.z();
2117
2118 // check points
2119 G4double cosphi = GetCosStartPhi();
2120 G4double sinphi = GetSinStartPhi();
2121 G4double delphi = GetDeltaPhiAngle()/npoints;
2122 G4double cosdel = std::cos(delphi);
2123 G4double sindel = std::sin(delphi);
2124 G4double hzero = 2.*GetZHalfLength()/GetOuterRadius();
2125 for (G4int i=0; i<npoints+1; ++i)
2126 {
2127 G4double h = nx*cosphi + ny*sinphi + hzero;
2128 if (h < 0.) return true;
2129 G4double sintmp = sinphi;
2130 sinphi = sintmp*cosdel + cosphi*sindel;
2131 cosphi = cosphi*cosdel - sintmp*sindel;
2132 }
2133 return false;
2134}

Referenced by G4CutTubs().

◆ operator=()

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

Definition at line 189 of file G4CutTubs.cc.

190{
191 // Check assignment to self
192 //
193 if (this == &rhs) { return *this; }
194
195 // Copy base class data
196 //
198
199 // Copy data
200 //
201 kRadTolerance = rhs.kRadTolerance; kAngTolerance = rhs.kAngTolerance;
202 fRMin = rhs.fRMin; fRMax = rhs.fRMax; fDz = rhs.fDz;
203 fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi;
204 fZMin = rhs.fZMin; fZMax = rhs.fZMax;
205 sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPhi;
206 cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = rhs.cosHDPhiIT;
207 sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPhi;
208 sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPhi;
209 fPhiFullCutTube = rhs.fPhiFullCutTube;
210 halfCarTolerance = rhs.halfCarTolerance;
211 halfRadTolerance = rhs.halfRadTolerance;
212 halfAngTolerance = rhs.halfAngTolerance;
213 fLowNorm = rhs.fLowNorm; fHighNorm = rhs.fHighNorm;
214
215 return *this;
216}
G4CSGSolid & operator=(const G4CSGSolid &rhs)
Definition G4CSGSolid.cc:89

◆ SetDeltaPhiAngle()

void G4CutTubs::SetDeltaPhiAngle ( G4double newDPhi)
inline

◆ SetInnerRadius()

void G4CutTubs::SetInnerRadius ( G4double newRMin)
inline

◆ SetOuterRadius()

void G4CutTubs::SetOuterRadius ( G4double newRMax)
inline

◆ SetStartPhiAngle()

void G4CutTubs::SetStartPhiAngle ( G4double newSPhi,
G4bool trig = true )
inline

◆ SetZHalfLength()

void G4CutTubs::SetZHalfLength ( G4double newDz)
inline

◆ StreamInfo()

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

Reimplemented from G4CSGSolid.

Definition at line 1895 of file G4CutTubs.cc.

1896{
1897 G4long oldprc = os.precision(16);
1898 os << "-----------------------------------------------------------\n"
1899 << " *** Dump for solid - " << GetName() << " ***\n"
1900 << " ===================================================\n"
1901 << " Solid type: G4CutTubs\n"
1902 << " Parameters: \n"
1903 << " inner radius : " << fRMin/mm << " mm \n"
1904 << " outer radius : " << fRMax/mm << " mm \n"
1905 << " half length Z: " << fDz/mm << " mm \n"
1906 << " starting phi : " << fSPhi/degree << " degrees \n"
1907 << " delta phi : " << fDPhi/degree << " degrees \n"
1908 << " low Norm : " << fLowNorm << " \n"
1909 << " high Norm : " <<fHighNorm << " \n"
1910 << "-----------------------------------------------------------\n";
1911 os.precision(oldprc);
1912
1913 return os;
1914}

◆ SurfaceNormal()

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

Implements G4VSolid.

Definition at line 637 of file G4CutTubs.cc.

638{
639 G4int noSurfaces = 0;
640 G4double rho, pPhi;
641 G4double distZLow,distZHigh, distRMin, distRMax;
642 G4double distSPhi = kInfinity, distEPhi = kInfinity;
643 G4ThreeVector vZ=G4ThreeVector(0,0,fDz);
644
645 G4ThreeVector norm, sumnorm(0.,0.,0.);
646 G4ThreeVector nZ = G4ThreeVector(0, 0, 1.0);
647 G4ThreeVector nR, nPs, nPe;
648
649 rho = std::sqrt(p.x()*p.x() + p.y()*p.y());
650
651 distRMin = std::fabs(rho - fRMin);
652 distRMax = std::fabs(rho - fRMax);
653
654 // dist to Low Cut
655 //
656 distZLow =std::fabs((p+vZ).dot(fLowNorm));
657
658 // dist to High Cut
659 //
660 distZHigh = std::fabs((p-vZ).dot(fHighNorm));
661
662 if (!fPhiFullCutTube) // Protected against (0,0,z)
663 {
664 if ( rho > halfCarTolerance )
665 {
666 pPhi = std::atan2(p.y(),p.x());
667
668 if(pPhi < fSPhi- halfCarTolerance) { pPhi += twopi; }
669 else if(pPhi > fSPhi+fDPhi+ halfCarTolerance) { pPhi -= twopi; }
670
671 distSPhi = std::fabs(pPhi - fSPhi);
672 distEPhi = std::fabs(pPhi - fSPhi - fDPhi);
673 }
674 else if( fRMin == 0.0 )
675 {
676 distSPhi = 0.;
677 distEPhi = 0.;
678 }
679 nPs = G4ThreeVector( sinSPhi, -cosSPhi, 0 );
680 nPe = G4ThreeVector( -sinEPhi, cosEPhi, 0 );
681 }
682 if ( rho > halfCarTolerance ) { nR = G4ThreeVector(p.x()/rho,p.y()/rho,0); }
683
684 if( distRMax <= halfCarTolerance )
685 {
686 ++noSurfaces;
687 sumnorm += nR;
688 }
689 if( (fRMin != 0.0) && (distRMin <= halfCarTolerance) )
690 {
691 ++noSurfaces;
692 sumnorm -= nR;
693 }
694 if( fDPhi < twopi )
695 {
696 if (distSPhi <= halfAngTolerance)
697 {
698 ++noSurfaces;
699 sumnorm += nPs;
700 }
701 if (distEPhi <= halfAngTolerance)
702 {
703 ++noSurfaces;
704 sumnorm += nPe;
705 }
706 }
707 if (distZLow <= halfCarTolerance)
708 {
709 ++noSurfaces;
710 sumnorm += fLowNorm;
711 }
712 if (distZHigh <= halfCarTolerance)
713 {
714 ++noSurfaces;
715 sumnorm += fHighNorm;
716 }
717 if ( noSurfaces == 0 )
718 {
719#ifdef G4CSGDEBUG
720 G4Exception("G4CutTubs::SurfaceNormal(p)", "GeomSolids1002",
721 JustWarning, "Point p is not on surface !?" );
722 G4int oldprc = G4cout.precision(20);
723 G4cout<< "G4CutTubs::SN ( "<<p.x()<<", "<<p.y()<<", "<<p.z()<<" ); "
724 << G4endl << G4endl;
725 G4cout.precision(oldprc) ;
726#endif
727 norm = ApproxSurfaceNormal(p);
728 }
729 else if ( noSurfaces == 1 ) { norm = sumnorm; }
730 else { norm = sumnorm.unit(); }
731
732 return norm;
733}
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
Definition G4CutTubs.cc:740

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