Geant4  10.02.p03
G4TriangularFacet Class Reference

#include <G4TriangularFacet.hh>

Inheritance diagram for G4TriangularFacet:
Collaboration diagram for G4TriangularFacet:

Public Member Functions

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

Private Member Functions

void CopyFrom (const G4TriangularFacet &rhs)
 

Private Attributes

G4ThreeVector fSurfaceNormal
 
G4double fArea
 
G4ThreeVector fCircumcentre
 
G4double fRadius
 
G4int fIndices [3]
 
std::vector< G4ThreeVector > * fVertices
 
G4double fA
 
G4double fB
 
G4double fC
 
G4double fDet
 
G4double fSqrDist
 
G4ThreeVector fE1
 
G4ThreeVector fE2
 
G4bool fIsDefined
 

Additional Inherited Members

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

Detailed Description

Definition at line 65 of file G4TriangularFacet.hh.

Constructor & Destructor Documentation

◆ G4TriangularFacet() [1/3]

G4TriangularFacet::G4TriangularFacet ( )

Definition at line 167 of file G4TriangularFacet.cc.

168  : fSqrDist(0.)
169 {
170  fVertices = new vector<G4ThreeVector>(3);
171  G4ThreeVector zero(0,0,0);
172  SetVertex(0, zero);
173  SetVertex(1, zero);
174  SetVertex(2, zero);
175  for (G4int i = 0; i < 3; ++i) fIndices[i] = -1;
176  fIsDefined = false;
177  fSurfaceNormal.set(0,0,0);
178  fA = fB = fC = 0;
179  fE1 = zero;
180  fE2 = zero;
181  fDet = 0.0;
182  fArea = fRadius = 0.0;
183 }
void set(double x, double y, double z)
std::vector< G4ThreeVector > * fVertices
void SetVertex(G4int i, const G4ThreeVector &val)
int G4int
Definition: G4Types.hh:78
G4ThreeVector fSurfaceNormal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~G4TriangularFacet()

G4TriangularFacet::~G4TriangularFacet ( )

Definition at line 187 of file G4TriangularFacet.cc.

188 {
189  SetVertices(0);
190 }
void SetVertices(std::vector< G4ThreeVector > *v)
Here is the call graph for this function:

◆ G4TriangularFacet() [2/3]

G4TriangularFacet::G4TriangularFacet ( const G4ThreeVector vt0,
const G4ThreeVector vt1,
const G4ThreeVector vt2,
G4FacetVertexType  vertexType 
)

Definition at line 75 of file G4TriangularFacet.cc.

