GteSeparatePoints3.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 
11 
12 // Separate two point sets, if possible, by computing a plane for which the
13 // point sets lie on opposite sides. The algorithm computes the convex hull
14 // of the point sets, then uses the method of separating axes to determine if
15 // the two convex polyhedra are disjoint. The ComputeType is for the
16 // ConvexHull3 class.
17 
18 namespace gte
19 {
20 
21 template <typename Real, typename ComputeType>
23 {
24 public:
25  // The return value is 'true' if and only if there is a separation. If
26  // 'true', the returned plane is a separating plane. The code assumes
27  // that each point set has at least 4 noncoplanar points.
28  bool operator()(int numPoints0, Vector3<Real> const* points0,
29  int numPoints1, Vector3<Real> const* points1,
30  Plane3<Real>& separatingPlane) const;
31 
32 private:
33  int OnSameSide(Plane3<Real> const& plane, int numTriangles,
34  int const* indices, Vector3<Real> const* points) const;
35 
36  int WhichSide(Plane3<Real> const& plane, int numTriangles,
37  int const* indices, Vector3<Real> const* points) const;
38 };
39 
40 
41 template <typename Real, typename ComputeType>
43  Vector3<Real> const* points0, int numPoints1,
44  Vector3<Real> const* points1, Plane3<Real>& separatingPlane) const
45 {
46  // Construct convex hull of point set 0.
48  ch0(numPoints0, points0, (Real)0);
49  if (ch0.GetDimension() != 3)
50  {
51  return false;
52  }
53 
54  // Construct convex hull of point set 1.
56  ch1(numPoints1, points1, (Real)0);
57  if (ch1.GetDimension() != 3)
58  {
59  return false;
60  }
61 
62  auto const& hull0 = ch0.GetHullUnordered();
63  auto const& hull1 = ch1.GetHullUnordered();
64  int numTriangles0 = static_cast<int>(hull0.size());
65  int const* indices0 = reinterpret_cast<int const*>(&hull0[0]);
66  int numTriangles1 = static_cast<int>(hull1.size());
67  int const* indices1 = reinterpret_cast<int const*>(&hull1[0]);
68 
69  // Test faces of hull 0 for possible separation of points.
70  int i, i0, i1, i2, side0, side1;
71  Vector3<Real> diff0, diff1;
72  for (i = 0; i < numTriangles0; ++i)
73  {
74  // Look up face (assert: i0 != i1 && i0 != i2 && i1 != i2).
75  i0 = indices0[3 * i];
76  i1 = indices0[3 * i + 1];
77  i2 = indices0[3 * i + 2];
78 
79  // Compute potential separating plane (assert: normal != (0,0,0)).
80  separatingPlane = Plane3<Real>({ points0[i0], points0[i1],
81  points0[i2] });
82 
83  // Determine whether hull 1 is on same side of plane.
84  side1 = OnSameSide(separatingPlane, numTriangles1, indices1, points1);
85 
86  if (side1)
87  {
88  // Determine on which side of plane hull 0 lies.
89  side0 = WhichSide(separatingPlane, numTriangles0, indices0,
90  points0);
91  if (side0*side1 <= 0) // Plane separates hulls.
92  {
93  return true;
94  }
95  }
96  }
97 
98  // Test faces of hull 1 for possible separation of points.
99  for (i = 0; i < numTriangles1; ++i)
100  {
101  // Look up edge (assert: i0 != i1 && i0 != i2 && i1 != i2).
102  i0 = indices1[3 * i];
103  i1 = indices1[3 * i + 1];
104  i2 = indices1[3 * i + 2];
105 
106  // Compute perpendicular to face (assert: normal != (0,0,0)).
107  separatingPlane = Plane3<Real>({ points1[i0], points1[i1],
108  points1[i2] });
109 
110  // Determine whether hull 0 is on same side of plane.
111  side0 = OnSameSide(separatingPlane, numTriangles0, indices0, points0);
112  if (side0)
113  {
114  // Determine on which side of plane hull 1 lies.
115  side1 = WhichSide(separatingPlane, numTriangles1, indices1,
116  points1);
117  if (side0*side1 <= 0) // Plane separates hulls.
118  {
119  return true;
120  }
121  }
122  }
123 
124  // Build edge set for hull 0.
125  std::set<std::pair<int, int>> edgeSet0;
126  for (i = 0; i < numTriangles0; ++i)
127  {
128  // Look up face (assert: i0 != i1 && i0 != i2 && i1 != i2).
129  i0 = indices0[3 * i];
130  i1 = indices0[3 * i + 1];
131  i2 = indices0[3 * i + 2];
132  edgeSet0.insert(std::make_pair(i0, i1));
133  edgeSet0.insert(std::make_pair(i0, i2));
134  edgeSet0.insert(std::make_pair(i1, i2));
135  }
136 
137  // Build edge list for hull 1.
138  std::set<std::pair<int, int>> edgeSet1;
139  for (i = 0; i < numTriangles1; ++i)
140  {
141  // Look up face (assert: i0 != i1 && i0 != i2 && i1 != i2).
142  i0 = indices1[3 * i];
143  i1 = indices1[3 * i + 1];
144  i2 = indices1[3 * i + 2];
145  edgeSet1.insert(std::make_pair(i0, i1));
146  edgeSet1.insert(std::make_pair(i0, i2));
147  edgeSet1.insert(std::make_pair(i1, i2));
148  }
149 
150  // Test planes whose normals are cross products of two edges, one from
151  // each hull.
152  for (auto const& e0 : edgeSet0)
153  {
154  // Get edge.
155  diff0 = points0[e0.second] - points0[e0.first];
156 
157  for (auto const& e1 : edgeSet1)
158  {
159  diff1 = points1[e1.second] - points1[e1.first];
160 
161  // Compute potential separating plane.
162  separatingPlane.normal = UnitCross(diff0, diff1);
163  separatingPlane.constant = Dot(separatingPlane.normal,
164  points0[e0.first]);
165 
166  // Determine if hull 0 is on same side of plane.
167  side0 = OnSameSide(separatingPlane, numTriangles0, indices0,
168  points0);
169  side1 = OnSameSide(separatingPlane, numTriangles1, indices1,
170  points1);
171 
172  if (side0*side1 < 0) // Plane separates hulls.
173  {
174  return true;
175  }
176  }
177  }
178 
179  return false;
180 }
181 
182 template <typename Real, typename ComputeType>
184  int numTriangles, int const* indices, Vector3<Real> const* points) const
185 {
186  // test if all points on same side of plane (nx,ny,nz)*(x,y,z) = c
187  int posSide = 0, negSide = 0;
188 
189  for (int t = 0; t < numTriangles; ++t)
190  {
191  for (int i = 0; i < 3; ++i)
192  {
193  int v = indices[3 * t + i];
194  Real c0 = Dot(plane.normal, points[v]);
195  if (c0 > plane.constant)
196  {
197  ++posSide;
198  }
199  else if (c0 < plane.constant)
200  {
201  ++negSide;
202  }
203 
204  if (posSide && negSide)
205  {
206  // Plane splits point set.
207  return 0;
208  }
209  }
210  }
211 
212  return (posSide ? +1 : -1);
213 }
214 
215 template <typename Real, typename ComputeType>
217  int numTriangles, int const* indices, Vector3<Real> const* points) const
218 {
219  // Establish which side of plane hull is on.
220  for (int t = 0; t < numTriangles; ++t)
221  {
222  for (int i = 0; i < 3; ++i)
223  {
224  int v = indices[3 * t + i];
225  Real c0 = Dot(plane.normal, points[v]);
226  if (c0 > plane.constant)
227  {
228  // Positive side.
229  return +1;
230  }
231  if (c0 < plane.constant)
232  {
233  // Negative side.
234  return -1;
235  }
236  }
237  }
238 
239  // Hull is effectively collinear.
240  return 0;
241 }
242 
243 
244 }
std::vector< TriangleKey< true > > const & GetHullUnordered() const
int OnSameSide(Plane3< Real > const &plane, int numTriangles, int const *indices, Vector3< Real > const *points) const
Vector< N, Real > UnitCross(Vector< N, Real > const &v0, Vector< N, Real > const &v1, bool robust=false)
Definition: GteVector3.h:130
int WhichSide(Plane3< Real > const &plane, int numTriangles, int const *indices, Vector3< Real > const *points) const
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
GLsizei GLenum const void * indices
Definition: glcorearb.h:401
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
int GetDimension() const
bool operator()(int numPoints0, Vector3< Real > const *points0, int numPoints1, Vector3< Real > const *points1, Plane3< Real > &separatingPlane) const
GLdouble GLdouble t
Definition: glext.h:239
const GLdouble * v
Definition: glcorearb.h:832
Vector< N, Real > normal
Definition: GteHyperplane.h:40


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