GteIntrAlignedBox3OrientedBox3.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>
13 #include <Mathematics/GteFIQuery.h>
14 #include <Mathematics/GteTIQuery.h>
15 
16 // The queries consider the box to be a solid.
17 //
18 // The test-intersection query uses the method of separating axes. The set of
19 // potential separating directions includes the 3 face normals of box0, the 3
20 // face normals of box1, and 9 directions, each of which is the cross product
21 // of an edge of box0 and and an edge of box1.
22 //
23 // The separating axes involving cross products of edges has numerical
24 // robustness problems when the two edges are nearly parallel. The cross
25 // product of the edges is nearly the zero vector, so normalization of the
26 // cross product may produce unit-length directions that are not close to the
27 // true direction. Such a pair of edges occurs when a box0 face normal N0 and
28 // a box1 face normal N1 are nearly parallel. In this case, you may skip the
29 // edge-edge directions, which is equivalent to projecting the boxes onto the
30 // plane with normal N0 and applying a 2D separating axis test. The ability
31 // to do so involves choosing a small nonnegative epsilon . It is used to
32 // determine whether two face normals, one from each box, are nearly parallel:
33 // |Dot(N0,N1)| >= 1 - epsilon. If the input is negative, it is clamped to
34 // zero.
35 //
36 // The pair of integers 'separating', say, (i0,i1), identify the axis that
37 // reported separation; there may be more than one but only one is
38 // reported. If the separating axis is a face normal N[i0] of the aligned
39 // box0 in dimension i0, then (i0,-1) is returned. If the axis is a face
40 // normal box1.Axis[i1], then (-1,i1) is returned. If the axis is a cross
41 // product of edges, Cross(N[i0],box1.Axis[i1]), then (i0,i1) is returned.
42 
43 namespace gte
44 {
45 
46 template <typename Real>
47 class TIQuery<Real, AlignedBox3<Real>, OrientedBox3<Real>>
48 {
49 public:
50  struct Result
51  {
52  // The 'epsilon' value must be nonnegative.
53  Result(Real inEpsilon = (Real)0);
54 
55  bool intersect;
56  Real epsilon;
57  int separating[2];
58  };
59 
60  Result operator()(AlignedBox3<Real> const& box0,
61  OrientedBox3<Real> const& box1);
62 };
63 
64 
65 template <typename Real>
67 Result(Real inEpsilon)
68 {
69  if (inEpsilon >= (Real)0)
70  {
71  epsilon = inEpsilon;
72  }
73  else
74  {
75  epsilon = (Real)0;
76  }
77 }
78 
79 template <typename Real>
82  AlignedBox3<Real> const& box0, OrientedBox3<Real> const& box1)
83 {
84  Result result;
85 
86  // Get the centered form of the aligned box. The axes are implicitly
87  // A0[0] = (1,0,0), A0[1] = (0,1,0), and A0[2] = (0,0,1).
88  Vector3<Real> C0, E0;
89  box0.GetCenteredForm(C0, E0);
90 
91  // Convenience variables.
92  Vector3<Real> const& C1 = box1.center;
93  Vector3<Real> const* A1 = &box1.axis[0];
94  Vector3<Real> const& E1 = box1.extent;
95 
96  Real const cutoff = (Real)1 - result.epsilon;
97  bool existsParallelPair = false;
98 
99  // Compute the difference of box centers.
100  Vector3<Real> D = C1 - C0;
101 
102  Real dot01[3][3]; // dot01[i][j] = Dot(A0[i],A1[j]) = A1[j][i]
103  Real absDot01[3][3]; // |dot01[i][j]|
104  Real r0, r1, r; // interval radii and distance between centers
105  Real r01; // r0 + r1
106 
107  // Test for separation on the axis C0 + t*A0[0].
108  for (int i = 0; i < 3; ++i)
109  {
110  dot01[0][i] = A1[i][0];
111  absDot01[0][i] = std::abs(A1[i][0]);
112  if (absDot01[0][i] >= cutoff)
113  {
114  existsParallelPair = true;
115  }
116  }
117  r = std::abs(D[0]);
118  r1 = E1[0] * absDot01[0][0] + E1[1] * absDot01[0][1] + E1[2] * absDot01[0][2];
119  r01 = E0[0] + r1;
120  if (r > r01)
121  {
122  result.intersect = false;
123  result.separating[0] = 0;
124  result.separating[1] = -1;
125  return result;
126  }
127 
128  // Test for separation on the axis C0 + t*A0[1].
129  for (int i = 0; i < 3; ++i)
130  {
131  dot01[1][i] = A1[i][1];
132  absDot01[1][i] = std::abs(A1[i][1]);
133  if (absDot01[1][i] >= cutoff)
134  {
135  existsParallelPair = true;
136  }
137  }
138  r = std::abs(D[1]);
139  r1 = E1[0] * absDot01[1][0] + E1[1] * absDot01[1][1] + E1[2] * absDot01[1][2];
140  r01 = E0[1] + r1;
141  if (r > r01)
142  {
143  result.intersect = false;
144  result.separating[0] = 1;
145  result.separating[1] = -1;
146  return result;
147  }
148 
149  // Test for separation on the axis C0 + t*A0[2].
150  for (int i = 0; i < 3; ++i)
151  {
152  dot01[2][i] = A1[i][2];
153  absDot01[2][i] = std::abs(A1[i][2]);
154  if (absDot01[2][i] >= cutoff)
155  {
156  existsParallelPair = true;
157  }
158  }
159  r = std::abs(D[2]);
160  r1 = E1[0] * absDot01[2][0] + E1[1] * absDot01[2][1] + E1[2] * absDot01[2][2];
161  r01 = E0[2] + r1;
162  if (r > r01)
163  {
164  result.intersect = false;
165  result.separating[0] = 2;
166  result.separating[1] = -1;
167  return result;
168  }
169 
170  // Test for separation on the axis C0 + t*A1[0].
171  r = std::abs(Dot(D, A1[0]));
172  r0 = E0[0] * absDot01[0][0] + E0[1] * absDot01[1][0] + E0[2] * absDot01[2][0];
173  r01 = r0 + E1[0];
174  if (r > r01)
175  {
176  result.intersect = false;
177  result.separating[0] = -1;
178  result.separating[1] = 0;
179  return result;
180  }
181 
182  // Test for separation on the axis C0 + t*A1[1].
183  r = std::abs(Dot(D, A1[1]));
184  r0 = E0[0] * absDot01[0][1] + E0[1] * absDot01[1][1] + E0[2] * absDot01[2][1];
185  r01 = r0 + E1[1];
186  if (r > r01)
187  {
188  result.intersect = false;
189  result.separating[0] = -1;
190  result.separating[1] = 1;
191  return result;
192  }
193 
194  // Test for separation on the axis C0 + t*A1[2].
195  r = std::abs(Dot(D, A1[2]));
196  r0 = E0[0] * absDot01[0][2] + E0[1] * absDot01[1][2] + E0[2] * absDot01[2][2];
197  r01 = r0 + E1[2];
198  if (r > r01)
199  {
200  result.intersect = false;
201  result.separating[0] = -1;
202  result.separating[1] = 2;
203  return result;
204  }
205 
206  // At least one pair of box axes was parallel, so the separation is
207  // effectively in 2D. The edge-edge axes do not need to be tested.
208  if (existsParallelPair)
209  {
210  result.intersect = true;
211  return result;
212  }
213 
214  // Test for separation on the axis C0 + t*A0[0]xA1[0].
215  r = std::abs(D[2] * dot01[1][0] - D[1] * dot01[2][0]);
216  r0 = E0[1] * absDot01[2][0] + E0[2] * absDot01[1][0];
217  r1 = E1[1] * absDot01[0][2] + E1[2] * absDot01[0][1];
218  r01 = r0 + r1;
219  if (r > r01)
220  {
221  result.intersect = false;
222  result.separating[0] = 0;
223  result.separating[1] = 0;
224  return result;
225  }
226 
227  // Test for separation on the axis C0 + t*A0[0]xA1[1].
228  r = std::abs(D[2] * dot01[1][1] - D[1] * dot01[2][1]);
229  r0 = E0[1] * absDot01[2][1] + E0[2] * absDot01[1][1];
230  r1 = E1[0] * absDot01[0][2] + E1[2] * absDot01[0][0];
231  r01 = r0 + r1;
232  if (r > r01)
233  {
234  result.intersect = false;
235  result.separating[0] = 0;
236  result.separating[1] = 1;
237  return result;
238  }
239 
240  // Test for separation on the axis C0 + t*A0[0]xA1[2].
241  r = std::abs(D[2] * dot01[1][2] - D[1] * dot01[2][2]);
242  r0 = E0[1] * absDot01[2][2] + E0[2] * absDot01[1][2];
243  r1 = E1[0] * absDot01[0][1] + E1[1] * absDot01[0][0];
244  r01 = r0 + r1;
245  if (r > r01)
246  {
247  result.intersect = false;
248  result.separating[0] = 0;
249  result.separating[1] = 2;
250  return result;
251  }
252 
253  // Test for separation on the axis C0 + t*A0[1]xA1[0].
254  r = std::abs(D[0] * dot01[2][0] - D[2] * dot01[0][0]);
255  r0 = E0[0] * absDot01[2][0] + E0[2] * absDot01[0][0];
256  r1 = E1[1] * absDot01[1][2] + E1[2] * absDot01[1][1];
257  r01 = r0 + r1;
258  if (r > r01)
259  {
260  result.intersect = false;
261  result.separating[0] = 1;
262  result.separating[1] = 0;
263  return result;
264  }
265 
266  // Test for separation on the axis C0 + t*A0[1]xA1[1].
267  r = std::abs(D[0] * dot01[2][1] - D[2] * dot01[0][1]);
268  r0 = E0[0] * absDot01[2][1] + E0[2] * absDot01[0][1];
269  r1 = E1[0] * absDot01[1][2] + E1[2] * absDot01[1][0];
270  r01 = r0 + r1;
271  if (r > r01)
272  {
273  result.intersect = false;
274  result.separating[0] = 1;
275  result.separating[1] = 1;
276  return result;
277  }
278 
279  // Test for separation on the axis C0 + t*A0[1]xA1[2].
280  r = std::abs(D[0] * dot01[2][2] - D[2] * dot01[0][2]);
281  r0 = E0[0] * absDot01[2][2] + E0[2] * absDot01[0][2];
282  r1 = E1[0] * absDot01[1][1] + E1[1] * absDot01[1][0];
283  r01 = r0 + r1;
284  if (r > r01)
285  {
286  result.intersect = false;
287  result.separating[0] = 1;
288  result.separating[1] = 2;
289  return result;
290  }
291 
292  // Test for separation on the axis C0 + t*A0[2]xA1[0].
293  r = std::abs(D[1] * dot01[0][0] - D[0] * dot01[1][0]);
294  r0 = E0[0] * absDot01[1][0] + E0[1] * absDot01[0][0];
295  r1 = E1[1] * absDot01[2][2] + E1[2] * absDot01[2][1];
296  r01 = r0 + r1;
297  if (r > r01)
298  {
299  result.intersect = false;
300  result.separating[0] = 2;
301  result.separating[1] = 0;
302  return result;
303  }
304 
305  // Test for separation on the axis C0 + t*A0[2]xA1[1].
306  r = std::abs(D[1] * dot01[0][1] - D[0] * dot01[1][1]);
307  r0 = E0[0] * absDot01[1][1] + E0[1] * absDot01[0][1];
308  r1 = E1[0] * absDot01[2][2] + E1[2] * absDot01[2][0];
309  r01 = r0 + r1;
310  if (r > r01)
311  {
312  result.intersect = false;
313  result.separating[0] = 2;
314  result.separating[1] = 1;
315  return result;
316  }
317 
318  // Test for separation on the axis C0 + t*A0[2]xA1[2].
319  r = std::abs(D[1] * dot01[0][2] - D[0] * dot01[1][2]);
320  r0 = E0[0] * absDot01[1][2] + E0[1] * absDot01[0][2];
321  r1 = E1[0] * absDot01[2][1] + E1[1] * absDot01[2][0];
322  r01 = r0 + r1;
323  if (r > r01)
324  {
325  result.intersect = false;
326  result.separating[0] = 2;
327  result.separating[1] = 2;
328  return result;
329  }
330 
331  result.intersect = true;
332  return result;
333 }
334 
335 
336 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLboolean r
Definition: glcorearb.h:1217
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