79  : fSqrDist(0.)
80 {
81  fVertices = new vector<G4ThreeVector>(3);
82 
83  SetVertex(0, vt0);
84  if (vertexType == ABSOLUTE)
85  {
86  SetVertex(1, vt1);
87  SetVertex(2, vt2);
88  fE1 = vt1 - vt0;
89  fE2 = vt2 - vt0;
90  }
91  else
92  {
93  SetVertex(1, vt0 + vt1);
94  SetVertex(2, vt0 + vt2);
95  fE1 = vt1;
96  fE2 = vt2;
97  }
98 
99  for (G4int i = 0; i < 3; ++i) fIndices[i] = -1;
100 
101  G4double eMag1 = fE1.mag();
102  G4double eMag2 = fE2.mag();
103  G4double eMag3 = (fE2-fE1).mag();
104 
105  if (eMag1 <= kCarTolerance || eMag2 <= kCarTolerance
106  || eMag3 <= kCarTolerance)
107  {
108  ostringstream message;
109  message << "Length of sides of facet are too small." << G4endl
110  << "fVertices[0] = " << GetVertex(0) << G4endl
111  << "fVertices[1] = " << GetVertex(1) << G4endl
112  << "fVertices[2] = " << GetVertex(2) << G4endl
113  << "Side lengths = fVertices[0]->fVertices[1]" << eMag1 << G4endl
114  << "Side lengths = fVertices[0]->fVertices[2]" << eMag2 << G4endl
115  << "Side lengths = fVertices[1]->fVertices[2]" << eMag3;
116  G4Exception("G4TriangularFacet::G4TriangularFacet()",
117  "GeomSolids1001", JustWarning, message);
118  fIsDefined = false;
119  fSurfaceNormal.set(0,0,0);
120  fA = fB = fC = 0.0;
121  fDet = 0.0;
122  fArea = fRadius = 0.0;
123  }
124  else
125  {
126  fIsDefined = true;
128  fA = fE1.mag2();
129  fB = fE1.dot(fE2);
130  fC = fE2.mag2();
131  fDet = fabs(fA*fC - fB*fB);
132 
133  // sMin = -0.5*kCarTolerance/sqrt(fA);
134  // sMax = 1.0 - sMin;
135  // tMin = -0.5*kCarTolerance/sqrt(fC);
136  // G4ThreeVector vtmp = 0.25 * (fE1 + fE2);
137 
138  fArea = 0.5 * (fE1.cross(fE2)).mag();
139  G4double lambda0, lambda1;
140  if(std::fabs(fArea) < kCarTolerance*kCarTolerance)
141  {
142  ostringstream message;
143  message << "Area of Facet is too small, possible flat triangle!" << G4endl
144  << " fVertices[0] = " << GetVertex(0) << G4endl
145  << " fVertices[1] = " << GetVertex(1) << G4endl
146  << " fVertices[2] = " << GetVertex(2) << G4endl
147  << "Area = " << fArea;
148  G4Exception("G4TriangularFacet::G4TriangularFacet()",
149  "GeomSolids1001", JustWarning, message);
150  lambda0 = 0.5;
151  lambda1 = 0.5;
152  }
153  else
154  {
155  lambda0 = (fA-fB) * fC / (8.0*fArea*fArea);
156  lambda1 = (fC-fB) * fA / (8.0*fArea*fArea);
157  }
158  G4ThreeVector p0 = GetVertex(0);
159  fCircumcentre = p0 + lambda0*fE1 + lambda1*fE2;
160  G4double radiusSqr = (fCircumcentre-p0).mag2();
161  fRadius = sqrt(radiusSqr);
162  }
163 }
void set(double x, double y, double z)
std::vector< G4ThreeVector > * fVertices
static const G4double kCarTolerance
Definition: G4VFacet.hh:102
void SetVertex(G4int i, const G4ThreeVector &val)
int G4int
Definition: G4Types.hh:78
double mag2() const
G4ThreeVector fCircumcentre
Hep3Vector cross(const Hep3Vector &) const
double mag() const
Hep3Vector unit() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
double dot(const Hep3Vector &) const
#define G4endl
Definition: G4ios.hh:61
double G4double
Definition: G4Types.hh:76
G4ThreeVector GetVertex(G4int i) const
G4ThreeVector fSurfaceNormal
Here is the call graph for this function:

◆ G4TriangularFacet() [3/3]

G4TriangularFacet::G4TriangularFacet ( const G4TriangularFacet right)

Definition at line 208 of file G4TriangularFacet.cc.

209  : G4VFacet(rhs)
210 {
211  CopyFrom(rhs);
212 }
void CopyFrom(const G4TriangularFacet &rhs)
Here is the call graph for this function:

Member Function Documentation

◆ AllocatedMemory()

G4int G4TriangularFacet::AllocatedMemory ( )
inlinevirtual

Implements G4VFacet.

Definition at line 165 of file G4TriangularFacet.hh.

166 {
167  G4int size = sizeof(*this);
168  size += GetNumberOfVertices() * sizeof(G4ThreeVector);
169  return size;
170 }
CLHEP::Hep3Vector G4ThreeVector
int G4int
Definition: G4Types.hh:78
G4int GetNumberOfVertices() const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CopyFrom()

