IntrLine2Line2.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. #include <Mathematics/Line.h>
  10. #include <Mathematics/FIQuery.h>
  11. #include <Mathematics/TIQuery.h>
  12. #include <limits>
  13. namespace WwiseGTE
  14. {
  15. template <typename Real>
  16. class TIQuery<Real, Line2<Real>, Line2<Real>>
  17. {
  18. public:
  19. struct Result
  20. {
  21. bool intersect;
  22. // The number is 0 (no intersection), 1 (lines intersect in a
  23. // single point) or std::numeric_limits<int>::max() (lines are
  24. // the same).
  25. int numIntersections;
  26. };
  27. Result operator()(Line2<Real> const& line0, Line2<Real> const& line1)
  28. {
  29. Result result;
  30. // The intersection of two lines is a solution to P0 + s0*D0 =
  31. // P1 + s1*D1. Rewrite this as s0*D0 - s1*D1 = P1 - P0 = Q. If
  32. // DotPerp(D0, D1)) = 0, the lines are parallel. Additionally, if
  33. // DotPerp(Q, D1)) = 0, the lines are the same. If
  34. // Dotperp(D0, D1)) is not zero, then
  35. // s0 = DotPerp(Q, D1))/DotPerp(D0, D1))
  36. // produces the point of intersection. Also,
  37. // s1 = DotPerp(Q, D0))/DotPerp(D0, D1))
  38. Vector2<Real> diff = line1.origin - line0.origin;
  39. Real D0DotPerpD1 = DotPerp(line0.direction, line1.direction);
  40. if (D0DotPerpD1 != (Real)0)
  41. {
  42. // The lines are not parallel.
  43. result.intersect = true;
  44. result.numIntersections = 1;
  45. }
  46. else
  47. {
  48. // The lines are parallel.
  49. Normalize(diff);
  50. Real diffNDotPerpD1 = DotPerp(diff, line1.direction);
  51. if (diffNDotPerpD1 != (Real)0)
  52. {
  53. // The lines are parallel but distinct.
  54. result.intersect = false;
  55. result.numIntersections = 0;
  56. }
  57. else
  58. {
  59. // The lines are the same.
  60. result.intersect = true;
  61. result.numIntersections = std::numeric_limits<int>::max();
  62. }
  63. }
  64. return result;
  65. }
  66. };
  67. template <typename Real>
  68. class FIQuery<Real, Line2<Real>, Line2<Real>>
  69. {
  70. public:
  71. struct Result
  72. {
  73. bool intersect;
  74. // The number is 0 (no intersection), 1 (lines intersect in a
  75. // single point) or std::numeric_limits<int>::max() (lines are
  76. // the same).
  77. int numIntersections;
  78. // If numIntersections is 1, the intersection is
  79. // point = line0.origin + line0parameter[0] * line0.direction
  80. // = line1.origin + line1parameter[0] * line1.direction
  81. // If numIntersections is maxInt, point is not valid but the
  82. // intervals are
  83. // line0Parameter[] = { -maxReal, +maxReal }
  84. // line1Parameter[] = { -maxReal, +maxReal }
  85. Real line0Parameter[2], line1Parameter[2];
  86. Vector2<Real> point;
  87. };
  88. Result operator()(Line2<Real> const& line0, Line2<Real> const& line1)
  89. {
  90. Result result;
  91. // The intersection of two lines is a solution to P0 + s0*D0 =
  92. // P1 + s1*D1. Rewrite this as s0*D0 - s1*D1 = P1 - P0 = Q. If
  93. // DotPerp(D0, D1)) = 0, the lines are parallel. Additionally, if
  94. // DotPerp(Q, D1)) = 0, the lines are the same. If
  95. // Dotperp(D0, D1)) is not zero, then
  96. // s0 = DotPerp(Q, D1))/DotPerp(D0, D1))
  97. // produces the point of intersection. Also,
  98. // s1 = DotPerp(Q, D0))/DotPerp(D0, D1))
  99. Vector2<Real> diff = line1.origin - line0.origin;
  100. Real D0DotPerpD1 = DotPerp(line0.direction, line1.direction);
  101. if (D0DotPerpD1 != (Real)0)
  102. {
  103. // The lines are not parallel.
  104. result.intersect = true;
  105. result.numIntersections = 1;
  106. Real invD0DotPerpD1 = (Real)1 / D0DotPerpD1;
  107. Real diffDotPerpD0 = DotPerp(diff, line0.direction);
  108. Real diffDotPerpD1 = DotPerp(diff, line1.direction);
  109. Real s0 = diffDotPerpD1 * invD0DotPerpD1;
  110. Real s1 = diffDotPerpD0 * invD0DotPerpD1;
  111. result.line0Parameter[0] = s0;
  112. result.line1Parameter[0] = s1;
  113. result.point = line0.origin + s0 * line0.direction;
  114. }
  115. else
  116. {
  117. // The lines are parallel.
  118. Normalize(diff);
  119. Real diffNDotPerpD1 = DotPerp(diff, line1.direction);
  120. if (std::fabs(diffNDotPerpD1) != (Real)0)
  121. {
  122. // The lines are parallel but distinct.
  123. result.intersect = false;
  124. result.numIntersections = 0;
  125. }
  126. else
  127. {
  128. // The lines are the same.
  129. result.intersect = true;
  130. result.numIntersections = std::numeric_limits<int>::max();
  131. Real maxReal = std::numeric_limits<Real>::max();
  132. result.line0Parameter[0] = -maxReal;
  133. result.line0Parameter[1] = +maxReal;
  134. result.line1Parameter[0] = -maxReal;
  135. result.line1Parameter[1] = +maxReal;
  136. }
  137. }
  138. return result;
  139. }
  140. };
  141. }