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

#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
 
G4double SurfaceTriangle (const G4ThreeVector &p1, const G4ThreeVector &p2, const G4ThreeVector &p3, G4ThreeVector *p4)
 
G4ThreeVector GetPointOnFace () override
 
 G4PolyPhiFace (__void__ &)
 
void Diagnose (G4VSolid *solid)
 
- Public Member Functions inherited from G4VCSGface
 G4VCSGface ()=default
 
virtual ~G4VCSGface ()=default
 

Protected Member Functions

G4bool InsideEdgesExact (G4double r, G4double z, G4double normSign, const G4ThreeVector &p, const G4ThreeVector &v)
 
G4bool InsideEdges (G4double r, G4double z)
 
G4bool InsideEdges (G4double r, G4double z, G4double *distRZ2, G4PolyPhiFaceVertex **base3Dnorm=nullptr, G4ThreeVector **head3Dnorm=nullptr)
 
G4double ExactZOrder (G4double z, G4double qx, G4double qy, G4double qz, const G4ThreeVector &v, G4double normSign, const G4PolyPhiFaceVertex *vert) const
 
void CopyStuff (const G4PolyPhiFace &source)
 
G4double Area2 (const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)
 
G4bool Left (const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)
 
G4bool LeftOn (const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)
 
G4bool Collinear (const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)
 
G4bool IntersectProp (const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c, const G4TwoVector &d)
 
G4bool Between (const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)
 
G4bool Intersect (const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c, const G4TwoVector &d)
 
G4bool Diagonalie (G4PolyPhiFaceVertex *a, G4PolyPhiFaceVertex *b)
 
G4bool InCone (G4PolyPhiFaceVertex *a, G4PolyPhiFaceVertex *b)
 
G4bool Diagonal (G4PolyPhiFaceVertex *a, G4PolyPhiFaceVertex *b)
 
void EarInit ()
 
void Triangulate ()
 

Protected Attributes

G4int numEdges = 0
 
G4PolyPhiFaceEdgeedges = nullptr
 
G4PolyPhiFaceVertexcorners = nullptr
 
G4ThreeVector normal
 
G4ThreeVector radial
 
G4ThreeVector surface
 
G4ThreeVector surface_point
 
G4double rMin
 
G4double rMax
 
G4double zMin
 
G4double zMax
 
G4bool allBehind = false
 
G4double kCarTolerance
 
G4double fSurfaceArea = 0.0
 
G4PolyPhiFaceVertextriangles = nullptr
 

Detailed Description

Definition at line 75 of file G4PolyPhiFace.hh.

Constructor & Destructor Documentation

◆ G4PolyPhiFace() [1/3]

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

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 //
101
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 xyVector -= normal;
234 else
235 xyVector += normal;
236 }
237
238 //
239 // Combine it with the r/z direction from the face
240 //
241 edge->v0->norm3D = rNorm*xyVector.unit() + G4ThreeVector( 0, 0, zNorm );
242 } while( prevEdge=edge, ++edge < edges+maxEdges );
243
244 //
245 // Build point on surface
246 //
247 G4double rAve = 0.5*(rMax-rMin),
248 zAve = 0.5*(zMax-zMin);
249 surface = G4ThreeVector( rAve*radial.x(), rAve*radial.y(), zAve );
250}
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
Hep3Vector unit() const
double x() const
double y() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4ThreeVector surface
G4PolyPhiFaceEdge * edges
G4ThreeVector radial
G4PolyPhiFaceVertex * corners
G4ThreeVector normal
G4double kCarTolerance
G4double Amin() const
G4double Bmin() const
G4double Bmax() const
G4double Amax() const
G4PolyPhiFaceVertex * v1
G4ThreeVector norm3D
G4PolyPhiFaceVertex * v0
G4ThreeVector norm3D
G4PolyPhiFaceVertex * next
G4PolyPhiFaceVertex * prev
#define DBL_MIN
Definition templates.hh:54

◆ ~G4PolyPhiFace()

G4PolyPhiFace::~G4PolyPhiFace ( )
override