void G4TriangularFacet::CopyFrom ( const G4TriangularFacet rhs)
private

Definition at line 194 of file G4TriangularFacet.cc.

195 {
196  char *p = (char *) &rhs;
197  copy(p, p + sizeof(*this), (char *)this);
198 
199  if (fIndices[0] < 0 && fVertices)
200  {
201  fVertices = new vector<G4ThreeVector>(3);
202  for (G4int i = 0; i < 3; ++i) (*fVertices)[i] = (*rhs.fVertices)[i];
203  }
204 }
std::vector< G4ThreeVector > * fVertices
int G4int
Definition: G4Types.hh:78
Here is the caller graph for this function:

◆ Distance() [1/3]

G4ThreeVector G4TriangularFacet::Distance ( const G4ThreeVector p)

Definition at line 268 of file G4TriangularFacet.cc.

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

◆ Distance() [2/3]

G4double G4TriangularFacet::Distance ( const G4ThreeVector p,
G4double  minDist 
)
virtual

Implements G4VFacet.

Definition at line 452 of file G4TriangularFacet.cc.

454 {
455  //
456  // Start with quicky test to determine if the surface of the sphere enclosing
457  // the triangle is any closer to p than minDist. If not, then don't bother
458  // about more accurate test.
459  //
460  G4double dist = kInfinity;
461  if ((p-fCircumcentre).mag()-fRadius < minDist)
462  {
463  //
464  // It's possible that the triangle is closer than minDist,
465  // so do more accurate assessment.
466  //
467  dist = Distance(p).mag();
468  }
469  return dist;
470 }
static const G4double kInfinity
Definition: geomdefs.hh:42
G4ThreeVector fCircumcentre
double mag() const
double G4double
Definition: G4Types.hh:76
G4ThreeVector Distance(const G4ThreeVector &p)
Here is the call graph for this function:

◆ Distance() [3/3]

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

Implements G4VFacet.

Definition at line 487 of file G4TriangularFacet.cc.

490 {
491  //
492  // Start with quicky test to determine if the surface of the sphere enclosing
493  // the triangle is any closer to p than minDist. If not, then don't bother
494  // about more accurate test.
495  //
496  G4double dist = kInfinity;
497  if ((p-fCircumcentre).mag()-fRadius < minDist)
498  {
499  //
500  // It's possible that the triangle is closer than minDist,
501  // so do more accurate assessment.
502  //
503  G4ThreeVector v = Distance(p);
504  G4double dist1 = sqrt(fSqrDist);
506  G4bool wrongSide = (dir > 0.0 && !outgoing) || (dir < 0.0 && outgoing);
507  if (dist1 <= kCarTolerance)
508  {
509  //
510  // Point p is very close to triangle. Check if it's on the wrong side,
511  // in which case return distance of 0.0 otherwise .
512  //
513  if (wrongSide) dist = 0.0;
514  else dist = dist1;
515  }
516  else if (!wrongSide) dist = dist1;
517  }
518  return dist;
519 }
static const G4double kInfinity
Definition: geomdefs.hh:42
static const G4double kCarTolerance
Definition: G4VFacet.hh:102
TDirectory * dir
G4ThreeVector fCircumcentre
bool G4bool
Definition: G4Types.hh:79
double dot(const Hep3Vector &) const
double G4double
Definition: G4Types.hh:76
G4ThreeVector fSurfaceNormal
G4ThreeVector Distance(const G4ThreeVector &p)
Here is the call graph for this function:

◆ Extent()

G4double G4TriangularFacet::Extent ( const G4ThreeVector  axis)
virtual

Implements G4VFacet.

Definition at line 528 of file G4TriangularFacet.cc.

