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

G4GenericTrap is a solid which represents an arbitrary trapezoid with up to 8 vertices standing on two parallel planes perpendicular to the Z axis. Points can be identical in order to create shapes with less than 8 vertices. More...

#include <G4GenericTrap.hh>

Inheritance diagram for G4GenericTrap:

Public Member Functions

 G4GenericTrap (const G4String &name, G4double halfZ, const std::vector< G4TwoVector > &vertices)
 G4GenericTrap (__void__ &)
 G4GenericTrap (const G4GenericTrap &rhs)
G4GenericTrapoperator= (const G4GenericTrap &rhs)
 ~G4GenericTrap () override=default
G4double GetZHalfLength () const
G4int GetNofVertices () const
G4TwoVector GetVertex (G4int index) const
const std::vector< G4TwoVector > & GetVertices () const
G4double GetTwistAngle (G4int index) const
G4bool IsTwisted () const
G4int GetVisSubdivisions () const
void SetVisSubdivisions (G4int subdiv)
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
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
G4GeometryType GetEntityType () const override
G4bool IsFaceted () const override
G4VSolidClone () const override
std::ostream & StreamInfo (std::ostream &os) const override
G4ThreeVector GetPointOnSurface () const override
G4double GetCubicVolume () override
G4double GetSurfaceArea () override
void DescribeYourselfTo (G4VGraphicsScene &scene) const override
G4VisExtent GetExtent () const override
G4PolyhedronCreatePolyhedron () const override
G4PolyhedronGetPolyhedron () const override
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
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

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
Protected Attributes inherited from G4VSolid
G4double kCarTolerance

Detailed Description

G4GenericTrap is a solid which represents an arbitrary trapezoid with up to 8 vertices standing on two parallel planes perpendicular to the Z axis. Points can be identical in order to create shapes with less than 8 vertices.

Definition at line 83 of file G4GenericTrap.hh.

Constructor & Destructor Documentation

◆ G4GenericTrap() [1/3]

G4GenericTrap::G4GenericTrap ( const G4String & name,
G4double halfZ,
const std::vector< G4TwoVector > & vertices )

Constructs an generic trapezoid, given its vertices.

Parameters
[in]nameThe solid name.
[in]halfZHalf length in Z.
[in]verticesThe (x,y) coordinates of the vertices.

Definition at line 67 of file G4GenericTrap.cc.

69 : G4VSolid(name)
70{
71 halfTolerance = 0.5*kCarTolerance;
72 CheckParameters(halfZ, vertices);
73 ComputeLateralSurfaces();
74 ComputeBoundingBox();
75 ComputeScratchLength();
76}
G4VSolid(const G4String &name)
Definition G4VSolid.cc:59
G4double kCarTolerance
Definition G4VSolid.hh:418

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

◆ G4GenericTrap() [2/3]

G4GenericTrap::G4GenericTrap ( __void__ & a)

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

Definition at line 82 of file G4GenericTrap.cc.

83 : G4VSolid(a)
84{
85}

◆ G4GenericTrap() [3/3]

G4GenericTrap::G4GenericTrap ( const G4GenericTrap & rhs)

Copy constructor and assignment operator.

Definition at line 91 of file G4GenericTrap.cc.

92 : G4VSolid(rhs),
93 halfTolerance(rhs.halfTolerance), fScratch(rhs.fScratch),
94 fDz(rhs.fDz), fVertices(rhs.fVertices), fIsTwisted(rhs.fIsTwisted),
95 fMinBBox(rhs.fMinBBox), fMaxBBox(rhs.fMaxBBox),
96 fVisSubdivisions(rhs.fVisSubdivisions),
97 fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume)
98{
99 for (auto i = 0; i < 5; ++i) { fTwist[i] = rhs.fTwist[i]; }
100 for (auto i = 0; i < 4; ++i) { fDelta[i] = rhs.fDelta[i]; }
101 for (auto i = 0; i < 8; ++i) { fPlane[i] = rhs.fPlane[i]; }
102 for (auto i = 0; i < 4; ++i) { fSurf[i] = rhs.fSurf[i]; }
103 for (auto i = 0; i < 4; ++i) { f4k[i] = rhs.f4k[i]; }
104 for (auto i = 0; i < 4; ++i) { fArea[i] = rhs.fArea[i]; }
105}

◆ ~G4GenericTrap()

G4GenericTrap::~G4GenericTrap ( )
overridedefault

Default Destructor.

Member Function Documentation

◆ BoundingLimits()

void G4GenericTrap::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 870 of file G4GenericTrap.cc.

872{
873 pMin = fMinBBox;
874 pMax = fMaxBBox;
875}

Referenced by CalculateExtent().

◆ CalculateExtent()

G4bool G4GenericTrap::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 882 of file G4GenericTrap.cc.

886{
887 G4ThreeVector bmin, bmax;
888 G4bool exist;
889
890 // Check bounding box (bbox)
891 //
892 BoundingLimits(bmin,bmax);
893 G4BoundingEnvelope bbox(bmin,bmax);
894#ifdef G4BBOX_EXTENT
895 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
896#endif
897 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
898 {
899 return exist = pMin < pMax;
900 }
901
902 // Set bounding envelope (benv) and calculate extent
903 //
904 // To build the bounding envelope with plane faces, each lateral face of
905 // the trapezoid is subdivided in two triangles. Subdivision is done by
906 // duplication of vertices in the bases in a way that the envelope be
907 // a convex polyhedron (some faces of the envelope can be degenerated)
908 //
910 G4ThreeVectorList baseA(8), baseB(8);
911 for (G4int i = 0; i < 4; ++i)
912 {
913 G4TwoVector va = GetVertex(i);
914 G4TwoVector vb = GetVertex(i+4);
915 baseA[2*i].set(va.x(), va.y(),-dz);
916 baseB[2*i].set(vb.x(), vb.y(), dz);
917 }
918 for (G4int i = 0; i < 4; ++i)
919 {
920 G4int k1 = 2*i, k2 = (2*i + 2)%8;
921 G4double ax = (baseA[k2].x() - baseA[k1].x());
922 G4double ay = (baseA[k2].y() - baseA[k1].y());
923 G4double bx = (baseB[k2].x() - baseB[k1].x());
924 G4double by = (baseB[k2].y() - baseB[k1].y());
925 G4double znorm = ax*by - ay*bx;
926 baseA[k1+1] = (znorm < 0.0) ? baseA[k2] : baseA[k1];
927 baseB[k1+1] = (znorm < 0.0) ? baseB[k1] : baseB[k2];
928 }
929
930 std::vector<const G4ThreeVectorList *> polygons(2);
931 polygons[0] = &baseA;
932 polygons[1] = &baseB;
933
934 G4BoundingEnvelope benv(bmin, bmax, polygons);
935 exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
936 return exist;
937}
std::vector< G4ThreeVector > G4ThreeVectorList
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
double x() const
double y() const
G4double GetZHalfLength() const
G4TwoVector GetVertex(G4int index) const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override