Definition at line 285 of file G4PolyPhiFace.cc.

286{
287 delete [] edges;
288 delete [] corners;
289}

◆ G4PolyPhiFace() [2/3]

G4PolyPhiFace::G4PolyPhiFace ( const G4PolyPhiFace & source)

Definition at line 295 of file G4PolyPhiFace.cc.

296{
297 CopyStuff( source );
298}
void CopyStuff(const G4PolyPhiFace &source)

◆ G4PolyPhiFace() [3/3]

G4PolyPhiFace::G4PolyPhiFace ( __void__ & )

Definition at line 276 of file G4PolyPhiFace.cc.

277 : numEdges(0), rMin(0.), rMax(0.), zMin(0.), zMax(0.), kCarTolerance(0.)
278{
279}

Member Function Documentation

◆ Area2()

G4double G4PolyPhiFace::Area2 ( const G4TwoVector & a,
const G4TwoVector & b,
const G4TwoVector & c )
protected

Definition at line 916 of file G4PolyPhiFace.cc.

919{
920 return ((b.x()-a.x())*(c.y()-a.y())-
921 (c.x()-a.x())*(b.y()-a.y()));
922}
double x() const
double y() const

Referenced by Collinear(), Left(), and LeftOn().

◆ Between()

G4bool G4PolyPhiFace::Between ( const G4TwoVector & a,
const G4TwoVector & b,
const G4TwoVector & c )
protected

Definition at line 969 of file G4PolyPhiFace.cc.

970{
971 if( !Collinear(a,b,c) ) { return false; }
972
973 if(a.x()!=b.x())
974 {
975 return ((a.x()<=c.x())&&(c.x()<=b.x()))||
976 ((a.x()>=c.x())&&(c.x()>=b.x()));
977 }
978 else
979 {
980 return ((a.y()<=c.y())&&(c.y()<=b.y()))||
981 ((a.y()>=c.y())&&(c.y()>=b.y()));
982 }
983}
G4bool Collinear(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)

Referenced by Intersect().

◆ CalculateExtent()

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

Implements G4VCSGface.

Definition at line 601 of file G4PolyPhiFace.cc.

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

◆ Clone()

G4VCSGface * G4PolyPhiFace::Clone ( )
inlineoverridevirtual

Implements G4VCSGface.

◆ Collinear()

G4bool G4PolyPhiFace::Collinear ( const G4TwoVector & a,
const G4TwoVector & b,
const G4TwoVector & c )
protected

Definition at line 944 of file G4PolyPhiFace.cc.

947{
948 return Area2(a,b,c)==0;
949}
G4double Area2(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)

Referenced by Between(), and IntersectProp().

◆ CopyStuff()

void G4PolyPhiFace::CopyStuff ( const G4PolyPhiFace & source)
protected

Definition at line 320 of file G4PolyPhiFace.cc.

321{
322 //
323 // The simple stuff
324 //
325 numEdges = source.numEdges;
326 normal = source.normal;
327 radial = source.radial;
328 surface = source.surface;
329 rMin = source.rMin;
330 rMax = source.rMax;
331 zMin = source.zMin;
332 zMax = source.zMax;
333 allBehind = source.allBehind;
334 triangles = nullptr;
335
337 fSurfaceArea = source.fSurfaceArea;
338
339 const std::size_t maxEdges = (numEdges > 0) ? numEdges : 1;
340
341 //
342 // Corner dynamic array
343 //
344 corners = new G4PolyPhiFaceVertex[maxEdges];
346 *sourceCorn = source.corners;
347 do // Loop checking, 13.08.2015, G.Cosmo
348 {
349 *corn = *sourceCorn;
350 } while( ++sourceCorn, ++corn < corners+maxEdges );
351
352 //
353 // Edge dynamic array
354 //
355 edges = new G4PolyPhiFaceEdge[maxEdges];
356
357 G4PolyPhiFaceVertex* prev = corners+maxEdges-1,
358 * here = corners;
359 G4PolyPhiFaceEdge* edge = edges,
360 * sourceEdge = source.edges;
361 do // Loop checking, 13.08.2015, G.Cosmo
362 {
363 *edge = *sourceEdge;
364 edge->v0 = prev;
365 edge->v1 = here;
366 } while( ++sourceEdge, ++edge, prev=here, ++here < corners+maxEdges );
367}
G4double fSurfaceArea
G4PolyPhiFaceVertex * triangles

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

