Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4TriangularFacet.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// $Id$
27//
28// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29//
30// CHANGE HISTORY
31// --------------
32//
33// 31 October 2004, P R Truscott, QinetiQ Ltd, UK - Created.
34//
35// 01 August 2007 P R Truscott, QinetiQ Ltd, UK
36// Significant modification to correct for errors and enhance
37// based on patches/observations kindly provided by Rickard
38// Holmberg.
39//
40// 26 September 2007
41// P R Truscott, QinetiQ Ltd, UK
42// Further chamges implemented to the Intersect member
43// function to correctly treat rays nearly parallel to the
44// plane of the triangle.
45//
46// 12 April 2010 P R Truscott, QinetiQ, bug fixes to treat optical
47// photon transport, in particular internal reflection
48// at surface.
49//
50// 22 August 2011 I Hrivnacova, Orsay, fix in Intersect() to take into
51// account geometrical tolerance and cases of zero distance
52// from surface.
53//
54// 12 October 2012 M Gayer, CERN
55// New implementation reducing memory requirements by 50%,
56// and considerable CPU speedup together with the new
57// implementation of G4TessellatedSolid.
58//
59// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60
61#include "G4TriangularFacet.hh"
62
63#include "Randomize.hh"
65
66using namespace std;
67
68///////////////////////////////////////////////////////////////////////////////
69//
70// Definition of triangular facet using absolute vectors to fVertices.
71// From this for first vector is retained to define the facet location and
72// two relative vectors (E0 and E1) define the sides and orientation of
73// the outward surface normal.
74//
76 const G4ThreeVector &vt1,
77 const G4ThreeVector &vt2,
78 G4FacetVertexType vertexType)
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." << endl
110 << "fVertices[0] = " << GetVertex(0) << endl
111 << "fVertices[1] = " << GetVertex(1) << endl
112 << "fVertices[2] = " << GetVertex(2) << endl
113 << "Side lengths = fVertices[0]->fVertices[1]" << eMag1 << endl
114 << "Side lengths = fVertices[0]->fVertices[2]" << eMag2 << endl
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;
127 fSurfaceNormal = fE1.cross(fE2).unit();
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 = (fA-fB) * fC / (8.0*fArea*fArea);
140 G4double lambda1 = (fC-fB) * fA / (8.0*fArea*fArea);
141 G4ThreeVector p0 = GetVertex(0);
142 fCircumcentre = p0 + lambda0*fE1 + lambda1*fE2;
143 G4double radiusSqr = (fCircumcentre-p0).mag2();
144 fRadius = sqrt(radiusSqr);
145 }
146}
147
148///////////////////////////////////////////////////////////////////////////////
149//
151 : fSqrDist(0.)
152{
153 fVertices = new vector<G4ThreeVector>(3);
154 G4ThreeVector zero(0,0,0);
155 SetVertex(0, zero);
156 SetVertex(1, zero);
157 SetVertex(2, zero);
158 for (G4int i = 0; i < 3; ++i) fIndices[i] = -1;
159 fIsDefined = false;
160 fSurfaceNormal.set(0,0,0);
161 fA = fB = fC = 0;
162 fE1 = zero;
163 fE2 = zero;
164 fDet = 0.0;
165 fArea = fRadius = 0.0;
166}
167
168///////////////////////////////////////////////////////////////////////////////
169//
171{
172 SetVertices(0);
173}
174
175///////////////////////////////////////////////////////////////////////////////
176//
177void G4TriangularFacet::CopyFrom (const G4TriangularFacet &rhs)
178{
179 char *p = (char *) &rhs;
180 copy(p, p + sizeof(*this), (char *)this);
181
182 if (fIndices[0] < 0 && fVertices)
183 {
184 fVertices = new vector<G4ThreeVector>(3);
185 for (G4int i = 0; i < 3; ++i) (*fVertices)[i] = (*rhs.fVertices)[i];
186 }
187}
188
189///////////////////////////////////////////////////////////////////////////////
190//
192 : G4VFacet(rhs)
193{
194 CopyFrom(rhs);
195}
196
197///////////////////////////////////////////////////////////////////////////////
198//
201{
202 SetVertices(0);
203
204 if (this != &rhs)
205 CopyFrom(rhs);
206
207 return *this;
208}
209
210///////////////////////////////////////////////////////////////////////////////
211//
212// GetClone
213//
214// Simple member function to generate fA duplicate of the triangular facet.
215//
217{
220 return fc;
221}
222
223///////////////////////////////////////////////////////////////////////////////
224//
225// GetFlippedFacet
226//
227// Member function to generate an identical facet, but with the normal vector
228// pointing at 180 degrees.
229//
231{
232 G4TriangularFacet *flipped =
234 return flipped;
235}
236
237///////////////////////////////////////////////////////////////////////////////
238//
239// Distance (G4ThreeVector)
240//
241// Determines the vector between p and the closest point on the facet to p.
242// This is based on the algorithm published in "Geometric Tools for Computer
243// Graphics," Philip J Scheider and David H Eberly, Elsevier Science (USA),
244// 2003. at the time of writing, the algorithm is also available in fA
245// technical note "Distance between point and triangle in 3D," by David Eberly
246// at http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf
247//
248// The by-product is the square-distance fSqrDist, which is retained
249// in case needed by the other "Distance" member functions.
250//
252{
253 G4ThreeVector D = GetVertex(0) - p;
254 G4double d = fE1.dot(D);
255 G4double e = fE2.dot(D);
256 G4double f = D.mag2();
257 G4double q = fB*e - fC*d;
258 G4double t = fB*d - fA*e;
259 fSqrDist = 0.;
260
261 if (q+t <= fDet)
262 {
263 if (q < 0.0)
264 {
265 if (t < 0.0)
266 {
267 //
268 // We are in region 4.
269 //
270 if (d < 0.0)
271 {
272 t = 0.0;
273 if (-d >= fA) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
274 else {q = -d/fA; fSqrDist = d*q + f;}
275 }
276 else
277 {
278 q = 0.0;
279 if (e >= 0.0) {t = 0.0; fSqrDist = f;}
280 else if (-e >= fC) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
281 else {t = -e/fC; fSqrDist = e*t + f;}
282 }
283 }
284 else
285 {
286 //
287 // We are in region 3.
288 //
289 q = 0.0;
290 if (e >= 0.0) {t = 0.0; fSqrDist = f;}
291 else if (-e >= fC) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
292 else {t = -e/fC; fSqrDist = e*t + f;}
293 }
294 }
295 else if (t < 0.0)
296 {
297 //
298 // We are in region 5.
299 //
300 t = 0.0;
301 if (d >= 0.0) {q = 0.0; fSqrDist = f;}
302 else if (-d >= fA) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
303 else {q = -d/fA; fSqrDist = d*q + f;}
304 }
305 else
306 {
307 //
308 // We are in region 0.
309 //
310 q = q / fDet;
311 t = t / fDet;
312 fSqrDist = q*(fA*q + fB*t + 2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
313 }
314 }
315 else
316 {
317 if (q < 0.0)
318 {
319 //
320 // We are in region 2.
321 //
322 G4double tmp0 = fB + d;
323 G4double tmp1 = fC + e;
324 if (tmp1 > tmp0)
325 {
326 G4double numer = tmp1 - tmp0;
327 G4double denom = fA - 2.0*fB + fC;
328 if (numer >= denom) {q = 1.0; t = 0.0; fSqrDist = fA + 2.0*d + f;}
329 else
330 {
331 q = numer/denom;
332 t = 1.0 - q;
333 fSqrDist = q*(fA*q + fB*t +2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
334 }
335 }
336 else
337 {
338 q = 0.0;
339 if (tmp1 <= 0.0) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
340 else if (e >= 0.0) {t = 0.0; fSqrDist = f;}
341 else {t = -e/fC; fSqrDist = e*t + f;}
342 }
343 }
344 else if (t < 0.0)
345 {
346 //
347 // We are in region 6.
348 //
349 G4double tmp0 = fB + e;
350 G4double tmp1 = fA + d;
351 if (tmp1 > tmp0)
352 {
353 G4double numer = tmp1 - tmp0;
354 G4double denom = fA - 2.0*fB + fC;
355 if (numer >= denom) {t = 1.0; q = 0.0; fSqrDist = fC + 2.0*e + f;}
356 else
357 {
358 t = numer/denom;
359 q = 1.0 - t;
360 fSqrDist = q*(fA*q + fB*t +2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
361 }
362 }
363 else
364 {
365 t = 0.0;
366 if (tmp1 <= 0.0) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
367 else if (d >= 0.0) {q = 0.0; fSqrDist = f;}
368 else {q = -d/fA; fSqrDist = d*q + f;}
369 }
370 }
371 else
372 //
373 // We are in region 1.
374 //
375 {
376 G4double numer = fC + e - fB - d;
377 if (numer <= 0.0)
378 {
379 q = 0.0;
380 t = 1.0;
381 fSqrDist = fC + 2.0*e + f;
382 }
383 else
384 {
385 G4double denom = fA - 2.0*fB + fC;
386 if (numer >= denom) {q = 1.0; t = 0.0; fSqrDist = fA + 2.0*d + f;}
387 else
388 {
389 q = numer/denom;
390 t = 1.0 - q;
391 fSqrDist = q*(fA*q + fB*t + 2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
392 }
393 }
394 }
395 }
396 //
397 //
398 // Do fA check for rounding errors in the distance-squared. It appears that
399 // the conventional methods for calculating fSqrDist breaks down when very
400 // near to or at the surface (as required by transport).
401 // We'll therefore also use the magnitude-squared of the vector displacement.
402 // (Note that I've also tried to get around this problem by using the
403 // existing equations for
404 //
405 // fSqrDist = function(fA,fB,fC,d,q,t)
406 //
407 // and use fA more accurate addition process which minimises errors and
408 // breakdown of cummutitivity [where (A+B)+C != A+(B+C)] but this still
409 // doesn't work.
410 // Calculation from u = D + q*fE1 + t*fE2 is less efficient, but appears
411 // more robust.
412 //
413 if (fSqrDist < 0.0) fSqrDist = 0.;
414 G4ThreeVector u = D + q*fE1 + t*fE2;
415 G4double u2 = u.mag2();
416 //
417 // The following (part of the roundoff error check) is from Oliver Merle'q
418 // updates.
419 //
420 if (fSqrDist > u2) fSqrDist = u2;
421
422 return u;
423}
424
425///////////////////////////////////////////////////////////////////////////////
426//
427// Distance (G4ThreeVector, G4double)
428//
429// Determines the closest distance between point p and the facet. This makes
430// use of G4ThreeVector G4TriangularFacet::Distance, which stores the
431// square of the distance in variable fSqrDist. If approximate methods show
432// the distance is to be greater than minDist, then forget about further
433// computation and return fA very large number.
434//
436 G4double minDist)
437{
438 //
439 // Start with quicky test to determine if the surface of the sphere enclosing
440 // the triangle is any closer to p than minDist. If not, then don't bother
441 // about more accurate test.
442 //
443 G4double dist = kInfinity;
444 if ((p-fCircumcentre).mag()-fRadius < minDist)
445 {
446 //
447 // It's possible that the triangle is closer than minDist,
448 // so do more accurate assessment.
449 //
450 dist = Distance(p).mag();
451 }
452 return dist;
453}
454
455///////////////////////////////////////////////////////////////////////////////
456//
457// Distance (G4ThreeVector, G4double, G4bool)
458//
459// Determine the distance to point p. kInfinity is returned if either:
460// (1) outgoing is TRUE and the dot product of the normal vector to the facet
461// and the displacement vector from p to the triangle is negative.
462// (2) outgoing is FALSE and the dot product of the normal vector to the facet
463// and the displacement vector from p to the triangle is positive.
464// If approximate methods show the distance is to be greater than minDist, then
465// forget about further computation and return fA very large number.
466//
467// This method has been heavily modified thanks to the valuable comments and
468// corrections of Rickard Holmberg.
469//
471 G4double minDist,
472 const G4bool outgoing)
473{
474 //
475 // Start with quicky test to determine if the surface of the sphere enclosing
476 // the triangle is any closer to p than minDist. If not, then don't bother
477 // about more accurate test.
478 //
479 G4double dist = kInfinity;
480 if ((p-fCircumcentre).mag()-fRadius < minDist)
481 {
482 //
483 // It's possible that the triangle is closer than minDist,
484 // so do more accurate assessment.
485 //
486 G4ThreeVector v = Distance(p);
487 G4double dist1 = sqrt(fSqrDist);
488 G4double dir = v.dot(fSurfaceNormal);
489 G4bool wrongSide = (dir > 0.0 && !outgoing) || (dir < 0.0 && outgoing);
490 if (dist1 <= kCarTolerance)
491 {
492 //
493 // Point p is very close to triangle. Check if it's on the wrong side,
494 // in which case return distance of 0.0 otherwise .
495 //
496 if (wrongSide) dist = 0.0;
497 else dist = dist1;
498 }
499 else if (!wrongSide) dist = dist1;
500 }
501 return dist;
502}
503
504///////////////////////////////////////////////////////////////////////////////
505//
506// Extent
507//
508// Calculates the furthest the triangle extends in fA particular direction
509// defined by the vector axis.
510//
512{
513 G4double ss = GetVertex(0).dot(axis);
514 G4double sp = GetVertex(1).dot(axis);
515 if (sp > ss) ss = sp;
516 sp = GetVertex(2).dot(axis);
517 if (sp > ss) ss = sp;
518 return ss;
519}
520
521///////////////////////////////////////////////////////////////////////////////
522//
523// Intersect
524//
525// Member function to find the next intersection when going from p in the
526// direction of v. If:
527// (1) "outgoing" is TRUE, only consider the face if we are going out through
528// the face.
529// (2) "outgoing" is FALSE, only consider the face if we are going in through
530// the face.
531// Member functions returns TRUE if there is an intersection, FALSE otherwise.
532// Sets the distance (distance along w), distFromSurface (orthogonal distance)
533// and normal.
534//
535// Also considers intersections that happen with negative distance for small
536// distances of distFromSurface = 0.5*kCarTolerance in the wrong direction.
537// This is to detect kSurface without doing fA full Inside(p) in
538// G4TessellatedSolid::Distance(p,v) calculation.
539//
540// This member function is thanks the valuable work of Rickard Holmberg. PT.
541// However, "gotos" are the Work of the Devil have been exorcised with
542// extreme prejudice!!
543//
544// IMPORTANT NOTE: These calculations are predicated on v being fA unit
545// vector. If G4TessellatedSolid or other classes call this member function
546// with |v| != 1 then there will be errors.
547//
549 const G4ThreeVector &v,
550 G4bool outgoing,
551 G4double &distance,
552 G4double &distFromSurface,
553 G4ThreeVector &normal)
554{
555 //
556 // Check whether the direction of the facet is consistent with the vector v
557 // and the need to be outgoing or ingoing. If inconsistent, disregard and
558 // return false.
559 //
560 G4double w = v.dot(fSurfaceNormal);
561 if ((outgoing && w < -dirTolerance) || (!outgoing && w > dirTolerance))
562 {
563 distance = kInfinity;
564 distFromSurface = kInfinity;
565 normal.set(0,0,0);
566 return false;
567 }
568 //
569 // Calculate the orthogonal distance from p to the surface containing the
570 // triangle. Then determine if we're on the right or wrong side of the
571 // surface (at fA distance greater than kCarTolerance to be consistent with
572 // "outgoing".
573 //
574 const G4ThreeVector &p0 = GetVertex(0);
575 G4ThreeVector D = p0 - p;
576 distFromSurface = D.dot(fSurfaceNormal);
577 G4bool wrongSide = (outgoing && distFromSurface < -0.5*kCarTolerance) ||
578 (!outgoing && distFromSurface > 0.5*kCarTolerance);
579 if (wrongSide)
580 {
581 distance = kInfinity;
582 distFromSurface = kInfinity;
583 normal.set(0,0,0);
584 return false;
585 }
586
587 wrongSide = (outgoing && distFromSurface < 0.0)
588 || (!outgoing && distFromSurface > 0.0);
589 if (wrongSide)
590 {
591 //
592 // We're slightly on the wrong side of the surface. Check if we're close
593 // enough using fA precise distance calculation.
594 //
595 G4ThreeVector u = Distance(p);
596 if (fSqrDist <= kCarTolerance*kCarTolerance)
597 {
598 //
599 // We're very close. Therefore return fA small negative number
600 // to pretend we intersect.
601 //
602 // distance = -0.5*kCarTolerance
603 distance = 0.0;
604 normal = fSurfaceNormal;
605 return true;
606 }
607 else
608 {
609 //
610 // We're close to the surface containing the triangle, but sufficiently
611 // far from the triangle, and on the wrong side compared to the directions
612 // of the surface normal and v. There is no intersection.
613 //
614 distance = kInfinity;
615 distFromSurface = kInfinity;
616 normal.set(0,0,0);
617 return false;
618 }
619 }
620 if (w < dirTolerance && w > -dirTolerance)
621 {
622 //
623 // The ray is within the plane of the triangle. Project the problem into 2D
624 // in the plane of the triangle. First try to create orthogonal unit vectors
625 // mu and nu, where mu is fE1/|fE1|. This is kinda like
626 // the original algorithm due to Rickard Holmberg, but with better
627 // mathematical justification than the original method ... however,
628 // beware Rickard's was less time-consuming.
629 //
630 // Note that vprime is not fA unit vector. We need to keep it unnormalised
631 // since the values of distance along vprime (s0 and s1) for intersection
632 // with the triangle will be used to determine if we cut the plane at the
633 // same time.
634 //
635 G4ThreeVector mu = fE1.unit();
636 G4ThreeVector nu = fSurfaceNormal.cross(mu);
637 G4TwoVector pprime(p.dot(mu), p.dot(nu));
638 G4TwoVector vprime(v.dot(mu), v.dot(nu));
639 G4TwoVector P0prime(p0.dot(mu), p0.dot(nu));
640 G4TwoVector E0prime(fE1.mag(), 0.0);
641 G4TwoVector E1prime(fE2.dot(mu), fE2.dot(nu));
642 G4TwoVector loc[2];
644 vprime, P0prime, E0prime, E1prime, loc))
645 {
646 //
647 // There is an intersection between the line and triangle in 2D.
648 // Now check which part of the line intersects with the plane
649 // containing the triangle in 3D.
650 //
651 G4double vprimemag = vprime.mag();
652 G4double s0 = (loc[0] - pprime).mag()/vprimemag;
653 G4double s1 = (loc[1] - pprime).mag()/vprimemag;
654 G4double normDist0 = fSurfaceNormal.dot(s0*v) - distFromSurface;
655 G4double normDist1 = fSurfaceNormal.dot(s1*v) - distFromSurface;
656
657 if ((normDist0 < 0.0 && normDist1 < 0.0)
658 || (normDist0 > 0.0 && normDist1 > 0.0)
659 || (normDist0 == 0.0 && normDist1 == 0.0) )
660 {
661 distance = kInfinity;
662 distFromSurface = kInfinity;
663 normal.set(0,0,0);
664 return false;
665 }
666 else
667 {
668 G4double dnormDist = normDist1 - normDist0;
669 if (fabs(dnormDist) < DBL_EPSILON)
670 {
671 distance = s0;
672 normal = fSurfaceNormal;
673 if (!outgoing) distFromSurface = -distFromSurface;
674 return true;
675 }
676 else
677 {
678 distance = s0 - normDist0*(s1-s0)/dnormDist;
679 normal = fSurfaceNormal;
680 if (!outgoing) distFromSurface = -distFromSurface;
681 return true;
682 }
683 }
684 }
685 else
686 {
687 distance = kInfinity;
688 distFromSurface = kInfinity;
689 normal.set(0,0,0);
690 return false;
691 }
692 }
693 //
694 //
695 // Use conventional algorithm to determine the whether there is an
696 // intersection. This involves determining the point of intersection of the
697 // line with the plane containing the triangle, and then calculating if the
698 // point is within the triangle.
699 //
700 distance = distFromSurface / w;
701 G4ThreeVector pp = p + v*distance;
702 G4ThreeVector DD = p0 - pp;
703 G4double d = fE1.dot(DD);
704 G4double e = fE2.dot(DD);
705 G4double ss = fB*e - fC*d;
706 G4double t = fB*d - fA*e;
707
708 G4double sTolerance = (fabs(fB)+ fabs(fC) + fabs(d) + fabs(e))*kCarTolerance;
709 G4double tTolerance = (fabs(fA)+ fabs(fB) + fabs(d) + fabs(e))*kCarTolerance;
710 G4double detTolerance = (fabs(fA)+ fabs(fC) + 2*fabs(fB) )*kCarTolerance;
711
712 //if (ss < 0.0 || t < 0.0 || ss+t > fDet)
713 if (ss < -sTolerance || t < -tTolerance || ( ss+t - fDet ) > detTolerance)
714 {
715 //
716 // The intersection is outside of the triangle.
717 //
718 distance = distFromSurface = kInfinity;
719 normal.set(0,0,0);
720 return false;
721 }
722 else
723 {
724 //
725 // There is an intersection. Now we only need to set the surface normal.
726 //
727 normal = fSurfaceNormal;
728 if (!outgoing) distFromSurface = -distFromSurface;
729 return true;
730 }
731}
732
733////////////////////////////////////////////////////////////////////////
734//
735// GetPointOnFace
736//
737// Auxiliary method for get fA random point on surface
738//
740{
741 G4double alpha = G4RandFlat::shoot(0., 1.);
742 G4double beta = G4RandFlat::shoot(0., 1.);
743 G4double lambda1 = alpha*beta;
744 G4double lambda0 = alpha-lambda1;
745
746 return GetVertex(0) + lambda0*fE1 + lambda1*fE2;
747}
748
749////////////////////////////////////////////////////////////////////////
750//
751// GetArea
752//
753// Auxiliary method for returning the surface fArea
754//
756{
757 return fArea;
758}
759
760////////////////////////////////////////////////////////////////////////
761//
763{
764 return "G4TriangularFacet";
765}
766
767////////////////////////////////////////////////////////////////////////
768//
770{
771 return fSurfaceNormal;
772}
773
774////////////////////////////////////////////////////////////////////////
775//
777{
778 fSurfaceNormal = normal;
779}
@ JustWarning
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
G4FacetVertexType
Definition: G4VFacet.hh:56
@ ABSOLUTE
Definition: G4VFacet.hh:56
double mag() const
Hep3Vector unit() const
double mag2() const
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
double mag() const
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])
void SetSurfaceNormal(G4ThreeVector normal)
void SetVertex(G4int i, const G4ThreeVector &val)
G4ThreeVector GetPointOnFace() const
void SetVertices(std::vector< G4ThreeVector > *v)
G4bool Intersect(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool outgoing, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal)
G4TriangularFacet & operator=(const G4TriangularFacet &right)
G4TriangularFacet * GetFlippedFacet()
G4GeometryType GetEntityType() const
G4ThreeVector Distance(const G4ThreeVector &p)
G4ThreeVector GetVertex(G4int i) const
G4ThreeVector GetSurfaceNormal() const
G4double Extent(const G4ThreeVector axis)
static const G4double kCarTolerance
Definition: G4VFacet.hh:102
static const G4double dirTolerance
Definition: G4VFacet.hh:101
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define DBL_EPSILON
Definition: templates.hh:87