Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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// G4TriangularFacet implementation
27//
28// 31.10.2004, P R Truscott, QinetiQ Ltd, UK - Created.
29// 01.08.2007, P R Truscott, QinetiQ Ltd, UK
30// Significant modification to correct for errors and enhance
31// based on patches/observations kindly provided by Rickard
32// Holmberg.
33// 12.10.2012, M Gayer, CERN
34// New implementation reducing memory requirements by 50%,
35// and considerable CPU speedup together with the new
36// implementation of G4TessellatedSolid.
37// 23.02.2016, E Tcherniaev, CERN
38// Improved test to detect degenerate (too small or
39// too narrow) triangles.
40// --------------------------------------------------------------------
41
42#include "G4TriangularFacet.hh"
43
44#include "Randomize.hh"
46
47using namespace std;
48
49///////////////////////////////////////////////////////////////////////////////
50//
51// Definition of triangular facet using absolute vectors to fVertices.
52// From this for first vector is retained to define the facet location and
53// two relative vectors (E0 and E1) define the sides and orientation of
54// the outward surface normal.
55//
57 const G4ThreeVector& vt1,
58 const G4ThreeVector& vt2,
59 G4FacetVertexType vertexType)
60 : G4VFacet()
61{
62 fVertices = new vector<G4ThreeVector>(3);
63
64 SetVertex(0, vt0);
65 if (vertexType == ABSOLUTE)
66 {
67 SetVertex(1, vt1);
68 SetVertex(2, vt2);
69 fE1 = vt1 - vt0;
70 fE2 = vt2 - vt0;
71 }
72 else
73 {
74 SetVertex(1, vt0 + vt1);
75 SetVertex(2, vt0 + vt2);
76 fE1 = vt1;
77 fE2 = vt2;
78 }
79
80 G4ThreeVector E1xE2 = fE1.cross(fE2);
81 fArea = 0.5 * E1xE2.mag();
82 for (G4int i = 0; i < 3; ++i) fIndices[i] = -1;
83
84 fIsDefined = true;
85 G4double delta = kCarTolerance; // Set tolerance for checking
86
87 // Check length of edges
88 //
89 G4double leng1 = fE1.mag();
90 G4double leng2 = (fE2-fE1).mag();
91 G4double leng3 = fE2.mag();
92 if (leng1 <= delta || leng2 <= delta || leng3 <= delta)
93 {
94 fIsDefined = false;
95 }
96
97 // Check min height of triangle
98 //
99 if (fIsDefined)
100 {
101 if (2.*fArea/std::max(std::max(leng1,leng2),leng3) <= delta)
102 {
103 fIsDefined = false;
104 }
105 }
106
107 // Define facet
108 //
109 if (!fIsDefined)
110 {
111 ostringstream message;
112 message << "Facet is too small or too narrow." << G4endl
113 << "Triangle area = " << fArea << G4endl
114 << "P0 = " << GetVertex(0) << G4endl
115 << "P1 = " << GetVertex(1) << G4endl
116 << "P2 = " << GetVertex(2) << G4endl
117 << "Side1 length (P0->P1) = " << leng1 << G4endl
118 << "Side2 length (P1->P2) = " << leng2 << G4endl
119 << "Side3 length (P2->P0) = " << leng3;
120 G4Exception("G4TriangularFacet::G4TriangularFacet()",
121 "GeomSolids1001", JustWarning, message);
122 fSurfaceNormal.set(0,0,0);
123 fA = fB = fC = 0.0;
124 fDet = 0.0;
125 fCircumcentre = vt0 + 0.5*fE1 + 0.5*fE2;
126 fArea = fRadius = 0.0;
127 }
128 else
129 {
130 fSurfaceNormal = E1xE2.unit();
131 fA = fE1.mag2();
132 fB = fE1.dot(fE2);
133 fC = fE2.mag2();
134 fDet = std::fabs(fA*fC - fB*fB);
135
136 fCircumcentre =
137 vt0 + (E1xE2.cross(fE1)*fC + fE2.cross(E1xE2)*fA) / (2.*E1xE2.mag2());
138 fRadius = (fCircumcentre - vt0).mag();
139 }
140}
141
142///////////////////////////////////////////////////////////////////////////////
143//
145 : fSqrDist(0.)
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) fIndices[i] = -1;
153 fIsDefined = false;
154 fSurfaceNormal.set(0,0,0);
155 fA = fB = fC = 0;
156 fE1 = zero;
157 fE2 = zero;
158 fDet = 0.0;
159 fArea = fRadius = 0.0;
160}
161
162///////////////////////////////////////////////////////////////////////////////
163//
165{
166 SetVertices(nullptr);
167}
168
169///////////////////////////////////////////////////////////////////////////////
170//
171void G4TriangularFacet::CopyFrom (const G4TriangularFacet& rhs)
172{
173 char *p = (char *) &rhs;
174 copy(p, p + sizeof(*this), (char *)this);
175
176 if (fIndices[0] < 0 && fVertices == nullptr)
177 {
178 fVertices = new vector<G4ThreeVector>(3);
179 for (G4int i = 0; i < 3; ++i) (*fVertices)[i] = (*rhs.fVertices)[i];
180 }
181}
182
183///////////////////////////////////////////////////////////////////////////////
184//
185void G4TriangularFacet::MoveFrom (G4TriangularFacet& rhs)
186{
187 fSurfaceNormal = move(rhs.fSurfaceNormal);
188 fArea = move(rhs.fArea);
189 fCircumcentre = move(rhs.fCircumcentre);
190 fRadius = move(rhs.fRadius);
191 fIndices = move(rhs.fIndices);
192 fA = move(rhs.fA); fB = move(rhs.fB); fC = move(rhs.fC);
193 fDet = move(rhs.fDet);
194 fSqrDist = move(rhs.fSqrDist);
195 fE1 = move(rhs.fE1); fE2 = move(rhs.fE2);
196 fIsDefined = move(rhs.fIsDefined);
197 fVertices = move(rhs.fVertices);
198 rhs.fVertices = nullptr;
199}
200
201///////////////////////////////////////////////////////////////////////////////
202//
204 : G4VFacet(rhs)
205{
206 CopyFrom(rhs);
207}
208
209///////////////////////////////////////////////////////////////////////////////
210//
212 : G4VFacet(rhs)
213{
214 MoveFrom(rhs);
215}
216
217///////////////////////////////////////////////////////////////////////////////
218//
221{
222 SetVertices(nullptr);
223
224 if (this != &rhs)
225 {
226 delete fVertices;
227 CopyFrom(rhs);
228 }
229
230 return *this;
231}
232
233///////////////////////////////////////////////////////////////////////////////
234//
237{
238 SetVertices(nullptr);
239
240 if (this != &rhs)
241 {
242 delete fVertices;
243 MoveFrom(rhs);
244 }
245
246 return *this;
247}
248
249///////////////////////////////////////////////////////////////////////////////
250//
251// GetClone
252//
253// Simple member function to generate fA duplicate of the triangular facet.
254//
256{
259 return fc;
260}
261
262///////////////////////////////////////////////////////////////////////////////
263//
264// GetFlippedFacet
265//
266// Member function to generate an identical facet, but with the normal vector
267// pointing at 180 degrees.
268//
270{
271 G4TriangularFacet* flipped =
273 return flipped;
274}
275
276///////////////////////////////////////////////////////////////////////////////
277//
278// Distance (G4ThreeVector)
279//
280// Determines the vector between p and the closest point on the facet to p.
281// This is based on the algorithm published in "Geometric Tools for Computer
282// Graphics," Philip J Scheider and David H Eberly, Elsevier Science (USA),
283// 2003. at the time of writing, the algorithm is also available in fA
284// technical note "Distance between point and triangle in 3D," by David Eberly
285// at http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf
286//
287// The by-product is the square-distance fSqrDist, which is retained
288// in case needed by the other "Distance" member functions.
289//
291{
292 G4ThreeVector D = GetVertex(0) - p;
293 G4double d = fE1.dot(D);
294 G4double e = fE2.dot(D);
295 G4double f = D.mag2();
296 G4double q = fB*e - fC*d;
297 G4double t = fB*d - fA*e;
298 fSqrDist = 0.;
299
300 if (q+t <= fDet)
301 {
302 if (q < 0.0)
303 {
304 if (t < 0.0)
305 {
306 //
307 // We are in region 4.
308 //
309 if (d < 0.0)
310 {
311 t = 0.0;
312 if (-d >= fA) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
313 else {q = -d/fA; fSqrDist = d*q + f;}
314 }
315 else
316 {
317 q = 0.0;
318 if (e >= 0.0) {t = 0.0; fSqrDist = f;}
319 else if (-e >= fC) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
320 else {t = -e/fC; fSqrDist = e*t + f;}
321 }
322 }
323 else
324 {
325 //
326 // We are in region 3.
327 //
328 q = 0.0;
329 if (e >= 0.0) {t = 0.0; fSqrDist = f;}
330 else if (-e >= fC) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
331 else {t = -e/fC; fSqrDist = e*t + f;}
332 }
333 }
334 else if (t < 0.0)
335 {
336 //
337 // We are in region 5.
338 //
339 t = 0.0;
340 if (d >= 0.0) {q = 0.0; fSqrDist = f;}
341 else if (-d >= fA) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
342 else {q = -d/fA; fSqrDist = d*q + f;}
343 }
344 else
345 {
346 //
347 // We are in region 0.
348 //
349 q = q / fDet;
350 t = t / fDet;
351 fSqrDist = q*(fA*q + fB*t + 2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
352 }
353 }
354 else
355 {
356 if (q < 0.0)
357 {
358 //
359 // We are in region 2.
360 //
361 G4double tmp0 = fB + d;
362 G4double tmp1 = fC + e;
363 if (tmp1 > tmp0)
364 {
365 G4double numer = tmp1 - tmp0;
366 G4double denom = fA - 2.0*fB + fC;
367 if (numer >= denom) {q = 1.0; t = 0.0; fSqrDist = fA + 2.0*d + f;}
368 else
369 {
370 q = numer/denom;
371 t = 1.0 - q;
372 fSqrDist = q*(fA*q + fB*t +2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
373 }
374 }
375 else
376 {
377 q = 0.0;
378 if (tmp1 <= 0.0) {t = 1.0; fSqrDist = fC + 2.0*e + f;}
379 else if (e >= 0.0) {t = 0.0; fSqrDist = f;}
380 else {t = -e/fC; fSqrDist = e*t + f;}
381 }
382 }
383 else if (t < 0.0)
384 {
385 //
386 // We are in region 6.
387 //
388 G4double tmp0 = fB + e;
389 G4double tmp1 = fA + d;
390 if (tmp1 > tmp0)
391 {
392 G4double numer = tmp1 - tmp0;
393 G4double denom = fA - 2.0*fB + fC;
394 if (numer >= denom) {t = 1.0; q = 0.0; fSqrDist = fC + 2.0*e + f;}
395 else
396 {
397 t = numer/denom;
398 q = 1.0 - t;
399 fSqrDist = q*(fA*q + fB*t +2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
400 }
401 }
402 else
403 {
404 t = 0.0;
405 if (tmp1 <= 0.0) {q = 1.0; fSqrDist = fA + 2.0*d + f;}
406 else if (d >= 0.0) {q = 0.0; fSqrDist = f;}
407 else {q = -d/fA; fSqrDist = d*q + f;}
408 }
409 }
410 else
411 //
412 // We are in region 1.
413 //
414 {
415 G4double numer = fC + e - fB - d;
416 if (numer <= 0.0)
417 {
418 q = 0.0;
419 t = 1.0;
420 fSqrDist = fC + 2.0*e + f;
421 }
422 else
423 {
424 G4double denom = fA - 2.0*fB + fC;
425 if (numer >= denom) {q = 1.0; t = 0.0; fSqrDist = fA + 2.0*d + f;}
426 else
427 {
428 q = numer/denom;
429 t = 1.0 - q;
430 fSqrDist = q*(fA*q + fB*t + 2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
431 }
432 }
433 }
434 }
435 //
436 //
437 // Do fA check for rounding errors in the distance-squared. It appears that
438 // the conventional methods for calculating fSqrDist breaks down when very
439 // near to or at the surface (as required by transport).
440 // We'll therefore also use the magnitude-squared of the vector displacement.
441 // (Note that I've also tried to get around this problem by using the
442 // existing equations for
443 //
444 // fSqrDist = function(fA,fB,fC,d,q,t)
445 //
446 // and use fA more accurate addition process which minimises errors and
447 // breakdown of cummutitivity [where (A+B)+C != A+(B+C)] but this still
448 // doesn't work.
449 // Calculation from u = D + q*fE1 + t*fE2 is less efficient, but appears
450 // more robust.
451 //
452 if (fSqrDist < 0.0) fSqrDist = 0.;
453 G4ThreeVector u = D + q*fE1 + t*fE2;
454 G4double u2 = u.mag2();
455 //
456 // The following (part of the roundoff error check) is from Oliver Merle'q
457 // updates.
458 //
459 if (fSqrDist > u2) fSqrDist = u2;
460
461 return u;
462}
463
464///////////////////////////////////////////////////////////////////////////////
465//
466// Distance (G4ThreeVector, G4double)
467//
468// Determines the closest distance between point p and the facet. This makes
469// use of G4ThreeVector G4TriangularFacet::Distance, which stores the
470// square of the distance in variable fSqrDist. If approximate methods show
471// the distance is to be greater than minDist, then forget about further
472// computation and return fA very large number.
473//
475 G4double minDist)
476{
477 //
478 // Start with quicky test to determine if the surface of the sphere enclosing
479 // the triangle is any closer to p than minDist. If not, then don't bother
480 // about more accurate test.
481 //
482 G4double dist = kInfinity;
483 if ((p-fCircumcentre).mag()-fRadius < minDist)
484 {
485 //
486 // It's possible that the triangle is closer than minDist,
487 // so do more accurate assessment.
488 //
489 dist = Distance(p).mag();
490 }
491 return dist;
492}
493
494///////////////////////////////////////////////////////////////////////////////
495//
496// Distance (G4ThreeVector, G4double, G4bool)
497//
498// Determine the distance to point p. kInfinity is returned if either:
499// (1) outgoing is TRUE and the dot product of the normal vector to the facet
500// and the displacement vector from p to the triangle is negative.
501// (2) outgoing is FALSE and the dot product of the normal vector to the facet
502// and the displacement vector from p to the triangle is positive.
503// If approximate methods show the distance is to be greater than minDist, then
504// forget about further computation and return fA very large number.
505//
506// This method has been heavily modified thanks to the valuable comments and
507// corrections of Rickard Holmberg.
508//
510 G4double minDist,
511 const G4bool outgoing)
512{
513 //
514 // Start with quicky test to determine if the surface of the sphere enclosing
515 // the triangle is any closer to p than minDist. If not, then don't bother
516 // about more accurate test.
517 //
518 G4double dist = kInfinity;
519 if ((p-fCircumcentre).mag()-fRadius < minDist)
520 {
521 //
522 // It's possible that the triangle is closer than minDist,
523 // so do more accurate assessment.
524 //
525 G4ThreeVector v = Distance(p);
526 G4double dist1 = sqrt(fSqrDist);
527 G4double dir = v.dot(fSurfaceNormal);
528 G4bool wrongSide = (dir > 0.0 && !outgoing) || (dir < 0.0 && outgoing);
529 if (dist1 <= kCarTolerance)
530 {
531 //
532 // Point p is very close to triangle. Check if it's on the wrong side,
533 // in which case return distance of 0.0 otherwise .
534 //
535 if (wrongSide) dist = 0.0;
536 else dist = dist1;
537 }
538 else if (!wrongSide) dist = dist1;
539 }
540 return dist;
541}
542
543///////////////////////////////////////////////////////////////////////////////
544//
545// Extent
546//
547// Calculates the furthest the triangle extends in fA particular direction
548// defined by the vector axis.
549//
551{
552 G4double ss = GetVertex(0).dot(axis);
553 G4double sp = GetVertex(1).dot(axis);
554 if (sp > ss) ss = sp;
555 sp = GetVertex(2).dot(axis);
556 if (sp > ss) ss = sp;
557 return ss;
558}
559
560///////////////////////////////////////////////////////////////////////////////
561//
562// Intersect
563//
564// Member function to find the next intersection when going from p in the
565// direction of v. If:
566// (1) "outgoing" is TRUE, only consider the face if we are going out through
567// the face.
568// (2) "outgoing" is FALSE, only consider the face if we are going in through
569// the face.
570// Member functions returns TRUE if there is an intersection, FALSE otherwise.
571// Sets the distance (distance along w), distFromSurface (orthogonal distance)
572// and normal.
573//
574// Also considers intersections that happen with negative distance for small
575// distances of distFromSurface = 0.5*kCarTolerance in the wrong direction.
576// This is to detect kSurface without doing fA full Inside(p) in
577// G4TessellatedSolid::Distance(p,v) calculation.
578//
579// This member function is thanks the valuable work of Rickard Holmberg. PT.
580// However, "gotos" are the Work of the Devil have been exorcised with
581// extreme prejudice!!
582//
583// IMPORTANT NOTE: These calculations are predicated on v being fA unit
584// vector. If G4TessellatedSolid or other classes call this member function
585// with |v| != 1 then there will be errors.
586//
588 const G4ThreeVector& v,
589 G4bool outgoing,
590 G4double& distance,
591 G4double& distFromSurface,
592 G4ThreeVector& normal)
593{
594 //
595 // Check whether the direction of the facet is consistent with the vector v
596 // and the need to be outgoing or ingoing. If inconsistent, disregard and
597 // return false.
598 //
599 G4double w = v.dot(fSurfaceNormal);
600 if ((outgoing && w < -dirTolerance) || (!outgoing && w > dirTolerance))
601 {
602 distance = kInfinity;
603 distFromSurface = kInfinity;
604 normal.set(0,0,0);
605 return false;
606 }
607 //
608 // Calculate the orthogonal distance from p to the surface containing the
609 // triangle. Then determine if we're on the right or wrong side of the
610 // surface (at fA distance greater than kCarTolerance to be consistent with
611 // "outgoing".
612 //
613 const G4ThreeVector& p0 = GetVertex(0);
614 G4ThreeVector D = p0 - p;
615 distFromSurface = D.dot(fSurfaceNormal);
616 G4bool wrongSide = (outgoing && distFromSurface < -0.5*kCarTolerance) ||
617 (!outgoing && distFromSurface > 0.5*kCarTolerance);
618
619 if (wrongSide)
620 {
621 distance = kInfinity;
622 distFromSurface = kInfinity;
623 normal.set(0,0,0);
624 return false;
625 }
626
627 wrongSide = (outgoing && distFromSurface < 0.0)
628 || (!outgoing && distFromSurface > 0.0);
629 if (wrongSide)
630 {
631 //
632 // We're slightly on the wrong side of the surface. Check if we're close
633 // enough using fA precise distance calculation.
634 //
635 G4ThreeVector u = Distance(p);
636 if (fSqrDist <= kCarTolerance*kCarTolerance)
637 {
638 //
639 // We're very close. Therefore return fA small negative number
640 // to pretend we intersect.
641 //
642 // distance = -0.5*kCarTolerance
643 distance = 0.0;
644 normal = fSurfaceNormal;
645 return true;
646 }
647 else
648 {
649 //
650 // We're close to the surface containing the triangle, but sufficiently
651 // far from the triangle, and on the wrong side compared to the directions
652 // of the surface normal and v. There is no intersection.
653 //
654 distance = kInfinity;
655 distFromSurface = kInfinity;
656 normal.set(0,0,0);
657 return false;
658 }
659 }
660 if (w < dirTolerance && w > -dirTolerance)
661 {
662 //
663 // The ray is within the plane of the triangle. Project the problem into 2D
664 // in the plane of the triangle. First try to create orthogonal unit vectors
665 // mu and nu, where mu is fE1/|fE1|. This is kinda like
666 // the original algorithm due to Rickard Holmberg, but with better
667 // mathematical justification than the original method ... however,
668 // beware Rickard's was less time-consuming.
669 //
670 // Note that vprime is not fA unit vector. We need to keep it unnormalised
671 // since the values of distance along vprime (s0 and s1) for intersection
672 // with the triangle will be used to determine if we cut the plane at the
673 // same time.
674 //
675 G4ThreeVector mu = fE1.unit();
676 G4ThreeVector nu = fSurfaceNormal.cross(mu);
677 G4TwoVector pprime(p.dot(mu), p.dot(nu));
678 G4TwoVector vprime(v.dot(mu), v.dot(nu));
679 G4TwoVector P0prime(p0.dot(mu), p0.dot(nu));
680 G4TwoVector E0prime(fE1.mag(), 0.0);
681 G4TwoVector E1prime(fE2.dot(mu), fE2.dot(nu));
682 G4TwoVector loc[2];
684 vprime, P0prime, E0prime, E1prime, loc))
685 {
686 //
687 // There is an intersection between the line and triangle in 2D.
688 // Now check which part of the line intersects with the plane
689 // containing the triangle in 3D.
690 //
691 G4double vprimemag = vprime.mag();
692 G4double s0 = (loc[0] - pprime).mag()/vprimemag;
693 G4double s1 = (loc[1] - pprime).mag()/vprimemag;
694 G4double normDist0 = fSurfaceNormal.dot(s0*v) - distFromSurface;
695 G4double normDist1 = fSurfaceNormal.dot(s1*v) - distFromSurface;
696
697 if ((normDist0 < 0.0 && normDist1 < 0.0)
698 || (normDist0 > 0.0 && normDist1 > 0.0)
699 || (normDist0 == 0.0 && normDist1 == 0.0) )
700 {
701 distance = kInfinity;
702 distFromSurface = kInfinity;
703 normal.set(0,0,0);
704 return false;
705 }
706 else
707 {
708 G4double dnormDist = normDist1 - normDist0;
709 if (fabs(dnormDist) < DBL_EPSILON)
710 {
711 distance = s0;
712 normal = fSurfaceNormal;
713 if (!outgoing) distFromSurface = -distFromSurface;
714 return true;
715 }
716 else
717 {
718 distance = s0 - normDist0*(s1-s0)/dnormDist;
719 normal = fSurfaceNormal;
720 if (!outgoing) distFromSurface = -distFromSurface;
721 return true;
722 }
723 }
724 }
725 else
726 {
727 distance = kInfinity;
728 distFromSurface = kInfinity;
729 normal.set(0,0,0);
730 return false;
731 }
732 }
733 //
734 //
735 // Use conventional algorithm to determine the whether there is an
736 // intersection. This involves determining the point of intersection of the
737 // line with the plane containing the triangle, and then calculating if the
738 // point is within the triangle.
739 //
740 distance = distFromSurface / w;
741 G4ThreeVector pp = p + v*distance;
742 G4ThreeVector DD = p0 - pp;
743 G4double d = fE1.dot(DD);
744 G4double e = fE2.dot(DD);
745 G4double ss = fB*e - fC*d;
746 G4double t = fB*d - fA*e;
747
748 G4double sTolerance = (fabs(fB)+ fabs(fC) + fabs(d) + fabs(e))*kCarTolerance;
749 G4double tTolerance = (fabs(fA)+ fabs(fB) + fabs(d) + fabs(e))*kCarTolerance;
750 G4double detTolerance = (fabs(fA)+ fabs(fC) + 2*fabs(fB) )*kCarTolerance;
751
752 //if (ss < 0.0 || t < 0.0 || ss+t > fDet)
753 if (ss < -sTolerance || t < -tTolerance || ( ss+t - fDet ) > detTolerance)
754 {
755 //
756 // The intersection is outside of the triangle.
757 //
758 distance = distFromSurface = kInfinity;
759 normal.set(0,0,0);
760 return false;
761 }
762 else
763 {
764 //
765 // There is an intersection. Now we only need to set the surface normal.
766 //
767 normal = fSurfaceNormal;
768 if (!outgoing) distFromSurface = -distFromSurface;
769 return true;
770 }
771}
772
773////////////////////////////////////////////////////////////////////////
774//
775// GetPointOnFace
776//
777// Auxiliary method, returns a uniform random point on the facet
778//
780{
783 if (u+v > 1.) { u = 1. - u; v = 1. - v; }
784 return GetVertex(0) + u*fE1 + v*fE2;
785}
786
787////////////////////////////////////////////////////////////////////////
788//
789// GetArea
790//
791// Auxiliary method for returning the surface fArea
792//
794{
795 return fArea;
796}
797
798////////////////////////////////////////////////////////////////////////
799//
801{
802 return "G4TriangularFacet";
803}
804
805////////////////////////////////////////////////////////////////////////
806//
808{
809 return fSurfaceNormal;
810}
811
812////////////////////////////////////////////////////////////////////////
813//
815{
816 fSurfaceNormal = normal;
817}
double D(double temp)
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4FacetVertexType
Definition: G4VFacet.hh:48
@ ABSOLUTE
Definition: G4VFacet.hh:48
#define G4endl
Definition: G4ios.hh:57
#define G4UniformRand()
Definition: Randomize.hh:52
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])
G4double GetArea() const
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 dirTolerance
Definition: G4VFacet.hh:92
G4double kCarTolerance
Definition: G4VFacet.hh:93
#define DBL_EPSILON
Definition: templates.hh:66