◆ Diagnose()

void G4PolyPhiFace::Diagnose ( G4VSolid * solid)

Definition at line 259 of file G4PolyPhiFace.cc.

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

◆ Diagonal()

G4bool G4PolyPhiFace::Diagonal ( G4PolyPhiFaceVertex * a,
G4PolyPhiFaceVertex * b )
protected

Definition at line 1065 of file G4PolyPhiFace.cc.

1066{
1067 return InCone(a,b) && InCone(b,a) && Diagonalie(a,b);
1068}
G4bool Diagonalie(G4PolyPhiFaceVertex *a, G4PolyPhiFaceVertex *b)
G4bool InCone(G4PolyPhiFaceVertex *a, G4PolyPhiFaceVertex *b)

Referenced by EarInit(), and Triangulate().

◆ Diagonalie()

G4bool G4PolyPhiFace::Diagonalie ( G4PolyPhiFaceVertex * a,
G4PolyPhiFaceVertex * b )
protected

Definition at line 1006 of file G4PolyPhiFace.cc.

1008{
1010 G4PolyPhiFaceVertex *corner_next=triangles;
1011
1012 // For each Edge (corner,corner_next)
1013 do // Loop checking, 13.08.2015, G.Cosmo
1014 {
1015 corner_next=corner->next;
1016
1017 // Skip edges incident to a of b
1018 //
1019 if( (corner!=a)&&(corner_next!=a)
1020 &&(corner!=b)&&(corner_next!=b) )
1021 {
1022 G4TwoVector rz1,rz2,rz3,rz4;
1023 rz1 = G4TwoVector(a->r,a->z);
1024 rz2 = G4TwoVector(b->r,b->z);
1025 rz3 = G4TwoVector(corner->r,corner->z);
1026 rz4 = G4TwoVector(corner_next->r,corner_next->z);
1027 if( Intersect(rz1,rz2,rz3,rz4) ) { return false; }
1028 }
1029 corner=corner->next;
1030
1031 } while( corner != triangles );
1032
1033 return true;
1034}
CLHEP::Hep2Vector G4TwoVector
G4bool Intersect(const G4ThreeVector &p, const G4ThreeVector &v, G4bool outgoing, G4double surfTolerance, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal, G4bool &allBehind) override

Referenced by Diagonal().

◆ Distance()

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

Implements G4VCSGface.

Definition at line 426 of file G4PolyPhiFace.cc.

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

◆ EarInit()

void G4PolyPhiFace::EarInit ( )
protected

Definition at line 1073 of file G4PolyPhiFace.cc.

1074{
1076 G4PolyPhiFaceVertex* c_prev, *c_next;
1077
1078 do // Loop checking, 13.08.2015, G.Cosmo
1079 {
1080 // We need to determine three consecutive vertices
1081 //
1082 c_next=corner->next;
1083 c_prev=corner->prev;
1084
1085 // Calculation of ears
1086 //
1087 corner->ear=Diagonal(c_prev,c_next);
1088 corner=corner->next;
1089
1090 } while( corner!=triangles );
1091}
G4bool Diagonal(G4PolyPhiFaceVertex *a, G4PolyPhiFaceVertex *b)

Referenced by Triangulate().

◆ ExactZOrder()

G4double G4PolyPhiFace::ExactZOrder ( G4double z,
G4double qx,
G4double qy,
G4double qz,
const G4ThreeVector & v,
G4double normSign,
const G4PolyPhiFaceVertex * vert ) const
inlineprotected

Referenced by InsideEdgesExact().

◆ Extent()

G4double G4PolyPhiFace::Extent ( const G4ThreeVector axis)
overridevirtual

