ContPointInPolygon2.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Vector2.h>
  9. // Given a polygon as an order list of vertices (x[i],y[i]) for 0 <= i < N
  10. // and a test point (xt,yt), return 'true' if (xt,yt) is in the polygon and
  11. // 'false' if it is not. All queries require that the number of vertices
  12. // satisfies N >= 3.
  13. namespace WwiseGTE
  14. {
  15. template <typename Real>
  16. class PointInPolygon2
  17. {
  18. public:
  19. // The class object stores a copy of 'points', so be careful about
  20. // the persistence of 'points' when you have created a
  21. // PointInPolygon2 object.
  22. PointInPolygon2(int numPoints, Vector2<Real> const* points)
  23. :
  24. mNumPoints(numPoints),
  25. mPoints(points)
  26. {
  27. }
  28. // Simple polygons (ray-intersection counting).
  29. bool Contains(Vector2<Real> const& p) const
  30. {
  31. bool inside = false;
  32. for (int i = 0, j = mNumPoints - 1; i < mNumPoints; j = i++)
  33. {
  34. Vector2<Real> const& U0 = mPoints[i];
  35. Vector2<Real> const& U1 = mPoints[j];
  36. Real rhs, lhs;
  37. if (p[1] < U1[1]) // U1 above ray
  38. {
  39. if (U0[1] <= p[1]) // U0 on or below ray
  40. {
  41. lhs = (p[1] - U0[1]) * (U1[0] - U0[0]);
  42. rhs = (p[0] - U0[0]) * (U1[1] - U0[1]);
  43. if (lhs > rhs)
  44. {
  45. inside = !inside;
  46. }
  47. }
  48. }
  49. else if (p[1] < U0[1]) // U1 on or below ray, U0 above ray
  50. {
  51. lhs = (p[1] - U0[1]) * (U1[0] - U0[0]);
  52. rhs = (p[0] - U0[0]) * (U1[1] - U0[1]);
  53. if (lhs < rhs)
  54. {
  55. inside = !inside;
  56. }
  57. }
  58. }
  59. return inside;
  60. }
  61. // Algorithms for convex polygons. The input polygons must have
  62. // vertices in counterclockwise order.
  63. // O(N) algorithm (which-side-of-edge tests)
  64. bool ContainsConvexOrderN(Vector2<Real> const& p) const
  65. {
  66. for (int i1 = 0, i0 = mNumPoints - 1; i1 < mNumPoints; i0 = i1++)
  67. {
  68. Real nx = mPoints[i1][1] - mPoints[i0][1];
  69. Real ny = mPoints[i0][0] - mPoints[i1][0];
  70. Real dx = p[0] - mPoints[i0][0];
  71. Real dy = p[1] - mPoints[i0][1];
  72. if (nx * dx + ny * dy > (Real)0)
  73. {
  74. return false;
  75. }
  76. }
  77. return true;
  78. }
  79. // O(log N) algorithm (bisection and recursion, like BSP tree)
  80. bool ContainsConvexOrderLogN(Vector2<Real> const& p) const
  81. {
  82. return SubContainsPoint(p, 0, 0);
  83. }
  84. // The polygon must have exactly four vertices. This method is like
  85. // the O(log N) and uses three which-side-of-segment test instead of
  86. // four which-side-of-edge tests. If the polygon does not have four
  87. // vertices, the function returns false.
  88. bool ContainsQuadrilateral(Vector2<Real> const& p) const
  89. {
  90. if (mNumPoints != 4)
  91. {
  92. return false;
  93. }
  94. Real nx = mPoints[2][1] - mPoints[0][1];
  95. Real ny = mPoints[0][0] - mPoints[2][0];
  96. Real dx = p[0] - mPoints[0][0];
  97. Real dy = p[1] - mPoints[0][1];
  98. if (nx * dx + ny * dy > (Real)0)
  99. {
  100. // P potentially in <V0,V1,V2>
  101. nx = mPoints[1][1] - mPoints[0][1];
  102. ny = mPoints[0][0] - mPoints[1][0];
  103. if (nx * dx + ny * dy > (Real)0.0)
  104. {
  105. return false;
  106. }
  107. nx = mPoints[2][1] - mPoints[1][1];
  108. ny = mPoints[1][0] - mPoints[2][0];
  109. dx = p[0] - mPoints[1][0];
  110. dy = p[1] - mPoints[1][1];
  111. if (nx * dx + ny * dy > (Real)0)
  112. {
  113. return false;
  114. }
  115. }
  116. else
  117. {
  118. // P potentially in <V0,V2,V3>
  119. nx = mPoints[0][1] - mPoints[3][1];
  120. ny = mPoints[3][0] - mPoints[0][0];
  121. if (nx * dx + ny * dy > (Real)0)
  122. {
  123. return false;
  124. }
  125. nx = mPoints[3][1] - mPoints[2][1];
  126. ny = mPoints[2][0] - mPoints[3][0];
  127. dx = p[0] - mPoints[3][0];
  128. dy = p[1] - mPoints[3][1];
  129. if (nx * dx + ny * dy > (Real)0)
  130. {
  131. return false;
  132. }
  133. }
  134. return true;
  135. }
  136. private:
  137. // For recursion in ContainsConvexOrderLogN.
  138. bool SubContainsPoint(Vector2<Real> const& p, int i0, int i1) const
  139. {
  140. Real nx, ny, dx, dy;
  141. int diff = i1 - i0;
  142. if (diff == 1 || (diff < 0 && diff + mNumPoints == 1))
  143. {
  144. nx = mPoints[i1][1] - mPoints[i0][1];
  145. ny = mPoints[i0][0] - mPoints[i1][0];
  146. dx = p[0] - mPoints[i0][0];
  147. dy = p[1] - mPoints[i0][1];
  148. return nx * dx + ny * dy <= (Real)0;
  149. }
  150. // Bisect the index range.
  151. int mid;
  152. if (i0 < i1)
  153. {
  154. mid = (i0 + i1) >> 1;
  155. }
  156. else
  157. {
  158. mid = (i0 + i1 + mNumPoints) >> 1;
  159. if (mid >= mNumPoints)
  160. {
  161. mid -= mNumPoints;
  162. }
  163. }
  164. // Determine which side of the splitting line contains the point.
  165. nx = mPoints[mid][1] - mPoints[i0][1];
  166. ny = mPoints[i0][0] - mPoints[mid][0];
  167. dx = p[0] - mPoints[i0][0];
  168. dy = p[1] - mPoints[i0][1];
  169. if (nx * dx + ny * dy > (Real)0)
  170. {
  171. // P potentially in <V(i0),V(i0+1),...,V(mid-1),V(mid)>
  172. return SubContainsPoint(p, i0, mid);
  173. }
  174. else
  175. {
  176. // P potentially in <V(mid),V(mid+1),...,V(i1-1),V(i1)>
  177. return SubContainsPoint(p, mid, i1);
  178. }
  179. }
  180. int mNumPoints;
  181. Vector2<Real> const* mPoints;
  182. };
  183. }