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

G4EllipticalCone is a full cone with elliptical base which can be cut in Z. The height in Z corresponds to where the elliptical cone hits the Z-axis if it had no Z cut. More...

#include <G4EllipticalCone.hh>

Inheritance diagram for G4EllipticalCone:

Public Member Functions

 G4EllipticalCone (const G4String &pName, G4double pxSemiAxis, G4double pySemiAxis, G4double zMax, G4double pzTopCut)
 ~G4EllipticalCone () override
G4double GetSemiAxisMin () const
G4double GetSemiAxisMax () const
G4double GetSemiAxisX () const
G4double GetSemiAxisY () const
G4double GetZMax () const
G4double GetZTopCut () const
void SetSemiAxis (G4double x, G4double y, G4double z)
void SetZCut (G4double newzTopCut)
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
G4VSolidClone () const override
G4ThreeVector GetPointOnSurface () const override
std::ostream & StreamInfo (std::ostream &os) const override
G4PolyhedronGetPolyhedron () const override
void DescribeYourselfTo (G4VGraphicsScene &scene) const override
G4VisExtent GetExtent () const override
G4PolyhedronCreatePolyhedron () const override
 G4EllipticalCone (__void__ &)
 G4EllipticalCone (const G4EllipticalCone &rhs)
G4EllipticalConeoperator= (const G4EllipticalCone &rhs)
Public Member Functions inherited from G4VSolid
 G4VSolid (const G4String &name)
virtual ~G4VSolid ()
 G4VSolid (const G4VSolid &rhs)
G4VSolidoperator= (const G4VSolid &rhs)
G4bool operator== (const G4VSolid &s) const
G4String GetName () const
void SetName (const G4String &name)
G4double GetTolerance () const
virtual void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
virtual G4int GetNumOfConstituents () const
virtual G4bool IsFaceted () const
void DumpInfo () const
virtual const G4VSolidGetConstituentSolid (G4int no) const
virtual G4VSolidGetConstituentSolid (G4int no)
virtual const G4DisplacedSolidGetDisplacedSolidPtr () const
virtual G4DisplacedSolidGetDisplacedSolidPtr ()
 G4VSolid (__void__ &)
G4double EstimateCubicVolume (G4int nStat, G4double epsilon) const
G4double EstimateSurfaceArea (G4int nStat, G4double epsilon) const

Protected Attributes

G4bool fRebuildPolyhedron = false
G4PolyhedronfpPolyhedron = nullptr
Protected Attributes inherited from G4VSolid
G4double kCarTolerance

Additional Inherited Members

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

Detailed Description

G4EllipticalCone is a full cone with elliptical base which can be cut in Z. The height in Z corresponds to where the elliptical cone hits the Z-axis if it had no Z cut.

Definition at line 92 of file G4EllipticalCone.hh.

Constructor & Destructor Documentation

◆ G4EllipticalCone() [1/3]

G4EllipticalCone::G4EllipticalCone ( const G4String & pName,
G4double pxSemiAxis,
G4double pySemiAxis,
G4double zMax,
G4double pzTopCut )

Constructs an elliptical cone, with cut in Z.

Parameters
[in]nameThe solid name.
[in]pxSemiAxisScalar value, defining the scaling along X-axis.
[in]pySemiAxisScalar value, defining the scaling along Y-axis.
[in]zMaxThe Z-coordinate at the apex.
[in]pzTopCutUpper cut plane level.

Definition at line 65 of file G4EllipticalCone.cc.

70 : G4VSolid(pName), zTopCut(0.)
71{
72 halfCarTol = 0.5*kCarTolerance;
73
74 // Check Semi-Axis & Z-cut
75 //
76 if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.) || (pzMax <= 0.) )
77 {
78 std::ostringstream message;
79 message << "Invalid semi-axis or height for solid: " << GetName()
80 << "\n X semi-axis, Y semi-axis, height = "
81 << pxSemiAxis << ", " << pySemiAxis << ", " << pzMax;
82 G4Exception("G4EllipticalCone::G4EllipticalCone()", "GeomSolids0002",
83 FatalErrorInArgument, message);
84 }
85
86 if ( pzTopCut <= 0 )
87 {
88 std::ostringstream message;
89 message << "Invalid z-coordinate for cutting plane for solid: " << GetName()
90 << "\n Z top cut = " << pzTopCut;
91 G4Exception("G4EllipticalCone::G4EllipticalCone()", "GeomSolids0002",
92 FatalErrorInArgument, message);
93 }
94
95 SetSemiAxis( pxSemiAxis, pySemiAxis, pzMax );
96 SetZCut(pzTopCut);
98}
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
void SetSemiAxis(G4double x, G4double y, G4double z)
G4double GetSurfaceArea() override
void SetZCut(G4double newzTopCut)
G4String GetName() const
G4VSolid(const G4String &name)
Definition G4VSolid.cc:59
G4double kCarTolerance
Definition G4VSolid.hh:418