Implements G4VCSGface.

Definition at line 581 of file G4PolyPhiFace.cc.

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

◆ GetPointOnFace()

G4ThreeVector G4PolyPhiFace::GetPointOnFace ( )
overridevirtual

Implements G4VCSGface.

Definition at line 904 of file G4PolyPhiFace.cc.

905{
906 Triangulate();
907 return surface_point;
908}
G4ThreeVector surface_point

◆ InCone()

G4bool G4PolyPhiFace::InCone ( G4PolyPhiFaceVertex * a,
G4PolyPhiFaceVertex * b )
protected

Definition at line 1039 of file G4PolyPhiFace.cc.

1040{
1041 // a0,a and a1 are consecutive vertices
1042 //
1044 a1=a->next;
1045 a0=a->prev;
1046
1047 G4TwoVector arz,arz0,arz1,brz;
1048 arz=G4TwoVector(a->r,a->z);arz0=G4TwoVector(a0->r,a0->z);
1049 arz1=G4TwoVector(a1->r,a1->z);brz=G4TwoVector(b->r,b->z);
1050
1051
1052 if(LeftOn(arz,arz1,arz0)) // If a is convex vertex
1053 {
1054 return Left(arz,brz,arz0)&&Left(brz,arz,arz1);
1055 }
1056 else // Else a is reflex
1057 {
1058 return !( LeftOn(arz,brz,arz1)&&LeftOn(brz,arz,arz0));
1059 }
1060}
const G4double a0
G4bool LeftOn(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)
G4bool Left(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)

Referenced by Diagonal().

◆ Inside()

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

Implements G4VCSGface.

Definition at line 468 of file G4PolyPhiFace.cc.

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

◆ InsideEdges() [1/2]

G4bool G4PolyPhiFace::InsideEdges ( G4double r,
G4double z )
protected

Definition at line 780 of file G4PolyPhiFace.cc.

781{
782 //
783 // Quick check of extent
784 //
785 if ( r < rMin || r > rMax ) return false;
786 if ( z < zMin || z > zMax ) return false;
787
788 //
789 // More thorough check
790 //
791 G4double notUsed;
792
793 return InsideEdges( r, z, &notUsed, nullptr );
794}

Referenced by Distance(), Inside(), InsideEdges(), and Normal().

◆ InsideEdges() [2/2]

G4bool G4PolyPhiFace::InsideEdges ( G4double r,
G4double z,
G4double * distRZ2,
G4PolyPhiFaceVertex ** base3Dnorm = nullptr,
G4ThreeVector ** head3Dnorm = nullptr )
protected

Definition at line 800 of file G4PolyPhiFace.cc.

804{
805 G4double bestDistance2 = kInfinity;
806 G4bool answer = false;
807
808 G4PolyPhiFaceEdge* edge = edges;
809 do // Loop checking, 13.08.2015, G.Cosmo
810 {
811 G4PolyPhiFaceVertex* testMe = nullptr;
812 G4PolyPhiFaceVertex* v0_vertex = edge->v0;
813 G4PolyPhiFaceVertex* v1_vertex = edge->v1;
814 //
815 // Get distance perpendicular to the edge
816 //
817 G4double dr = (r-v0_vertex->r), dz = (z-v0_vertex->z);
818
819 G4double distOut = dr*edge->tz - dz*edge->tr;
820 G4double distance2 = distOut*distOut;
821 if (distance2 > bestDistance2) continue; // No hope!
822
823 //
824 // Check to see if normal intersects edge within the edge's boundary
825 //
826 G4double q = dr*edge->tr + dz*edge->tz;
827
828 //
829 // If it doesn't, penalize distance2 appropriately
830 //
831 if (q < 0)
832 {
833 distance2 += q*q;
834 testMe = v0_vertex;
835 }
836 else if (q > edge->length)
837 {
838 G4double s2 = q-edge->length;
839 distance2 += s2*s2;
840 testMe = v1_vertex;
841 }
842
843 //
844 // Closest edge so far?
845 //
846 if (distance2 < bestDistance2)
847 {
848 bestDistance2 = distance2;
849 if (testMe != nullptr)
850 {
851 G4double distNorm = dr*testMe->rNorm + dz*testMe->zNorm;
852 answer = (distNorm <= 0);
853 if (base3Dnorm != nullptr)
854 {
855 *base3Dnorm = testMe;
856 *head3Dnorm = &testMe->norm3D;
857 }
858 }
859 else
860 {
861 answer = (distOut <= 0);
862 if (base3Dnorm != nullptr)
863 {
864 *base3Dnorm = v0_vertex;
865 *head3Dnorm = &edge->norm3D;
866 }
867 }
868 }
869 } while( ++edge < edges + numEdges );
870
871 *bestDist2 = bestDistance2;
872 return answer;
873}

