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

G4PolyPhiFace is a face that bounds a polycone or polyhedra when it has a phi opening. Specifically, it is a face that lies on a plane that passes through the Z axis, having boundaries that are straight lines of arbitrary length and direction, but with corners aways on the same side of the Z axis. More...

#include <G4PolyPhiFace.hh>

Inheritance diagram for G4PolyPhiFace:

Public Member Functions

 G4PolyPhiFace (const G4ReduciblePolygon *rz, G4double phi, G4double deltaPhi, G4double phiOther)
 ~G4PolyPhiFace () override
 G4PolyPhiFace (const G4PolyPhiFace &source)
G4PolyPhiFaceoperator= (const G4PolyPhiFace &source)
G4bool Intersect (const G4ThreeVector &p, const G4ThreeVector &v, G4bool outgoing, G4double surfTolerance, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal, G4bool &allBehind) override
G4double Distance (const G4ThreeVector &p, G4bool outgoing) override
EInside Inside (const G4ThreeVector &p, G4double tolerance, G4double *bestDistance) override
G4ThreeVector Normal (const G4ThreeVector &p, G4double *bestDistance) override
G4double Extent (const G4ThreeVector axis) override
void CalculateExtent (const EAxis axis, const G4VoxelLimits &voxelLimit, const G4AffineTransform &tranform, G4SolidExtentList &extentList) override
G4VCSGfaceClone () override
G4double SurfaceArea () override
 G4PolyPhiFace (__void__ &)
void Diagnose (G4VSolid *solid)
Public Member Functions inherited from G4VCSGface
 G4VCSGface ()=default
virtual ~G4VCSGface ()=default

Detailed Description

G4PolyPhiFace is a face that bounds a polycone or polyhedra when it has a phi opening. Specifically, it is a face that lies on a plane that passes through the Z axis, having boundaries that are straight lines of arbitrary length and direction, but with corners aways on the same side of the Z axis.

Definition at line 83 of file G4PolyPhiFace.hh.

Constructor & Destructor Documentation

◆ G4PolyPhiFace() [1/3]

G4PolyPhiFace::G4PolyPhiFace ( const G4ReduciblePolygon * rz,
G4double phi,
G4double deltaPhi,
G4double phiOther )

Constructor where points r,z should be supplied in clockwise order in r,z. For example: [1]------—[2] ^ R | | | | | +--> z [0]------—[3]

Parameters
[in]rzPointer to previous r,Z section.
[in]phiInitial Phi starting angle.
[in]deltaPhiTotal Phi angle.
[in]phiOtherPhi angle of next section.

Definition at line 51 of file G4PolyPhiFace.cc.