Referenced by Clone(), G4EllipticalCone(), GetZTopCut(), and operator=().

◆ ~G4EllipticalCone()

G4EllipticalCone::~G4EllipticalCone ( )
override

Destructor.

Definition at line 116 of file G4EllipticalCone.cc.

117{
118 delete fpPolyhedron; fpPolyhedron = nullptr;
119}
G4Polyhedron * fpPolyhedron

◆ G4EllipticalCone() [2/3]

G4EllipticalCone::G4EllipticalCone ( __void__ & a)

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

Definition at line 105 of file G4EllipticalCone.cc.

106 : G4VSolid(a), halfCarTol(0.),
107 xSemiAxis(0.), ySemiAxis(0.), zheight(0.), zTopCut(0.),
108 cosAxisMin(0.), invXX(0.), invYY(0.)
109{
110}

◆ G4EllipticalCone() [3/3]

G4EllipticalCone::G4EllipticalCone ( const G4EllipticalCone & rhs)

Copy constructor and assignment operator.

Definition at line 125 of file G4EllipticalCone.cc.

126 : G4VSolid(rhs), halfCarTol(rhs.halfCarTol),
127 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
128 fMinZBaseArea(rhs.fMinZBaseArea), fMaxZBaseArea(rhs.fMaxZBaseArea),
129 xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
130 zheight(rhs.zheight), zTopCut(rhs.zTopCut),
131 cosAxisMin(rhs.cosAxisMin), invXX(rhs.invXX), invYY(rhs.invYY)
132{
133}

Member Function Documentation

◆ BoundingLimits()

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

Computes the bounding limits of the solid.

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

Reimplemented from G4VSolid.

Definition at line 203 of file G4EllipticalCone.cc.

205{
206 G4double zcut = GetZTopCut();
207 G4double height = GetZMax();
208 G4double xmax = GetSemiAxisX()*(height+zcut);
209 G4double ymax = GetSemiAxisY()*(height+zcut);
210 pMin.set(-xmax,-ymax,-zcut);
211 pMax.set( xmax, ymax, zcut);
212
213 // Check correctness of the bounding box
214 //
215 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
216 {
217 std::ostringstream message;
218 message << "Bad bounding box (min >= max) for solid: "
219 << GetName() << " !"
220 << "\npMin = " << pMin
221 << "\npMax = " << pMax;
222 G4Exception("G4EllipticalCone::BoundingLimits()", "GeomMgt0001",
223 JustWarning, message);
224 DumpInfo();
225 }
226}
@ JustWarning
double G4double
Definition G4Types.hh:83
double z() const
double x() const
double y() const
void set(double x, double y, double z)
G4double GetSemiAxisX() const
G4double GetSemiAxisY() const
G4double GetZMax() const
G4double GetZTopCut() const
void DumpInfo() const

Referenced by CalculateExtent(), and GetExtent().

◆ CalculateExtent()

G4bool G4EllipticalCone::CalculateExtent ( const EAxis pAxis,
const G4VoxelLimits & pVoxelLimit,
const G4AffineTransform & pTransform,
G4double & pMin,
G4double & pMax ) const
overridevirtual

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

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

Implements G4VSolid.

Definition at line 233 of file G4EllipticalCone.cc.

237{
238 G4ThreeVector bmin,bmax;
239 G4bool exist;
240
241 // Check bounding box (bbox)
242 //
243 BoundingLimits(bmin,bmax);
244 G4BoundingEnvelope bbox(bmin,bmax);
245#ifdef G4BBOX_EXTENT
246 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
247#endif
248 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
249 {
250 return exist = pMin < pMax;
251 }
252
253 // Set bounding envelope (benv) and calculate extent
254 //
255 static const G4int NSTEPS = 48; // number of steps for whole circle
256 static const G4double ang = twopi/NSTEPS;
257 static const G4double sinHalf = std::sin(0.5*ang);
258 static const G4double cosHalf = std::cos(0.5*ang);
259 static const G4double sinStep = 2.*sinHalf*cosHalf;
260 static const G4double cosStep = 1. - 2.*sinHalf*sinHalf;
261 G4double zcut = bmax.z();
262 G4double height = GetZMax();
263 G4double sxmin = GetSemiAxisX()*(height-zcut)/cosHalf;
264 G4double symin = GetSemiAxisY()*(height-zcut)/cosHalf;
265 G4double sxmax = bmax.x()/cosHalf;
266 G4double symax = bmax.y()/cosHalf;
267
268 G4double sinCur = sinHalf;
269 G4double cosCur = cosHalf;
270 G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
271 for (G4int k=0; k<NSTEPS; ++k)
272 {
273 baseA[k].set(sxmax*cosCur,symax*sinCur,-zcut);
274 baseB[k].set(sxmin*cosCur,symin*sinCur, zcut);
275
276 G4double sinTmp = sinCur;
277 sinCur = sinCur*cosStep + cosCur*sinStep;
278 cosCur = cosCur*cosStep - sinTmp*sinStep;
279 }
280
281 std::vector<const G4ThreeVectorList *> polygons(2);
282 polygons[0] = &baseA;
283 polygons[1] = &baseB;
284 G4BoundingEnvelope benv(bmin,bmax,polygons);
285 exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
286 return exist;
287}
std::vector< G4ThreeVector > G4ThreeVectorList
CLHEP::Hep3Vector G4ThreeVector
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override