◆ InsideEdgesExact()

G4bool G4PolyPhiFace::InsideEdgesExact ( G4double r,
G4double z,
G4double normSign,
const G4ThreeVector & p,
const G4ThreeVector & v )
protected

Definition at line 650 of file G4PolyPhiFace.cc.

654{
655 //
656 // Quick check of extent
657 //
658 if ( (r < rMin-kCarTolerance)
659 || (r > rMax+kCarTolerance) ) return false;
660
661 if ( (z < zMin-kCarTolerance)
662 || (z > zMax+kCarTolerance) ) return false;
663
664 //
665 // Exact check: loop over all vertices
666 //
667 G4double qx = p.x() + v.x(),
668 qy = p.y() + v.y(),
669 qz = p.z() + v.z();
670
671 G4int answer = 0;
673 *prev = corners+numEdges-1;
674
675 G4double cornZ, prevZ;
676
677 prevZ = ExactZOrder( z, qx, qy, qz, v, normSign, prev );
678 do // Loop checking, 13.08.2015, G.Cosmo
679 {
680 //
681 // Get z order of this vertex, and compare to previous vertex
682 //
683 cornZ = ExactZOrder( z, qx, qy, qz, v, normSign, corn );
684
685 if (cornZ < 0)
686 {
687 if (prevZ < 0) continue;
688 }
689 else if (cornZ > 0)
690 {
691 if (prevZ > 0) continue;
692 }
693 else
694 {
695 //
696 // By chance, we overlap exactly (within precision) with
697 // the current vertex. Continue if the same happened previously
698 // (e.g. the previous vertex had the same z value)
699 //
700 if (prevZ == 0) continue;
701
702 //
703 // Otherwise, to decide what to do, we need to know what is
704 // coming up next. Specifically, we need to find the next vertex
705 // with a non-zero z order.
706 //
707 // One might worry about infinite loops, but the above conditional
708 // should prevent it
709 //
710 G4PolyPhiFaceVertex *next = corn;
711 G4double nextZ;
712 do // Loop checking, 13.08.2015, G.Cosmo
713 {
714 ++next;
715 if (next == corners+numEdges) next = corners;
716
717 nextZ = ExactZOrder( z, qx, qy, qz, v, normSign, next );
718 } while( nextZ == 0 );
719
720 //
721 // If we won't be changing direction, go to the next vertex
722 //
723 if (nextZ*prevZ < 0) continue;
724 }
725
726
727 //
728 // We overlap in z with the side of the face that stretches from
729 // vertex "prev" to "corn". On which side (left or right) do
730 // we lay with respect to this segment?
731 //
732 G4ThreeVector qa( qx - prev->x, qy - prev->y, qz - prev->z ),
733 qb( qx - corn->x, qy - corn->y, qz - corn->z );
734
735 G4double aboveOrBelow = normSign*qa.cross(qb).dot(v);
736
737 if (aboveOrBelow > 0)
738 ++answer;
739 else if (aboveOrBelow < 0)
740 --answer;
741 else
742 {
743 //
744 // A precisely zero answer here means we exactly
745 // intersect (within roundoff) the edge of the face.
746 // Return true in this case.
747 //
748 return true;
749 }
750 } while( prevZ = cornZ, prev=corn, ++corn < corners+numEdges );
751
752 return answer!=0;
753}
int G4int
Definition G4Types.hh:85
G4double ExactZOrder(G4double z, G4double qx, G4double qy, G4double qz, const G4ThreeVector &v, G4double normSign, const G4PolyPhiFaceVertex *vert) const