55{
57
58 numEdges = rz->NumVertices();
59
60 rMin = rz->Amin();
61 rMax = rz->Amax();
62 zMin = rz->Bmin();
63 zMax = rz->Bmax();
64
65 //
66 // Is this the "starting" phi edge of the two?
67 //
68 G4bool start = (phiOther > phi);
69
70 //
71 // Build radial vector
72 //
73 radial = G4ThreeVector( std::cos(phi), std::sin(phi), 0.0 );
74
75 //
76 // Build normal
77 //
78 G4double zSign = start ? 1 : -1;
79 normal = G4ThreeVector( zSign*radial.y(), -zSign*radial.x(), 0 );
80
81 //
82 // Is allBehind?
83 //
84 allBehind = (zSign*(std::cos(phiOther)*radial.y() - std::sin(phiOther)*radial.x()) < 0);
85
86 //
87 // Adjacent edges
88 //
89 G4double midPhi = phi + (start ? +0.5 : -0.5)*deltaPhi;
90 G4double cosMid = std::cos(midPhi),
91 sinMid = std::sin(midPhi);
92 //
93 // Allocate corners
94 //
95 const std::size_t maxEdges = numEdges>0 ? numEdges : 1;
96 corners = new G4PolyPhiFaceVertex[maxEdges];
97 //
98 // Fill them
99 //
100 G4ReduciblePolygonIterator iterRZ(rz);
101
102 G4PolyPhiFaceVertex* corn = corners;
103 G4PolyPhiFaceVertex* helper = corners;
104
105 iterRZ.Begin();
106 do // Loop checking, 13.08.2015, G.Cosmo
107 {
108 corn->r = iterRZ.GetA();
109 corn->z = iterRZ.GetB();
110 corn->x = corn->r*radial.x();
111 corn->y = corn->r*radial.y();
112
113 // Add pointer on prev corner
114 //
115 if( corn == corners )
116 { corn->prev = corners+maxEdges-1;}
117 else
118 { corn->prev = helper; }
119
120 // Add pointer on next corner
121 //
122 if( corn < corners+maxEdges-1 )
123 { corn->next = corn+1;}
124 else
125 { corn->next = corners; }
126
127 helper = corn;
128 } while( ++corn, iterRZ.Next() );
129
130 //
131 // Allocate edges
132 //
133 edges = new G4PolyPhiFaceEdge[maxEdges];
134
135 //
136 // Fill them
137 //
138 G4double rFact = std::cos(0.5*deltaPhi);
139 G4double rFactNormalize = 1.0/std::sqrt(1.0+rFact*rFact);
140
141 G4PolyPhiFaceVertex* prev = corners+maxEdges-1,
142 * here = corners;
143 G4PolyPhiFaceEdge* edge = edges;
144 do // Loop checking, 13.08.2015, G.Cosmo
145 {
146 G4ThreeVector sideNorm;
147
148 edge->v0 = prev;
149 edge->v1 = here;
150
151 G4double dr = here->r - prev->r,
152 dz = here->z - prev->z;
153
154 edge->length = std::sqrt( dr*dr + dz*dz );
155
156 edge->tr = dr/edge->length;
157 edge->tz = dz/edge->length;
158
159 if ((here->r < DBL_MIN) && (prev->r < DBL_MIN))
160 {
161 //
162 // Sigh! Always exceptions!
163 // This edge runs at r==0, so its adjoing surface is not a
164 // PolyconeSide or PolyhedraSide, but the opposite PolyPhiFace.
165 //
166 G4double zSignOther = start ? -1 : 1;
167 sideNorm = G4ThreeVector( zSignOther*std::sin(phiOther),
168 -zSignOther*std::cos(phiOther), 0 );
169 }
170 else
171 {
172 sideNorm = G4ThreeVector( edge->tz*cosMid,
173 edge->tz*sinMid,
174 -edge->tr*rFact );
175 sideNorm *= rFactNormalize;
176 }
177 sideNorm += normal;
178
179 edge->norm3D = sideNorm.unit();
180 } while( edge++, prev=here, ++here < corners+maxEdges );
181
182 //
183 // Go back and fill in corner "normals"
184 //
185 G4PolyPhiFaceEdge* prevEdge = edges+maxEdges-1;
186 edge = edges;
187 do // Loop checking, 13.08.2015, G.Cosmo
188 {
189 //
190 // Calculate vertex 2D normals (on the phi surface)
191 //
192 G4double rPart = prevEdge->tr + edge->tr;
193 G4double zPart = prevEdge->tz + edge->tz;
194 G4double norm = std::sqrt( rPart*rPart + zPart*zPart );
195 G4double rNorm = +zPart/norm;
196 G4double zNorm = -rPart/norm;
197
198 edge->v0->rNorm = rNorm;
199 edge->v0->zNorm = zNorm;
200
201 //
202 // Calculate the 3D normals.
203 //
204 // Find the vector perpendicular to the z axis
205 // that defines the plane that contains the vertex normal
206 //
207 G4ThreeVector xyVector;
208
209 if (edge->v0->r < DBL_MIN)
210 {
211 //
212 // This is a vertex at r==0, which is a special
213 // case. The normal we will construct lays in the
214 // plane at the center of the phi opening.
215 //
216 // We also know that rNorm < 0
217 //
218 G4double zSignOther = start ? -1 : 1;
219 G4ThreeVector normalOther( zSignOther*std::sin(phiOther),
220 -zSignOther*std::cos(phiOther), 0 );
221
222 xyVector = - normal - normalOther;
223 }
224 else
225 {
226 //
227 // This is a vertex at r > 0. The plane
228 // is the average of the normal and the
229 // normal of the adjacent phi face
230 //
231 xyVector = G4ThreeVector( cosMid, sinMid, 0 );
232 if (rNorm < 0)
233 {
234 xyVector -= normal;
235 }
236 else
237 {
238 xyVector += normal;
239 }
240 }
241
242 //
243 // Combine it with the r/z direction from the face
244 //
245 edge->v0->norm3D = rNorm*xyVector.unit() + G4ThreeVector( 0, 0, zNorm );
246 } while( prevEdge=edge, ++edge < edges+maxEdges );
247
248 //
249 // Build point on surface
250 //
251 G4double rAve = 0.5*(rMax-rMin),
252 zAve = 0.5*(zMax-zMin);
253 surface = G4ThreeVector( rAve*radial.x(), rAve*radial.y(), zAve );
254}
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
Hep3Vector unit() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4double Amin() const
G4double Bmin() const
G4double Amax() const
G4PolyPhiFaceVertex * v1
G4ThreeVector norm3D
G4PolyPhiFaceVertex * v0
G4ThreeVector norm3D
G4PolyPhiFaceVertex * next
G4PolyPhiFaceVertex * prev
#define DBL_MIN
Definition templates.hh:54

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

