IntrLine2Triangle2.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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/TIQuery.h>
  10. #include <Mathematics/Line.h>
  11. #include <Mathematics/Triangle.h>
  12. #include <Mathematics/Vector2.h>
  13. // The queries consider the triangle to be a solid.
  14. namespace WwiseGTE
  15. {
  16. template <typename Real>
  17. class TIQuery<Real, Line2<Real>, Triangle2<Real>>
  18. {
  19. public:
  20. struct Result
  21. {
  22. bool intersect;
  23. };
  24. Result operator()(Line2<Real> const& line, Triangle2<Real> const& triangle)
  25. {
  26. Result result;
  27. // Determine on which side of the line the vertices lie. The
  28. // table of possibilities is listed next with n = numNegative,
  29. // p = numPositive and z = numZero.
  30. //
  31. // n p z intersection
  32. // ------------------------------------
  33. // 0 3 0 none
  34. // 0 2 1 vertex
  35. // 0 1 2 edge
  36. // 0 0 3 none (degenerate triangle)
  37. // 1 2 0 segment (2 edges clipped)
  38. // 1 1 1 segment (1 edge clipped)
  39. // 1 0 2 edge
  40. // 2 1 0 segment (2 edges clipped)
  41. // 2 0 1 vertex
  42. // 3 0 0 none
  43. Real s[3];
  44. int numPositive = 0, numNegative = 0, numZero = 0;
  45. for (int i = 0; i < 3; ++i)
  46. {
  47. Vector2<Real> diff = triangle.v[i] - line.origin;
  48. s[i] = DotPerp(line.direction, diff);
  49. if (s[i] > (Real)0)
  50. {
  51. ++numPositive;
  52. }
  53. else if (s[i] < (Real)0)
  54. {
  55. ++numNegative;
  56. }
  57. else
  58. {
  59. ++numZero;
  60. }
  61. }
  62. result.intersect =
  63. (numZero == 0 && (numPositive == 0 || numNegative == 0)) ||
  64. (numZero == 3);
  65. return result;
  66. }
  67. };
  68. template <typename Real>
  69. class FIQuery<Real, Line2<Real>, Triangle2<Real>>
  70. {
  71. public:
  72. struct Result
  73. {
  74. bool intersect;
  75. int numIntersections;
  76. std::array<Real, 2> parameter;
  77. std::array<Vector2<Real>, 2> point;
  78. };
  79. Result operator()(Line2<Real> const& line, Triangle2<Real> const& triangle)
  80. {
  81. Result result;
  82. DoQuery(line.origin, line.direction, triangle, result);
  83. for (int i = 0; i < result.numIntersections; ++i)
  84. {
  85. result.point[i] = line.origin + result.parameter[i] * line.direction;
  86. }
  87. return result;
  88. }
  89. protected:
  90. void DoQuery(Vector2<Real> const& lineOrigin,
  91. Vector2<Real> const& lineDirection, Triangle2<Real> const& triangle,
  92. Result& result)
  93. {
  94. // Determine on which side of the line the vertices lie. The
  95. // table of possibilities is listed next with n = numNegative,
  96. // p = numPositive and z = numZero.
  97. //
  98. // n p z intersection
  99. // ------------------------------------
  100. // 0 3 0 none
  101. // 0 2 1 vertex
  102. // 0 1 2 edge
  103. // 0 0 3 none (degenerate triangle)
  104. // 1 2 0 segment (2 edges clipped)
  105. // 1 1 1 segment (1 edge clipped)
  106. // 1 0 2 edge
  107. // 2 1 0 segment (2 edges clipped)
  108. // 2 0 1 vertex
  109. // 3 0 0 none
  110. Real s[3];
  111. int numPositive = 0, numNegative = 0, numZero = 0;
  112. for (int i = 0; i < 3; ++i)
  113. {
  114. Vector2<Real> diff = triangle.v[i] - lineOrigin;
  115. s[i] = DotPerp(lineDirection, diff);
  116. if (s[i] > (Real)0)
  117. {
  118. ++numPositive;
  119. }
  120. else if (s[i] < (Real)0)
  121. {
  122. ++numNegative;
  123. }
  124. else
  125. {
  126. ++numZero;
  127. }
  128. }
  129. if (numZero == 0 && numPositive > 0 && numNegative > 0)
  130. {
  131. result.intersect = true;
  132. result.numIntersections = 2;
  133. Real sign = (Real)3 - numPositive * (Real)2;
  134. for (int i0 = 0; i0 < 3; ++i0)
  135. {
  136. if (sign * s[i0] > (Real)0)
  137. {
  138. int i1 = (i0 + 1) % 3, i2 = (i0 + 2) % 3;
  139. Real s1 = s[i1] / (s[i1] - s[i0]);
  140. Vector2<Real> p1 = (triangle.v[i1] - lineOrigin) +
  141. s1 * (triangle.v[i0] - triangle.v[i1]);
  142. result.parameter[0] = Dot(lineDirection, p1);
  143. Real s2 = s[i2] / (s[i2] - s[i0]);
  144. Vector2<Real> p2 = (triangle.v[i2] - lineOrigin) +
  145. s2 * (triangle.v[i0] - triangle.v[i2]);
  146. result.parameter[1] = Dot(lineDirection, p2);
  147. break;
  148. }
  149. }
  150. return;
  151. }
  152. if (numZero == 1)
  153. {
  154. result.intersect = true;
  155. for (int i0 = 0; i0 < 3; ++i0)
  156. {
  157. if (s[i0] == (Real)0)
  158. {
  159. int i1 = (i0 + 1) % 3, i2 = (i0 + 2) % 3;
  160. result.parameter[0] =
  161. Dot(lineDirection, triangle.v[i0] - lineOrigin);
  162. if (numPositive == 2 || numNegative == 2)
  163. {
  164. result.numIntersections = 1;
  165. // Used by derived classes.
  166. result.parameter[1] = result.parameter[0];
  167. }
  168. else
  169. {
  170. result.numIntersections = 2;
  171. Real s1 = s[i1] / (s[i1] - s[i2]);
  172. Vector2<Real> p1 = (triangle.v[i1] - lineOrigin) +
  173. s1 * (triangle.v[i2] - triangle.v[i1]);
  174. result.parameter[1] = Dot(lineDirection, p1);
  175. }
  176. break;
  177. }
  178. }
  179. return;
  180. }
  181. if (numZero == 2)
  182. {
  183. result.intersect = true;
  184. result.numIntersections = 2;
  185. for (int i0 = 0; i0 < 3; ++i0)
  186. {
  187. if (s[i0] != (Real)0)
  188. {
  189. int i1 = (i0 + 1) % 3, i2 = (i0 + 2) % 3;
  190. result.parameter[0] =
  191. Dot(lineDirection, triangle.v[i1] - lineOrigin);
  192. result.parameter[1] =
  193. Dot(lineDirection, triangle.v[i2] - lineOrigin);
  194. break;
  195. }
  196. }
  197. return;
  198. }
  199. // (n,p,z) one of (3,0,0), (0,3,0), (0,0,3)
  200. result.intersect = false;
  201. result.numIntersections = 0;
  202. }
  203. };
  204. }