Referenced by Intersect().

◆ Intersect() [1/2]

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

Implements G4VCSGface.

Definition at line 371 of file G4PolyPhiFace.cc.

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

Referenced by Diagonalie().

◆ Intersect() [2/2]

G4bool G4PolyPhiFace::Intersect ( const G4TwoVector & a,
const G4TwoVector & b,
const G4TwoVector & c,
const G4TwoVector & d )
protected

Definition at line 988 of file G4PolyPhiFace.cc.

991{
992 if( IntersectProp(a,b,c,d) )
993 { return true; }
994 else if( Between(a,b,c)||
995 Between(a,b,d)||
996 Between(c,d,a)||
997 Between(c,d,b) )
998 { return true; }
999 else
1000 { return false; }
1001}
G4bool IntersectProp(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c, const G4TwoVector &d)
G4bool Between(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c)

◆ IntersectProp()

G4bool G4PolyPhiFace::IntersectProp ( const G4TwoVector & a,
const G4TwoVector & b,
const G4TwoVector & c,
const G4TwoVector & d )
protected

Definition at line 954 of file G4PolyPhiFace.cc.

957{
958 if( Collinear(a,b,c) || Collinear(a,b,d)||
959 Collinear(c,d,a) || Collinear(c,d,b) ) { return false; }
960
961 G4bool Positive;
962 Positive = !(Left(a,b,c))^!(Left(a,b,d));
963 return Positive && ((!Left(c,d,a)^!Left(c,d,b)) != 0);
964}

Referenced by Intersect().

◆ Left()

G4bool G4PolyPhiFace::Left ( const G4TwoVector & a,
const G4TwoVector & b,
const G4TwoVector & c )
protected

Definition at line 926 of file G4PolyPhiFace.cc.

929{
930 return Area2(a,b,c)>0;
931}

Referenced by InCone(), and IntersectProp().

◆ LeftOn()

G4bool G4PolyPhiFace::LeftOn ( const G4TwoVector & a,
const G4TwoVector & b,
const G4TwoVector & c )
protected

Definition at line 935 of file G4PolyPhiFace.cc.

938{
939 return Area2(a,b,c)>=0;
940}

Referenced by InCone().

◆ Normal()

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

Implements G4VCSGface.

Definition at line 540 of file G4PolyPhiFace.cc.

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

◆ operator=()

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

Definition at line 304 of file G4PolyPhiFace.cc.

305{
306 if (this == &source) { return *this; }
307
308 delete [] edges;
309 delete [] corners;
310
311 CopyStuff( source );
312
313 return *this;
314}

◆ SurfaceArea()

G4double G4PolyPhiFace::SurfaceArea ( )
overridevirtual

Implements G4VCSGface.

Definition at line 896 of file G4PolyPhiFace.cc.

897{
898 if ( fSurfaceArea==0. ) { Triangulate(); }
899 return fSurfaceArea;
900}

◆ SurfaceTriangle()

G4double G4PolyPhiFace::SurfaceTriangle ( const G4ThreeVector & p1,
const G4ThreeVector & p2,
const G4ThreeVector & p3,
G4ThreeVector * p4 )

Definition at line 878 of file G4PolyPhiFace.cc.

882{
883 G4ThreeVector v, w;
884
885 v = p3 - p1;
886 w = p1 - p2;
887 G4double lambda1 = G4UniformRand();
888 G4double lambda2 = lambda1*G4UniformRand();
889
890 *p4=p2 + lambda1*w + lambda2*v;
891 return 0.5*(v.cross(w)).mag();
892}
#define G4UniformRand()
Definition Randomize.hh:52
Hep3Vector cross(const Hep3Vector &) const
double mag() const