◆ ~G4PolyPhiFace()

G4PolyPhiFace::~G4PolyPhiFace ( )
override

Destructor. Removes edges and corners.

Definition at line 291 of file G4PolyPhiFace.cc.

292{
293 delete [] edges;
294 delete [] corners;
295}

◆ G4PolyPhiFace() [2/3]

G4PolyPhiFace::G4PolyPhiFace ( const G4PolyPhiFace & source)

Copy constructor and assignment operator.

Definition at line 301 of file G4PolyPhiFace.cc.

302{
303 CopyStuff( source );
304}

◆ G4PolyPhiFace() [3/3]

G4PolyPhiFace::G4PolyPhiFace ( __void__ & )

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

Definition at line 282 of file G4PolyPhiFace.cc.

283 : rMin(0.), rMax(0.), zMin(0.), zMax(0.), kCarTolerance(0.)
284{
285}
const G4double kCarTolerance

Member Function Documentation

◆ CalculateExtent()

void G4PolyPhiFace::CalculateExtent ( const EAxis axis,
const G4VoxelLimits & voxelLimit,
const G4AffineTransform & tranform,
G4SolidExtentList & extentList )
overridevirtual

Calculates the extent of the face for the voxel navigator.

Parameters
[in]axisThe axis in which to check the shapes 3D extent against.
[in]voxelLimitLimits along x, y, and/or z axes.
[in]tranformA coordinate transformation on which to apply to the shape before testing.
[out]extentListThe list of (voxel) extents along the axis.

Implements G4VCSGface.

Definition at line 607 of file G4PolyPhiFace.cc.

611{
612 //
613 // Construct a (sometimes big) clippable polygon,
614 //
615 // Perform the necessary transformations while doing so
616 //
617 G4ClippablePolygon polygon;
618
619 G4PolyPhiFaceVertex* corner = corners;
620 do // Loop checking, 13.08.2015, G.Cosmo
621 {
622 G4ThreeVector point( 0, 0, corner->z );
623 point += radial*corner->r;
624
625 polygon.AddVertexInOrder( transform.TransformPoint( point ) );
626 } while( ++corner < corners + numEdges );
627
628 //
629 // Clip away
630 //
631 if (polygon.PartialClip( voxelLimit, axis ))
632 {
633 //
634 // Add it to the list
635 //
636 polygon.SetNormal( transform.TransformAxis(normal) );
637 extentList.AddSurface( polygon );
638 }
639}
G4bool PartialClip(const G4VoxelLimits &voxelLimit, const EAxis IgnoreMe)
void AddVertexInOrder(const G4ThreeVector &vertex)
void SetNormal(const G4ThreeVector &newNormal)
void AddSurface(const G4ClippablePolygon &surface)
const axis_t axis_to_type< N >::axis
Definition pugixml.cc:9668

◆ Clone()

G4VCSGface * G4PolyPhiFace::Clone ( )
inlineoverridevirtual

Method invoked by the copy constructor or the assignment operator. Its purpose is to return a pointer to a duplicate copy of the face.

Implements G4VCSGface.

◆ Diagnose()

void G4PolyPhiFace::Diagnose ( G4VSolid * solid)

Throws an exception if something is found inconsistent with the solid. For debugging purposes only.

Definition at line 263 of file G4PolyPhiFace.cc.

264{
265 G4PolyPhiFaceVertex* corner = corners;
266 do // Loop checking, 13.08.2015, G.Cosmo
267 {
268 G4ThreeVector test(corner->x, corner->y, corner->z);
269 test -= 1E-6*corner->norm3D;
270
271 if (owner->Inside(test) != kInside)
272 {
273 G4Exception( "G4PolyPhiFace::Diagnose()", "GeomSolids0002",
274 FatalException, "Bad vertex normal found." );
275 }
276 } while( ++corner < corners+numEdges );
277}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
@ kInside
Definition geomdefs.hh:70

◆ Distance()