◆ Clone()

G4VSolid * G4EllipticalCone::Clone ( ) const
overridevirtual

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

Returns
A pointer to the new cloned allocated solid.

Reimplemented from G4VSolid.

Definition at line 836 of file G4EllipticalCone.cc.

837{
838 return new G4EllipticalCone(*this);
839}
G4EllipticalCone(const G4String &pName, G4double pxSemiAxis, G4double pySemiAxis, G4double zMax, G4double pzTopCut)

◆ CreatePolyhedron()

G4Polyhedron * G4EllipticalCone::CreatePolyhedron ( ) const
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 963 of file G4EllipticalCone.cc.

964{
965 return new G4PolyhedronEllipticalCone(xSemiAxis, ySemiAxis, zheight, zTopCut);
966}

Referenced by GetPolyhedron().

◆ DescribeYourselfTo()

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

A "double dispatch" function which identifies the solid to the graphics scene for visualization.

Implements G4VSolid.

Definition at line 949 of file G4EllipticalCone.cc.

950{
951 scene.AddSolid(*this);
952}
virtual void AddSolid(const G4Box &)=0

◆ DistanceToIn() [1/2]

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

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

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

Implements G4VSolid.

Definition at line 622 of file G4EllipticalCone.cc.

623{
624 G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
625 G4double ds = (hp - zheight)*cosAxisMin;
626 G4double dz = std::abs(p.z()) - zTopCut;
627 G4double dist = std::max(ds,dz);
628 return (dist > 0) ? dist : 0.;
629}

◆ DistanceToIn() [2/2]

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

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

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

Implements G4VSolid.

Definition at line 382 of file G4EllipticalCone.cc.