529 {
530  G4double ss = GetVertex(0).dot(axis);
531  G4double sp = GetVertex(1).dot(axis);
532  if (sp > ss) ss = sp;
533  sp = GetVertex(2).dot(axis);
534  if (sp > ss) ss = sp;
535  return ss;
536 }
double dot(const Hep3Vector &) const
double G4double
Definition: G4Types.hh:76
G4ThreeVector GetVertex(G4int i) const
Here is the call graph for this function:

◆ GetArea()

G4double G4TriangularFacet::GetArea ( )
virtual

Implements G4VFacet.

Definition at line 773 of file G4TriangularFacet.cc.

774 {
775  return fArea;
776 }
Here is the caller graph for this function:

◆ GetCircumcentre()

G4ThreeVector G4TriangularFacet::GetCircumcentre ( ) const
inlinevirtual

Implements G4VFacet.

Definition at line 155 of file G4TriangularFacet.hh.

156 {
157  return fCircumcentre;
158 }
G4ThreeVector fCircumcentre

◆ GetClone()

G4VFacet * G4TriangularFacet::GetClone ( )
virtual

Implements G4VFacet.

Definition at line 233 of file G4TriangularFacet.cc.

234 {
235  G4TriangularFacet *fc =
237  return fc;
238 }
G4ThreeVector GetVertex(G4int i) const
Here is the call graph for this function:

◆ GetEntityType()

G4GeometryType G4TriangularFacet::GetEntityType ( ) const
virtual

Implements G4VFacet.

Definition at line 780 of file G4TriangularFacet.cc.

781 {
782  return "G4TriangularFacet";
783 }

◆ GetFlippedFacet()

G4TriangularFacet * G4TriangularFacet::GetFlippedFacet ( )

Definition at line 247 of file G4TriangularFacet.cc.

248 {
249  G4TriangularFacet *flipped =
251  return flipped;
252 }
G4ThreeVector GetVertex(G4int i) const
Here is the call graph for this function:

◆ GetNumberOfVertices()

G4int G4TriangularFacet::GetNumberOfVertices ( ) const
inlinevirtual

Implements G4VFacet.

Definition at line 139 of file G4TriangularFacet.hh.

140 {
141  return 3;
142 }
Here is the caller graph for this function:

◆ GetPointOnFace()

G4ThreeVector G4TriangularFacet::GetPointOnFace ( ) const
virtual

Implements G4VFacet.

Definition at line 757 of file G4TriangularFacet.cc.

758 {
759  G4double alpha = G4RandFlat::shoot(0., 1.);
760  G4double beta = G4RandFlat::shoot(0., 1.);
761  G4double lambda1 = alpha*beta;
762  G4double lambda0 = alpha-lambda1;
763 
764  return GetVertex(0) + lambda0*fE1 + lambda1*fE2;
765 }
ThreeVector shoot(const G4int Ap, const G4int Af)
double G4double
Definition: G4Types.hh:76
static const G4double alpha
G4ThreeVector GetVertex(G4int i) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetRadius()

G4double G4TriangularFacet::GetRadius ( ) const
inlinevirtual

Implements G4VFacet.

Definition at line 160 of file G4TriangularFacet.hh.

161 {
162  return fRadius;
163 }

◆ GetSurfaceNormal()

G4ThreeVector G4TriangularFacet::GetSurfaceNormal ( ) const
virtual

Implements G4VFacet.

Definition at line 787 of file G4TriangularFacet.cc.

788 {
789  return fSurfaceNormal;
790 }
G4ThreeVector fSurfaceNormal
Here is the caller graph for this function:

◆ GetVertex()

G4ThreeVector G4TriangularFacet::GetVertex ( G4int  i) const
inlinevirtual

Implements G4VFacet.

Definition at line 144 of file G4TriangularFacet.hh.

145 {
146  G4int indice = fIndices[i];
147  return indice < 0 ? (*fVertices)[i] : (*fVertices)[indice];
148 }
int G4int
Definition: G4Types.hh:78
Here is the caller graph for this function:

◆ GetVertexIndex()