G4double G4PolyPhiFace::Distance ( const G4ThreeVector & p,
G4bool outgoing )
overridevirtual

Determines the distance of a point from either the inside or outside surfaces of the face.

Parameters
[in]pPosition.
[in]outgoingFlag, true, to consider only inside surfaces or false, to consider only outside surfaces.
Returns
The distance to the closest surface satisfying requirements or kInfinity if no such surface exists.

Implements G4VCSGface.

Definition at line 432 of file G4PolyPhiFace.cc.

433{
434 G4double normSign = outgoing ? +1 : -1;
435 //
436 // Correct normal?
437 //
438 G4ThreeVector ps = p - surface;
439 G4double distPhi = -normSign*normal.dot(ps);
440
441 if (distPhi < -0.5*kCarTolerance)
442 {
443 return kInfinity;
444 }
445 if (distPhi < 0)
446 {
447 distPhi = 0.0;
448 }
449
450 //
451 // Calculate projected point in r,z
452 //
453 G4double r = radial.dot(p);
454
455 //
456 // Are we inside the face?
457 //
458 G4double distRZ2;
459
460 if (InsideEdges( r, p.z(), &distRZ2, nullptr ))
461 {
462 //
463 // Yup, answer is just distPhi
464 //
465 return distPhi;
466 }
467
468 //
469 // Nope. Penalize by distance out
470 //
471 return std::sqrt( distPhi*distPhi + distRZ2 );
472}
double z() const
double dot(const Hep3Vector &) const

◆ Extent()

G4double G4PolyPhiFace::Extent ( const G4ThreeVector axis)
overridevirtual

Returns the face extent along the axis.

Parameters
[in]axisUnit vector defining the direction.
Returns
The largest point along the given axis of the face's extent.

Implements G4VCSGface.

Definition at line 587 of file G4PolyPhiFace.cc.

588{
589 G4double max = -kInfinity;
590
591 G4PolyPhiFaceVertex* corner = corners;
592 do // Loop checking, 13.08.2015, G.Cosmo
593 {
594 G4double here = axis.x()*corner->r*radial.x()
595 + axis.y()*corner->r*radial.y()
596 + axis.z()*corner->z;
597 if (here > max) { max = here; }
598 } while( ++corner < corners + numEdges );
599
600 return max;
601}
T max(const T t1, const T t2)
brief Return the largest of the two arguments

◆ Inside()

EInside G4PolyPhiFace::Inside ( const G4ThreeVector & p,
G4double tolerance,
G4double * bestDistance )
overridevirtual

Determines whether a point is inside, outside, or on the surface of the face.

Parameters
[in]pPosition.
[in]toleranceTolerance defining the bounds of the "kSurface", nominally equal to kCarTolerance/2.
[out]bestDistanceDistance to the closest surface (in or out).
Returns
kInside if the point is closest to the inside surface; kOutside if the point is closest to the outside surface; kSurface if the point is withing tolerance of the surface.

Implements G4VCSGface.

Definition at line 476 of file G4PolyPhiFace.cc.

479{
480 //
481 // Get distance along phi, which if negative means the point
482 // is nominally inside the shape.
483 //
484 G4ThreeVector ps = p - surface;
485 G4double distPhi = normal.dot(ps);
486
487 //
488 // Calculate projected point in r,z
489 //
490 G4double r = radial.dot(p);
491
492 //
493 // Are we inside the face?
494 //
495 G4double distRZ2;
496 G4PolyPhiFaceVertex* base3Dnorm = nullptr;
497 G4ThreeVector* head3Dnorm = nullptr;
498
499 if (InsideEdges( r, p.z(), &distRZ2, &base3Dnorm, &head3Dnorm ))
500 {
501 //
502 // Looks like we're inside. Distance is distance in phi.
503 //
504 *bestDistance = std::fabs(distPhi);
505
506 //
507 // Use distPhi to decide fate
508 //
509 if (distPhi < -tolerance) { return kInside; }
510 if (distPhi < tolerance) { return kSurface; }
511 return kOutside;
512 }
513
514 //
515 // We're outside the extent of the face,
516 // so the distance is penalized by distance from edges in RZ
517 //
518 *bestDistance = std::sqrt( distPhi*distPhi + distRZ2 );
519
520 //
521 // Use edge normal to decide fate
522 //
523 G4ThreeVector cc( base3Dnorm->r*radial.x(),
524 base3Dnorm->r*radial.y(),
525 base3Dnorm->z );
526 cc = p - cc;
527 G4double normDist = head3Dnorm->dot(cc);
528 if ( distRZ2 > tolerance*tolerance )
529 {
530 //
531 // We're far enough away that kSurface is not possible
532 //
533 return normDist < 0 ? kInside : kOutside;
534 }
535
536 if (normDist < -tolerance) { return kInside; }
537 if (normDist < tolerance) { return kSurface; }
538 return kOutside;
539}
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69