Referenced by Triangulate().

◆ Triangulate()

void G4PolyPhiFace::Triangulate ( )
protected

Definition at line 1096 of file G4PolyPhiFace.cc.

1097{
1098 // The copy of Polycone is made and this copy is reordered in order to
1099 // have a list of triangles. This list is used for GetPointOnFace().
1100
1101 const std::size_t maxEdges = (numEdges > 0) ? numEdges : 1;
1102 auto tri_help = new G4PolyPhiFaceVertex[maxEdges];
1103 triangles = tri_help;
1105
1106 std::vector<G4double> areas;
1107 std::vector<G4ThreeVector> points;
1108 G4double area=0.;
1109 G4PolyPhiFaceVertex *v0,*v1,*v2,*v3,*v4;
1110 v2=triangles;
1111
1112 // Make copy for prev/next for triang=corners
1113 //
1114 G4PolyPhiFaceVertex* helper = corners;
1115 G4PolyPhiFaceVertex* helper2 = corners;
1116 do // Loop checking, 13.08.2015, G.Cosmo
1117 {
1118 triang->r = helper->r;
1119 triang->z = helper->z;
1120 triang->x = helper->x;
1121 triang->y = helper->y;
1122
1123 // add pointer on prev corner
1124 //
1125 if( helper==corners )
1126 { triang->prev=triangles+maxEdges-1; }
1127 else
1128 { triang->prev=helper2; }
1129
1130 // add pointer on next corner
1131 //
1132 if( helper<corners+maxEdges-1 )
1133 { triang->next=triang+1; }
1134 else
1135 { triang->next=triangles; }
1136 helper2=triang;
1137 helper=helper->next;
1138 triang=triang->next;
1139
1140 } while( helper!=corners );
1141
1142 EarInit();
1143
1145 G4int i=0;
1146 G4ThreeVector p1,p2,p3,p4;
1147 const G4int max_n_loops=numEdges*10000; // protection against infinite loop
1148
1149 // Each step of outer loop removes one ear
1150 //
1151 while(n>3) // Loop checking, 13.08.2015, G.Cosmo
1152 { // Inner loop searches for one ear
1153 v2=triangles;
1154 do // Loop checking, 13.08.2015, G.Cosmo
1155 {
1156 if(v2->ear) // Ear found. Fill variables
1157 {
1158 // (v1,v3) is diagonal
1159 //
1160 v3=v2->next; v4=v3->next;
1161 v1=v2->prev; v0=v1->prev;
1162
1163 // Calculate areas and points
1164
1165 p1=G4ThreeVector((v2)->x,(v2)->y,(v2)->z);
1166 p2=G4ThreeVector((v1)->x,(v1)->y,(v1)->z);
1167 p3=G4ThreeVector((v3)->x,(v3)->y,(v3)->z);
1168
1169 G4double result1 = SurfaceTriangle(p1,p2,p3,&p4 );
1170 points.push_back(p4);
1171 areas.push_back(result1);
1172 area=area+result1;
1173
1174 // Update earity of diagonal endpoints
1175 //
1176 v1->ear=Diagonal(v0,v3);
1177 v3->ear=Diagonal(v1,v4);
1178
1179 // Cut off the ear v2
1180 // Has to be done for a copy and not for real PolyPhiFace
1181 //
1182 v1->next=v3;
1183 v3->prev=v1;
1184 triangles=v3; // In case the head was v2
1185 --n;
1186
1187 break; // out of inner loop
1188 } // end if ear found
1189
1190 v2=v2->next;
1191
1192 } while( v2!=triangles );
1193
1194 ++i;
1195 if(i>=max_n_loops)
1196 {
1197 G4Exception( "G4PolyPhiFace::Triangulation()",
1198 "GeomSolids0003", FatalException,
1199 "Maximum number of steps is reached for triangulation!" );
1200 }
1201 } // end outer while loop
1202
1203 if(v2->next != nullptr)
1204 {
1205 // add last triangle
1206 //
1207 v2=v2->next;
1208 p1=G4ThreeVector((v2)->x,(v2)->y,(v2)->z);
1209 p2=G4ThreeVector((v2->next)->x,(v2->next)->y,(v2->next)->z);
1210 p3=G4ThreeVector((v2->prev)->x,(v2->prev)->y,(v2->prev)->z);
1211 G4double result1 = SurfaceTriangle(p1,p2,p3,&p4 );
1212 points.push_back(p4);
1213 areas.push_back(result1);
1214 area=area+result1;
1215 }
1216
1217 // Surface Area is stored
1218 //
1219 fSurfaceArea = area;
1220
1221 // Second Step: choose randomly one surface
1222 //
1223 G4double chose = area*G4UniformRand();
1224
1225 // Third Step: Get a point on choosen surface
1226 //
1227 G4double Achose1, Achose2;
1228 Achose1=0; Achose2=0.;
1229 i=0;
1230 do // Loop checking, 13.08.2015, G.Cosmo
1231 {
1232 Achose2+=areas[i];
1233 if(chose>=Achose1 && chose<Achose2)
1234 {
1235 G4ThreeVector point;
1236 point=points[i];
1237 surface_point=point;
1238 break;
1239 }
1240 ++i; Achose1=Achose2;
1241 } while( i<numEdges-2 );
1242
1243 delete [] tri_help;
1244 tri_help = nullptr;
1245}
G4double SurfaceTriangle(const G4ThreeVector &p1, const G4ThreeVector &p2, const G4ThreeVector &p3, G4ThreeVector *p4)

