IntrHalfspace2Polygon2.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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/FIQuery.h>
  9. #include <Mathematics/Halfspace.h>
  10. #include <Mathematics/OrientedBox.h>
  11. #include <Mathematics/Vector2.h>
  12. #include <vector>
  13. // The queries consider the box to be a solid and the polygon to be a
  14. // convex solid.
  15. namespace WwiseGTE
  16. {
  17. template <typename Real>
  18. class FIQuery<Real, Halfspace<2, Real>, std::vector<Vector2<Real>>>
  19. {
  20. public:
  21. struct Result
  22. {
  23. bool intersect;
  24. // If 'intersect' is true, the halfspace and polygon intersect
  25. // in a convex polygon.
  26. std::vector<Vector2<Real>> polygon;
  27. };
  28. Result operator()(Halfspace<2, Real> const& halfspace,
  29. std::vector<Vector2<Real>> const& polygon)
  30. {
  31. Result result;
  32. // Determine whether the polygon vertices are outside the
  33. // halfspace, inside the halfspace, or on the halfspace boundary.
  34. int const numVertices = static_cast<int>(polygon.size());
  35. std::vector<Real> distance(numVertices);
  36. int positive = 0, negative = 0, positiveIndex = -1;
  37. for (int i = 0; i < numVertices; ++i)
  38. {
  39. distance[i] = Dot(halfspace.normal, polygon[i]) - halfspace.constant;
  40. if (distance[i] > (Real)0)
  41. {
  42. ++positive;
  43. if (positiveIndex == -1)
  44. {
  45. positiveIndex = i;
  46. }
  47. }
  48. else if (distance[i] < (Real)0)
  49. {
  50. ++negative;
  51. }
  52. }
  53. if (positive == 0)
  54. {
  55. // The polygon is strictly outside the halfspace.
  56. result.intersect = false;
  57. return result;
  58. }
  59. if (negative == 0)
  60. {
  61. // The polygon is contained in the closed halfspace, so it is
  62. // fully visible and no clipping is necessary.
  63. result.intersect = true;
  64. return result;
  65. }
  66. // The line transversely intersects the polygon. Clip the polygon.
  67. Vector2<Real> vertex;
  68. int curr, prev;
  69. Real t;
  70. if (positiveIndex > 0)
  71. {
  72. // Compute the first clip vertex on the line.
  73. curr = positiveIndex;
  74. prev = curr - 1;
  75. t = distance[curr] / (distance[curr] - distance[prev]);
  76. vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
  77. result.polygon.push_back(vertex);
  78. // Include the vertices on the positive side of line.
  79. while (curr < numVertices && distance[curr] >(Real)0)
  80. {
  81. result.polygon.push_back(polygon[curr++]);
  82. }
  83. // Compute the kast clip vertex on the line.
  84. if (curr < numVertices)
  85. {
  86. prev = curr - 1;
  87. }
  88. else
  89. {
  90. curr = 0;
  91. prev = numVertices - 1;
  92. }
  93. t = distance[curr] / (distance[curr] - distance[prev]);
  94. vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
  95. result.polygon.push_back(vertex);
  96. }
  97. else // positiveIndex is 0
  98. {
  99. // Include the vertices on the positive side of line.
  100. curr = 0;
  101. while (curr < numVertices && distance[curr] >(Real)0)
  102. {
  103. result.polygon.push_back(polygon[curr++]);
  104. }
  105. // Compute the last clip vertex on the line.
  106. prev = curr - 1;
  107. t = distance[curr] / (distance[curr] - distance[prev]);
  108. vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
  109. result.polygon.push_back(vertex);
  110. // Skip the vertices on the negative side of the line.
  111. while (curr < numVertices && distance[curr] <= (Real)0)
  112. {
  113. curr++;
  114. }
  115. // Compute the first clip vertex on the line.
  116. if (curr < numVertices)
  117. {
  118. prev = curr - 1;
  119. t = distance[curr] / (distance[curr] - distance[prev]);
  120. vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
  121. result.polygon.push_back(vertex);
  122. // Keep the vertices on the positive side of the line.
  123. while (curr < numVertices && distance[curr] >(Real)0)
  124. {
  125. result.polygon.push_back(polygon[curr++]);
  126. }
  127. }
  128. else
  129. {
  130. curr = 0;
  131. prev = numVertices - 1;
  132. t = distance[curr] / (distance[curr] - distance[prev]);
  133. vertex = polygon[curr] + t * (polygon[prev] - polygon[curr]);
  134. result.polygon.push_back(vertex);
  135. }
  136. }
  137. result.intersect = true;
  138. return result;
  139. }
  140. };
  141. }