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

G4TriangularFacet defines a facet with 3 vertices, used for the contruction of G4TessellatedSolid. Vertices shall be supplied in anti-clockwise order looking from the outsider of the solid where it belongs. More...

#include <G4TriangularFacet.hh>

Inheritance diagram for G4TriangularFacet:

Public Member Functions

 G4TriangularFacet ()
 G4TriangularFacet (const G4ThreeVector &Pt0, const G4ThreeVector &vt1, const G4ThreeVector &vt2, G4FacetVertexType vType)
 ~G4TriangularFacet () override
 G4TriangularFacet (const G4TriangularFacet &right)
 G4TriangularFacet (G4TriangularFacet &&right) noexcept
G4TriangularFacetoperator= (const G4TriangularFacet &right)
G4TriangularFacetoperator= (G4TriangularFacet &&right) noexcept
G4VFacetGetClone () override
G4TriangularFacetGetFlippedFacet ()
G4ThreeVector Distance (const G4ThreeVector &p)
G4double Distance (const G4ThreeVector &p, G4double minDist) override
G4double Distance (const G4ThreeVector &p, G4double minDist, const G4bool outgoing) override
G4double Extent (const G4ThreeVector axis) override
G4bool Intersect (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool outgoing, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal) override
G4double GetArea () const override
G4ThreeVector GetPointOnFace () const override
G4ThreeVector GetSurfaceNormal () const override
void SetSurfaceNormal (const G4ThreeVector &normal)
G4GeometryType GetEntityType () const override
G4bool IsDefined () const override
G4int GetNumberOfVertices () const override
G4ThreeVector GetVertex (G4int i) const override
void SetVertex (G4int i, const G4ThreeVector &val) override
void SetVertices (std::vector< G4ThreeVector > *v) override
G4double GetRadius () const override
G4ThreeVector GetCircumcentre () const override
G4int AllocatedMemory () override
G4int GetVertexIndex (G4int i) const override
void SetVertexIndex (G4int i, G4int j) override
Public Member Functions inherited from G4VFacet
 G4VFacet ()
virtual ~G4VFacet ()=default
G4bool operator== (const G4VFacet &right) const
void ApplyTranslation (const G4ThreeVector &v)
std::ostream & StreamInfo (std::ostream &os) const
G4bool IsInside (const G4ThreeVector &p) const

Additional Inherited Members

Protected Attributes inherited from G4VFacet
G4double kCarTolerance
Static Protected Attributes inherited from G4VFacet
static const G4double dirTolerance = 1.0E-14

Detailed Description

G4TriangularFacet defines a facet with 3 vertices, used for the contruction of G4TessellatedSolid. Vertices shall be supplied in anti-clockwise order looking from the outsider of the solid where it belongs.

Definition at line 65 of file G4TriangularFacet.hh.

Constructor & Destructor Documentation

◆ G4TriangularFacet() [1/4]

G4TriangularFacet::G4TriangularFacet ( )

Default Constructor.

Definition at line 145 of file G4TriangularFacet.cc.

146{
147 fVertices = new vector<G4ThreeVector>(3);
148 G4ThreeVector zero(0,0,0);
149 SetVertex(0, zero);
150 SetVertex(1, zero);
151 SetVertex(2, zero);
152 for (G4int i = 0; i < 3; ++i)
153 {
154 fIndices[i] = -1;
155 }
156 fIsDefined = false;
157 fSurfaceNormal.set(0,0,0);
158 fA = fB = fC = 0;
159 fE1 = zero;
160 fE2 = zero;
161 fDet = 0.0;
162 fArea = fRadius = 0.0;
163}
CLHEP::Hep3Vector G4ThreeVector
int G4int
Definition G4Types.hh:85
void SetVertex(G4int i, const G4ThreeVector &val) override

Referenced by G4TriangularFacet(), G4TriangularFacet(), GetClone(), GetFlippedFacet(), operator=(), operator=(), and SetVertexIndex().

◆ G4TriangularFacet() [2/4]

G4TriangularFacet::G4TriangularFacet ( const G4ThreeVector & Pt0,
const G4ThreeVector & vt1,
const G4ThreeVector & vt2,
G4FacetVertexType vType )

Constructs a facet with 3 vertices, given its parameters.

