IntrSegment2Segment2.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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/Segment.h>
  9. #include <Mathematics/IntrIntervals.h>
  10. #include <Mathematics/IntrLine2Line2.h>
  11. namespace WwiseGTE
  12. {
  13. template <typename Real>
  14. class TIQuery<Real, Segment2<Real>, Segment2<Real>>
  15. {
  16. public:
  17. struct Result
  18. {
  19. bool intersect;
  20. // The number is 0 (no intersection), 1 (segments intersect in a
  21. // single point), or 2 (segments are collinear and intersect in a
  22. // segment).
  23. int numIntersections;
  24. };
  25. Result operator()(Segment2<Real> const& segment0, Segment2<Real> const& segment1)
  26. {
  27. Result result;
  28. Vector2<Real> seg0Origin, seg0Direction, seg1Origin, seg1Direction;
  29. Real seg0Extent, seg1Extent;
  30. segment0.GetCenteredForm(seg0Origin, seg0Direction, seg0Extent);
  31. segment1.GetCenteredForm(seg1Origin, seg1Direction, seg1Extent);
  32. FIQuery<Real, Line2<Real>, Line2<Real>> llQuery;
  33. Line2<Real> line0(seg0Origin, seg0Direction);
  34. Line2<Real> line1(seg1Origin, seg1Direction);
  35. auto llResult = llQuery(line0, line1);
  36. if (llResult.numIntersections == 1)
  37. {
  38. // Test whether the line-line intersection is on the segments.
  39. if (std::fabs(llResult.line0Parameter[0]) <= seg0Extent
  40. && std::fabs(llResult.line1Parameter[0]) <= seg1Extent)
  41. {
  42. result.intersect = true;
  43. result.numIntersections = 1;
  44. }
  45. else
  46. {
  47. result.intersect = false;
  48. result.numIntersections = 0;
  49. }
  50. }
  51. else if (llResult.numIntersections == std::numeric_limits<int>::max())
  52. {
  53. // Compute the location of segment1 endpoints relative to
  54. // segment0.
  55. Vector2<Real> diff = seg1Origin - seg0Origin;
  56. Real t = Dot(seg0Direction, diff);
  57. // Get the parameter intervals of the segments relative to
  58. // segment0.
  59. std::array<Real, 2> interval0 = { -seg0Extent, seg0Extent };
  60. std::array<Real, 2> interval1 = { t - seg1Extent, t + seg1Extent };
  61. // Compute the intersection of the intervals.
  62. FIQuery<Real, std::array<Real, 2>, std::array<Real, 2>> iiQuery;
  63. auto iiResult = iiQuery(interval0, interval1);
  64. result.intersect = iiResult.intersect;
  65. result.numIntersections = iiResult.numIntersections;
  66. }
  67. else
  68. {
  69. result.intersect = false;
  70. result.numIntersections = 0;
  71. }
  72. return result;
  73. }
  74. };
  75. template <typename Real>
  76. class FIQuery<Real, Segment2<Real>, Segment2<Real>>
  77. {
  78. public:
  79. struct Result
  80. {
  81. bool intersect;
  82. // The number is 0 (no intersection), 1 (segments intersect in a
  83. // a single point), or 2 (segments are collinear and intersect
  84. // in a segment).
  85. int numIntersections;
  86. // If numIntersections is 1, the intersection is
  87. // point[0]
  88. // = segment0.origin + segment0Parameter[0] * segment0.direction
  89. // = segment1.origin + segment1Parameter[0] * segment1.direction
  90. // If numIntersections is 2, the endpoints of the segment of
  91. // intersection are
  92. // point[i]
  93. // = segment0.origin + segment0Parameter[i] * segment0.direction
  94. // = segment1.origin + segment1Parameter[i] * segment1.direction
  95. // with segment0Parameter[0] <= segment0Parameter[1] and
  96. // segment1Parameter[0] <= segment1Parameter[1].
  97. Real segment0Parameter[2], segment1Parameter[2];
  98. Vector2<Real> point[2];
  99. };
  100. Result operator()(Segment2<Real> const& segment0, Segment2<Real> const& segment1)
  101. {
  102. Result result;
  103. Vector2<Real> seg0Origin, seg0Direction, seg1Origin, seg1Direction;
  104. Real seg0Extent, seg1Extent;
  105. segment0.GetCenteredForm(seg0Origin, seg0Direction, seg0Extent);
  106. segment1.GetCenteredForm(seg1Origin, seg1Direction, seg1Extent);
  107. FIQuery<Real, Line2<Real>, Line2<Real>> llQuery;
  108. Line2<Real> line0(seg0Origin, seg0Direction);
  109. Line2<Real> line1(seg1Origin, seg1Direction);
  110. auto llResult = llQuery(line0, line1);
  111. if (llResult.numIntersections == 1)
  112. {
  113. // Test whether the line-line intersection is on the segments.
  114. if (std::fabs(llResult.line0Parameter[0]) <= seg0Extent
  115. && std::fabs(llResult.line1Parameter[0]) <= seg1Extent)
  116. {
  117. result.intersect = true;
  118. result.numIntersections = 1;
  119. result.segment0Parameter[0] = llResult.line0Parameter[0];
  120. result.segment1Parameter[0] = llResult.line1Parameter[0];
  121. result.point[0] = llResult.point;
  122. }
  123. else
  124. {
  125. result.intersect = false;
  126. result.numIntersections = 0;
  127. }
  128. }
  129. else if (llResult.numIntersections == std::numeric_limits<int>::max())
  130. {
  131. // Compute the location of segment1 endpoints relative to
  132. // segment0.
  133. Vector2<Real> diff = seg1Origin - seg0Origin;
  134. Real t = Dot(seg0Direction, diff);
  135. // Get the parameter intervals of the segments relative to
  136. // segment0.
  137. std::array<Real, 2> interval0 = { -seg0Extent, seg0Extent };
  138. std::array<Real, 2> interval1 = { t - seg1Extent, t + seg1Extent };
  139. // Compute the intersection of the intervals.
  140. FIQuery<Real, std::array<Real, 2>, std::array<Real, 2>> iiQuery;
  141. auto iiResult = iiQuery(interval0, interval1);
  142. if (iiResult.intersect)
  143. {
  144. result.intersect = true;
  145. result.numIntersections = iiResult.numIntersections;
  146. for (int i = 0; i < iiResult.numIntersections; ++i)
  147. {
  148. result.segment0Parameter[i] = iiResult.overlap[i];
  149. result.segment1Parameter[i] = iiResult.overlap[i] - t;
  150. result.point[i] = seg0Origin +
  151. result.segment0Parameter[i] * seg0Direction;
  152. }
  153. }
  154. else
  155. {
  156. result.intersect = false;
  157. result.numIntersections = 0;
  158. }
  159. }
  160. else
  161. {
  162. result.intersect = false;
  163. result.numIntersections = 0;
  164. }
  165. return result;
  166. }
  167. };
  168. }