GteIntrTriangle3OrientedBox3.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/GteTIQuery.h>
11 #include <Mathematics/GteFIQuery.h>
15 
16 namespace gte
17 {
18 
19 template <typename Real>
20 class TIQuery<Real, Triangle3<Real>, OrientedBox3<Real>>
21 {
22 public:
23  struct Result
24  {
25  bool intersect;
26  };
27 
28  Result operator()(Triangle3<Real> const& triangle, OrientedBox3<Real> const& box);
29 
30 private:
31  void GetProjection(Vector3<Real> const& axis, Triangle3<Real> const& triangle,
32  Real& imin, Real& imax);
33 
34  void GetProjection(Vector3<Real> const& axis, OrientedBox3<Real> const& box,
35  Real& imin, Real& imax);
36 };
37 
38 template <typename Real>
39 class FIQuery<Real, Triangle3<Real>, OrientedBox3<Real>>
40 {
41 public:
42  struct Result
43  {
44  std::vector<Vector3<Real>> insidePolygon;
45  std::vector<std::vector<Vector3<Real>>> outsidePolygons;
46  };
47 
48  Result operator()(Triangle3<Real> const& triangle, OrientedBox3<Real> const& box);
49 };
50 
51 
52 template <typename Real>
55  Triangle3<Real> const& triangle, OrientedBox3<Real> const& box)
56 {
57  // The method of separating axes is the algorithm implemented here.
58  Result result;
59 
60  Real min0, max0, min1, max1;
61  Vector3<Real> D, edge[3];
62 
63  // Test direction of triangle normal.
64  edge[0] = triangle.v[1] - triangle.v[0];
65  edge[1] = triangle.v[2] - triangle.v[0];
66  D = Cross(edge[0], edge[1]);
67  min0 = Dot(D, triangle.v[0]);
68  max0 = min0;
69  GetProjection(D, box, min1, max1);
70  if (max1 < min0 || max0 < min1)
71  {
72  result.intersect = false;
73  return result;
74  }
75 
76  // Test direction of box faces.
77  for (int i = 0; i < 3; ++i)
78  {
79  D = box.axis[i];
80  GetProjection(D, triangle, min0, max0);
81  Real DdC = Dot(D, box.center);
82  min1 = DdC - box.extent[i];
83  max1 = DdC + box.extent[i];
84  if (max1 < min0 || max0 < min1)
85  {
86  result.intersect = false;
87  return result;
88  }
89  }
90 
91  // Test direction of triangle-box edge cross products.
92  edge[2] = edge[1] - edge[0];
93  for (int i0 = 0; i0 < 3; ++i0)
94  {
95  for (int i1 = 0; i1 < 3; ++i1)
96  {
97  D = Cross(edge[i0], box.axis[i1]);
98  GetProjection(D, triangle, min0, max0);
99  GetProjection(D, box, min1, max1);
100  if (max1 < min0 || max0 < min1)
101  {
102  result.intersect = false;
103  return result;
104  }
105  }
106  }
107 
108  result.intersect = true;
109  return result;
110 }
111 
112 template <typename Real>
114  Vector3<Real> const& axis, Triangle3<Real> const& triangle, Real& imin, Real& imax)
115 {
116  Real dot[3] =
117  {
118  Dot(axis, triangle.v[0]),
119  Dot(axis, triangle.v[1]),
120  Dot(axis, triangle.v[2])
121  };
122 
123  imin = dot[0];
124  imax = imin;
125 
126  if (dot[1] < imin)
127  {
128  imin = dot[1];
129  }
130  else if (dot[1] > imax)
131  {
132  imax = dot[1];
133  }
134 
135  if (dot[2] < imin)
136  {
137  imin = dot[2];
138  }
139  else if (dot[2] > imax)
140  {
141  imax = dot[2];
142  }
143 }
144 
145 template <typename Real>
146 void TIQuery<Real, Triangle3<Real>, OrientedBox3<Real>>::GetProjection(
147  Vector3<Real> const& axis, OrientedBox3<Real> const& box, Real& imin, Real& imax)
148 {
149  Real origin = Dot(axis, box.center);
150  Real maximumExtent =
151  fabs(box.extent[0] * Dot(axis, box.axis[0])) +
152  fabs(box.extent[1] * Dot(axis, box.axis[1])) +
153  fabs(box.extent[2] * Dot(axis, box.axis[2]));
154 
155  imin = origin - maximumExtent;
156  imax = origin + maximumExtent;
157 }
158 
159 template <typename Real>
162  Triangle3<Real> const& triangle, OrientedBox3<Real> const& box)
163 {
164  Result result;
165 
166  // Start with the triangle and clip it against each face of the box.
167  // The largest number of vertices for the polygon of intersection is 7.
168  result.insidePolygon.resize(3);
169  for (int i = 0; i < 3; ++i)
170  {
171  result.insidePolygon[i] = triangle.v[i];
172  }
173 
174  Plane3<Real> plane;
176  typename FIQuery<Real, std::vector<Vector3<Real>>, Plane3<Real>>::Result ppResult;
177  for (int dir = -1; dir <= 1; dir += 2)
178  {
179  for (int side = 0; side < 3; ++side)
180  {
181  // Create a plane for the box face that points inside the box.
182  plane.normal = ((Real)dir) * box.axis[side];
183  plane.constant = Dot(plane.normal, box.center) - box.extent[side];
184 
185  ppResult = ppQuery(result.insidePolygon, plane);
186  switch (ppResult.configuration)
187  {
189  result.insidePolygon = ppResult.positivePolygon;
190  result.outsidePolygons.push_back(ppResult.negativePolygon);
191  break;
195  // The result.insidePolygon is already ppResult.positivePolygon.
196  //result.insidePolygon = ppResult.positivePolygon;
197  break;
201  result.insidePolygon.clear();
202  result.outsidePolygons.push_back(ppResult.negativePolygon);
203  return result;
205  // A triangle coplanar with a box face will be processed as if
206  // it is inside the box.
207  result.insidePolygon = ppResult.intersection;
208  break;
209  default:
210  result.insidePolygon.clear();
211  result.outsidePolygons.clear();
212  break;
213  }
214  }
215  }
216 
217  return result;
218 }
219 
220 }
std::array< Vector< N, Real >, N > axis
Vector< N, Real > extent
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Vector< N, Real > normal
Definition: GteHyperplane.h:40
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
std::array< Vector< N, Real >, 3 > v
Definition: GteTriangle.h:30
Vector< N, Real > center
GLuint64EXT * result
Definition: glext.h:10003


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