GteContPointInPolyhedron3.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.1 (2016/11/25)
7 
8 #pragma once
9 
10 #include <LowLevel/GteLogger.h>
14 #include <vector>
15 
16 // This class contains various implementations for point-in-polyhedron
17 // queries. The planes stored with the faces are used in all cases to
18 // reject ray-face intersection tests, a quick culling operation.
19 //
20 // The algorithm is to cast a ray from the input point P and test for
21 // intersection against each face of the polyhedron. If the ray only
22 // intersects faces at interior points (not vertices, not edge points),
23 // then the point is inside when the number of intersections is odd and
24 // the point is outside when the number of intersections is even. If the
25 // ray intersects an edge or a vertex, then the counting must be handled
26 // differently. The details are tedious. As an alternative, the approach
27 // here is to allow you to specify 2*N+1 rays, where N >= 0. You should
28 // choose these rays randomly. Each ray reports "inside" or "outside".
29 // Whichever result occurs N+1 or more times is the "winner". The input
30 // rayQuantity is 2*N+1. The input array Direction must have rayQuantity
31 // elements. If you are feeling lucky, choose rayQuantity to be 1.
32 
33 namespace gte
34 {
35 
36 template <typename Real>
38 {
39 public:
40  // For simple polyhedra with triangle faces.
42  {
43  public:
44  // When you view the face from outside, the vertices are
45  // counterclockwise ordered. The Indices array stores the indices
46  // into the vertex array.
47  int indices[3];
48 
49  // The normal vector is unit length and points to the outside of the
50  // polyhedron.
52  };
53 
54  // The Contains query will use ray-triangle intersection queries.
55  PointInPolyhedron3(int numPoints, Vector3<Real> const* points,
56  int numFaces, TriangleFace const* faces, int numRays,
57  Vector3<Real> const* directions);
58 
59  // For simple polyhedra with convex polygon faces.
60  class ConvexFace
61  {
62  public:
63  // When you view the face from outside, the vertices are
64  // counterclockwise ordered. The Indices array stores the indices
65  // into the vertex array.
66  std::vector<int> indices;
67 
68  // The normal vector is unit length and points to the outside of the
69  // polyhedron.
71  };
72 
73  // The Contains query will use ray-convexpolygon intersection queries. A
74  // ray-convexpolygon intersection query can be implemented in many ways.
75  // In this context, uiMethod is one of three value:
76  // 0 : Use a triangle fan and perform a ray-triangle intersection query
77  // for each triangle.
78  // 1 : Find the point of intersection of ray and plane of polygon. Test
79  // whether that point is inside the convex polygon using an O(N)
80  // test.
81  // 2 : Find the point of intersection of ray and plane of polygon. Test
82  // whether that point is inside the convex polygon using an O(log N)
83  // test.
84  PointInPolyhedron3(int numPoints, Vector3<Real> const* points,
85  int numFaces, ConvexFace const* faces, int numRays,
86  Vector3<Real> const* directions, unsigned int method);
87 
88  // For simple polyhedra with simple polygon faces that are generally
89  // not all convex.
90  class SimpleFace
91  {
92  public:
93  // When you view the face from outside, the vertices are
94  // counterclockwise ordered. The Indices array stores the indices
95  // into the vertex array.
96  std::vector<int> indices;
97 
98  // The normal vector is unit length and points to the outside of the
99  // polyhedron.
101 
102  // Each simple face may be triangulated. The indices are relative to
103  // the vertex array. Each triple of indices represents a triangle in
104  // the triangulation.
105  std::vector<int> triangles;
106  };
107 
108  // The Contains query will use ray-simplepolygon intersection queries. A
109  // ray-simplepolygon intersection query can be implemented in a couple of
110  // ways. In this context, uiMethod is one of two value:
111  // 0 : Iterate over the triangles of each face and perform a
112  // ray-triangle intersection query for each triangle. This requires
113  // that the SimpleFace::Triangles array be initialized for each
114  // face.
115  // 1 : Find the point of intersection of ray and plane of polygon. Test
116  // whether that point is inside the polygon using an O(N) test. The
117  // SimpleFace::Triangles array is not used for this method, so it
118  // does not have to be initialized for each face.
119  PointInPolyhedron3(int numPoints, Vector3<Real> const* points,
120  int numFaces, SimpleFace const* faces, int numRays,
121  Vector3<Real> const* directions, unsigned int method);
122 
123  // This function will select the actual algorithm based on which
124  // constructor you used for this class.
125  bool Contains(Vector3<Real> const& p) const;
126 
127 private:
128  // For all types of faces. The ray origin is the test point. The ray
129  // direction is one of those passed to the constructors. The plane origin
130  // is a point on the plane of the face. The plane normal is a unit-length
131  // normal to the face and that points outside the polyhedron.
132  static bool FastNoIntersect(Ray3<Real> const& ray,
133  Plane3<Real> const& plane);
134 
135  // For triangle faces.
136  bool ContainsT0(Vector3<Real> const& p) const;
137 
138  // For convex faces.
139  bool ContainsC0(Vector3<Real> const& p) const;
140  bool ContainsC1C2(Vector3<Real> const& p, unsigned int method) const;
141 
142  // For simple faces.
143  bool ContainsS0(Vector3<Real> const& p) const;
144  bool ContainsS1(Vector3<Real> const& p) const;
145 
148 
153 
154  unsigned int mMethod;
155  int mNumRays;
157 
158  // Temporary storage for those methods that reduce the problem to 2D
159  // point-in-polygon queries. The array stores the projections of
160  // face vertices onto the plane of the face. It is resized as needed.
161  mutable std::vector<Vector2<Real>> mProjVertices;
162 };
163 
164 
165 template <typename Real>
167  Vector3<Real> const* points, int numFaces, TriangleFace const* faces,
168  int numRays, Vector3<Real> const* directions)
169  :
170  mNumPoints(numPoints),
171  mPoints(points),
172  mNumFaces(numFaces),
173  mTFaces(faces),
174  mCFaces(nullptr),
175  mSFaces(nullptr),
176  mMethod(0),
177  mNumRays(numRays),
178  mDirections(directions)
179 {
180 }
181 
182 template <typename Real>
184  Vector3<Real> const* points, int numFaces, ConvexFace const* faces,
185  int numRays, Vector3<Real> const* directions, unsigned int method)
186  :
187  mNumPoints(numPoints),
188  mPoints(points),
189  mNumFaces(numFaces),
190  mTFaces(nullptr),
191  mCFaces(faces),
192  mSFaces(nullptr),
193  mMethod(method),
194  mNumRays(numRays),
195  mDirections(directions)
196 {
197 }
198 
199 template <typename Real>
201  Vector3<Real> const* points, int numFaces, SimpleFace const* faces,
202  int numRays, Vector3<Real> const* directions, unsigned int method)
203  :
204  mNumPoints(numPoints),
205  mPoints(points),
206  mNumFaces(numFaces),
207  mTFaces(nullptr),
208  mCFaces(nullptr),
209  mSFaces(faces),
210  mMethod(method),
211  mNumRays(numRays),
212  mDirections(directions)
213 {
214 }
215 
216 template <typename Real>
218 {
219  if (mTFaces)
220  {
221  return ContainsT0(p);
222  }
223 
224  if (mCFaces)
225  {
226  if (mMethod == 0)
227  {
228  return ContainsC0(p);
229  }
230 
231  return ContainsC1C2(p, mMethod);
232  }
233 
234  if (mSFaces)
235  {
236  if (mMethod == 0)
237  {
238  return ContainsS0(p);
239  }
240 
241  if (mMethod == 1)
242  {
243  return ContainsS1(p);
244  }
245  }
246 
247  return false;
248 }
249 
250 template <typename Real>
252  Plane3<Real> const& plane)
253 {
254  Real planeDistance = Dot(plane.normal, ray.origin) - plane.constant;
255  Real planeAngle = Dot(plane.normal, ray.direction);
256 
257  if (planeDistance < (Real)0)
258  {
259  // The ray origin is on the negative side of the plane.
260  if (planeAngle <= (Real)0)
261  {
262  // The ray points away from the plane.
263  return true;
264  }
265  }
266 
267  if (planeDistance >(Real)0)
268  {
269  // The ray origin is on the positive side of the plane.
270  if (planeAngle >= (Real)0)
271  {
272  // The ray points away from the plane.
273  return true;
274  }
275  }
276 
277  return false;
278 }
279 
280 template <typename Real>
282 {
283  int insideCount = 0;
284 
286  Triangle3<Real> triangle;
287  Ray3<Real> ray;
288  ray.origin = p;
289 
290  for (int j = 0; j < mNumRays; ++j)
291  {
292  ray.direction = mDirections[j];
293 
294  // Zero intersections to start with.
295  bool odd = false;
296 
297  TriangleFace const* face = mTFaces;
298  for (int i = 0; i < mNumFaces; ++i, ++face)
299  {
300  // Attempt to quickly cull the triangle.
301  if (FastNoIntersect(ray, face->plane))
302  {
303  continue;
304  }
305 
306  // Get the triangle vertices.
307  for (int k = 0; k < 3; ++k)
308  {
309  triangle.v[k] = mPoints[face->indices[k]];
310  }
311 
312  // Test for intersection.
313  if (rtQuery(ray, triangle).intersect)
314  {
315  // The ray intersects the triangle.
316  odd = !odd;
317  }
318  }
319 
320  if (odd)
321  {
322  insideCount++;
323  }
324  }
325 
326  return insideCount > mNumRays / 2;
327 }
328 
329 template <typename Real>
331 {
332  int insideCount = 0;
333 
335  Triangle3<Real> triangle;
336  Ray3<Real> ray;
337  ray.origin = p;
338 
339  for (int j = 0; j < mNumRays; ++j)
340  {
341  ray.direction = mDirections[j];
342 
343  // Zero intersections to start with.
344  bool odd = false;
345 
346  ConvexFace const* face = mCFaces;
347  for (int i = 0; i < mNumFaces; ++i, ++face)
348  {
349  // Attempt to quickly cull the triangle.
350  if (FastNoIntersect(ray, face->plane))
351  {
352  continue;
353  }
354 
355  // Process the triangles in a trifan of the face.
356  size_t numVerticesM1 = face->indices.size() - 1;
357  triangle.v[0] = mPoints[face->indices[0]];
358  for (size_t k = 1; k < numVerticesM1; ++k)
359  {
360  triangle.v[1] = mPoints[face->indices[k]];
361  triangle.v[2] = mPoints[face->indices[k + 1]];
362 
363  if (rtQuery(ray, triangle).intersect)
364  {
365  // The ray intersects the triangle.
366  odd = !odd;
367  }
368  }
369  }
370 
371  if (odd)
372  {
373  insideCount++;
374  }
375  }
376 
377  return insideCount > mNumRays / 2;
378 }
379 
380 template <typename Real>
382 {
383  int insideCount = 0;
384 
386  Triangle3<Real> triangle;
387  Ray3<Real> ray;
388  ray.origin = p;
389 
390  for (int j = 0; j < mNumRays; ++j)
391  {
392  ray.direction = mDirections[j];
393 
394  // Zero intersections to start with.
395  bool odd = false;
396 
397  SimpleFace const* face = mSFaces;
398  for (int i = 0; i < mNumFaces; ++i, ++face)
399  {
400  // Attempt to quickly cull the triangle.
401  if (FastNoIntersect(ray, face->plane))
402  {
403  continue;
404  }
405 
406  // The triangulation must exist to use it.
407  size_t numTriangles = face->triangles.size() / 3;
408  LogAssert(numTriangles > 0, "Triangulation must exist.");
409 
410  // Process the triangles in a triangulation of the face.
411  int const* currIndex = &face->triangles[0];
412  for (size_t t = 0; t < numTriangles; ++t)
413  {
414  // Get the triangle vertices.
415  for (int k = 0; k < 3; ++k)
416  {
417  triangle.v[k] = mPoints[*currIndex++];
418  }
419 
420  // Test for intersection.
421  if (rtQuery(ray, triangle).intersect)
422  {
423  // The ray intersects the triangle.
424  odd = !odd;
425  }
426  }
427  }
428 
429  if (odd)
430  {
431  insideCount++;
432  }
433  }
434 
435  return insideCount > mNumRays / 2;
436 }
437 
438 template <typename Real>
440  unsigned int method) const
441 {
442  int insideCount = 0;
443 
445  Ray3<Real> ray;
446  ray.origin = p;
447 
448  for (int j = 0; j < mNumRays; ++j)
449  {
450  ray.direction = mDirections[j];
451 
452  // Zero intersections to start with.
453  bool odd = false;
454 
455  ConvexFace const* face = mCFaces;
456  for (int i = 0; i < mNumFaces; ++i, ++face)
457  {
458  // Attempt to quickly cull the triangle.
459  if (FastNoIntersect(ray, face->plane))
460  {
461  continue;
462  }
463 
464  // Compute the ray-plane intersection.
465  auto result = rpQuery(ray, face->plane);
466 
467  // If you trigger this assertion, numerical round-off errors have
468  // led to a discrepancy between FastNoIntersect and the Find()
469  // result.
470  LogAssert(result.intersect, "Unexpected condition.");
471 
472  // Get a coordinate system for the plane. Use vertex 0 as the
473  // origin.
474  Vector3<Real> const& V0 = mPoints[face->indices[0]];
475  Vector3<Real> basis[3];
476  basis[0] = face->plane.normal;
477  ComputeOrthogonalComplement(1, basis);
478 
479  // Project the intersection onto the plane.
480  Vector3<Real> diff = result.point - V0;
481  Vector2<Real> projIntersect{
482  Dot(basis[1], diff), Dot(basis[2], diff) };
483 
484  // Project the face vertices onto the plane of the face.
485  if (face->indices.size() > mProjVertices.size())
486  {
487  mProjVertices.resize(face->indices.size());
488  }
489 
490  // Project the remaining vertices. Vertex 0 is always the origin.
491  size_t numIndices = face->indices.size();
493  for (size_t k = 1; k < numIndices; ++k)
494  {
495  diff = mPoints[face->indices[k]] - V0;
496  mProjVertices[k][0] = Dot(basis[1], diff);
497  mProjVertices[k][1] = Dot(basis[2], diff);
498  }
499 
500  // Test whether the intersection point is in the convex polygon.
501  PointInPolygon2<Real> PIP(static_cast<int>(mProjVertices.size()),
502  &mProjVertices[0]);
503 
504  if (method == 1)
505  {
506  if (PIP.ContainsConvexOrderN(projIntersect))
507  {
508  // The ray intersects the triangle.
509  odd = !odd;
510  }
511  }
512  else
513  {
514  if (PIP.ContainsConvexOrderLogN(projIntersect))
515  {
516  // The ray intersects the triangle.
517  odd = !odd;
518  }
519  }
520  }
521 
522  if (odd)
523  {
524  insideCount++;
525  }
526  }
527 
528  return insideCount > mNumRays / 2;
529 }
530 
531 template <typename Real>
533 {
534  int insideCount = 0;
535 
537  Ray3<Real> ray;
538  ray.origin = p;
539 
540  for (int j = 0; j < mNumRays; ++j)
541  {
542  ray.direction = mDirections[j];
543 
544  // Zero intersections to start with.
545  bool odd = false;
546 
547  SimpleFace const* face = mSFaces;
548  for (int i = 0; i < mNumFaces; ++i, ++face)
549  {
550  // Attempt to quickly cull the triangle.
551  if (FastNoIntersect(ray, face->plane))
552  {
553  continue;
554  }
555 
556  // Compute the ray-plane intersection.
557  auto result = rpQuery(ray, face->plane);
558 
559  // If you trigger this assertion, numerical round-off errors have
560  // led to a discrepancy between FastNoIntersect and the Find()
561  // result.
562  LogAssert(result.intersect, "Unexpected condition.");
563 
564  // Get a coordinate system for the plane. Use vertex 0 as the
565  // origin.
566  Vector3<Real> const& V0 = mPoints[face->indices[0]];
567  Vector3<Real> basis[3];
568  basis[0] = face->plane.normal;
569  ComputeOrthogonalComplement(1, basis);
570 
571  // Project the intersection onto the plane.
572  Vector3<Real> diff = result.point - V0;
573  Vector2<Real> projIntersect{
574  Dot(basis[1], diff), Dot(basis[2], diff) };
575 
576  // Project the face vertices onto the plane of the face.
577  if (face->indices.size() > mProjVertices.size())
578  {
579  mProjVertices.resize(face->indices.size());
580  }
581 
582  // Project the remaining vertices. Vertex 0 is always the origin.
583  size_t numIndices = face->indices.size();
585  for (size_t k = 1; k < numIndices; ++k)
586  {
587  diff = mPoints[face->indices[k]] - V0;
588  mProjVertices[k][0] = Dot(basis[1], diff);
589  mProjVertices[k][1] = Dot(basis[2], diff);
590  }
591 
592  // Test whether the intersection point is in the convex polygon.
593  PointInPolygon2<Real> PIP(static_cast<int>(mProjVertices.size()),
594  &mProjVertices[0]);
595 
596  if (PIP.Contains(projIntersect))
597  {
598  // The ray intersects the triangle.
599  odd = !odd;
600  }
601  }
602 
603  if (odd)
604  {
605  insideCount++;
606  }
607  }
608 
609  return insideCount > mNumRays / 2;
610 }
611 
612 
613 }
static bool FastNoIntersect(Ray3< Real > const &ray, Plane3< Real > const &plane)
Vector< N, Real > direction
Definition: GteRay.h:29
PointInPolyhedron3(int numPoints, Vector3< Real > const *points, int numFaces, TriangleFace const *faces, int numRays, Vector3< Real > const *directions)
#define LogAssert(condition, message)
Definition: GteLogger.h:86
bool Contains(Vector3< Real > const &p) const
Vector3< Real > const * mPoints
bool Contains(Vector2< Real > const &p) const
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
bool ContainsConvexOrderLogN(Vector2< Real > const &p) const
bool ContainsC0(Vector3< Real > const &p) const
bool ContainsT0(Vector3< Real > const &p) const
GLsizei GLenum const void * indices
Definition: glcorearb.h:401
Vector3< Real > const * mDirections
static Vector Zero()
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
bool ContainsConvexOrderN(Vector2< Real > const &p) const
GLdouble GLdouble t
Definition: glext.h:239
bool ContainsC1C2(Vector3< Real > const &p, unsigned int method) const
Vector< N, Real > normal
Definition: GteHyperplane.h:40
bool ContainsS1(Vector3< Real > const &p) const
std::vector< Vector2< Real > > mProjVertices
Vector< N, Real > origin
Definition: GteRay.h:29
Real ComputeOrthogonalComplement(int numInputs, Vector2< Real > *v, bool robust=false)
Definition: GteVector2.h:123
bool ContainsS0(Vector3< Real > const &p) const
GLfloat GLfloat p
Definition: glext.h:11668
std::array< Vector< N, Real >, 3 > v
Definition: GteTriangle.h:30
GLuint64EXT * result
Definition: glext.h:10003
GLenum GLuint GLint GLenum face
Definition: glext.h:3311


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