IntrRay2Ray2.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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/IntrLine2Line2.h>
  9. #include <Mathematics/Ray.h>
  10. namespace WwiseGTE
  11. {
  12. template <typename Real>
  13. class TIQuery<Real, Ray2<Real>, Ray2<Real>>
  14. {
  15. public:
  16. struct Result
  17. {
  18. bool intersect;
  19. // The number is 0 (no intersection), 1 (rays intersect in a
  20. // single point), 2 (rays are collinear and intersect in a
  21. // segment; ray directions are opposite of each other), or
  22. // std::numeric_limits<int>::max() (intersection is a ray; ray
  23. // directions are the same).
  24. int numIntersections;
  25. };
  26. Result operator()(Ray2<Real> const& ray0, Ray2<Real> const& ray1)
  27. {
  28. Result result;
  29. FIQuery<Real, Line2<Real>, Line2<Real>> llQuery;
  30. Line2<Real> line0(ray0.origin, ray0.direction);
  31. Line2<Real> line1(ray1.origin, ray1.direction);
  32. auto llResult = llQuery(line0, line1);
  33. if (llResult.numIntersections == 1)
  34. {
  35. // Test whether the line-line intersection is on the rays.
  36. if (llResult.line0Parameter[0] >= (Real)0
  37. && llResult.line1Parameter[0] >= (Real)0)
  38. {
  39. result.intersect = true;
  40. result.numIntersections = 1;
  41. }
  42. else
  43. {
  44. result.intersect = false;
  45. result.numIntersections = 0;
  46. }
  47. }
  48. else if (llResult.numIntersections == std::numeric_limits<int>::max())
  49. {
  50. if (Dot(ray0.direction, ray1.direction) > (Real)0)
  51. {
  52. // The rays are collinear and in the same direction, so
  53. // they must overlap.
  54. result.intersect = true;
  55. result.numIntersections = std::numeric_limits<int>::max();
  56. }
  57. else
  58. {
  59. // The rays are collinear but in opposite directions.
  60. // Test whether they overlap. Ray0 has interval
  61. // [0,+infinity) and ray1 has interval (-infinity,t]
  62. // relative to ray0.direction.
  63. Vector2<Real> diff = ray1.origin - ray0.origin;
  64. Real t = Dot(ray0.direction, diff);
  65. if (t > (Real)0)
  66. {
  67. result.intersect = true;
  68. result.numIntersections = 2;
  69. }
  70. else if (t < (Real)0)
  71. {
  72. result.intersect = false;
  73. result.numIntersections = 0;
  74. }
  75. else // t == 0
  76. {
  77. result.intersect = true;
  78. result.numIntersections = 1;
  79. }
  80. }
  81. }
  82. else
  83. {
  84. result.intersect = false;
  85. result.numIntersections = 0;
  86. }
  87. return result;
  88. }
  89. };
  90. template <typename Real>
  91. class FIQuery<Real, Ray2<Real>, Ray2<Real>>
  92. {
  93. public:
  94. struct Result
  95. {
  96. bool intersect;
  97. // The number is 0 (no intersection), 1 (rays intersect in a
  98. // single point), 2 (rays are collinear and intersect in a
  99. // segment; ray directions are opposite of each other), or
  100. // std::numeric_limits<int>::max() (intersection is a ray; ray
  101. // directions are the same).
  102. int numIntersections;
  103. // If numIntersections is 1, the intersection is
  104. // point[0] = ray0.origin + ray0Parameter[0] * ray0.direction
  105. // = ray1.origin + ray1Parameter[0] * ray1.direction
  106. // If numIntersections is 2, the segment of intersection is formed
  107. // by the ray origins,
  108. // ray0Parameter[0] = ray1Parameter[0] = 0
  109. // point[0] = ray0.origin
  110. // = ray1.origin + ray1Parameter[1] * ray1.direction
  111. // point[1] = ray1.origin
  112. // = ray0.origin + ray0Parameter[1] * ray0.direction
  113. // where ray0Parameter[1] >= 0 and ray1Parameter[1] >= 0.
  114. // If numIntersections is maxInt, let
  115. // ray1.origin = ray0.origin + t * ray0.direction
  116. // then
  117. // ray0Parameter[] = { max(t,0), +maxReal }
  118. // ray1Parameter[] = { -min(t,0), +maxReal }
  119. // point[0] = ray0.origin + ray0Parameter[0] * ray0.direction
  120. Real ray0Parameter[2], ray1Parameter[2];
  121. Vector2<Real> point[2];
  122. };
  123. Result operator()(Ray2<Real> const& ray0, Ray2<Real> const& ray1)
  124. {
  125. Result result;
  126. FIQuery<Real, Line2<Real>, Line2<Real>> llQuery;
  127. Line2<Real> line0(ray0.origin, ray0.direction);
  128. Line2<Real> line1(ray1.origin, ray1.direction);
  129. auto llResult = llQuery(line0, line1);
  130. if (llResult.numIntersections == 1)
  131. {
  132. // Test whether the line-line intersection is on the rays.
  133. if (llResult.line0Parameter[0] >= (Real)0
  134. && llResult.line1Parameter[0] >= (Real)0)
  135. {
  136. result.intersect = true;
  137. result.numIntersections = 1;
  138. result.ray0Parameter[0] = llResult.line0Parameter[0];
  139. result.ray1Parameter[0] = llResult.line1Parameter[0];
  140. result.point[0] = llResult.point;
  141. }
  142. else
  143. {
  144. result.intersect = false;
  145. result.numIntersections = 0;
  146. }
  147. }
  148. else if (llResult.numIntersections == std::numeric_limits<int>::max())
  149. {
  150. // Compute t for which ray1.origin =
  151. // ray0.origin + t*ray0.direction.
  152. Real maxReal = std::numeric_limits<Real>::max();
  153. Vector2<Real> diff = ray1.origin - ray0.origin;
  154. Real t = Dot(ray0.direction, diff);
  155. if (Dot(ray0.direction, ray1.direction) > (Real)0)
  156. {
  157. // The rays are collinear and in the same direction, so
  158. // they must overlap.
  159. result.intersect = true;
  160. result.numIntersections = std::numeric_limits<int>::max();
  161. if (t >= (Real)0)
  162. {
  163. result.ray0Parameter[0] = t;
  164. result.ray0Parameter[1] = maxReal;
  165. result.ray1Parameter[0] = (Real)0;
  166. result.ray1Parameter[1] = maxReal;
  167. result.point[0] = ray1.origin;
  168. }
  169. else
  170. {
  171. result.ray0Parameter[0] = (Real)0;
  172. result.ray0Parameter[1] = maxReal;
  173. result.ray1Parameter[0] = -t;
  174. result.ray1Parameter[1] = maxReal;
  175. result.point[0] = ray0.origin;
  176. }
  177. }
  178. else
  179. {
  180. // The rays are collinear but in opposite directions.
  181. // Test whether they overlap. Ray0 has interval
  182. // [0,+infinity) and ray1 has interval (-infinity,t1]
  183. // relative to ray0.direction.
  184. if (t >= (Real)0)
  185. {
  186. result.intersect = true;
  187. result.numIntersections = 2;
  188. result.ray0Parameter[0] = (Real)0;
  189. result.ray0Parameter[1] = t;
  190. result.ray1Parameter[0] = (Real)0;
  191. result.ray1Parameter[1] = t;
  192. result.point[0] = ray0.origin;
  193. result.point[1] = ray1.origin;
  194. }
  195. else
  196. {
  197. result.intersect = false;
  198. result.numIntersections = 0;
  199. }
  200. }
  201. }
  202. else
  203. {
  204. result.intersect = false;
  205. result.numIntersections = 0;
  206. }
  207. return result;
  208. }
  209. };
  210. }