◆ Intersect()

G4bool G4PolyPhiFace::Intersect ( const G4ThreeVector & p,
const G4ThreeVector & v,
G4bool outgoing,
G4double surfTolerance,
G4double & distance,
G4double & distFromSurface,
G4ThreeVector & normal,
G4bool & allBehind )
overridevirtual

Determines the distance along a line to the face.

Parameters
[in]pPosition.
[in]vDirection (assumed to be a unit vector).
[in]outgoingFlag true, to consider only inside surfaces; false, to consider only outside surfaces.
[in]surfToleranceMinimum distance from the surface.
[out]distanceDistance to intersection.
[out]distFromSurfaceDistance from surface (along surface normal), < 0 if the point is in front of the surface.
[out]normalNormal of surface at intersection point.
[out]allBehindFlag, true, if entire surface is behind normal.
Returns
true if there is an intersection, false otherwise.

Implements G4VCSGface.

Definition at line 377 of file G4PolyPhiFace.cc.

385{
386 G4double normSign = outgoing ? +1 : -1;
387
388 //
389 // These don't change
390 //
391 isAllBehind = allBehind;
392 aNormal = normal;
393
394 //
395 // Correct normal? Here we have straight sides, and can safely ignore
396 // intersections where the dot product with the normal is zero.
397 //
398 G4double dotProd = normSign*normal.dot(v);
399
400 if (dotProd <= 0) { return false; }
401
402 //
403 // Calculate distance to surface. If the side is too far
404 // behind the point, we must reject it.
405 //
406 G4ThreeVector ps = p - surface;
407 distFromSurface = -normSign*ps.dot(normal);
408
409 if (distFromSurface < -surfTolerance) { return false; }
410
411 //
412 // Calculate precise distance to intersection with the side
413 // (along the trajectory, not normal to the surface)
414 //
415 distance = distFromSurface/dotProd;
416
417 //
418 // Calculate intersection point in r,z
419 //
420 G4ThreeVector ip = p + distance*v;
421
422 G4double r = radial.dot(ip);
423
424 //
425 // And is it inside the r/z extent?
426 //
427 return InsideEdgesExact( r, ip.z(), normSign, p, v );
428}

◆ Normal()

G4ThreeVector G4PolyPhiFace::Normal ( const G4ThreeVector & p,
G4double * bestDistance )
overridevirtual

Returns the normal of surface closest to the point.

Parameters
[in]pPosition.
[out]bestDistanceDistance to the closest surface (in or out).
Returns
The normal of the surface nearest the point.

Implements G4VCSGface.

Definition at line 546 of file G4PolyPhiFace.cc.

548{
549 //
550 // Get distance along phi, which if negative means the point
551 // is nominally inside the shape.
552 //
553 G4double distPhi = normal.dot(p);
554
555 //
556 // Calculate projected point in r,z
557 //
558 G4double r = radial.dot(p);
559
560 //
561 // Are we inside the face?
562 //
563 G4double distRZ2;
564
565 if (InsideEdges( r, p.z(), &distRZ2, nullptr ))
566 {
567 //
568 // Yup, answer is just distPhi
569 //
570 *bestDistance = std::fabs(distPhi);
571 }
572 else
573 {
574 //
575 // Nope. Penalize by distance out
576 //
577 *bestDistance = std::sqrt( distPhi*distPhi + distRZ2 );
578 }
579
580 return normal;
581}

◆ operator=()

G4PolyPhiFace & G4PolyPhiFace::operator= ( const G4PolyPhiFace & source)

Definition at line 310 of file G4PolyPhiFace.cc.

311{
312 if (this == &source) { return *this; }
313
314 delete [] edges;
315 delete [] corners;
316
317 CopyStuff( source );
318
319 return *this;
320}

◆ SurfaceArea()

G4double G4PolyPhiFace::SurfaceArea ( )
overridevirtual

Returning an estimation of the face surface area, in internal units.

Implements G4VCSGface.

Definition at line 906 of file G4PolyPhiFace.cc.

907{
908 if ( fSurfaceArea==0. ) { Triangulate(); }
909 return fSurfaceArea;
910}

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