G4int G4TriangularFacet::GetVertexIndex ( G4int  i) const
inlinevirtual

Implements G4VFacet.

Definition at line 172 of file G4TriangularFacet.hh.

173 {
174  if (i < 3) return fIndices[i];
175  else return 999999999;
176 }
Here is the caller graph for this function:

◆ Intersect()

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

Implements G4VFacet.

Definition at line 565 of file G4TriangularFacet.cc.

571 {
572  //
573  // Check whether the direction of the facet is consistent with the vector v
574  // and the need to be outgoing or ingoing. If inconsistent, disregard and
575  // return false.
576  //
578  if ((outgoing && w < -dirTolerance) || (!outgoing && w > dirTolerance))
579  {
580  distance = kInfinity;
581  distFromSurface = kInfinity;
582  normal.set(0,0,0);
583  return false;
584  }
585  //
586  // Calculate the orthogonal distance from p to the surface containing the
587  // triangle. Then determine if we're on the right or wrong side of the
588  // surface (at fA distance greater than kCarTolerance to be consistent with
589  // "outgoing".
590  //
591  const G4ThreeVector &p0 = GetVertex(0);
592  G4ThreeVector D = p0 - p;
593  distFromSurface = D.dot(fSurfaceNormal);
594  G4bool wrongSide = (outgoing && distFromSurface < -0.5*kCarTolerance) ||
595  (!outgoing && distFromSurface > 0.5*kCarTolerance);
596 
597  if (wrongSide)
598  {
599  distance = kInfinity;
600  distFromSurface = kInfinity;
601  normal.set(0,0,0);
602  return false;
603  }
604 
605  wrongSide = (outgoing && distFromSurface < 0.0)
606  || (!outgoing && distFromSurface > 0.0);
607  if (wrongSide)
608  {
609  //
610  // We're slightly on the wrong side of the surface. Check if we're close
611  // enough using fA precise distance calculation.
612  //
613  G4ThreeVector u = Distance(p);
615  {
616  //
617  // We're very close. Therefore return fA small negative number
618  // to pretend we intersect.
619  //
620  // distance = -0.5*kCarTolerance
621  distance = 0.0;
622  normal = fSurfaceNormal;
623  return true;
624  }
625  else
626  {
627  //
628  // We're close to the surface containing the triangle, but sufficiently
629  // far from the triangle, and on the wrong side compared to the directions
630  // of the surface normal and v. There is no intersection.
631  //
632  distance = kInfinity;
633  distFromSurface = kInfinity;
634  normal.set(0,0,0);
635  return false;
636  }
637  }
638  if (w < dirTolerance && w > -dirTolerance)
639  {
640  //
641  // The ray is within the plane of the triangle. Project the problem into 2D
642  // in the plane of the triangle. First try to create orthogonal unit vectors
643  // mu and nu, where mu is fE1/|fE1|. This is kinda like
644  // the original algorithm due to Rickard Holmberg, but with better
645  // mathematical justification than the original method ... however,
646  // beware Rickard's was less time-consuming.
647  //
648  // Note that vprime is not fA unit vector. We need to keep it unnormalised
649  // since the values of distance along vprime (s0 and s1) for intersection
650  // with the triangle will be used to determine if we cut the plane at the
651  // same time.
652  //
653  G4ThreeVector mu = fE1.unit();
655  G4TwoVector pprime(p.dot(mu), p.dot(nu));
656  G4TwoVector vprime(v.dot(mu), v.dot(nu));
657  G4TwoVector P0prime(p0.dot(mu), p0.dot(nu));
658  G4TwoVector E0prime(fE1.mag(), 0.0);
659  G4TwoVector E1prime(fE2.dot(mu), fE2.dot(nu));
660  G4TwoVector loc[2];
662  vprime, P0prime, E0prime, E1prime, loc))
663  {
664  //
665  // There is an intersection between the line and triangle in 2D.
666  // Now check which part of the line intersects with the plane
667  // containing the triangle in 3D.
668  //
669  G4double vprimemag = vprime.mag();
670  G4double s0 = (loc[0] - pprime).mag()/vprimemag;
671  G4double s1 = (loc[1] - pprime).mag()/vprimemag;
672  G4double normDist0 = fSurfaceNormal.dot(s0*v) - distFromSurface;
673  G4double normDist1 = fSurfaceNormal.dot(s1*v) - distFromSurface;
674 
675  if ((normDist0 < 0.0 && normDist1 < 0.0)
676  || (normDist0 > 0.0 && normDist1 > 0.0)
677  || (normDist0 == 0.0 && normDist1 == 0.0) )
678  {
679  distance = kInfinity;
680  distFromSurface = kInfinity;
681  normal.set(0,0,0);
682  return false;
683  }
684  else
685  {
686  G4double dnormDist = normDist1 - normDist0;
687  if (fabs(dnormDist) < DBL_EPSILON)
688  {
689  distance = s0;
690  normal = fSurfaceNormal;
691  if (!outgoing) distFromSurface = -distFromSurface;
692  return true;
693  }
694  else
695  {
696  distance = s0 - normDist0*(s1-s0)/dnormDist;
697  normal = fSurfaceNormal;
698  if (!outgoing) distFromSurface = -distFromSurface;
699  return true;
700  }
701  }
702  }
703  else
704  {
705  distance = kInfinity;
706  distFromSurface = kInfinity;
707  normal.set(0,0,0);
708  return false;
709  }
710  }
711  //
712  //
713  // Use conventional algorithm to determine the whether there is an
714  // intersection. This involves determining the point of intersection of the
715  // line with the plane containing the triangle, and then calculating if the
716  // point is within the triangle.
717  //
718  distance = distFromSurface / w;
719  G4ThreeVector pp = p + v*distance;
720  G4ThreeVector DD = p0 - pp;
721  G4double d = fE1.dot(DD);
722  G4double e = fE2.dot(DD);
723  G4double ss = fB*e - fC*d;
724  G4double t = fB*d - fA*e;
725 
726  G4double sTolerance = (fabs(fB)+ fabs(fC) + fabs(d) + fabs(e))*kCarTolerance;
727  G4double tTolerance = (fabs(fA)+ fabs(fB) + fabs(d) + fabs(e))*kCarTolerance;
728  G4double detTolerance = (fabs(fA)+ fabs(fC) + 2*fabs(fB) )*kCarTolerance;
729 
730  //if (ss < 0.0 || t < 0.0 || ss+t > fDet)
731  if (ss < -sTolerance || t < -tTolerance || ( ss+t - fDet ) > detTolerance)
732  {
733  //
734  // The intersection is outside of the triangle.
735  //
736  distance = distFromSurface = kInfinity;
737  normal.set(0,0,0);
738  return false;
739  }
740  else
741  {
742  //
743  // There is an intersection. Now we only need to set the surface normal.
744  //
745  normal = fSurfaceNormal;
746  if (!outgoing) distFromSurface = -distFromSurface;
747  return true;
748  }
749 }
void set(double x, double y, double z)
static const G4double kInfinity
Definition: geomdefs.hh:42
Float_t d
static const G4double kCarTolerance
Definition: G4VFacet.hh:102
Hep3Vector cross(const Hep3Vector &) const
static const G4double dirTolerance
Definition: G4VFacet.hh:101
bool G4bool
Definition: G4Types.hh:79
double mag() const
Hep3Vector unit() const
#define DBL_EPSILON
Definition: templates.hh:87
double mag() const
static G4bool IntersectLineAndTriangle2D(const G4TwoVector &p, const G4TwoVector &v, const G4TwoVector &p0, const G4TwoVector &e0, const G4TwoVector &e1, G4TwoVector location[2])
double dot(const Hep3Vector &) const
double D(double temp)
double G4double
Definition: G4Types.hh:76
G4ThreeVector GetVertex(G4int i) const
G4ThreeVector fSurfaceNormal
G4ThreeVector Distance(const G4ThreeVector &p)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsDefined()