◆ Clone()

G4VSolid * G4GenericTrap::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 961 of file G4GenericTrap.cc.

962{
963 return new G4GenericTrap(*this);
964}
G4GenericTrap(const G4String &name, G4double halfZ, const std::vector< G4TwoVector > &vertices)

◆ CreatePolyhedron()

G4Polyhedron * G4GenericTrap::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 1531 of file G4GenericTrap.cc.

1532{
1533 // Approximation of Twisted Side
1534 // Construct extra Points, if Twisted Side
1535 //
1536 G4Polyhedron* polyhedron;
1537 G4int nVertices, nFacets;
1538
1539 G4int subdivisions = 0;
1540 if (fIsTwisted)
1541 {
1542 if (GetVisSubdivisions() != 0)
1543 {
1544 subdivisions = GetVisSubdivisions();
1545 }
1546 else
1547 {
1548 // Estimation of Number of Subdivisions for smooth visualisation
1549 //
1550 G4double maxTwist = 0.;
1551 for(G4int i = 0; i < 4; ++i)
1552 {
1553 if (GetTwistAngle(i) > maxTwist) { maxTwist = GetTwistAngle(i); }
1554 }
1555
1556 // Computes bounding vectors for the shape
1557 //
1558 G4double Dx, Dy;
1559 Dx = 0.5*(fMaxBBox.x() - fMinBBox.y());
1560 Dy = 0.5*(fMaxBBox.y() - fMinBBox.y());
1561 if (Dy > Dx) { Dx = Dy; }
1562
1563 subdivisions = 8*G4int(maxTwist/(Dx*Dx*Dx)*fDz);
1564 if (subdivisions < 4) { subdivisions = 4; }
1565 if (subdivisions > 30) { subdivisions = 30; }
1566 }
1567 }
1568 G4int sub4 = 4*subdivisions;
1569 nVertices = 8 + subdivisions*4;
1570 nFacets = 6 + subdivisions*4;
1571 G4double cf = 1./(subdivisions + 1);
1572 polyhedron = new G4Polyhedron(nVertices, nFacets);
1573
1574 // Set vertices
1575 //
1576 G4int icur = 0;
1577 for (G4int i = 0; i < 4; ++i)
1578 {
1579 G4ThreeVector v(fVertices[i].x(),fVertices[i].y(),-fDz);
1580 polyhedron->SetVertex(++icur, v);
1581 }
1582 for (G4int i = 0; i < subdivisions; ++i)
1583 {
1584 for (G4int j = 0; j < 4; ++j)
1585 {
1586 G4TwoVector u = fVertices[j]+cf*(i+1)*(fVertices[j+4]-fVertices[j]);
1587 G4ThreeVector v(u.x(),u.y(),-fDz+cf*2*fDz*(i+1));
1588 polyhedron->SetVertex(++icur, v);
1589 }
1590 }
1591 for (G4int i = 4; i < 8; ++i)
1592 {
1593 G4ThreeVector v(fVertices[i].x(),fVertices[i].y(),fDz);
1594 polyhedron->SetVertex(++icur, v);
1595 }
1596
1597 // Set facets
1598 //
1599 icur = 0;
1600 polyhedron->SetFacet(++icur, 1, 4, 3, 2); // Z-plane
1601 for (G4int i = 0; i < subdivisions + 1; ++i)
1602 {
1603 G4int is = i*4;
1604 polyhedron->SetFacet(++icur, 5+is, 8+is, 4+is, 1+is);
1605 polyhedron->SetFacet(++icur, 8+is, 7+is, 3+is, 4+is);
1606 polyhedron->SetFacet(++icur, 7+is, 6+is, 2+is, 3+is);
1607 polyhedron->SetFacet(++icur, 6+is, 5+is, 1+is, 2+is);
1608 }
1609 polyhedron->SetFacet(++icur, 5+sub4, 6+sub4, 7+sub4, 8+sub4); // Z-plane
1610
1611 polyhedron->SetReferences();
1612 polyhedron->InvertFacets();
1613
1614 return polyhedron;
1615}
G4double GetTwistAngle(G4int index) const
G4int GetVisSubdivisions() const
void SetVertex(G4int index, const G4Point3D &v)
void SetFacet(G4int index, G4int iv1, G4int iv2, G4int iv3, G4int iv4=0)

Referenced by GetPolyhedron().

◆ DescribeYourselfTo()

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

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

Implements G4VSolid.

Definition at line 1513 of file G4GenericTrap.cc.

1514{
1515 scene.AddSolid(*this);
1516}
virtual void AddSolid(const G4Box &)=0

◆ DistanceToIn() [1/2]

G4double G4GenericTrap::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 570 of file G4GenericTrap.cc.

571{
572 G4double x = p.x(), y = p.y(), z = p.z();
573 G4double dist = std::abs(z) - fDz;
574 for (auto i = 0; i < 4; ++i)
575 {
576 if (fTwist[i] == 0.)
577 {
578 G4double distPlane = fSurf[i].D*x + fSurf[i].E*y + fSurf[i].F*z + fSurf[i].G;
579 dist = std::max(distPlane, dist);
580 }
581 else
582 {
583 G4double A = fSurf[i].A;
584 G4double B = fSurf[i].B;
585 G4double C = fSurf[i].C;
586 G4double Cz = C*z;
587 G4double CzF = Cz + fSurf[i].F;
588 G4double gradx = A*z + fSurf[i].D;
589 G4double grady = B*z + fSurf[i].E;
590 G4double gradz = A*x + B*y + Cz + CzF;
591 G4double fun = gradx*x + grady*y + CzF*z + fSurf[i].G;
592 G4double grad2 = gradx*gradx + grady*grady + gradz*gradz;
593 G4double divisor = std::sqrt(grad2) + std::sqrt(grad2 + f4k[i]*std::abs(fun));
594 G4double distSurf = 2.*fun/divisor;
595 dist = std::max(distSurf, dist);
596 }
597 }
598 return (dist > 0.) ? dist : 0.; // return safety distance
599}
G4double C(G4double temp)
G4double B(G4double temperature)
const G4double A[17]
double z() const
double x() const
double y() const

