GteIntrSegment3Triangle3.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector3.h>
11 #include <Mathematics/GteSegment.h>
13 #include <Mathematics/GteFIQuery.h>
14 #include <Mathematics/GteTIQuery.h>
15 
16 namespace gte
17 {
18 
19 template <typename Real>
20 class TIQuery<Real, Segment3<Real>, Triangle3<Real>>
21 {
22 public:
23  struct Result
24  {
25  bool intersect;
26  };
27 
28  Result operator()(Segment3<Real> const& segment,
29  Triangle3<Real> const& triangle);
30 };
31 
32 template <typename Real>
33 class FIQuery<Real, Segment3<Real>, Triangle3<Real>>
34 {
35 public:
36  struct Result
37  {
38  Result();
39 
40  bool intersect;
41  Real parameter;
42  Real triangleBary[3];
44  };
45 
46  Result operator()(Segment3<Real> const& segment,
47  Triangle3<Real> const& triangle);
48 };
49 
50 
51 template <typename Real>
54  Segment3<Real> const& segment, Triangle3<Real> const& triangle)
55 {
56  Result result;
57 
58  Vector3<Real> segOrigin, segDirection;
59  Real segExtent;
60  segment.GetCenteredForm(segOrigin, segDirection, segExtent);
61 
62  // Compute the offset origin, edges, and normal.
63  Vector3<Real> diff = segOrigin - triangle.v[0];
64  Vector3<Real> edge1 = triangle.v[1] - triangle.v[0];
65  Vector3<Real> edge2 = triangle.v[2] - triangle.v[0];
66  Vector3<Real> normal = Cross(edge1, edge2);
67 
68  // Solve Q + t*D = b1*E1 + b2*E2 (Q = diff, D = segment direction,
69  // E1 = edge1, E2 = edge2, N = Cross(E1,E2)) by
70  // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
71  // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
72  // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
73  Real DdN = Dot(segDirection, normal);
74  Real sign;
75  if (DdN > (Real)0)
76  {
77  sign = (Real)1;
78  }
79  else if (DdN < (Real)0)
80  {
81  sign = (Real)-1;
82  DdN = -DdN;
83  }
84  else
85  {
86  // Segment and triangle are parallel, call it a "no intersection"
87  // even if the segment does intersect.
88  result.intersect = false;
89  return result;
90  }
91 
92  Real DdQxE2 = sign*DotCross(segDirection, diff, edge2);
93  if (DdQxE2 >= (Real)0)
94  {
95  Real DdE1xQ = sign*DotCross(segDirection, edge1, diff);
96  if (DdE1xQ >= (Real)0)
97  {
98  if (DdQxE2 + DdE1xQ <= DdN)
99  {
100  // Line intersects triangle, check whether segment does.
101  Real QdN = -sign*Dot(diff, normal);
102  Real extDdN = segExtent*DdN;
103  if (-extDdN <= QdN && QdN <= extDdN)
104  {
105  // Segment intersects triangle.
106  result.intersect = true;
107  return result;
108  }
109  // else: |t| > extent, no intersection
110  }
111  // else: b1+b2 > 1, no intersection
112  }
113  // else: b2 < 0, no intersection
114  }
115  // else: b1 < 0, no intersection
116 
117  result.intersect = false;
118  return result;
119 }
120 
121 template <typename Real>
123  :
124  parameter((Real)0)
125 {
126  triangleBary[0] = (Real)0;
127  triangleBary[1] = (Real)0;
128  triangleBary[2] = (Real)0;
129 }
130 
131 template <typename Real>
134  Segment3<Real> const& segment, Triangle3<Real> const& triangle)
135 {
136  Result result;
137 
138  Vector3<Real> segOrigin, segDirection;
139  Real segExtent;
140  segment.GetCenteredForm(segOrigin, segDirection, segExtent);
141 
142  // Compute the offset origin, edges, and normal.
143  Vector3<Real> diff = segOrigin - triangle.v[0];
144  Vector3<Real> edge1 = triangle.v[1] - triangle.v[0];
145  Vector3<Real> edge2 = triangle.v[2] - triangle.v[0];
146  Vector3<Real> normal = Cross(edge1, edge2);
147 
148  // Solve Q + t*D = b1*E1 + b2*E2 (Q = diff, D = segment direction,
149  // E1 = edge1, E2 = edge2, N = Cross(E1,E2)) by
150  // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
151  // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
152  // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
153  Real DdN = Dot(segDirection, normal);
154  Real sign;
155  if (DdN > (Real)0)
156  {
157  sign = (Real)1;
158  }
159  else if (DdN < (Real)0)
160  {
161  sign = (Real)-1;
162  DdN = -DdN;
163  }
164  else
165  {
166  // Segment and triangle are parallel, call it a "no intersection"
167  // even if the segment does intersect.
168  result.intersect = false;
169  return result;
170  }
171 
172  Real DdQxE2 = sign*DotCross(segDirection, diff, edge2);
173  if (DdQxE2 >= (Real)0)
174  {
175  Real DdE1xQ = sign*DotCross(segDirection, edge1, diff);
176  if (DdE1xQ >= (Real)0)
177  {
178  if (DdQxE2 + DdE1xQ <= DdN)
179  {
180  // Line intersects triangle, check whether segment does.
181  Real QdN = -sign*Dot(diff, normal);
182  Real extDdN = segExtent*DdN;
183  if (-extDdN <= QdN && QdN <= extDdN)
184  {
185  // Segment intersects triangle.
186  result.intersect = true;
187  Real inv = ((Real)1) / DdN;
188  result.parameter = QdN*inv;
189  result.triangleBary[1] = DdQxE2*inv;
190  result.triangleBary[2] = DdE1xQ*inv;
191  result.triangleBary[0] = (Real)1 - result.triangleBary[1]
192  - result.triangleBary[2];
193  result.point = segOrigin +
194  result.parameter * segDirection;
195  return result;
196  }
197  // else: |t| > extent, no intersection
198  }
199  // else: b1+b2 > 1, no intersection
200  }
201  // else: b2 < 0, no intersection
202  }
203  // else: b1 < 0, no intersection
204 
205  result.intersect = false;
206  return result;
207 }
208 
209 
210 }
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Real DotCross(Vector< N, Real > const &v0, Vector< N, Real > const &v1, Vector< N, Real > const &v2)
Definition: GteVector3.h:140
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
GLuint64EXT * result
Definition: glext.h:10003


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00