G4bool G4TriangularFacet::IsDefined ( ) const
inlinevirtual

Implements G4VFacet.

Definition at line 134 of file G4TriangularFacet.hh.

135 {
136  return fIsDefined;
137 }
Here is the caller graph for this function:

◆ operator=()

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

Definition at line 217 of file G4TriangularFacet.cc.

218 {
219  SetVertices(0);
220 
221  if (this != &rhs)
222  CopyFrom(rhs);
223 
224  return *this;
225 }
void SetVertices(std::vector< G4ThreeVector > *v)
void CopyFrom(const G4TriangularFacet &rhs)
Here is the call graph for this function:

◆ SetSurfaceNormal()

void G4TriangularFacet::SetSurfaceNormal ( G4ThreeVector  normal)

Definition at line 794 of file G4TriangularFacet.cc.

795 {
797 }
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
G4ThreeVector fSurfaceNormal
Here is the call graph for this function:

◆ SetVertex()

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

Implements G4VFacet.

Definition at line 150 of file G4TriangularFacet.hh.

151 {
152  (*fVertices)[i] = val;
153 }
Here is the caller graph for this function:

◆ SetVertexIndex()

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

Implements G4VFacet.

Definition at line 178 of file G4TriangularFacet.hh.

179 {
180  fIndices[i] = j;
181 }
Here is the caller graph for this function:

◆ SetVertices()

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

Implements G4VFacet.

Definition at line 183 of file G4TriangularFacet.hh.

184 {
185  if (fIndices[0] < 0 && fVertices)
186  {
187  delete fVertices;
188  fVertices = 0;
189  }
190  fVertices = v;
191 }
std::vector< G4ThreeVector > * fVertices
Here is the caller graph for this function:

Member Data Documentation

◆ fA

G4double G4TriangularFacet::fA
private

Definition at line 123 of file G4TriangularFacet.hh.

◆ fArea

G4double G4TriangularFacet::fArea
private

Definition at line 116 of file G4TriangularFacet.hh.

◆ fB

G4double G4TriangularFacet::fB
private

Definition at line 123 of file G4TriangularFacet.hh.

◆ fC

G4double G4TriangularFacet::fC
private

Definition at line 123 of file G4TriangularFacet.hh.

◆ fCircumcentre

G4ThreeVector G4TriangularFacet::fCircumcentre
private

Definition at line 117 of file G4TriangularFacet.hh.

◆ fDet

G4double G4TriangularFacet::fDet
private

Definition at line 124 of file G4TriangularFacet.hh.

◆ fE1

G4ThreeVector G4TriangularFacet::fE1
private

Definition at line 126 of file G4TriangularFacet.hh.

◆ fE2

G4ThreeVector G4TriangularFacet::fE2
private

Definition at line 126 of file G4TriangularFacet.hh.

◆ fIndices

G4int G4TriangularFacet::fIndices[3]
private

Definition at line 119 of file G4TriangularFacet.hh.

◆ fIsDefined

G4bool G4TriangularFacet::fIsDefined
private

Definition at line 127 of file G4TriangularFacet.hh.

◆ fRadius

G4double G4TriangularFacet::fRadius
private

Definition at line 118 of file G4TriangularFacet.hh.

◆ fSqrDist

G4double G4TriangularFacet::fSqrDist
private

Definition at line 125 of file G4TriangularFacet.hh.

◆ fSurfaceNormal

G4ThreeVector G4TriangularFacet::fSurfaceNormal
private

Definition at line 115 of file G4TriangularFacet.hh.

◆ fVertices

std::vector<G4ThreeVector>* G4TriangularFacet::fVertices
private

Definition at line 121 of file G4TriangularFacet.hh.


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