◆ DistanceToIn() [2/2]

G4double G4GenericTrap::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 315 of file G4GenericTrap.cc.

317{
318 G4double px = p.x(), py = p.y(), pz = p.z();
319 G4double vx = v.x(), vy = v.y(), vz = v.z();
320
321 // Find intersections with the bounding polyhedron
322 //
323 if (std::abs(pz) - fDz >= -halfTolerance && pz*vz >= 0) { return kInfinity; }
324 G4double invz = (vz == 0) ? kInfinity : -1./vz;
325 G4double dz = std::copysign(fDz,invz);
326 G4double xin = (pz - dz)*invz;
327 G4double xout = (pz + dz)*invz;
328
329 // Check plane faces
330 for (auto k = 0; k < 4; ++k)
331 {
332 if (fTwist[k] != 0) { continue; } // skip twisted faces
333 const G4GenericTrapPlane& surf = fPlane[2*k];
334 G4double cosa = surf.A*vx + surf.B*vy + surf.C*vz;
335 G4double dist = surf.A*px + surf.B*py + surf.C*pz + surf.D;
336 if (dist >= -halfTolerance)
337 {
338 if (cosa >= 0.) { return kInfinity; } // point flies away
339 G4double tmp = -dist/cosa;
340 xin = std::max(tmp, xin);
341 }
342 else
343 {
344 if (cosa > 0) { xout = std::min(-dist/cosa, xout); }
345 if (cosa < 0) { xin = std::max(-dist/cosa, xin); }
346 }
347 }
348
349 // Check planes around twisted faces, each twisted face is bounded by two planes
350 G4double tin = xin;
351 G4double tout = xout;
352 for (auto i = 0; i < 4; ++i)
353 {
354 if (fTwist[i] == 0) { continue; } // skip plane faces
355
356 // check intersection with 1st bounding plane
357 const G4GenericTrapPlane& surf1 = fPlane[2*i];
358 G4double cosa = surf1.A*vx + surf1.B*vy + surf1.C*vz;
359 G4double dist = surf1.A*px + surf1.B*py + surf1.C*pz + surf1.D;
360 if (dist >= -halfTolerance)
361 {
362 if (cosa >= 0.) { return kInfinity; } // point flies away
363 G4double tmp = -dist/cosa;
364 tin = std::max(tmp, tin);
365 }
366 else
367 {
368 if (cosa > 0) { tout = std::min(-dist/cosa, tout); }
369 if (cosa < 0) { tin = std::max(-dist/cosa, tin); }
370 }
371
372 // check intersection with 2nd bounding plane
373 const G4GenericTrapPlane& surf2 = fPlane[2*i + 1];
374 cosa = surf2.A*vx + surf2.B*vy + surf2.C*vz;
375 dist = surf2.A*px + surf2.B*py + surf2.C*pz + surf2.D;
376 if (dist >= -halfTolerance)
377 {
378 if (cosa >= 0.) { return kInfinity; } // point flies away
379 G4double tmp = -dist/cosa;
380 tin = std::max(tmp, tin);
381 }
382 else
383 {
384 if (cosa > 0) { tout = std::min(-dist/cosa, tout); }
385 if (cosa < 0) { tin = std::max(-dist/cosa, tin); }
386 }
387 }
388 if (tout - tin <= halfTolerance) { return kInfinity; } // touch or no hit
389
390 // if point is outside of the bounding box
391 // then move it to the surface of the bounding polyhedron
392 G4double t0 = 0., x0 = px, y0 = py, z0 = pz;
393 if (x0 < fMinBBox.x() - halfTolerance ||
394 y0 < fMinBBox.y() - halfTolerance ||
395 z0 < fMinBBox.z() - halfTolerance ||
396 x0 > fMaxBBox.x() + halfTolerance ||
397 y0 > fMaxBBox.y() + halfTolerance ||
398 z0 > fMaxBBox.z() + halfTolerance)
399 {
400 t0 = tin;
401 x0 += vx*t0;
402 y0 += vy*t0;
403 z0 += vz*t0;
404 }
405
406 // Check intersections with twisted faces
407 //
408 G4double ttin[2] = { DBL_MAX, DBL_MAX };
409 G4double ttout[2] = { tout, tout };
410
411 if (tin - xin < halfTolerance) { ttin[0] = xin; }
412 if (xout - tout < halfTolerance) { ttout[0] = xout; }
413 G4double tminimal = tin - halfTolerance;
414 G4double tmaximal = tout + halfTolerance;
415
416 constexpr G4double EPSILON = 1000.*DBL_EPSILON;
417 for (auto i = 0; i < 4; ++i)
418 {
419 if (fTwist[i] == 0) { continue; } // skip plane faces
420
421 // twisted face, solve quadratic equation
422 G4double ABC = fSurf[i].A*vx + fSurf[i].B*vy + fSurf[i].C*vz;
423 G4double ABCF = fSurf[i].A*x0 + fSurf[i].B*y0 + fSurf[i].C*z0 + fSurf[i].F;
424 G4double A = ABC*vz;
425 G4double B = 0.5*(fSurf[i].D*vx + fSurf[i].E*vy + ABCF*vz + ABC*z0);
426 G4double C = fSurf[i].D*x0 + fSurf[i].E*y0 + ABCF*z0 + fSurf[i].G;
427 if (std::abs(A) <= EPSILON)
428 {
429 // case 1: track is parallel to the surface
430 if (std::abs(B) <= EPSILON)
431 {
432 // check position of the track relative to the surface,
433 // for the reason of precision it's better to use (x0,y0,z0) instead of (px,py,pz)
434 auto j = (i + 1)%4;
435 G4double z = (z0 + fDz);
436 G4TwoVector a = fVertices[i] + fDelta[i]*z;
437 G4TwoVector b = fVertices[j] + fDelta[j]*z;
438 G4double dx = b.x() - a.x();
439 G4double dy = b.y() - a.y();
440 G4double leng = std::sqrt(dx*dx + dy*dy);
441 G4double dist = dx*(y0 - a.y()) - dy*(x0 - a.x());
442 if (dist >= -halfTolerance*leng) { return kInfinity; }
443 continue;
444 }
445
446 // case 2: single root
447 G4double tmp = t0 - 0.5*C/B;
448 // compute normal at the intersection point and check direction
449 G4double x = px + vx*tmp;
450 G4double y = py + vy*tmp;
451 G4double z = pz + vz*tmp;
452 const G4GenericTrapSurface& surf = fSurf[i];
453 G4double nx = surf.A*z + surf.D;
454 G4double ny = surf.B*z + surf.E;
455 G4double nz = surf.A*x + surf.B*y + 2.*surf.C*z + surf.F;
456
457 if (nx*vx + ny*vy + nz*vz >= 0.) // point is flying to outside
458 {
459 auto k = (i == 3) ? 0 : i + 1;
460 G4double tz = (pz + fDz);
461 G4TwoVector a = fVertices[i] + fDelta[i]*tz;
462 G4TwoVector b = fVertices[k] + fDelta[k]*tz;
463 G4double dx = b.x() - a.x();
464 G4double dy = b.y() - a.y();
465 G4double leng = std::sqrt(dx*dx + dy*dy);
466 G4double dist = dx*(py - a.y()) - dy*(px - a.x());
467 if (dist >= -halfTolerance*leng) { return kInfinity; } // point is flies away
468
469 if (tmp < tminimal || tmp > tmaximal) { continue; }
470 if (std::abs(tmp - ttout[0]) < halfTolerance) { continue; }
471 if (tmp < ttout[0])
472 {
473 ttout[1] = ttout[0];
474 ttout[0] = tmp;
475 }
476 else { ttout[1] = std::min(tmp, ttout[1]); }
477 }
478 else // point is flying to inside
479 {
480 if (tmp < tminimal || tmp > tmaximal) { continue; }
481 if (std::abs(tmp - ttin[0]) < halfTolerance) { continue; }
482 if (tmp < ttin[0])
483 {
484 ttin[1] = ttin[0];
485 ttin[0] = tmp;
486 }
487 else { ttin[1] = std::min(tmp, ttin[1]); }
488 }
489 continue;
490 }
491
492 // case 3: scratch or no intersection
493 G4double D = B*B - A*C;
494 if (D < 0.25*fScratch*fScratch*A*A)
495 {
496 if (A > 0) { return kInfinity; }
497 continue;
498 }
499
500 // case 4: two intersection points
501 G4double tmp = -B - std::copysign(std::sqrt(D), B);
502 G4double t1 = tmp/A + t0;
503 G4double t2 = C/tmp + t0;
504 G4double tsurfin = std::min(t1, t2);
505 G4double tsurfout = std::max(t1, t2);
506 if (A < 0) { std::swap(tsurfin, tsurfout); }
507
508 if (tsurfin >= tminimal && tsurfin <= tmaximal)
509 {
510 if (std::abs(tsurfin - ttin[0]) >= halfTolerance)
511 {
512 if (tsurfin < ttin[0])
513 {
514 ttin[1] = ttin[0];
515 ttin[0] = tsurfin;
516 }
517 else { ttin[1] = std::min(tsurfin, ttin[1]); }
518 }
519 }
520 if (tsurfout >= tminimal && tsurfout <= tmaximal)
521 {
522 if (std::abs(tsurfout - ttout[0]) >= halfTolerance)
523 {
524 if (tsurfout < ttout[0])
525 {
526 ttout[1] = ttout[0];
527 ttout[0] = tsurfout;
528 }
529 else { ttout[1] = std::min(tsurfout, ttout[1]); }
530 }
531 }
532 }
533
534 // Compute distance to In
535 //
536 if (ttin[0] == DBL_MAX) { return kInfinity; } // no entry point
537
538 // single entry point
539 if (ttin[1] == DBL_MAX)
540 {
541 G4double distin = ttin[0];
542 G4double distout = (distin >= ttout[0] - halfTolerance) ? ttout[1] : ttout[0];
543 G4double dist = (distout <= halfTolerance || distout - distin <= halfTolerance) ? kInfinity : distin;
544 return (dist < halfTolerance) ? 0. : dist;
545 }
546
547 // two entry points
548 if (ttin[1] < ttout[0])
549 {
550 G4double distin = ttin[1], distout = ttout[0];
551 G4double dist = (distout <= halfTolerance || distout - distin <= halfTolerance) ? kInfinity : distin;
552 return (dist < halfTolerance) ? 0. : dist;
553 }
554
555 // check 1st pair of in-out points
556 G4double distin1 = ttin[0], distout1 = ttout[0];
557 G4double dist1 = (distout1 <= halfTolerance || distout1 - distin1 <= halfTolerance) ? kInfinity : distin1;
558 if (dist1 != kInfinity) { return (dist1 < halfTolerance) ? 0. : dist1; }
559
560 // check 2nd pair of in-out points
561 G4double distin2 = ttin[1], distout2 = ttout[1];
562 G4double dist2 = (distout2 <= halfTolerance || distout2 - distin2 <= halfTolerance) ? kInfinity : distin2;
563 return (dist2 < halfTolerance) ? 0. : dist2;
564}
G4double D(G4double temp)
#define DBL_EPSILON
Definition templates.hh:66
#define DBL_MAX
Definition templates.hh:62