384{
385 G4double distMin = kInfinity;
386
387 // code from EllipticalTube
388
389 G4double sigz = p.z()+zTopCut;
390
391 //
392 // Check z = -dz planer surface
393 //
394
395 if (sigz < halfCarTol)
396 {
397 //
398 // We are "behind" the shape in z, and so can
399 // potentially hit the rear face. Correct direction?
400 //
401 if (v.z() <= 0)
402 {
403 //
404 // As long as we are far enough away, we know we
405 // can't intersect
406 //
407 if (sigz < 0) { return kInfinity; }
408
409 //
410 // Otherwise, we don't intersect unless we are
411 // on the surface of the ellipse
412 //
413
414 if ( sqr(p.x()/( xSemiAxis - halfCarTol ))
415 + sqr(p.y()/( ySemiAxis - halfCarTol )) <= sqr( zheight + zTopCut ) )
416 {
417 return kInfinity;
418 }
419 }
420 else
421 {
422 //
423 // How far?
424 //
425 G4double q = -sigz/v.z();
426
427 //
428 // Where does that place us?
429 //
430 G4double xi = p.x() + q*v.x(),
431 yi = p.y() + q*v.y();
432
433 //
434 // Is this on the surface (within ellipse)?
435 //
436 if ( sqr(xi/xSemiAxis) + sqr(yi/ySemiAxis) <= sqr( zheight + zTopCut ) )
437 {
438 //
439 // Yup. Return q, unless we are on the surface
440 //
441 return (sigz < -halfCarTol) ? q : 0;
442 }
443 if (xi/(xSemiAxis*xSemiAxis)*v.x() + yi/(ySemiAxis*ySemiAxis)*v.y() >= 0)
444 {
445 //
446 // Else, if we are traveling outwards, we know
447 // we must miss
448 //
449 // return kInfinity;
450 }
451 }
452 }
453
454 //
455 // Check z = +dz planer surface
456 //
457 sigz = p.z() - zTopCut;
458
459 if (sigz > -halfCarTol)
460 {
461 if (v.z() >= 0)
462 {
463 if (sigz > 0) { return kInfinity; }
464
465 if ( sqr(p.x()/( xSemiAxis - halfCarTol ))
466 + sqr(p.y()/( ySemiAxis - halfCarTol )) <= sqr( zheight-zTopCut ) )
467 {
468 return kInfinity;
469 }
470 }
471 else
472 {
473 G4double q = -sigz/v.z();
474
475 G4double xi = p.x() + q*v.x(),
476 yi = p.y() + q*v.y();
477
478 if ( sqr(xi/xSemiAxis) + sqr(yi/ySemiAxis) <= sqr( zheight - zTopCut ) )
479 {
480 return (sigz > -halfCarTol) ? q : 0;
481 }
482 if (xi/(xSemiAxis*xSemiAxis)*v.x() + yi/(ySemiAxis*ySemiAxis)*v.y() >= 0)
483 {
484 // return kInfinity;
485 }
486 }
487 }
488
489#if 0
490
491 // check to see if Z plane is relevant
492 //
493 if (p.z() < -zTopCut - halfCarTol)
494 {
495 if (v.z() <= 0.0) { return distMin; }
496
497 G4double lambda = (-zTopCut - p.z())/v.z();
498
499 if ( sqr((lambda*v.x()+p.x())/xSemiAxis) +
500 sqr((lambda*v.y()+p.y())/ySemiAxis) <=
501 sqr(zTopCut + zheight + halfCarTol) )
502 {
503 return distMin = std::fabs(lambda);
504 }
505 }
506
507 if (p.z() > zTopCut + halfCarTol)
508 {
509 if (v.z() >= 0.0) { return distMin; }
510
511 G4double lambda = (zTopCut - p.z()) / v.z();
512
513 if ( sqr((lambda*v.x() + p.x())/xSemiAxis) +
514 sqr((lambda*v.y() + p.y())/ySemiAxis) <=
515 sqr(zheight - zTopCut + halfCarTol) )
516 {
517 return distMin = std::fabs(lambda);
518 }
519 }
520
521 if (p.z() > zTopCut - halfCarTol
522 && p.z() < zTopCut + halfCarTol )
523 {
524 if (v.z() > 0.) { return kInfinity; }
525
526 return distMin = 0.;
527 }
528
529 if (p.z() < -zTopCut + halfCarTol
530 && p.z() > -zTopCut - halfCarTol)
531 {
532 if (v.z() < 0.) { return distMin = kInfinity; }
533
534 return distMin = 0.;
535 }
536
537#endif
538
539 // if we are here then it either intersects or grazes the curved surface
540 // or it does not intersect at all
541 //
542 G4double A = sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) - sqr(v.z());
543 G4double B = 2*(v.x()*p.x()/sqr(xSemiAxis) +
544 v.y()*p.y()/sqr(ySemiAxis) + v.z()*(zheight-p.z()));
545 G4double C = sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis) -
546 sqr(zheight - p.z());
547
548 G4double discr = B*B - 4.*A*C;
549
550 // if the discriminant is negative it never hits the curved object
551 //
552 if ( discr < -halfCarTol ) { return distMin; }
553
554 // case below is when it hits or grazes the surface
555 //
556 if ( (discr >= -halfCarTol ) && (discr < halfCarTol ) )
557 {
558 return distMin = std::fabs(-B/(2.*A));
559 }
560
561 G4double plus = (-B+std::sqrt(discr))/(2.*A);
562 G4double minus = (-B-std::sqrt(discr))/(2.*A);
563
564 // Special case::Point on Surface, Check norm.dot(v)
565
566 if ( ( std::fabs(plus) < halfCarTol )||( std::fabs(minus) < halfCarTol ) )
567 {
568 G4ThreeVector truenorm(p.x()/(xSemiAxis*xSemiAxis),
569 p.y()/(ySemiAxis*ySemiAxis),
570 -( p.z() - zheight ));
571 if ( truenorm*v >= 0) // going outside the solid from surface
572 {
573 return kInfinity;
574 }
575 return 0;
576 }
577
578 // G4double lambda = std::fabs(plus) < std::fabs(minus) ? plus : minus;
579 G4double lambda = 0;
580
581 if ( minus > halfCarTol && minus < distMin )
582 {
583 lambda = minus ;
584 // check normal vector n * v < 0
585 G4ThreeVector pin = p + lambda*v;
586 if(std::fabs(pin.z())< zTopCut + halfCarTol)
587 {
588 G4ThreeVector truenorm(pin.x()/(xSemiAxis*xSemiAxis),
589 pin.y()/(ySemiAxis*ySemiAxis),
590 - ( pin.z() - zheight ));
591 if ( truenorm*v < 0)
592 { // yes, going inside the solid
593 distMin = lambda;
594 }
595 }
596 }
597 if ( plus > halfCarTol && plus < distMin )
598 {
599 lambda = plus ;
600 // check normal vector n * v < 0
601 G4ThreeVector pin = p + lambda*v;
602 if(std::fabs(pin.z()) < zTopCut + halfCarTol)
603 {
604 G4ThreeVector truenorm(pin.x()/(xSemiAxis*xSemiAxis),
605 pin.y()/(ySemiAxis*ySemiAxis),
606 - ( pin.z() - zheight ) );
607 if ( truenorm*v < 0)
608 { // yes, going inside the solid
609 distMin = lambda;
610 }
611 }
612 }
613 if (distMin < halfCarTol) { distMin=0.; }
614 return distMin ;
615}
G4double C(G4double temp)
G4double B(G4double temperature)
const G4double A[17]
T sqr(const T &x)
Definition templates.hh:128

