GteDistPoint3Frustum3.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 
12 
13 namespace gte
14 {
15 
16 template <typename Real>
17 class DCPQuery<Real, Vector3<Real>, Frustum3<Real>>
18 {
19 public:
20  struct Result
21  {
24  };
25 
26  Result operator()(Vector3<Real> const& point,
27  Frustum3<Real> const& frustum);
28 };
29 
30 
31 template <typename Real>
34  Vector3<Real> const& point, Frustum3<Real> const& frustum)
35 {
36  Result result;
37 
38  // Compute coordinates of point with respect to frustum coordinate system.
39  Vector3<Real> diff = point - frustum.origin;
40  Vector3<Real> test = {
41  Dot(diff, frustum.rVector),
42  Dot(diff, frustum.uVector),
43  Dot(diff, frustum.dVector) };
44 
45  // Perform calculations in octant with nonnegative R and U coordinates.
46  bool rSignChange;
47  if (test[0] < (Real)0)
48  {
49  rSignChange = true;
50  test[0] = -test[0];
51  }
52  else
53  {
54  rSignChange = false;
55  }
56 
57  bool uSignChange;
58  if (test[1] < (Real)0)
59  {
60  uSignChange = true;
61  test[1] = -test[1];
62  }
63  else
64  {
65  uSignChange = false;
66  }
67 
68  // Frustum derived parameters.
69  Real rmin = frustum.rBound;
70  Real rmax = frustum.GetDRatio()*rmin;
71  Real umin = frustum.uBound;
72  Real umax = frustum.GetDRatio()*umin;
73  Real dmin = frustum.dMin;
74  Real dmax = frustum.dMax;
75  Real rminSqr = rmin*rmin;
76  Real uminSqr = umin*umin;
77  Real dminSqr = dmin*dmin;
78  Real minRDDot = rminSqr + dminSqr;
79  Real minUDDot = uminSqr + dminSqr;
80  Real minRUDDot = rminSqr + minUDDot;
81  Real maxRDDot = frustum.GetDRatio()*minRDDot;
82  Real maxUDDot = frustum.GetDRatio()*minUDDot;
83  Real maxRUDDot = frustum.GetDRatio()*minRUDDot;
84 
85  // Algorithm computes closest point in all cases by determining in which
86  // Voronoi region of the vertices, edges, and faces of the frustum that
87  // the test point lives.
88  Vector3<Real> closest;
89  Real rDot, uDot, rdDot, udDot, rudDot, rEdgeDot, uEdgeDot, t;
90  if (test[2] >= dmax)
91  {
92  if (test[0] <= rmax)
93  {
94  if (test[1] <= umax)
95  {
96  // F-face
97  closest[0] = test[0];
98  closest[1] = test[1];
99  closest[2] = dmax;
100  }
101  else
102  {
103  // UF-edge
104  closest[0] = test[0];
105  closest[1] = umax;
106  closest[2] = dmax;
107  }
108  }
109  else
110  {
111  if (test[1] <= umax)
112  {
113  // LF-edge
114  closest[0] = rmax;
115  closest[1] = test[1];
116  closest[2] = dmax;
117  }
118  else
119  {
120  // LUF-vertex
121  closest[0] = rmax;
122  closest[1] = umax;
123  closest[2] = dmax;
124  }
125  }
126  }
127  else if (test[2] <= dmin)
128  {
129  if (test[0] <= rmin)
130  {
131  if (test[1] <= umin)
132  {
133  // N-face
134  closest[0] = test[0];
135  closest[1] = test[1];
136  closest[2] = dmin;
137  }
138  else
139  {
140  udDot = umin*test[1] + dmin*test[2];
141  if (udDot >= maxUDDot)
142  {
143  // UF-edge
144  closest[0] = test[0];
145  closest[1] = umax;
146  closest[2] = dmax;
147  }
148  else if (udDot >= minUDDot)
149  {
150  // U-face
151  uDot = dmin*test[1] - umin*test[2];
152  t = uDot / minUDDot;
153  closest[0] = test[0];
154  closest[1] = test[1] - t*dmin;
155  closest[2] = test[2] + t*umin;
156  }
157  else
158  {
159  // UN-edge
160  closest[0] = test[0];
161  closest[1] = umin;
162  closest[2] = dmin;
163  }
164  }
165  }
166  else
167  {
168  if (test[1] <= umin)
169  {
170  rdDot = rmin*test[0] + dmin*test[2];
171  if (rdDot >= maxRDDot)
172  {
173  // LF-edge
174  closest[0] = rmax;
175  closest[1] = test[1];
176  closest[2] = dmax;
177  }
178  else if (rdDot >= minRDDot)
179  {
180  // L-face
181  rDot = dmin*test[0] - rmin*test[2];
182  t = rDot / minRDDot;
183  closest[0] = test[0] - t*dmin;
184  closest[1] = test[1];
185  closest[2] = test[2] + t*rmin;
186  }
187  else
188  {
189  // LN-edge
190  closest[0] = rmin;
191  closest[1] = test[1];
192  closest[2] = dmin;
193  }
194  }
195  else
196  {
197  rudDot = rmin*test[0] + umin*test[1] + dmin*test[2];
198  rEdgeDot = umin*rudDot - minRUDDot*test[1];
199  if (rEdgeDot >= (Real)0)
200  {
201  rdDot = rmin*test[0] + dmin*test[2];
202  if (rdDot >= maxRDDot)
203  {
204  // LF-edge
205  closest[0] = rmax;
206  closest[1] = test[1];
207  closest[2] = dmax;
208  }
209  else if (rdDot >= minRDDot)
210  {
211  // L-face
212  rDot = dmin*test[0] - rmin*test[2];
213  t = rDot / minRDDot;
214  closest[0] = test[0] - t*dmin;
215  closest[1] = test[1];
216  closest[2] = test[2] + t*rmin;
217  }
218  else
219  {
220  // LN-edge
221  closest[0] = rmin;
222  closest[1] = test[1];
223  closest[2] = dmin;
224  }
225  }
226  else
227  {
228  uEdgeDot = rmin*rudDot - minRUDDot*test[0];
229  if (uEdgeDot >= (Real)0)
230  {
231  udDot = umin*test[1] + dmin*test[2];
232  if (udDot >= maxUDDot)
233  {
234  // UF-edge
235  closest[0] = test[0];
236  closest[1] = umax;
237  closest[2] = dmax;
238  }
239  else if (udDot >= minUDDot)
240  {
241  // U-face
242  uDot = dmin*test[1] - umin*test[2];
243  t = uDot / minUDDot;
244  closest[0] = test[0];
245  closest[1] = test[1] - t*dmin;
246  closest[2] = test[2] + t*umin;
247  }
248  else
249  {
250  // UN-edge
251  closest[0] = test[0];
252  closest[1] = umin;
253  closest[2] = dmin;
254  }
255  }
256  else
257  {
258  if (rudDot >= maxRUDDot)
259  {
260  // LUF-vertex
261  closest[0] = rmax;
262  closest[1] = umax;
263  closest[2] = dmax;
264  }
265  else if (rudDot >= minRUDDot)
266  {
267  // LU-edge
268  t = rudDot / minRUDDot;
269  closest[0] = t*rmin;
270  closest[1] = t*umin;
271  closest[2] = t*dmin;
272  }
273  else
274  {
275  // LUN-vertex
276  closest[0] = rmin;
277  closest[1] = umin;
278  closest[2] = dmin;
279  }
280  }
281  }
282  }
283  }
284  }
285  else
286  {
287  rDot = dmin*test[0] - rmin*test[2];
288  uDot = dmin*test[1] - umin*test[2];
289  if (rDot <= (Real)0.0)
290  {
291  if (uDot <= (Real)0)
292  {
293  // point inside frustum
294  closest = test;
295  }
296  else
297  {
298  udDot = umin*test[1] + dmin*test[2];
299  if (udDot >= maxUDDot)
300  {
301  // UF-edge
302  closest[0] = test[0];
303  closest[1] = umax;
304  closest[2] = dmax;
305  }
306  else
307  {
308  // U-face
309  t = uDot / minUDDot;
310  closest[0] = test[0];
311  closest[1] = test[1] - t*dmin;
312  closest[2] = test[2] + t*umin;
313  }
314  }
315  }
316  else
317  {
318  if (uDot <= (Real)0)
319  {
320  rdDot = rmin*test[0] + dmin*test[2];
321  if (rdDot >= maxRDDot)
322  {
323  // LF-edge
324  closest[0] = rmax;
325  closest[1] = test[1];
326  closest[2] = dmax;
327  }
328  else
329  {
330  // L-face
331  t = rDot / minRDDot;
332  closest[0] = test[0] - t*dmin;
333  closest[1] = test[1];
334  closest[2] = test[2] + t*rmin;
335  }
336  }
337  else
338  {
339  rudDot = rmin*test[0] + umin*test[1] + dmin*test[2];
340  rEdgeDot = umin*rudDot - minRUDDot*test[1];
341  if (rEdgeDot >= (Real)0)
342  {
343  rdDot = rmin*test[0] + dmin*test[2];
344  if (rdDot >= maxRDDot)
345  {
346  // LF-edge
347  closest[0] = rmax;
348  closest[1] = test[1];
349  closest[2] = dmax;
350  }
351  else // assert( rdDot >= minRDDot ) from geometry
352  {
353  // L-face
354  t = rDot / minRDDot;
355  closest[0] = test[0] - t*dmin;
356  closest[1] = test[1];
357  closest[2] = test[2] + t*rmin;
358  }
359  }
360  else
361  {
362  uEdgeDot = rmin*rudDot - minRUDDot*test[0];
363  if (uEdgeDot >= (Real)0)
364  {
365  udDot = umin*test[1] + dmin*test[2];
366  if (udDot >= maxUDDot)
367  {
368  // UF-edge
369  closest[0] = test[0];
370  closest[1] = umax;
371  closest[2] = dmax;
372  }
373  else // assert( udDot >= minUDDot ) from geometry
374  {
375  // U-face
376  t = uDot / minUDDot;
377  closest[0] = test[0];
378  closest[1] = test[1] - t*dmin;
379  closest[2] = test[2] + t*umin;
380  }
381  }
382  else
383  {
384  if (rudDot >= maxRUDDot)
385  {
386  // LUF-vertex
387  closest[0] = rmax;
388  closest[1] = umax;
389  closest[2] = dmax;
390  }
391  else // assert( rudDot >= minRUDDot ) from geometry
392  {
393  // LU-edge
394  t = rudDot / minRUDDot;
395  closest[0] = t*rmin;
396  closest[1] = t*umin;
397  closest[2] = t*dmin;
398  }
399  }
400  }
401  }
402  }
403  }
404 
405  diff = test - closest;
406 
407  // Convert back to original quadrant.
408  if (rSignChange)
409  {
410  closest[0] = -closest[0];
411  }
412 
413  if (uSignChange)
414  {
415  closest[1] = -closest[1];
416  }
417 
418  // Convert back to original coordinates.
419  result.frustumClosestPoint = frustum.origin +
420  closest[0] * frustum.rVector +
421  closest[1] * frustum.uVector +
422  closest[2] * frustum.dVector;
423 
424  result.sqrDistance = Dot(diff, diff);
425  result.distance = sqrt(result.sqrDistance);
426  return result;
427 }
428 
429 
430 }
GLsizei GLsizei GLfloat distance
Definition: glext.h:9704
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble t
Definition: glext.h:239
GLuint64EXT * result
Definition: glext.h:10003


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 03:59:59