◆ DistanceToOut() [1/2]

G4double G4GenericTrap::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 835 of file G4GenericTrap.cc.

836{
837 G4double x = p.x(), y = p.y(), z = p.z();
838 G4double dist = std::abs(z) - fDz;
839 for (auto i = 0; i < 4; ++i)
840 {
841 if (fTwist[i] == 0.)
842 {
843 G4double distPlane = fSurf[i].D*x + fSurf[i].E*y + fSurf[i].F*z + fSurf[i].G;
844 dist = std::max(distPlane, dist);
845 }
846 else
847 {
848 G4double A = fSurf[i].A;
849 G4double B = fSurf[i].B;
850 G4double C = fSurf[i].C;
851 G4double Cz = C*z;
852 G4double CzF = Cz + fSurf[i].F;
853 G4double gradx = A*z + fSurf[i].D;
854 G4double grady = B*z + fSurf[i].E;
855 G4double gradz = A*x + B*y + Cz + CzF;
856 G4double fun = gradx*x + grady*y + CzF*z + fSurf[i].G;
857 G4double grad2 = gradx*gradx + grady*grady + gradz*gradz;
858 G4double divisor = std::sqrt(grad2) + std::sqrt(grad2 + f4k[i]*std::abs(fun));
859 G4double distSurf = 2.*fun/divisor;
860 dist = std::max(distSurf, dist);
861 }
862 }
863 return (dist < 0.) ? -dist : 0.; // return safety distance
864}