Referenced by GetPointOnFace(), and SurfaceArea().

Member Data Documentation

◆ allBehind

G4bool G4PolyPhiFace::allBehind = false
protected

Definition at line 218 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), G4PolyPhiFace(), and Intersect().

◆ corners

G4PolyPhiFaceVertex* G4PolyPhiFace::corners = nullptr
protected

◆ edges

G4PolyPhiFaceEdge* G4PolyPhiFace::edges = nullptr
protected

Definition at line 209 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), G4PolyPhiFace(), InsideEdges(), operator=(), and ~G4PolyPhiFace().

◆ fSurfaceArea

G4double G4PolyPhiFace::fSurfaceArea = 0.0
protected

Definition at line 221 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), SurfaceArea(), and Triangulate().

◆ kCarTolerance

G4double G4PolyPhiFace::kCarTolerance
protected

Definition at line 220 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), Distance(), G4PolyPhiFace(), and InsideEdgesExact().

◆ normal

G4ThreeVector G4PolyPhiFace::normal
protected

◆ numEdges

G4int G4PolyPhiFace::numEdges = 0
protected

◆ radial

G4ThreeVector G4PolyPhiFace::radial
protected

◆ rMax

G4double G4PolyPhiFace::rMax
protected

Definition at line 216 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), G4PolyPhiFace(), InsideEdges(), and InsideEdgesExact().

◆ rMin

G4double G4PolyPhiFace::rMin
protected

Definition at line 216 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), G4PolyPhiFace(), and InsideEdgesExact().

◆ surface

G4ThreeVector G4PolyPhiFace::surface
protected

Definition at line 213 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), Distance(), G4PolyPhiFace(), Inside(), and Intersect().

◆ surface_point

G4ThreeVector G4PolyPhiFace::surface_point
protected

Definition at line 214 of file G4PolyPhiFace.hh.

Referenced by GetPointOnFace(), and Triangulate().

◆ triangles

G4PolyPhiFaceVertex* G4PolyPhiFace::triangles = nullptr
protected

Definition at line 222 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), Diagonalie(), EarInit(), and Triangulate().

◆ zMax

G4double G4PolyPhiFace::zMax
protected

Definition at line 217 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), G4PolyPhiFace(), InsideEdges(), and InsideEdgesExact().

◆ zMin

G4double G4PolyPhiFace::zMin
protected

Definition at line 217 of file G4PolyPhiFace.hh.

Referenced by CopyStuff(), G4PolyPhiFace(), and InsideEdgesExact().


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