GteIntrOrientedBox2OrientedBox2.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/GteVector2.h>
12 #include <Mathematics/GteFIQuery.h>
13 #include <Mathematics/GteTIQuery.h>
14 #include <vector>
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 2 edge normals of box0 and the
20 // 2 edge normals of box1. The integer 'separating' identifies the axis that
21 // reported separation; there may be more than one but only one is reported.
22 // The value is 0 when box0.axis[0] separates, 1 when box0.axis[1] separates,
23 // 2 when box1.axis[0] separates, or 3 when box1.axis[1] separates.
24 
25 namespace gte
26 {
27 
28 template <typename Real>
29 class TIQuery<Real, OrientedBox2<Real>, OrientedBox2<Real>>
30 {
31 public:
32  struct Result
33  {
34  bool intersect;
36  };
37 
38  Result operator()(OrientedBox2<Real> const& box0,
39  OrientedBox2<Real> const& box1);
40 };
41 
42 template <typename Real>
43 class FIQuery<Real, OrientedBox2<Real>, OrientedBox2<Real>>
44 {
45 public:
46  struct Result
47  {
48  bool intersect;
49 
50  // If 'intersect' is true, the boxes intersect in a convex 'polygon'.
51  std::vector<Vector2<Real>> polygon;
52  };
53 
54  Result operator()(OrientedBox2<Real> const& box0,
55  OrientedBox2<Real> const& box1);
56 
57 private:
58  // The line normals are inner pointing. The function returns true
59  // when the incoming polygon is outside the line, in which case the
60  // boxes do not intersect. If the function returns false, the outgoing
61  // polygon is the incoming polygon intersected with the closed halfspace
62  // defined by the line.
63  bool Outside(Vector2<Real> const& origin, Vector2<Real> const& normal,
64  std::vector<Vector2<Real>>& polygon);
65 };
66 
67 
68 template <typename Real>
71  OrientedBox2<Real> const& box0, OrientedBox2<Real> const& box1)
72 {
73  Result result;
74 
75  // Convenience variables.
76  Vector2<Real> const* A0 = &box0.axis[0];
77  Vector2<Real> const* A1 = &box1.axis[0];
78  Vector2<Real> const& E0 = box0.extent;
79  Vector2<Real> const& E1 = box1.extent;
80 
81  // Compute difference of box centers, D = C1-C0.
82  Vector2<Real> D = box1.center - box0.center;
83 
84  Real absA0dA1[2][2], rSum;
85 
86  // Test box0.axis[0].
87  absA0dA1[0][0] = std::abs(Dot(A0[0], A1[0]));
88  absA0dA1[0][1] = std::abs(Dot(A0[0], A1[1]));
89  rSum = E0[0] + E1[0] * absA0dA1[0][0] + E1[1] * absA0dA1[0][1];
90  if (std::abs(Dot(A0[0], D)) > rSum)
91  {
92  result.intersect = false;
93  result.separating = 0;
94  return result;
95  }
96 
97  // Test axis box0.axis[1].
98  absA0dA1[1][0] = std::abs(Dot(A0[1], A1[0]));
99  absA0dA1[1][1] = std::abs(Dot(A0[1], A1[1]));
100  rSum = E0[1] + E1[0] * absA0dA1[1][0] + E1[1] * absA0dA1[1][1];
101  if (std::abs(Dot(A0[1], D)) > rSum)
102  {
103  result.intersect = false;
104  result.separating = 1;
105  return result;
106  }
107 
108  // Test axis box1.axis[0].
109  rSum = E1[0] + E0[0] * absA0dA1[0][0] + E0[1] * absA0dA1[1][0];
110  if (std::abs(Dot(A1[0], D)) > rSum)
111  {
112  result.intersect = false;
113  result.separating = 2;
114  return result;
115  }
116 
117  // Test axis box1.axis[1].
118  rSum = E1[1] + E0[0] * absA0dA1[0][1] + E0[1] * absA0dA1[1][1];
119  if (std::abs(Dot(A1[1], D)) > rSum)
120  {
121  result.intersect = false;
122  result.separating = 3;
123  return result;
124  }
125 
126  result.intersect = true;
127  return result;
128 }
129 
130 template <typename Real>
133  OrientedBox2<Real> const& box0, OrientedBox2<Real> const& box1)
134 {
135  Result result;
136  result.intersect = true;
137 
138  // Initialize the intersection polygon to box0, listing the vertices
139  // in counterclockwise order.
140  std::array<Vector2<Real>, 4> vertex;
141  box0.GetVertices(vertex);
142  result.polygon.push_back(vertex[0]); // C - e0 * U0 - e1 * U1
143  result.polygon.push_back(vertex[1]); // C + e0 * U0 - e1 * U1
144  result.polygon.push_back(vertex[3]); // C + e0 * U0 + e1 * U1
145  result.polygon.push_back(vertex[2]); // C - e0 * U0 + e1 * U1
146 
147  // Clip the polygon using the lines defining edges of box1. The
148  // line normal points inside box1. The line origin is the first
149  // vertex of the edge when traversing box1 counterclockwise.
150  box1.GetVertices(vertex);
151  std::array<Vector2<Real>, 4> normal =
152  {
153  box1.axis[1], -box1.axis[0], box1.axis[0], -box1.axis[1]
154  };
155 
156  for (int i = 0; i < 4; ++i)
157  {
158  if (Outside(vertex[i], normal[i], result.polygon))
159  {
160  // The boxes are separated.
161  result.intersect = false;
162  result.polygon.clear();
163  break;
164  }
165  }
166 
167  return result;
168 }
169 
170 template <typename Real>
172  Vector2<Real> const& origin, Vector2<Real> const& normal,
173  std::vector<Vector2<Real>>& polygon)
174 {
175  // Determine whether the polygon vertices are outside the polygon, inside
176  // the polygon, or on the polygon boundary.
177  int const numVertices = static_cast<int>(polygon.size());
178  std::vector<Real> distance(numVertices);
179  int positive = 0, negative = 0, positiveIndex = -1;
180  for (int i = 0; i < numVertices; ++i)
181  {
182  distance[i] = Dot(normal, polygon[i] - origin);
183  if (distance[i] > (Real)0)
184  {
185  ++positive;
186  if (positiveIndex == -1)
187  {
188  positiveIndex = i;
189  }
190  }
191  else if (distance[i] < (Real)0)
192  {
193  ++negative;
194  }
195  }
196 
197  if (positive == 0)
198  {
199  // The polygon is strictly outside the line.
200  return true;
201  }
202 
203  if (negative == 0)
204  {
205  // The polygon is contained in the closed halfspace whose boundary
206  // is the line. It is fully visible and no clipping is necessary.
207  return false;
208  }
209 
210  // The line transversely intersects the polygon. Clip the polygon.
211  std::vector<Vector2<Real>> clipPolygon;
212  Vector2<Real> vertex;
213  int curr, prev;
214  Real t;
215 
216  if (positiveIndex > 0)
217  {
218  // Compute the first clip vertex on the line.
219  curr = positiveIndex;
220  prev = curr - 1;
221  t = distance[curr] / (distance[curr] - distance[prev]);
222  vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
223  clipPolygon.push_back(vertex);
224 
225  // Include the vertices on the positive side of line.
226  while (curr < numVertices && distance[curr] > (Real)0)
227  {
228  clipPolygon.push_back(polygon[curr++]);
229  }
230 
231  // Compute the kast clip vertex on the line.
232  if (curr < numVertices)
233  {
234  prev = curr - 1;
235  }
236  else
237  {
238  curr = 0;
239  prev = numVertices - 1;
240  }
241  t = distance[curr] / (distance[curr] - distance[prev]);
242  vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
243  clipPolygon.push_back(vertex);
244  }
245  else // positiveIndex is 0
246  {
247  // Include the vertices on the positive side of line.
248  curr = 0;
249  while (curr < numVertices && distance[curr] > (Real)0)
250  {
251  clipPolygon.push_back(polygon[curr++]);
252  }
253 
254  // Compute the last clip vertex on the line.
255  prev = curr - 1;
256  t = distance[curr] / (distance[curr] - distance[prev]);
257  vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
258  clipPolygon.push_back(vertex);
259 
260  // Skip the vertices on the negative side of the line.
261  while (curr < numVertices && distance[curr] <= (Real)0)
262  {
263  curr++;
264  }
265 
266  // Compute the first clip vertex on the line.
267  if (curr < numVertices)
268  {
269  prev = curr - 1;
270  t = distance[curr] / (distance[curr] - distance[prev]);
271  vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
272  clipPolygon.push_back(vertex);
273 
274  // Keep the vertices on the positive side of the line.
275  while (curr < numVertices && distance[curr] > (Real)0)
276  {
277  clipPolygon.push_back(polygon[curr++]);
278  }
279  }
280  else
281  {
282  curr = 0;
283  prev = numVertices - 1;
284  t = distance[curr] / (distance[curr] - distance[prev]);
285  vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
286  clipPolygon.push_back(vertex);
287  }
288  }
289 
290  polygon = clipPolygon;
291  return false;
292 }
293 
294 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
GLsizei GLsizei GLfloat distance
Definition: glext.h:9704
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble t
Definition: glext.h:239
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