◆ DistanceToOut() [1/2]

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

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

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

Implements G4VSolid.

Definition at line 798 of file G4EllipticalCone.cc.

799{
800#ifdef G4SPECSDEBUG
801 if( Inside(p) == kOutside )
802 {
803 std::ostringstream message;
804 G4long oldprc = message.precision(16);
805 message << "Point p is outside (!?) of solid: " << GetName() << "\n"
806 << "Position:\n"
807 << " p.x() = " << p.x()/mm << " mm\n"
808 << " p.y() = " << p.y()/mm << " mm\n"
809 << " p.z() = " << p.z()/mm << " mm";
810 message.precision(oldprc) ;
811 G4Exception("G4Ellipsoid::DistanceToOut(p)", "GeomSolids1002",
812 JustWarning, message);
813 DumpInfo();
814 }
815#endif
816 G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
817 G4double ds = (zheight - hp)*cosAxisMin;
818 G4double dz = zTopCut - std::abs(p.z());
819 G4double dist = std::min(ds,dz);
820 return (dist > 0) ? dist : 0.;
821}
long G4long
Definition G4Types.hh:87
EInside Inside(const G4ThreeVector &p) const override
@ kOutside
Definition geomdefs.hh:68

◆ DistanceToOut() [2/2]

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

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

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

Implements G4VSolid.

Definition at line 636 of file G4EllipticalCone.cc.

641{
642 G4double distMin, lambda;
643 enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
644
645 distMin = kInfinity;
646 surface = kNoSurf;
647
648 if (v.z() < 0.0)
649 {
650 lambda = (-p.z() - zTopCut)/v.z();
651
652 if ( (sqr((p.x() + lambda*v.x())/xSemiAxis) +
653 sqr((p.y() + lambda*v.y())/ySemiAxis)) <
654 sqr(zheight + zTopCut + halfCarTol) )
655 {
656 distMin = std::fabs(lambda);
657
658 if (!calcNorm) { return distMin; }
659 }
660 distMin = std::fabs(lambda);
661 surface = kPlaneSurf;
662 }
663
664 if (v.z() > 0.0)
665 {
666 lambda = (zTopCut - p.z()) / v.z();
667
668 if ( (sqr((p.x() + lambda*v.x())/xSemiAxis)
669 + sqr((p.y() + lambda*v.y())/ySemiAxis) )
670 < (sqr(zheight - zTopCut + halfCarTol)) )
671 {
672 distMin = std::fabs(lambda);
673 if (!calcNorm) { return distMin; }
674 }
675 distMin = std::fabs(lambda);
676 surface = kPlaneSurf;
677 }
678
679 // if we are here then it either intersects or grazes the
680 // curved surface...
681 //
682 G4double A = sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) - sqr(v.z());
683 G4double B = 2.*(v.x()*p.x()/sqr(xSemiAxis) +
684 v.y()*p.y()/sqr(ySemiAxis) + v.z()*(zheight-p.z()));
685 G4double C = sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis)
686 - sqr(zheight - p.z());
687
688 G4double discr = B*B - 4.*A*C;
689
690 if ( discr >= - halfCarTol && discr < halfCarTol )
691 {
692 if(!calcNorm) { return distMin = std::fabs(-B/(2.*A)); }
693 }
694
695 else if ( discr > halfCarTol )
696 {
697 G4double plus = (-B+std::sqrt(discr))/(2.*A);
698 G4double minus = (-B-std::sqrt(discr))/(2.*A);
699
700 if ( plus > halfCarTol && minus > halfCarTol )
701 {
702 // take the shorter distance
703 //
704 lambda = std::fabs(plus) < std::fabs(minus) ? plus : minus;
705 }
706 else
707 {
708 // at least one solution is close to zero or negative
709 // so, take small positive solution or zero
710 //
711 lambda = plus > -halfCarTol ? plus : 0;
712 }
713
714 if ( std::fabs(lambda) < distMin )
715 {
716 if( std::fabs(lambda) > halfCarTol)
717 {
718 distMin = std::fabs(lambda);
719 surface = kCurvedSurf;
720 }
721 else // Point is On the Surface, Check Normal
722 {
723 G4ThreeVector truenorm(p.x()/(xSemiAxis*xSemiAxis),
724 p.y()/(ySemiAxis*ySemiAxis),
725 -( p.z() - zheight ));
726 if( truenorm.dot(v) > 0 )
727 {
728 distMin = 0.0;
729 surface = kCurvedSurf;
730 }
731 }
732 }
733 }
734
735 // set normal if requested
736 //
737 if (calcNorm)
738 {
739 if (surface == kNoSurf)
740 {
741 *validNorm = false;
742 }
743 else
744 {
745 *validNorm = true;
746 switch (surface)
747 {
748 case kPlaneSurf:
749 {
750 *n = G4ThreeVector(0.,0.,(v.z() > 0.0 ? 1. : -1.));
751 }
752 break;
753
754 case kCurvedSurf:
755 {
756 G4ThreeVector pexit = p + distMin*v;
757 G4ThreeVector truenorm( pexit.x()/(xSemiAxis*xSemiAxis),
758 pexit.y()/(ySemiAxis*ySemiAxis),
759 -( pexit.z() - zheight ) );
760 truenorm /= truenorm.mag();
761 *n= truenorm;
762 }
763 break;
764
765 default: // Should never reach this case ...
766 DumpInfo();
767 std::ostringstream message;
768 G4long oldprc = message.precision(16);
769 message << "Undefined side for valid surface normal to solid."
770 << G4endl
771 << "Position:" << G4endl
772 << " p.x() = " << p.x()/mm << " mm" << G4endl
773 << " p.y() = " << p.y()/mm << " mm" << G4endl
774 << " p.z() = " << p.z()/mm << " mm" << G4endl
775 << "Direction:" << G4endl
776 << " v.x() = " << v.x() << G4endl
777 << " v.y() = " << v.y() << G4endl
778 << " v.z() = " << v.z() << G4endl
779 << "Proposed distance :" << G4endl
780 << " distMin = " << distMin/mm << " mm";
781 message.precision(oldprc);
782 G4Exception("G4EllipticalCone::DistanceToOut(p,v,..)",
783 "GeomSolids1002", JustWarning, message);
784 break;
785 }
786 }
787 }
788
789 if (distMin < halfCarTol) { distMin=0; }
790
791 return distMin;
792}
#define G4endl
Definition G4ios.hh:67