◆ DistanceToOut() [2/2]

G4double G4GenericTrap::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 605 of file G4GenericTrap.cc.

610{
611 G4double px = p.x(), py = p.y(), pz = p.z();
612 G4double vx = v.x(), vy = v.y(), vz = v.z();
613
614 // Check intersections with plane faces
615 //
616 if ((std::abs(pz) - fDz) >= -halfTolerance && pz*vz > 0.)
617 {
618 if (calcNorm)
619 {
620 *validNorm = true;
621 n->set(0., 0., std::copysign(1., pz));
622 }
623 return 0.;
624 }
625 G4double tout = (vz == 0) ? DBL_MAX : (std::copysign(fDz, vz) - pz)/vz;
626 G4int iface = (vz < 0) ? -4 : -2; // little trick for z-normal: (-4+3)=-1, (-2+3)=+1
627
628 for (auto i = 0; i < 4; ++i)
629 {
630 if (fTwist[i] != 0) { continue; } // skip twisted faces
631 const G4GenericTrapPlane& surf = fPlane[2*i];
632 G4double cosa = surf.A*vx + surf.B*vy + surf.C*vz;
633 if (cosa > 0)
634 {
635 G4double dist = surf.A*px + surf.B*py + surf.C*pz + surf.D;
636 if (dist >= -halfTolerance)
637 {
638 if (calcNorm)
639 {
640 *validNorm = true;
641 n->set(surf.A, surf.B, surf.C);
642 }
643 return 0.;
644 }
645 G4double tmp = -dist/cosa;
646 if (tout > tmp) { tout = tmp; iface = i; }
647 }
648 }
649
650 // Check intersections with twisted faces
651 //
652 constexpr G4double EPSILON = 1000.*DBL_EPSILON;
653 for (auto i = 0; i < 4; ++i)
654 {
655 if (fTwist[i] == 0) { continue; } // skip plane faces
656
657 // twisted face, solve quadratic equation
658 const G4GenericTrapSurface& surf = fSurf[i];
659 G4double ABC = surf.A*vx + surf.B*vy + surf.C*vz;
660 G4double ABCF = surf.A*px + surf.B*py + surf.C*pz + surf.F;
661 G4double A = ABC*vz;
662 G4double B = 0.5*(surf.D*vx + surf.E*vy + ABCF*vz + ABC*pz);
663 G4double C = surf.D*px + surf.E*py + ABCF*pz + surf.G;
664
665 if (std::abs(A) <= EPSILON)
666 {
667 // case 1: track is parallel to the surface
668 if (std::abs(B) <= EPSILON) { continue; }
669
670 // case 2: single root
671 G4double tmp = -0.5*C/B;
672 // compute normal at intersection point and check direction
673 G4double x = px + vx*tmp;
674 G4double y = py + vy*tmp;
675 G4double z = pz + vz*tmp;
676 G4double nx = surf.A*z + surf.D;
677 G4double ny = surf.B*z + surf.E;
678 G4double nz = surf.A*x + surf.B*y + 2.*surf.C*z + surf.F;
679
680 if (nx*vx + ny*vy + nz*vz > 0.) // point is flying to outside
681 {
682 auto k = (i + 1)%4;
683 G4double tz = (pz + fDz);
684 G4TwoVector a = fVertices[i] + fDelta[i]*tz;
685 G4TwoVector b = fVertices[k] + fDelta[k]*tz;
686 G4double dx = b.x() - a.x();
687 G4double dy = b.y() - a.y();
688 G4double leng = std::sqrt(dx*dx + dy*dy);
689 G4double dist = dx*(py - a.y()) - dy*(px - a.x());
690 if (dist >= -halfTolerance*leng) // point is on the surface
691 {
692 if (calcNorm)
693 {
694 *validNorm = false;
695 G4double normx = surf.A*pz + surf.D;
696 G4double normy = surf.B*pz + surf.E;
697 G4double normz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
698 G4double inv = 1./std::sqrt(normx*normx + normy*normy + normz*normz);
699 n->set(normx*inv, normy*inv, normz*inv);
700 }
701 return 0.;
702 }
703 if (tout > tmp) { tout = tmp; iface = i; }
704 }
705 continue;
706 }
707
708 // case 3: scratch or no intersection
709 G4double D = B*B - A*C;
710 if (D < 0.25*fScratch*fScratch*A*A)
711 {
712 // check position of the point
713 auto j = (i + 1)%4;
714 G4double tz = pz + fDz;
715 G4TwoVector a = fVertices[i] + fDelta[i]*tz;
716 G4TwoVector b = fVertices[j] + fDelta[j]*tz;
717 G4double dx = b.x() - a.x();
718 G4double dy = b.y() - a.y();
719 G4double leng = std::sqrt(dx*dx + dy*dy);
720 G4double dist = dx*(py - a.y()) - dy*(px - a.x());
721 if (dist <= -halfTolerance*leng) { continue; } // point is inside
722 if (A > 0 || dist > halfTolerance*leng) // convex surface (or point is outside)
723 {
724 if (calcNorm)
725 {
726 *validNorm = false;
727 G4double nx = surf.A*pz + surf.D;
728 G4double ny = surf.B*pz + surf.E;
729 G4double nz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
730 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
731 n->set(nx*inv, ny*inv, nz*inv);
732 }
733 return 0.;
734 }
735 continue;
736 }
737
738 // case 4: two intersection points
739 G4double tmp = -B - std::copysign(std::sqrt(D), B);
740 G4double t1 = tmp / A;
741 G4double t2 = C / tmp;
742 G4double tmin = std::min(t1, t2);
743 G4double tmax = std::max(t1, t2);
744
745 if (A < 0) // concave profile: tmin(out) -> tmax(in)
746 {
747 if (std::abs(tmax) < std::abs(tmin)) { continue; } // point flies inside
748 if (tmin <= halfTolerance) // point is on external side of the surface
749 {
750 G4double t = 0.5*(tmin + tmax);
751 G4double x = px + vx*t;
752 G4double y = py + vy*t;
753 G4double z = pz + vz*t;
754
755 auto j = (i + 1)%4;
756 G4double tz = z + fDz;
757 G4TwoVector a = fVertices[i] + fDelta[i]*tz;
758 G4TwoVector b = fVertices[j] + fDelta[j]*tz;
759 G4double dx = b.x() - a.x();
760 G4double dy = b.y() - a.y();
761 G4double leng = std::sqrt(dx*dx + dy*dy);
762 G4double dist = dx*(y - a.y()) - dy*(x - a.x());
763 if (dist <= -halfTolerance*leng) { continue; } // scratch
764 if (calcNorm)
765 {
766 *validNorm = false;
767 G4double nx = surf.A*pz + surf.D;
768 G4double ny = surf.B*pz + surf.E;
769 G4double nz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
770 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
771 n->set(nx*inv, ny*inv, nz*inv);
772 }
773 return 0.;
774 }
775 if (tout > tmin) { tout = tmin; iface = i; }
776 }
777 else // convex profile: tmin(in) -> tmax(out)
778 {
779 if (tmax < halfTolerance) // point is on the surface
780 {
781 if (calcNorm)
782 {
783 *validNorm = false;
784 G4double nx = surf.A*pz + surf.D;
785 G4double ny = surf.B*pz + surf.E;
786 G4double nz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
787 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
788 n->set(nx*inv, ny*inv, nz*inv);
789 }
790 return 0.;
791 }
792 if (tout > tmax) { tout = tmax; iface = i; }
793 }
794 }
795
796 // Compute normal, if required, and return distance to out
797 //
798 if (tout < halfTolerance) { tout = 0.; }
799 if (calcNorm)
800 {
801 if (iface < 0)
802 {
803 *validNorm = true;
804 n->set(0, 0, iface + 3); // little trick: (-4+3)=-1, (-2+3)=+1
805 }
806 else
807 {
808 const G4GenericTrapSurface& surf = fSurf[iface];
809 if (fTwist[iface] == 0)
810 {
811 *validNorm = true;
812 n->set(surf.D, surf.E, surf.F);
813 }
814 else
815 {
816 *validNorm = false;
817 G4double x = px + vx*tout;
818 G4double y = py + vy*tout;
819 G4double z = pz + vz*tout;
820 G4double nx = surf.A*z + surf.D;
821 G4double ny = surf.B*z + surf.E;
822 G4double nz = surf.A*x + surf.B*y + 2.*surf.C*z + surf.F;
823 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
824 n->set(nx*inv, ny*inv, nz*inv);
825 }
826 }
827 }
828 return tout;
829}

