GteIntrLine3Cone3.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.1 (2016/08/20)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector3.h>
11 #include <Mathematics/GteCone.h>
12 #include <Mathematics/GteLine.h>
14 
15 // The queries consider the cone to be single sided and solid.
16 
17 namespace gte
18 {
19 
20 template <typename Real>
21 class FIQuery<Real, Line3<Real>, Cone3<Real>>
22 {
23 public:
24  struct Result
25  {
26  // Default construction. Set 'intersect' to false, 'type' to 0,
27  // 'parameter' to (0,0), and 'point' to (veczero,veczero).
28  Result();
29 
30  bool intersect;
31 
32  // Because the intersection of line and cone with infinite height
33  // h > 0 can be a ray or a line, we use a 'type' value that allows
34  // you to decide how to interpret the parameter[] and point[] values.
35  // type intersect valid data
36  // 0 none none
37  // 1 point parameter[0] = parameter[1], finite
38  // point[0] = point[1]
39  // 2 segment parameter[0] < parameter[1], finite
40  // point[0,1] valid
41  // 3 ray parameter[0] finite, parameter[1] maxReal
42  // point[0] = rayOrigin, point[1] = lineDirection
43  // 4 ray parameter[0] -maxReal, parameter[1] finite
44  // point[0] = rayOrigin, point[1] = -lineDirection
45  // 5 line parameter[0] -maxReal, parameter[1] maxReal,
46  // point[0] = lineOrigin, point[1] = lineDirection
47  // If the cone height h is finite, only types 0, 1, or 2 can occur.
48  int type;
49  std::array<Real, 2> parameter; // Relative to incoming line.
50  std::array<Vector3<Real>, 2> point;
51  };
52 
53  Result operator()(Line3<Real> const& line, Cone3<Real> const& cone);
54 
55 protected:
56  void DoQuery(Vector3<Real> const& lineOrigin,
57  Vector3<Real> const& lineDirection, Cone3<Real> const& cone,
58  Result& result);
59 };
60 
61 
62 template <typename Real>
64  :
65  intersect(false),
66  type(0)
67 {
68  parameter.fill((Real)0);
69  point.fill({ (Real)0, (Real)0, (Real)0 });
70 }
71 
72 template <typename Real>
73 typename FIQuery<Real, Line3<Real>, Cone3<Real>>::Result
75  Cone3<Real> const& cone)
76 {
77  Result result;
78  DoQuery(line.origin, line.direction, cone, result);
79  switch (result.type)
80  {
81  case 1: // point
82  result.point[0] = line.origin + result.parameter[0] * line.direction;
83  result.point[1] = result.point[0];
84  break;
85  case 2: // segment
86  result.point[0] = line.origin + result.parameter[0] * line.direction;
87  result.point[1] = line.origin + result.parameter[1] * line.direction;
88  break;
89  case 3: // ray
90  result.point[0] = line.origin + result.parameter[0] * line.direction;
91  result.point[1] = line.direction;
92  break;
93  case 4: // ray
94  result.point[0] = line.origin + result.parameter[1] * line.direction;
95  result.point[1] = -line.direction;
96  break;
97  case 5: // line
98  result.point[0] = line.origin;
99  result.point[1] = line.direction;
100  break;
101  default: // no intersection
102  break;
103  }
104  return result;
105 }
106 
107 template <typename Real>
109  Vector3<Real> const& lineOrigin, Vector3<Real> const& lineDirection,
110  Cone3<Real> const& cone, Result& result)
111 {
112  // The cone has vertex V, unit-length axis direction D, angle theta in
113  // (0,pi/2), and height h in (0,+infinity). The line is P + t*U, where U
114  // is a unit-length direction vector. Define g = cos(theta). The cone
115  // is represented by
116  // (X-V)^T * (D*D^T - g^2*I) * (X-V) = 0, 0 <= Dot(D,X-V) <= h
117  // The first equation defines a double-sided cone. The first inequality
118  // in the second equation limits this to a single-sided cone containing
119  // the ray V + s*D with s >= 0. We will call this the 'positive cone'.
120  // The single-sided cone containing ray V + s * t with s <= 0 is called
121  // the 'negative cone'. The double-sided cone is the union of the
122  // positive cone and negative cone. The second inequality in the second
123  // equation limits the single-sided cone to the region bounded by the
124  // height. Setting X(t) = P + t*U, the equations are
125  // c2*t^2 + 2*c1*t + c0 = 0, 0 <= Dot(D,U)*t + Dot(D,P-V) <= h
126  // where
127  // c2 = Dot(D,U)^2 - g^2
128  // c1 = Dot(D,U)*Dot(D,P-V) - g^2*Dot(U,P-V)
129  // c0 = Dot(D,P-V)^2 - g^2*Dot(P-V,P-V)
130  // The following code computes the t-interval that satisfies the quadratic
131  // equation subject to the linear inequality constraints.
132 
133  Vector3<Real> PmV = lineOrigin - cone.ray.origin;
134  Real DdU = Dot(cone.ray.direction, lineDirection);
135  Real DdPmV = Dot(cone.ray.direction, PmV);
136  Real UdPmV = Dot(lineDirection, PmV);
137  Real PmVdPmV = Dot(PmV, PmV);
138  Real cosAngleSqr = cone.cosAngle * cone.cosAngle;
139  Real c2 = DdU * DdU - cosAngleSqr;
140  Real c1 = DdU * DdPmV - cosAngleSqr * UdPmV;
141  Real c0 = DdPmV * DdPmV - cosAngleSqr * PmVdPmV;
142  Real t;
143 
144  if (c2 != (Real)0)
145  {
146  Real discr = c1 * c1 - c0 * c2;
147  if (discr < (Real)0)
148  {
149  // The quadratic has no real-valued roots. The line does not
150  // intersect the double-sided cone.
151  result.intersect = false;
152  result.type = 0;
153  return;
154  }
155  else if (discr > (Real)0)
156  {
157  // The quadratic has two distinct real-valued roots. However, one
158  // or both of them might intersect the negative cone. We are
159  // interested only in those intersections with the positive cone.
160  Real root = sqrt(discr);
161  Real invC2 = ((Real)1) / c2;
162  int numParameters = 0;
163 
164  t = (-c1 - root) * invC2;
165  if (DdU * t + DdPmV >= (Real)0)
166  {
167  result.parameter[numParameters++] = t;
168  }
169 
170  t = (-c1 + root) * invC2;
171  if (DdU * t + DdPmV >= (Real)0)
172  {
173  result.parameter[numParameters++] = t;
174  }
175 
176  if (numParameters == 2)
177  {
178  // The line intersects the positive cone in two distinct
179  // points.
180  result.intersect = true;
181  result.type = 2;
182  if (result.parameter[0] > result.parameter[1])
183  {
184  std::swap(result.parameter[0], result.parameter[1]);
185  }
186  }
187  else if (numParameters == 1)
188  {
189  // The line intersects the positive cone in a single point and
190  // the negative cone in a single point. We report only the
191  // intersection with the positive cone.
192  result.intersect = true;
193  if (DdU > (Real)0)
194  {
195  result.type = 3;
196  result.parameter[1] = std::numeric_limits<Real>::max();
197  }
198  else
199  {
200  result.type = 4;
201  result.parameter[1] = result.parameter[0];
202  result.parameter[0] = -std::numeric_limits<Real>::max();
203 
204  }
205  }
206  else
207  {
208  // The line intersects the negative cone in two distinct
209  // points, but we are interested only in the intersections
210  // with the positive cone.
211  result.intersect = false;
212  result.type = 0;
213  return;
214  }
215  }
216  else // discr == 0
217  {
218  // One repeated real root; the line is tangent to the double-sided
219  // cone at a single point. Report only the point if it is on the
220  // positive cone.
221  t = -c1 / c2;
222  if (DdU * t + DdPmV >= (Real)0)
223  {
224  result.intersect = true;
225  result.type = 1;
226  result.parameter[0] = t;
227  result.parameter[1] = t;
228  }
229  else
230  {
231  result.intersect = false;
232  result.type = 0;
233  return;
234  }
235  }
236  }
237  else if (c1 != (Real)0)
238  {
239  // c2 = 0, c1 != 0; U is a direction vector on the cone boundary
240  t = -((Real)0.5)*c0 / c1;
241  if (DdU * t + DdPmV >= (Real)0)
242  {
243  // The line intersects the positive cone and the ray of
244  // intersection is interior to the positive cone.
245  result.intersect = true;
246  if (DdU > (Real)0)
247  {
248  result.type = 3;
249  result.parameter[0] = t;
250  result.parameter[1] = std::numeric_limits<Real>::max();
251  }
252  else
253  {
254  result.type = 4;
255  result.parameter[0] = -std::numeric_limits<Real>::max();
256  result.parameter[1] = t;
257  }
258  }
259  else
260  {
261  // The line intersects the negative cone and the ray of
262  // intersection is interior to the positive cone.
263  result.intersect = false;
264  result.type = 0;
265  return;
266  }
267  }
268  else if (c0 != (Real)0)
269  {
270  // c2 = c1 = 0, c0 != 0. Cross(D,U) is perpendicular to Cross(P-V,U)
271  result.intersect = false;
272  result.type = 0;
273  return;
274  }
275  else
276  {
277  // c2 = c1 = c0 = 0; the line is on the cone boundary.
278  result.intersect = true;
279  result.type = 5;
280  result.parameter[0] = -std::numeric_limits<Real>::max();
281  result.parameter[1] = +std::numeric_limits<Real>::max();
282  }
283 
284  if (cone.height < std::numeric_limits<Real>::max())
285  {
286  if (DdU != (Real)0)
287  {
288  // Clamp the intersection to the height of the cone.
289  Real invDdU = ((Real)1) / DdU;
290  std::array<Real, 2> hInterval;
291  if (DdU >(Real)0)
292  {
293  hInterval[0] = -DdPmV * invDdU;
294  hInterval[1] = (cone.height - DdPmV) * invDdU;
295  }
296  else // (DdU < (Real)0)
297  {
298  hInterval[0] = (cone.height - DdPmV) * invDdU;
299  hInterval[1] = -DdPmV * invDdU;
300  }
301 
302  FIIntervalInterval<Real> iiQuery;
303  auto iiResult = iiQuery(result.parameter, hInterval);
304  result.intersect = (iiResult.numIntersections > 0);
305  result.type = iiResult.numIntersections;
306  result.parameter = iiResult.overlap;
307  }
308  else if (result.intersect)
309  {
310  if (DdPmV > cone.height)
311  {
312  result.intersect = false;
313  result.type = 0;
314  }
315  }
316  }
317 }
318 
319 
320 }
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
Real height
Definition: GteCone.h:59
Ray< N, Real > ray
Definition: GteCone.h:57
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble t
Definition: glext.h:239
Real cosAngle
Definition: GteCone.h:64
GLuint64EXT * result
Definition: glext.h:10003
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:103


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