◆ GetCubicVolume()

G4double G4EllipticalCone::GetCubicVolume ( )
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 907 of file G4EllipticalCone.cc.

908{
909 if (fCubicVolume == 0)
910 {
911 G4AutoLock l(&elconeMutex);
912 G4double x0 = xSemiAxis*zheight; // x semi axis at z=0
913 G4double y0 = ySemiAxis*zheight; // y semi axis at z=0
914 G4double v0 = CLHEP::pi*x0*y0*zheight/3.;
915 G4double kmin = (zTopCut >= zheight ) ? 0. : (zheight - zTopCut)/zheight;
916 G4double kmax = (zTopCut >= zheight ) ? 2. : (zheight + zTopCut)/zheight;
917 fCubicVolume = (kmax - kmin)*(kmax*kmax + kmax*kmin + kmin*kmin)*v0;
918 l.unlock();
919 }
920 return fCubicVolume;
921}
G4TemplateAutoLock< G4Mutex > G4AutoLock

◆ GetEntityType()

G4GeometryType G4EllipticalCone::GetEntityType ( ) const
overridevirtual

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

Implements G4VSolid.

Definition at line 827 of file G4EllipticalCone.cc.

828{
829 return {"G4EllipticalCone"};
830}

◆ GetExtent()

G4VisExtent G4EllipticalCone::GetExtent ( ) const
overridevirtual

Provides extent (bounding box) as possible hint to the graphics view.

Reimplemented from G4VSolid.

Definition at line 954 of file G4EllipticalCone.cc.

955{
956 // Define the sides of the box into which the solid instance would fit.
957 //
958 G4ThreeVector pmin,pmax;
959 BoundingLimits(pmin,pmax);
960 return { pmin.x(), pmax.x(), pmin.y(), pmax.y(), pmin.z(), pmax.z() };
961}

◆ GetPointOnSurface()

G4ThreeVector G4EllipticalCone::GetPointOnSurface ( ) const
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 868 of file G4EllipticalCone.cc.