◆ GetCubicVolume()

G4double G4GenericTrap::GetCubicVolume ( )
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 1136 of file G4GenericTrap.cc.

1137{
1138 if (fCubicVolume == 0)
1139 {
1140 G4AutoLock l(&gentrapMutex);
1141 // diagonals
1142 G4TwoVector A = fVertices[3] - fVertices[1];
1143 G4TwoVector B = fVertices[2] - fVertices[0];
1144 G4TwoVector C = fVertices[7] - fVertices[5];
1145 G4TwoVector D = fVertices[6] - fVertices[4];
1146
1147 // kross products
1148 G4double AB = A.x()*B.y() - A.y()*B.x();
1149 G4double CD = C.x()*D.y() - C.y()*D.x();
1150 G4double AD = A.x()*D.y() - A.y()*D.x();
1151 G4double CB = C.x()*B.y() - C.y()*B.x();
1152
1153 fCubicVolume = ((AB + CD)/3. + (AD + CB)/6.)*fDz;
1154 l.unlock();
1155 }
1156 return fCubicVolume;
1157}
G4TemplateAutoLock< G4Mutex > G4AutoLock

◆ GetEntityType()

G4GeometryType G4GenericTrap::GetEntityType ( ) const
overridevirtual

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

Implements G4VSolid.

Definition at line 943 of file G4GenericTrap.cc.

944{
945 return { "G4GenericTrap" };
946}

Referenced by StreamInfo().

◆ GetExtent()

G4VisExtent G4GenericTrap::GetExtent ( ) const
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 1522 of file G4GenericTrap.cc.

1523{
1524 return { fMinBBox.x(), fMaxBBox.x(),
1525 fMinBBox.y(), fMaxBBox.y(),
1526 fMinBBox.z(), fMaxBBox.z() };
1527}

◆ GetNofVertices()

G4int G4GenericTrap::GetNofVertices ( ) const
inline

◆ GetPointOnSurface()

G4ThreeVector G4GenericTrap::GetPointOnSurface ( ) const
overridevirtual

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

Reimplemented from G4VSolid.

Definition at line 992 of file G4GenericTrap.cc.