Parameters
[in]Pt0The anchor point, first vertex.
[in]vt1Second vertex.
[in]vt2Third vertex.
[in]vTypeThe positioning type for the vertices, either: "ABSOLUTE" - vertices set in anti-clockwise order when looking from the outsider. "RELATIVE" - first vertex is Pt0, second is Pt0+vt1, and the third vertex is Pt0+vt2, still in anti-clockwise order.

Definition at line 55 of file G4TriangularFacet.cc.

59{
60 fVertices = new vector<G4ThreeVector>(3);
61
62 SetVertex(0, vt0);
63 if (vertexType == ABSOLUTE)
64 {
65 SetVertex(1, vt1);
66 SetVertex(2, vt2);
67 fE1 = vt1 - vt0;
68 fE2 = vt2 - vt0;
69 }
70 else
71 {
72 SetVertex(1, vt0 + vt1);
73 SetVertex(2, vt0 + vt2);
74 fE1 = vt1;
75 fE2 = vt2;
76 }
77
78 G4ThreeVector E1xE2 = fE1.cross(fE2);
79 fArea = 0.5 * E1xE2.mag();
80 for (G4int i = 0; i < 3; ++i)
81 {
82 fIndices[i] = -1;
83 }
84
85 fIsDefined = true;
86 G4double delta = kCarTolerance; // Set tolerance for checking
87
88 // Check length of edges
89 //
90 G4double leng1 = fE1.mag();
91 G4double leng2 = (fE2-fE1).mag();
92 G4double leng3 = fE2.mag();
93 if (leng1 <= delta || leng2 <= delta || leng3 <= delta)
94 {
95 fIsDefined = false;
96 }
97
98 // Check min height of triangle
99 //
100 if (fIsDefined)
101 {
102 if (2.*fArea/std::max(std::max(leng1,leng2),leng3) <= delta)
103 {
104 fIsDefined = false;
105 }
106 }
107
108 // Define facet
109 //
110 if (!fIsDefined)
111 {
112 ostringstream message;
113 message << "Facet is too small or too narrow." << G4endl
114 << "Triangle area = " << fArea << G4endl
115 << "P0 = " << GetVertex(0) << G4endl
116 << "P1 = " << GetVertex(1) << G4endl
117 << "P2 = " << GetVertex(2) << G4endl
118 << "Side1 length (P0->P1) = " << leng1 << G4endl
119 << "Side2 length (P1->P2) = " << leng2 << G4endl
120 << "Side3 length (P2->P0) = " << leng3;
121 G4Exception("G4TriangularFacet::G4TriangularFacet()",
122 "GeomSolids1001", JustWarning, message);
123 fSurfaceNormal.set(0,0,0);
124 fA = fB = fC = 0.0;
125 fDet = 0.0;
126 fCircumcentre = vt0 + 0.5*fE1 + 0.5*fE2;
127 fArea = fRadius = 0.0;
128 }
129 else
130 {
131 fSurfaceNormal = E1xE2.unit();
132 fA = fE1.mag2();
133 fB = fE1.dot(fE2);
134 fC = fE2.mag2();
135 fDet = std::fabs(fA*fC - fB*fB);
136
137 fCircumcentre =
138 vt0 + (E1xE2.cross(fE1)*fC + fE2.cross(E1xE2)*fA) / (2.*E1xE2.mag2());
139 fRadius = (fCircumcentre - vt0).mag();
140 }
141}
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
double G4double
Definition G4Types.hh:83
@ ABSOLUTE
Definition G4VFacet.hh:48
#define G4endl
Definition G4ios.hh:67
Hep3Vector unit() const
double mag2() const
Hep3Vector cross(const Hep3Vector &) const
double mag() const
G4ThreeVector GetVertex(G4int i) const override
G4double kCarTolerance
Definition G4VFacet.hh:185

◆ ~G4TriangularFacet()

G4TriangularFacet::~G4TriangularFacet ( )
override

Destructor.

Definition at line 167 of file G4TriangularFacet.cc.

168{
169 SetVertices(nullptr);
170}
void SetVertices(std::vector< G4ThreeVector > *v) override

◆ G4TriangularFacet() [3/4]

G4TriangularFacet::G4TriangularFacet ( const G4TriangularFacet & right)

Copy and move constructors.

Definition at line 209 of file G4TriangularFacet.cc.

210 : G4VFacet(rhs)
211{
212 CopyFrom(rhs);
213}

◆ G4TriangularFacet() [4/4]

G4TriangularFacet::G4TriangularFacet ( G4TriangularFacet && right)
noexcept

