IntrOrientedBox2Sector2.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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/TIQuery.h>
  9. #include <Mathematics/OrientedBox.h>
  10. #include <Mathematics/DistPointSegment.h>
  11. #include <Mathematics/IntrHalfspace2Polygon2.h>
  12. #include <Mathematics/Sector2.h>
  13. // The OrientedBox2 object is considered to be a solid.
  14. namespace WwiseGTE
  15. {
  16. template <typename Real>
  17. class TIQuery<Real, OrientedBox2<Real>, Sector2<Real>>
  18. {
  19. public:
  20. struct Result
  21. {
  22. bool intersect;
  23. };
  24. Result operator()(OrientedBox2<Real> const& box, Sector2<Real> const& sector)
  25. {
  26. Result result;
  27. // Determine whether the vertex is inside the box.
  28. Vector2<Real> CmV = box.center - sector.vertex;
  29. Vector2<Real> P{ Dot(box.axis[0], CmV), Dot(box.axis[1], CmV) };
  30. if (std::fabs(P[0]) <= box.extent[0] && std::fabs(P[1]) <= box.extent[1])
  31. {
  32. // The vertex is inside the box.
  33. result.intersect = true;
  34. return result;
  35. }
  36. // Test whether the box is outside the right ray boundary of the
  37. // sector.
  38. Vector2<Real> U0
  39. {
  40. +sector.cosAngle * sector.direction[0] + sector.sinAngle * sector.direction[1],
  41. -sector.sinAngle * sector.direction[0] + sector.cosAngle * sector.direction[1]
  42. };
  43. Vector2<Real> N0 = Perp(U0);
  44. Real prjcen0 = Dot(N0, CmV);
  45. Real radius0 = box.extent[0] * std::fabs(Dot(N0, box.axis[0]))
  46. + box.extent[1] * std::fabs(Dot(N0, box.axis[1]));
  47. if (prjcen0 > radius0)
  48. {
  49. result.intersect = false;
  50. return result;
  51. }
  52. // Test whether the box is outside the ray of the left boundary
  53. // of the sector.
  54. Vector2<Real> U1
  55. {
  56. +sector.cosAngle * sector.direction[0] - sector.sinAngle * sector.direction[1],
  57. +sector.sinAngle * sector.direction[0] + sector.cosAngle * sector.direction[1]
  58. };
  59. Vector2<Real> N1 = -Perp(U1);
  60. Real prjcen1 = Dot(N1, CmV);
  61. Real radius1 = box.extent[0] * std::fabs(Dot(N1, box.axis[0]))
  62. + box.extent[1] * std::fabs(Dot(N1, box.axis[1]));
  63. if (prjcen1 > radius1)
  64. {
  65. result.intersect = false;
  66. return result;
  67. }
  68. // Initialize the polygon of intersection to be the box.
  69. Vector2<Real> e0U0 = box.extent[0] * box.axis[0];
  70. Vector2<Real> e1U1 = box.extent[1] * box.axis[1];
  71. std::vector<Vector2<Real>> polygon;
  72. polygon.reserve(8);
  73. polygon.push_back(box.center - e0U0 - e1U1);
  74. polygon.push_back(box.center + e0U0 - e1U1);
  75. polygon.push_back(box.center + e0U0 + e1U1);
  76. polygon.push_back(box.center - e0U0 + e1U1);
  77. FIQuery<Real, Halfspace<2, Real>, std::vector<Vector2<Real>>> hpQuery;
  78. typename FIQuery<Real, Halfspace<2, Real>, std::vector<Vector2<Real>>>::Result hpResult;
  79. Halfspace<2, Real> halfspace;
  80. // Clip the box against the right-ray sector boundary.
  81. if (prjcen0 >= -radius0)
  82. {
  83. halfspace.normal = -N0;
  84. halfspace.constant = Dot(halfspace.normal, sector.vertex);
  85. hpResult = hpQuery(halfspace, polygon);
  86. polygon = std::move(hpResult.polygon);
  87. }
  88. // Clip the box against the left-ray sector boundary.
  89. if (prjcen1 >= -radius1)
  90. {
  91. halfspace.normal = -N1;
  92. halfspace.constant = Dot(halfspace.normal, sector.vertex);
  93. hpResult = hpQuery(halfspace, polygon);
  94. polygon = std::move(hpResult.polygon);
  95. }
  96. DCPQuery<Real, Vector2<Real>, Segment2<Real>> psQuery;
  97. typename DCPQuery<Real, Vector2<Real>, Segment2<Real>>::Result psResult;
  98. int const numVertices = static_cast<int>(polygon.size());
  99. if (numVertices >= 2)
  100. {
  101. for (int i0 = numVertices - 1, i1 = 0; i1 < numVertices; i0 = i1++)
  102. {
  103. Segment2<Real> segment(polygon[i0], polygon[i1]);
  104. psResult = psQuery(sector.vertex, segment);
  105. if (psResult.distance <= sector.radius)
  106. {
  107. result.intersect = true;
  108. return result;
  109. }
  110. }
  111. }
  112. result.intersect = false;
  113. return result;
  114. }
  115. };
  116. }