993{
994 if (fArea[0] + fArea[1] + fArea[2] + fArea[3] == 0.)
995 {
996 G4AutoLock l(&lateralareaMutex);
997 fArea[0] = GetLateralFaceArea(0);
998 fArea[1] = GetLateralFaceArea(1);
999 fArea[2] = GetLateralFaceArea(2);
1000 fArea[3] = GetLateralFaceArea(3);
1001 l.unlock();
1002 }
1003
1004 constexpr G4int iface[6][4] =
1005 { {0,1,2,3}, {0,4,5,1}, {1,5,6,2}, {2,6,7,3}, {3,7,4,0}, {4,5,6,7} };
1006
1007 G4bool isTwisted[6] = {false};
1008 for (auto i = 0; i < 4; ++i)
1009 {
1010 isTwisted[i + 1] = (fTwist[i] != 0.0);
1011 }
1012
1013 G4double ssurf[6];
1014 G4TwoVector A = fVertices[3] - fVertices[1];
1015 G4TwoVector B = fVertices[2] - fVertices[0];
1016 G4TwoVector C = fVertices[7] - fVertices[5];
1017 G4TwoVector D = fVertices[6] - fVertices[4];
1018 ssurf[0] = (A.x()*B.y() - A.y()*B.x())*0.5; // -fDz face
1019 ssurf[1] = ssurf[0] + fArea[0];
1020 ssurf[2] = ssurf[1] + fArea[1];
1021 ssurf[3] = ssurf[2] + fArea[2];
1022 ssurf[4] = ssurf[3] + fArea[3];
1023 ssurf[5] = ssurf[4] + (C.x()*D.y() - C.y()*D.x())*.5; // +fDz face
1024
1025 G4double select = ssurf[5]*G4QuickRand();
1026 G4int k;
1027 for (k = 0; k < 5; ++k)
1028 {
1029 if (select <= ssurf[k]) { break; }
1030 }
1031
1032 G4int i0 = iface[k][0];
1033 G4int i1 = iface[k][1];
1034 G4int i2 = iface[k][2];
1035 G4int i3 = iface[k][3];
1036 G4ThreeVector pp[4];
1037 pp[0].set(fVertices[i0].x(), fVertices[i0].y(), ((k == 5) ? fDz : -fDz));
1038 pp[1].set(fVertices[i1].x(), fVertices[i1].y(), ((k == 0) ? -fDz : fDz));
1039 pp[2].set(fVertices[i2].x(), fVertices[i2].y(), ((k == 0) ? -fDz : fDz));
1040 pp[3].set(fVertices[i3].x(), fVertices[i3].y(), ((k == 5) ? fDz : -fDz));
1041
1042 G4ThreeVector point;
1043 if (isTwisted[k])
1044 { // twisted face, rejection sampling
1045 G4double maxlength = std::max((pp[2] - pp[1]).mag(), (pp[3] - pp[0]).mag());
1046 point = (pp[0] + pp[1] + pp[2] + pp[3])*0.25;
1047 for (auto i = 0; i < 10000; ++i)
1048 {
1049 G4double u = G4QuickRand();
1050 G4ThreeVector p0 = pp[0] + (pp[1] - pp[0])*u;
1051 G4ThreeVector p1 = pp[3] + (pp[2] - pp[3])*u;
1052 G4double v = G4QuickRand()*(maxlength/(p1 - p0).mag());
1053 if (v >= 1.) { continue; }
1054 point = p0 + (p1 - p0)*v;
1055 break;
1056 }
1057 }
1058 else
1059 { // plane face
1060 G4double u = G4QuickRand();
1061 G4double v = G4QuickRand();
1062 if (u + v > 1.) { u = 1. - u; v = 1. - v; }
1063 G4double ss = (((pp[2] - pp[0]).cross(pp[3] - pp[0])).mag())*0.5;
1064 G4int j = (select > ssurf[k] - ss) ? 3 : 1;
1065 point = pp[0] + (pp[2] - pp[0])*u + (pp[j] - pp[0])*v;
1066 }
1067 return point;
1068}
G4double G4QuickRand(uint32_t seed=0)

◆ GetPolyhedron()

G4Polyhedron * G4GenericTrap::GetPolyhedron ( ) const
overridevirtual

Smart access function - creates on request and stores for future access. A null pointer means "not available".

Reimplemented from G4VSolid.

Definition at line 1493 of file G4GenericTrap.cc.

1494{
1495 if ( (fpPolyhedron == nullptr)
1496 || fRebuildPolyhedron
1497 || (fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1498 fpPolyhedron->GetNumberOfRotationSteps()) )
1499 {
1500 G4AutoLock l(&polyhedronMutex);
1501 delete fpPolyhedron;
1502 fpPolyhedron = CreatePolyhedron();
1503 fRebuildPolyhedron = false;
1504 l.unlock();
1505 }
1506 return fpPolyhedron;
1507}
G4Polyhedron * CreatePolyhedron() const override

◆ GetSurfaceArea()

G4double G4GenericTrap::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 1163 of file G4GenericTrap.cc.

1164{
1165 if (fSurfaceArea == 0)
1166 {
1167 G4AutoLock l(&gentrapMutex);
1168 G4TwoVector A = fVertices[3] - fVertices[1];
1169 G4TwoVector B = fVertices[2] - fVertices[0];
1170 G4TwoVector C = fVertices[7] - fVertices[5];
1171 G4TwoVector D = fVertices[6] - fVertices[4];
1172 G4double S_bot = (A.x()*B.y() - A.y()*B.x())*0.5;
1173 G4double S_top = (C.x()*D.y() - C.y()*D.x())*0.5;
1174 fArea[0] = GetLateralFaceArea(0);
1175 fArea[1] = GetLateralFaceArea(1);
1176 fArea[2] = GetLateralFaceArea(2);
1177 fArea[3] = GetLateralFaceArea(3);
1178 fSurfaceArea = S_bot + S_top + fArea[0] + fArea[1] + fArea[2] + fArea[3];
1179 l.unlock();
1180 }
1181 return fSurfaceArea;
1182}

◆ GetTwistAngle()

G4double G4GenericTrap::GetTwistAngle ( G4int index) const
inline

Referenced by CreatePolyhedron().

◆ GetVertex()

G4TwoVector G4GenericTrap::GetVertex ( G4int index) const
inline

Referenced by CalculateExtent().

◆ GetVertices()

const std::vector< G4TwoVector > & G4GenericTrap::GetVertices ( ) const
inline

◆ GetVisSubdivisions()

G4int G4GenericTrap::GetVisSubdivisions ( ) const
inline

Referenced by CreatePolyhedron().

◆ GetZHalfLength()

G4double G4GenericTrap::GetZHalfLength ( ) const
inline

Accessors and modifiers.

Referenced by CalculateExtent(), and G4GDMLWriteSolids::GenTrapWrite().

◆ Inside()

EInside G4GenericTrap::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 144 of file G4GenericTrap.cc.

145{
146 G4double px = p.x(), py = p.y(), pz = p.z();
147
148 // intersect edges by z = pz plane
149 G4TwoVector pp[4];
150 G4double z = (pz + fDz);
151 for (auto i = 0; i < 4; ++i)
152 {
153 pp[i] = fVertices[i] + fDelta[i]*z;
154 }
155
156 // estimate distance to the solid
157 G4double dist = std::abs(pz) - fDz;
158 for (auto i = 0; i < 4; ++i)
159 {
160 if (fTwist[i] == 0.)
161 {
162 G4double dd = fSurf[i].D*px + fSurf[i].E*py + fSurf[i].F*pz + fSurf[i].G;
163 dist = std::max(dd, dist);
164 }
165 else
166 {
167 auto j = (i + 1)%4;
168 G4TwoVector a = pp[i];
169 G4TwoVector b = pp[j];
170 G4double dx = b.x() - a.x();
171 G4double dy = b.y() - a.y();
172 G4double leng = std::sqrt(dx*dx + dy*dy);
173 G4double dd = (dx*(py - a.y()) - dy*(px - a.x()))/leng;
174 dist = std::max(dd, dist);
175 }
176 }
177 return (dist > halfTolerance) ? kOutside :
178 ((dist > -halfTolerance) ? kSurface : kInside);
179}
@ kInside
Definition geomdefs.hh:70
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69