869{
870 G4double phi = twopi*G4QuickRand();
871 G4double cosphi = std::cos(phi);
872 G4double sinphi = std::sin(phi);
873 G4double select = fSurfaceArea*G4QuickRand();
874 if (select < fMinZBaseArea + fMaxZBaseArea)
875 {
876 // elliptical bases
877 G4double z = (select < fMinZBaseArea) ? -zTopCut : zTopCut;
878 G4double a = xSemiAxis*(zheight - z);
879 G4double b = ySemiAxis*(zheight - z);
880 G4double rho = std::sqrt(G4QuickRand());
881 return { a*rho*cosphi, b*rho*sinphi, z };
882 }
883
884 // lateral surface (rejection sampling)
885 G4double ucut = zTopCut/zheight;
886 G4double a = xSemiAxis;
887 G4double b = ySemiAxis;
888 G4double h = zheight;
889 G4double aa = a*a;
890 G4double bb = b*b;
891 G4double aabb = aa*bb + bb*cosphi*cosphi + aa*sinphi*sinphi;
892 G4double ss_max = 4.*ucut*ucut*(std::max(aa, bb) + aa*bb);
893 G4double u;
894 for (auto i = 0; i < 10000; ++i)
895 {
896 u = ucut*(2.*G4QuickRand() - 1.);
897 G4double ss = (1. - u)*(1. - u)*aabb;
898 if (ss_max*sqr(G4QuickRand()) <= ss) { break; }
899 }
900 return { a*h*(1. - u)*cosphi, b*h*(1 - u)*sinphi, h*u };
901}
G4double G4QuickRand(uint32_t seed=0)

◆ GetPolyhedron()

G4Polyhedron * G4EllipticalCone::GetPolyhedron ( ) const
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 968 of file G4EllipticalCone.cc.

969{
970 if ( (fpPolyhedron == nullptr)
972 || (fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
973 fpPolyhedron->GetNumberOfRotationSteps()) )
974 {
975 G4AutoLock l(&polyhedronMutex);
976 delete fpPolyhedron;
978 fRebuildPolyhedron = false;
979 l.unlock();
980 }
981 return fpPolyhedron;
982}
G4Polyhedron * CreatePolyhedron() const override

◆ GetSemiAxisMax()

G4double G4EllipticalCone::GetSemiAxisMax ( ) const
inline

◆ GetSemiAxisMin()

G4double G4EllipticalCone::GetSemiAxisMin ( ) const
inline

Accessors.

◆ GetSemiAxisX()

G4double G4EllipticalCone::GetSemiAxisX ( ) const
inline

◆ GetSemiAxisY()

G4double G4EllipticalCone::GetSemiAxisY ( ) const
inline

◆ GetSurfaceArea()

G4double G4EllipticalCone::GetSurfaceArea ( )
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 927 of file G4EllipticalCone.cc.

928{
929 if (fSurfaceArea == 0)
930 {
931 G4AutoLock l(&elconeMutex);
932 G4double x0 = xSemiAxis*zheight; // x semi axis at z=0
933 G4double y0 = ySemiAxis*zheight; // y semi axis at z=0
935 G4double kmin = (zTopCut >= zheight ) ? 0. : (zheight - zTopCut)/zheight;
936 G4double kmax = (zTopCut >= zheight ) ? 2. : (zheight + zTopCut)/zheight;
937 fMinZBaseArea = pi*x0*y0*kmax*kmax;
938 fMaxZBaseArea = pi*x0*y0*kmin*kmin;
939 fSurfaceArea = (kmax - kmin)*(kmax + kmin)*s0 + fMinZBaseArea + fMaxZBaseArea;
940 l.unlock();
941 }
942 return fSurfaceArea;
943}
static G4double EllipticConeLateralArea(G4double a, G4double b, G4double h)
const G4double pi

Referenced by G4EllipticalCone(), SetSemiAxis(), and SetZCut().

◆ GetZMax()

◆ GetZTopCut()

G4double G4EllipticalCone::GetZTopCut ( ) const
inline

◆ Inside()

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

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

Implements G4VSolid.

Definition at line 293 of file G4EllipticalCone.cc.

294{
295 G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
296 G4double ds = (hp - zheight)*cosAxisMin;
297 G4double dz = std::abs(p.z()) - zTopCut;
298 G4double dist = std::max(ds,dz);
299
300 if (dist > halfCarTol) { return kOutside; }
301 return (dist > -halfCarTol) ? kSurface : kInside;
302}
@ kInside
Definition geomdefs.hh:70
@ kSurface
Definition geomdefs.hh:69

Referenced by DistanceToOut().

◆ operator=()

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

Definition at line 139 of file G4EllipticalCone.cc.

140{
141 // Check assignment to self
142 //
143 if (this == &rhs) { return *this; }
144
145 // Copy base class data
146 //
148
149 // Copy data
150 //
151 halfCarTol = rhs.halfCarTol;
152 fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
153 fMinZBaseArea = rhs.fMinZBaseArea; fMaxZBaseArea = rhs.fMaxZBaseArea;
154 xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
155 zheight = rhs.zheight; zTopCut = rhs.zTopCut;
156 cosAxisMin = rhs.cosAxisMin; invXX = rhs.invXX; invYY = rhs.invYY;
157
158 fRebuildPolyhedron = false;
159 delete fpPolyhedron; fpPolyhedron = nullptr;
160
161 return *this;
162}
G4VSolid & operator=(const G4VSolid &rhs)
Definition G4VSolid.cc:108