Definition at line 217 of file G4TriangularFacet.cc.

218 : G4VFacet(rhs)
219{
220 MoveFrom(rhs);
221}

Member Function Documentation

◆ AllocatedMemory()

G4int G4TriangularFacet::AllocatedMemory ( )
inlineoverridevirtual

Returns the allocated memory (sizeof) by the facet.

Implements G4VFacet.

◆ Distance() [1/3]

G4ThreeVector G4TriangularFacet::Distance ( const G4ThreeVector & p)

Determines the vector between p and the closest point on the facet to p.

Definition at line 296 of file G4TriangularFacet.cc.

297{
298 G4ThreeVector D = GetVertex(0) - p;
299 G4double d = fE1.dot(D);
300 G4double e = fE2.dot(D);
301 G4double f = D.mag2();
302 G4double q = fB*e - fC*d;
303 G4double t = fB*d - fA*e;
304 fSqrDist = 0.;
305
306 if (q+t <= fDet)
307 {
308 if (q < 0.0)
309 {
310 if (t < 0.0)
311 {
312 //
313 // We are in region 4.
314 //
315 if (d < 0.0)
316 {
317 t = 0.0;
318 if (-d >= fA) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
319 else {q = -d/fA; fSqrDist = d*q + f;}
320 }
321 else
322 {
323 q = 0.0;
324 if (e >= 0.0) {t = 0.0; fSqrDist = f;}
325 else if (-e >= fC) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
326 else {t = -e/fC; fSqrDist = e*t + f;}
327 }
328 }
329 else
330 {
331 //
332 // We are in region 3.
333 //
334 q = 0.0;
335 if (e >= 0.0) {t = 0.0; fSqrDist = f;}
336 else if (-e >= fC) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
337 else {t = -e/fC; fSqrDist = e*t + f;}
338 }
339 }
340 else if (t < 0.0)
341 {
342 //
343 // We are in region 5.
344 //
345 t = 0.0;
346 if (d >= 0.0) {q = 0.0; fSqrDist = f;}
347 else if (-d >= fA) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
348 else {q = -d/fA; fSqrDist = d*q + f;}
349 }
350 else
351 {
352 //
353 // We are in region 0.
354 //
355 G4double dist = fSurfaceNormal.dot(D);
356 fSqrDist = dist*dist;
357 return fSurfaceNormal*dist;
358 }
359 }
360 else
361 {
362 if (q < 0.0)
363 {
364 //
365 // We are in region 2.
366 //
367 G4double tmp0 = fB + d;
368 G4double tmp1 = fC + e;
369 if (tmp1 > tmp0)
370 {
371 G4double numer = tmp1 - tmp0;
372 G4double denom = fA - 2.0*fB + fC;
373 if (numer >= denom) {q = 1.0; t = 0.0; fSqrDist = fA + 2.0*d + f;}
374 else
375 {
376 q = numer/denom;
377 t = 1.0 - q;
378 fSqrDist = q*(fA*q + fB*t +2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
379 }
380 }
381 else
382 {
383 q = 0.0;
384 if (tmp1 <= 0.0) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
385 else if (e >= 0.0) {t = 0.0; fSqrDist = f;}
386 else {t = -e/fC; fSqrDist = e*t + f;}
387 }
388 }
389 else if (t < 0.0)
390 {
391 //
392 // We are in region 6.
393 //
394 G4double tmp0 = fB + e;
395 G4double tmp1 = fA + d;
396 if (tmp1 > tmp0)
397 {
398 G4double numer = tmp1 - tmp0;
399 G4double denom = fA - 2.0*fB + fC;
400 if (numer >= denom) {t = 1.0; q = 0.0; fSqrDist = fC + 2.0*e + f;}
401 else
402 {
403 t = numer/denom;
404 q = 1.0 - t;
405 fSqrDist = q*(fA*q + fB*t +2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
406 }
407 }
408 else
409 {
410 t = 0.0;
411 if (tmp1 <= 0.0) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
412 else if (d >= 0.0) {q = 0.0; fSqrDist = f;}
413 else {q = -d/fA; fSqrDist = d*q + f;}
414 }
415 }
416 else
417 //
418 // We are in region 1.
419 //
420 {
421 G4double numer = fC + e - fB - d;
422 if (numer <= 0.0)
423 {
424 q = 0.0;
425 t = 1.0;
426 fSqrDist = fC + 2.0*e + f;
427 }
428 else
429 {
430 G4double denom = fA - 2.0*fB + fC;
431 if (numer >= denom) {q = 1.0; t = 0.0; fSqrDist = fA + 2.0*d + f;}
432 else
433 {
434 q = numer/denom;
435 t = 1.0 - q;
436 fSqrDist = q*(fA*q + fB*t + 2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
437 }
438 }
439 }
440 }
441 //
442 //
443 // Do fA check for rounding errors in the distance-squared. It appears that
444 // the conventional methods for calculating fSqrDist breaks down when very
445 // near to or at the surface (as required by transport).
446 // We'll therefore also use the magnitude-squared of the vector displacement.
447 // (Note that I've also tried to get around this problem by using the
448 // existing equations for
449 //
450 // fSqrDist = function(fA,fB,fC,d,q,t)
451 //
452 // and use fA more accurate addition process which minimises errors and
453 // breakdown of cummutitivity [where (A+B)+C != A+(B+C)] but this still
454 // doesn't work.
455 // Calculation from u = D + q*fE1 + t*fE2 is less efficient, but appears
456 // more robust.
457 //
458 if (fSqrDist < 0.0) { fSqrDist = 0.; }
459 G4ThreeVector u = D + q*fE1 + t*fE2;
460 G4double u2 = u.mag2();
461 //
462 // The following (part of the roundoff error check) is from Oliver Merle'q
463 // updates.
464 //
465 if (fSqrDist > u2) { fSqrDist = u2; }
466
467 return u;
468}
G4double D(G4double temp)
double dot(const Hep3Vector &) const

Referenced by Distance(), Distance(), and Intersect().

◆ Distance() [2/3]

G4double G4TriangularFacet::Distance ( const G4ThreeVector & p,
G4double minDist )
overridevirtual

Determines the closest distance between point p and the facet.

Implements G4VFacet.

Definition at line 480 of file G4TriangularFacet.cc.

482{
483 //
484 // Start with quicky test to determine if the surface of the sphere enclosing
485 // the triangle is any closer to p than minDist. If not, then don't bother
486 // about more accurate test.
487 //
488 G4double dist = kInfinity;
489 if ((p-fCircumcentre).mag()-fRadius < minDist)
490 {
491 //
492 // It's possible that the triangle is closer than minDist,
493 // so do more accurate assessment.
494 //
495 dist = Distance(p).mag();
496 }
497 return dist;
498}
G4ThreeVector Distance(const G4ThreeVector &p)

◆ Distance() [3/3]

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

Determines the distance to point 'p'. kInfinity is returned if either: (1) outgoing is TRUE and the dot product of the normal vector to the facet and the displacement vector from p to the triangle is negative. (2) outgoing is FALSE and the dot product of the normal vector to the facet and the displacement vector from p to the triangle is positive.

Implements G4VFacet.

Definition at line 515 of file G4TriangularFacet.cc.

518{
519 //
520 // Start with quicky test to determine if the surface of the sphere enclosing
521 // the triangle is any closer to p than minDist. If not, then don't bother
522 // about more accurate test.
523 //
524 G4double dist = kInfinity;
525 if ((p-fCircumcentre).mag()-fRadius < minDist)
526 {
527 //
528 // It's possible that the triangle is closer than minDist,
529 // so do more accurate assessment.
530 //
531 G4ThreeVector v = Distance(p);
532 G4double dist1 = sqrt(fSqrDist);
533 G4double dir = v.dot(fSurfaceNormal);
534 G4bool wrongSide = (dir > 0.0 && !outgoing) || (dir < 0.0 && outgoing);
535 if (dist1 <= kCarTolerance)
536 {
537 //
538 // Point p is very close to triangle. Check if it's on the wrong side,
539 // in which case return distance of 0.0 otherwise .
540 //
541 if (wrongSide)
542 {
543 dist = 0.0;
544 }
545 else
546 {
547 dist = dist1;
548 }
549 }
550 else if (!wrongSide)
551 {
552 dist = dist1;
553 }
554 }
555 return dist;
556}
bool G4bool
Definition G4Types.hh:86

◆ Extent()

G4double G4TriangularFacet::Extent ( const G4ThreeVector axis)
overridevirtual

Calculates the furthest the triangle extends in fA particular direction defined by the vector axis.

Implements G4VFacet.

Definition at line 565 of file G4TriangularFacet.cc.

566{
567 G4double ss = GetVertex(0).dot(axis);
569 if (sp > ss) { ss = sp; }
570 sp = GetVertex(2).dot(axis);
571 if (sp > ss) { ss = sp; }
572 return ss;
573}
const axis_t axis_to_type< N >::axis
Definition pugixml.cc:9668

◆ GetArea()

G4double G4TriangularFacet::GetArea ( ) const
overridevirtual

Auxiliary method for returning the surface area.

Implements G4VFacet.

Definition at line 801 of file G4TriangularFacet.cc.

802{
803 return fArea;
804}

◆ GetCircumcentre()

G4ThreeVector G4TriangularFacet::GetCircumcentre ( ) const
inlineoverridevirtual

Returns the circumcentre point of the facet.

Implements G4VFacet.

◆ GetClone()

G4VFacet * G4TriangularFacet::GetClone ( )
overridevirtual

Returns a pointer to a newly allocated duplicate copy of the facet.

Implements G4VFacet.

Definition at line 261 of file G4TriangularFacet.cc.

262{
263 auto fc = new G4TriangularFacet (GetVertex(0), GetVertex(1),
264 GetVertex(2), ABSOLUTE);
265 return fc;
266}

◆ GetEntityType()

G4GeometryType G4TriangularFacet::GetEntityType ( ) const
overridevirtual

Returns the type ID, "G4TriangularFacet" of the facet.

Implements G4VFacet.

Definition at line 808 of file G4TriangularFacet.cc.

809{
810 return "G4TriangularFacet";
811}

◆ GetFlippedFacet()

G4TriangularFacet * G4TriangularFacet::GetFlippedFacet ( )

Generates and returns an identical facet, but with the normal vector pointing at 180 degrees.

Definition at line 275 of file G4TriangularFacet.cc.

276{
277 auto flipped = new G4TriangularFacet (GetVertex(0), GetVertex(1),
278 GetVertex(2), ABSOLUTE);
279 return flipped;
280}

◆ GetNumberOfVertices()

G4int G4TriangularFacet::GetNumberOfVertices ( ) const
inlineoverridevirtual

Returns the number of vertices, i.e. 3.

Implements G4VFacet.

◆ GetPointOnFace()

G4ThreeVector G4TriangularFacet::GetPointOnFace ( ) const
overridevirtual

Auxiliary method to get a uniform random point on the facet.

Implements G4VFacet.

Definition at line 783 of file G4TriangularFacet.cc.

784{
785 G4double u = G4QuickRand();
786 G4double v = G4QuickRand();
787 if (u + v > 1.)
788 {
789 u = 1. - u;
790 v = 1. - v;
791 }
792 return GetVertex(0) + u*fE1 + v*fE2;
793}
G4double G4QuickRand(uint32_t seed=0)

◆ GetRadius()

G4double G4TriangularFacet::GetRadius ( ) const
inlineoverridevirtual

Returns the radius to the anchor point and centered on the circumcentre.

Implements G4VFacet.

◆ GetSurfaceNormal()

G4ThreeVector G4TriangularFacet::GetSurfaceNormal ( ) const
overridevirtual

Returns/sets the normal vector to the facet.

Implements G4VFacet.

Definition at line 815 of file G4TriangularFacet.cc.

816{
817 return fSurfaceNormal;
818}

◆ GetVertex()

G4ThreeVector G4TriangularFacet::GetVertex ( G4int i) const
inlineoverridevirtual

Returns the vertex based on the index 'i'.

Implements G4VFacet.

Referenced by Distance(), Extent(), G4TriangularFacet(), GetClone(), GetFlippedFacet(), GetPointOnFace(), and Intersect().

◆ GetVertexIndex()

G4int G4TriangularFacet::GetVertexIndex ( G4int i) const
inlineoverridevirtual

Accessor/setter for the vertex index.

Implements G4VFacet.

◆ Intersect()

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

Finds the next intersection when going from 'p' in the direction of 'v'. If 'outgoing' is true, only consider the face if we are going out through the face; otherwise, if false, only consider the face if we are going in through the face.

Returns
true if there is an intersection, false otherwise.

Implements G4VFacet.

Definition at line 602 of file G4TriangularFacet.cc.

608{
609 //
610 // Check whether the direction of the facet is consistent with the vector v
611 // and the need to be outgoing or ingoing. If inconsistent, disregard and
612 // return false.
613 //
614 G4double w = v.dot(fSurfaceNormal);
615 if ((outgoing && w < -dirTolerance) || (!outgoing && w > dirTolerance))
616 {
617 distance = kInfinity;
618 distFromSurface = kInfinity;
619 normal.set(0,0,0);
620 return false;
621 }
622 //
623 // Calculate the orthogonal distance from p to the surface containing the
624 // triangle. Then determine if we're on the right or wrong side of the
625 // surface (at fA distance greater than kCarTolerance to be consistent with
626 // "outgoing".
627 //
628 const G4ThreeVector& p0 = GetVertex(0);
629 G4ThreeVector D = p0 - p;
630 distFromSurface = D.dot(fSurfaceNormal);
631 G4bool wrongSide = (outgoing && distFromSurface < -0.5*kCarTolerance) ||
632 (!outgoing && distFromSurface > 0.5*kCarTolerance);
633
634 if (wrongSide)
635 {
636 distance = kInfinity;
637 distFromSurface = kInfinity;
638 normal.set(0,0,0);
639 return false;
640 }
641
642 wrongSide = (outgoing && distFromSurface < 0.0)
643 || (!outgoing && distFromSurface > 0.0);
644 if (wrongSide)
645 {
646 //
647 // We're slightly on the wrong side of the surface. Check if we're close
648 // enough using fA precise distance calculation.
649 //
650 G4ThreeVector u = Distance(p);
651 if (fSqrDist <= kCarTolerance*kCarTolerance)
652 {
653 //
654 // We're very close. Therefore return fA small negative number
655 // to pretend we intersect.
656 //
657 // distance = -0.5*kCarTolerance
658 distance = 0.0;
659 normal = fSurfaceNormal;
660 return true;
661 }
662
663 //
664 // We're close to the surface containing the triangle, but sufficiently
665 // far from the triangle, and on the wrong side compared to the directions
666 // of the surface normal and v. There is no intersection.
667 //
668 distance = kInfinity;
669 distFromSurface = kInfinity;
670 normal.set(0,0,0);
671 return false;
672 }
673 if (w < dirTolerance && w > -dirTolerance)
674 {
675 //
676 // The ray is within the plane of the triangle. Project the problem into 2D
677 // in the plane of the triangle. First try to create orthogonal unit vectors
678 // mu and nu, where mu is fE1/|fE1|. This is kinda like
679 // the original algorithm due to Rickard Holmberg, but with better
680 // mathematical justification than the original method ... however,
681 // beware Rickard's was less time-consuming.
682 //
683 // Note that vprime is not fA unit vector. We need to keep it unnormalised
684 // since the values of distance along vprime (s0 and s1) for intersection
685 // with the triangle will be used to determine if we cut the plane at the
686 // same time.
687 //
688 G4ThreeVector mu = fE1.unit();
689 G4ThreeVector nu = fSurfaceNormal.cross(mu);
690 G4TwoVector pprime(p.dot(mu), p.dot(nu));
691 G4TwoVector vprime(v.dot(mu), v.dot(nu));
692 G4TwoVector P0prime(p0.dot(mu), p0.dot(nu));
693 G4TwoVector E0prime(fE1.mag(), 0.0);
694 G4TwoVector E1prime(fE2.dot(mu), fE2.dot(nu));
695 G4TwoVector loc[2];
697 vprime, P0prime, E0prime, E1prime, loc))
698 {
699 //
700 // There is an intersection between the line and triangle in 2D.
701 // Now check which part of the line intersects with the plane
702 // containing the triangle in 3D.
703 //
704 G4double vprimemag = vprime.mag();
705 G4double s0 = (loc[0] - pprime).mag()/vprimemag;
706 G4double s1 = (loc[1] - pprime).mag()/vprimemag;
707 G4double normDist0 = fSurfaceNormal.dot(s0*v) - distFromSurface;
708 G4double normDist1 = fSurfaceNormal.dot(s1*v) - distFromSurface;
709
710 if ((normDist0 < 0.0 && normDist1 < 0.0)
711 || (normDist0 > 0.0 && normDist1 > 0.0)
712 || (normDist0 == 0.0 && normDist1 == 0.0) )
713 {
714 distance = kInfinity;
715 distFromSurface = kInfinity;
716 normal.set(0,0,0);
717 return false;
718 }
719
720 G4double dnormDist = normDist1 - normDist0;
721 if (fabs(dnormDist) < DBL_EPSILON)
722 {
723 distance = s0;
724 normal = fSurfaceNormal;
725 if (!outgoing) { distFromSurface = -distFromSurface; }
726 return true;
727 }
728
729 distance = s0 - normDist0*(s1-s0)/dnormDist;
730 normal = fSurfaceNormal;
731 if (!outgoing) { distFromSurface = -distFromSurface; }
732 return true;
733 }
734 distance = kInfinity;
735 distFromSurface = kInfinity;
736 normal.set(0,0,0);
737 return false;
738 }
739 //
740 //
741 // Use conventional algorithm to determine the whether there is an
742 // intersection. This involves determining the point of intersection of the
743 // line with the plane containing the triangle, and then calculating if the
744 // point is within the triangle.
745 //
746 distance = distFromSurface / w;
747 G4ThreeVector pp = p + v*distance;
748 G4ThreeVector DD = p0 - pp;
749 G4double d = fE1.dot(DD);
750 G4double e = fE2.dot(DD);
751 G4double ss = fB*e - fC*d;
752 G4double t = fB*d - fA*e;
753
754 G4double sTolerance = (fabs(fB)+ fabs(fC) + fabs(d) + fabs(e))*kCarTolerance;
755 G4double tTolerance = (fabs(fA)+ fabs(fB) + fabs(d) + fabs(e))*kCarTolerance;
756 G4double detTolerance = (fabs(fA)+ fabs(fC) + 2*fabs(fB) )*kCarTolerance;
757
758 //if (ss < 0.0 || t < 0.0 || ss+t > fDet)
759 if (ss < -sTolerance || t < -tTolerance || ( ss+t - fDet ) > detTolerance)
760 {
761 //
762 // The intersection is outside of the triangle.
763 //
764 distance = distFromSurface = kInfinity;
765 normal.set(0,0,0);
766 return false;
767 }
768
769 //
770 // There is an intersection. Now we only need to set the surface normal.
771 //
772 normal = fSurfaceNormal;
773 if (!outgoing) { distFromSurface = -distFromSurface; }
774 return true;
775}
CLHEP::Hep2Vector G4TwoVector
void set(double x, double y)
void set(double x, double y, double z)
static G4bool IntersectLineAndTriangle2D(const G4TwoVector &p, const G4TwoVector &v, const G4TwoVector &p0, const G4TwoVector &e0, const G4TwoVector &e1, G4TwoVector location[2])
static const G4double dirTolerance
Definition G4VFacet.hh:184
#define DBL_EPSILON
Definition templates.hh:66

◆ IsDefined()

G4bool G4TriangularFacet::IsDefined ( ) const
inlineoverridevirtual

Returns true if the facet is defined.

Implements G4VFacet.

◆ operator=() [1/2]

G4TriangularFacet & G4TriangularFacet::operator= ( const G4TriangularFacet & right)

Assignment and move assignment operators.

Definition at line 226 of file G4TriangularFacet.cc.

227{
228 SetVertices(nullptr);
229
230 if (this != &rhs)
231 {
232 delete fVertices;
233 CopyFrom(rhs);
234 }
235
236 return *this;
237}

◆ operator=() [2/2]

G4TriangularFacet & G4TriangularFacet::operator= ( G4TriangularFacet && right)
noexcept

Definition at line 242 of file G4TriangularFacet.cc.

243{
244 SetVertices(nullptr);
245
246 if (this != &rhs)
247 {
248 delete fVertices;
249 MoveFrom(rhs);
250 }
251
252 return *this;
253}

◆ SetSurfaceNormal()

void G4TriangularFacet::SetSurfaceNormal ( const G4ThreeVector & normal)

Definition at line 822 of file G4TriangularFacet.cc.

823{
824 fSurfaceNormal = normal;
825}

◆ SetVertex()

void G4TriangularFacet::SetVertex ( G4int i,
const G4ThreeVector & val )
inlineoverridevirtual

Methods to set the vertices.

Implements G4VFacet.

Referenced by G4TriangularFacet(), and G4TriangularFacet().

◆ SetVertexIndex()

void G4TriangularFacet::SetVertexIndex ( G4int i,
G4int j )
inlineoverridevirtual

Implements G4VFacet.

◆ SetVertices()

void G4TriangularFacet::SetVertices ( std::vector< G4ThreeVector > * v)
inlineoverridevirtual

Implements G4VFacet.

Referenced by operator=(), operator=(), and ~G4TriangularFacet().


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