◆ IsFaceted()

G4bool G4GenericTrap::IsFaceted ( ) const
overridevirtual

Returns true if the solid has only planar faces; false if twisted.

Reimplemented from G4VSolid.

Definition at line 952 of file G4GenericTrap.cc.

953{
954 return (!fIsTwisted);
955}

◆ IsTwisted()

G4bool G4GenericTrap::IsTwisted ( ) const
inline

◆ operator=()

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

Definition at line 111 of file G4GenericTrap.cc.

112{
113 // Check assignment to self
114 if (this == &rhs) { return *this; }
115
116 // Copy base class data
118
119 // Copy data
120 halfTolerance = rhs.halfTolerance; fScratch = rhs.fScratch;
121 fDz = rhs.fDz; fVertices = rhs.fVertices; fIsTwisted = rhs.fIsTwisted;
122 fMinBBox = rhs.fMinBBox; fMaxBBox = rhs.fMaxBBox;
123 fVisSubdivisions = rhs.fVisSubdivisions;
124 fSurfaceArea = rhs.fSurfaceArea; fCubicVolume = rhs.fCubicVolume;
125
126 for (auto i = 0; i < 8; ++i) { fVertices[i] = rhs.fVertices[i]; }
127 for (auto i = 0; i < 5; ++i) { fTwist[i] = rhs.fTwist[i]; }
128 for (auto i = 0; i < 4; ++i) { fDelta[i] = rhs.fDelta[i]; }
129 for (auto i = 0; i < 8; ++i) { fPlane[i] = rhs.fPlane[i]; }
130 for (auto i = 0; i < 4; ++i) { fSurf[i] = rhs.fSurf[i]; }
131 for (auto i = 0; i < 4; ++i) { f4k[i] = rhs.f4k[i]; }
132 for (auto i = 0; i < 4; ++i) { fArea[i] = rhs.fArea[i]; }
133
134 fRebuildPolyhedron = false;
135 delete fpPolyhedron; fpPolyhedron = nullptr;
136
137 return *this;
138}
G4VSolid & operator=(const G4VSolid &rhs)
Definition G4VSolid.cc:108

◆ SetVisSubdivisions()

void G4GenericTrap::SetVisSubdivisions ( G4int subdiv)
inline

◆ StreamInfo()

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

Streams the object contents to an output stream.

Implements G4VSolid.

Definition at line 970 of file G4GenericTrap.cc.

971{
972 G4long oldprc = os.precision(16);
973 os << "-----------------------------------------------------------\n"
974 << " *** Dump for solid - " << GetName() << " ***\n"
975 << " ===================================================\n"
976 << "Solid geometry type: " << GetEntityType() << "\n"
977 << " half length Z: " << fDz/mm << "\n"
978 << " list of vertices:\n";
979 for (G4int i = 0; i < 8; ++i)
980 {
981 os << " #" << i << " " << fVertices[i] << "\n";
982 }
983 os << "-----------------------------------------------------------\n";
984 os.precision(oldprc);
985 return os;
986}
long G4long
Definition G4Types.hh:87
G4GeometryType GetEntityType() const override
G4String GetName() const

◆ SurfaceNormal()

G4ThreeVector G4GenericTrap::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 185 of file G4GenericTrap.cc.

186{
187 G4double halfToleranceSquared = halfTolerance*halfTolerance;
188 G4double px = p.x(), py = p.y(), pz = p.z();
189 G4double nx = 0, ny = 0, nz = 0;
190
191 // intersect edges by z = pz plane
192 G4TwoVector pp[4];
193 G4double tz = (pz + fDz);
194 for (auto i = 0; i < 4; ++i)
195 {
196 pp[i] = fVertices[i] + fDelta[i]*tz;
197 }
198
199 // check bottom and top faces
200 G4double dz = std::abs(pz) - fDz;
201 nz = std::copysign(G4double(std::abs(dz) <= halfTolerance), pz);
202
203 // check lateral faces
204 for (auto i = 0; i < 4; ++i)
205 {
206 if (fTwist[i] == 0.)
207 {
208 G4double dd = fSurf[i].D*px + fSurf[i].E*py + fSurf[i].F*pz + fSurf[i].G;
209 if (std::abs(dd) <= halfTolerance)
210 {
211 nx += fSurf[i].D;
212 ny += fSurf[i].E;
213 nz += fSurf[i].F;
214 }
215 }
216 else
217 {
218 auto j = (i + 1)%4;
219 G4TwoVector a = pp[i];
220 G4TwoVector b = pp[j];
221 G4double dx = b.x() - a.x();
222 G4double dy = b.y() - a.y();
223 G4double ll = dx*dx + dy*dy;
224 G4double dd = dx*(py - a.y()) - dy*(px - a.x());
225 if (dd*dd <= halfToleranceSquared*ll)
226 {
227 G4double x = fSurf[i].A*pz + fSurf[i].D;
228 G4double y = fSurf[i].B*pz + fSurf[i].E;
229 G4double z = fSurf[i].A*px + fSurf[i].B*py + 2.*fSurf[i].C*pz + fSurf[i].F;
230 G4double inv = 1./std::sqrt(x*x + y*y + z*z);
231 nx += x*inv;
232 ny += y*inv;
233 nz += z*inv;
234 }
235 }
236 }
237
238 // return normal
239 G4double mag2 = nx*nx + ny*ny + nz*nz;
240 if (mag2 == 0.)
241 {
242 return ApproxSurfaceNormal(p); // point is not on the surface
243 }
244 G4double mag = std::sqrt(mag2);
245 G4double inv = (mag == 1.) ? 1. : 1./mag;
246 return { nx*inv, ny*inv, nz*inv };
247}

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