◆ SetSemiAxis()

void G4EllipticalCone::SetSemiAxis ( G4double x,
G4double y,
G4double z )

Modifiers.

Definition at line 168 of file G4EllipticalCone.cc.

171{
172 xSemiAxis = newxSemiAxis;
173 ySemiAxis = newySemiAxis;
174 zheight = newzMax;
175 if (zTopCut > zheight) { zTopCut = zheight; }
176 G4double axmin = std::min(xSemiAxis, ySemiAxis);
177 cosAxisMin = axmin/std::sqrt(1. + axmin*axmin);
178 invXX = 1./(xSemiAxis*xSemiAxis);
179 invYY = 1./(ySemiAxis*ySemiAxis);
180 fCubicVolume = 0.0;
181 fSurfaceArea = 0.0;
183 fRebuildPolyhedron = true;
184}

Referenced by G4EllipticalCone().

◆ SetZCut()

void G4EllipticalCone::SetZCut ( G4double newzTopCut)

Definition at line 190 of file G4EllipticalCone.cc.

191{
192 zTopCut = std::min(newzTopCut, zheight);
193 fCubicVolume = 0.0;
194 fSurfaceArea = 0.0;
196 fRebuildPolyhedron = true;
197}

Referenced by G4EllipticalCone().

◆ StreamInfo()

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

Streams the object contents to an output stream.

Implements G4VSolid.

Definition at line 845 of file G4EllipticalCone.cc.

846{
847 G4long oldprc = os.precision(16);
848 os << "-----------------------------------------------------------\n"
849 << " *** Dump for solid - " << GetName() << " ***\n"
850 << " ===================================================\n"
851 << " Solid type: G4EllipticalCone\n"
852 << " Parameters: \n"
853
854 << " semi-axis x: " << xSemiAxis/mm << " mm \n"
855 << " semi-axis y: " << ySemiAxis/mm << " mm \n"
856 << " height z: " << zheight/mm << " mm \n"
857 << " half length in z: " << zTopCut/mm << " mm \n"
858 << "-----------------------------------------------------------\n";
859 os.precision(oldprc);
860
861 return os;
862}

◆ SurfaceNormal()

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

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

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

Implements G4VSolid.

Definition at line 308 of file G4EllipticalCone.cc.

309{
310 G4ThreeVector norm(0,0,0);
311 G4int nsurf = 0; // number of surfaces where p is placed
312
313 G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
314 G4double ds = (hp - zheight)*cosAxisMin;
315 if (std::abs(ds) <= halfCarTol)
316 {
317 norm = G4ThreeVector(p.x()*invXX, p.y()*invYY, hp - p.z());
318 G4double mag = norm.mag();
319 if (mag == 0) { return {0,0,1}; } // apex
320 norm *= (1/mag);
321 ++nsurf;
322 }
323 G4double dz = std::abs(p.z()) - zTopCut;
324 if (std::abs(dz) <= halfCarTol)
325 {
326 norm += G4ThreeVector(0., 0.,(p.z() < 0) ? -1. : 1.);
327 ++nsurf;
328 }
329
330 if (nsurf == 1)
331 {
332 return norm;
333 }
334 if (nsurf > 1)
335 {
336 return norm.unit(); // elliptic edge
337 }
338
339 // Point is not on the surface
340 //
341#ifdef G4CSGDEBUG
342 std::ostringstream message;
343 G4long oldprc = message.precision(16);
344 message << "Point p is not on surface (!?) of solid: "
345 << GetName() << G4endl;
346 message << "Position:\n";
347 message << " p.x() = " << p.x()/mm << " mm\n";
348 message << " p.y() = " << p.y()/mm << " mm\n";
349 message << " p.z() = " << p.z()/mm << " mm";
350 G4cout.precision(oldprc);
351 G4Exception("G4EllipticalCone::SurfaceNormal(p)", "GeomSolids1002",
352 JustWarning, message );
353 DumpInfo();
354#endif
355 return ApproxSurfaceNormal(p);
356}
G4GLOB_DLL std::ostream G4cout

Member Data Documentation

◆ fpPolyhedron

G4Polyhedron* G4EllipticalCone::fpPolyhedron = nullptr
mutableprotected

Definition at line 222 of file G4EllipticalCone.hh.

Referenced by GetPolyhedron(), operator=(), and ~G4EllipticalCone().

◆ fRebuildPolyhedron

G4bool G4EllipticalCone::fRebuildPolyhedron = false
mutableprotected

Definition at line 221 of file G4EllipticalCone.hh.

Referenced by GetPolyhedron(), operator=(), SetSemiAxis(), and SetZCut().


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