IntrLine3Ellipsoid3.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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/Hyperellipsoid.h>
  11. #include <Mathematics/Line.h>
  12. #include <Mathematics/Matrix3x3.h>
  13. // The queries consider the ellipsoid to be a solid.
  14. namespace WwiseGTE
  15. {
  16. template <typename Real>
  17. class TIQuery<Real, Line3<Real>, Ellipsoid3<Real>>
  18. {
  19. public:
  20. struct Result
  21. {
  22. bool intersect;
  23. };
  24. Result operator()(Line3<Real> const& line, Ellipsoid3<Real> const& ellipsoid)
  25. {
  26. // The ellipsoid is (X-K)^T*M*(X-K)-1 = 0 and the line is
  27. // X = P+t*D. Substitute the line equation into the ellipsoid
  28. // equation to obtain a quadratic equation
  29. // Q(t) = a2*t^2 + 2*a1*t + a0 = 0
  30. // where a2 = D^T*M*D, a1 = D^T*M*(P-K) and
  31. // a0 = (P-K)^T*M*(P-K)-1.
  32. Result result;
  33. Matrix3x3<Real> M;
  34. ellipsoid.GetM(M);
  35. Vector3<Real> diff = line.origin - ellipsoid.center;
  36. Vector3<Real> matDir = M * line.direction;
  37. Vector3<Real> matDiff = M * diff;
  38. Real a2 = Dot(line.direction, matDir);
  39. Real a1 = Dot(line.direction, matDiff);
  40. Real a0 = Dot(diff, matDiff) - (Real)1;
  41. // Intersection occurs when Q(t) has real roots.
  42. Real discr = a1 * a1 - a0 * a2;
  43. result.intersect = (discr >= (Real)0);
  44. return result;
  45. }
  46. };
  47. template <typename Real>
  48. class FIQuery<Real, Line3<Real>, Ellipsoid3<Real>>
  49. {
  50. public:
  51. struct Result
  52. {
  53. bool intersect;
  54. int numIntersections;
  55. std::array<Real, 2> parameter;
  56. std::array<Vector3<Real>, 2> point;
  57. };
  58. Result operator()(Line3<Real> const& line, Ellipsoid3<Real> const& ellipsoid)
  59. {
  60. Result result;
  61. DoQuery(line.origin, line.direction, ellipsoid, result);
  62. for (int i = 0; i < result.numIntersections; ++i)
  63. {
  64. result.point[i] = line.origin + result.parameter[i] * line.direction;
  65. }
  66. return result;
  67. }
  68. protected:
  69. void DoQuery(Vector3<Real> const& lineOrigin,
  70. Vector3<Real> const& lineDirection, Ellipsoid3<Real> const& ellipsoid,
  71. Result& result)
  72. {
  73. // The ellipsoid is (X-K)^T*M*(X-K)-1 = 0 and the line is
  74. // X = P+t*D. Substitute the line equation into the ellipsoid
  75. // equation to obtain a quadratic equation
  76. // Q(t) = a2*t^2 + 2*a1*t + a0 = 0
  77. // where a2 = D^T*M*D, a1 = D^T*M*(P-K) and
  78. // a0 = (P-K)^T*M*(P-K)-1.
  79. Matrix3x3<Real> M;
  80. ellipsoid.GetM(M);
  81. Vector3<Real> diff = lineOrigin - ellipsoid.center;
  82. Vector3<Real> matDir = M * lineDirection;
  83. Vector3<Real> matDiff = M * diff;
  84. Real a2 = Dot(lineDirection, matDir);
  85. Real a1 = Dot(lineDirection, matDiff);
  86. Real a0 = Dot(diff, matDiff) - (Real)1;
  87. // Intersection occurs when Q(t) has real roots.
  88. Real discr = a1 * a1 - a0 * a2;
  89. if (discr > (Real)0)
  90. {
  91. result.intersect = true;
  92. result.numIntersections = 2;
  93. Real root = std::sqrt(discr);
  94. Real inv = (Real)1 / a2;
  95. result.parameter[0] = (-a1 - root) * inv;
  96. result.parameter[1] = (-a1 + root) * inv;
  97. }
  98. else if (discr < (Real)0)
  99. {
  100. result.intersect = false;
  101. result.numIntersections = 0;
  102. }
  103. else
  104. {
  105. result.intersect = true;
  106. result.numIntersections = 1;
  107. result.parameter[0] = -a1 / a2;
  108. }
  109. }
  110. };
  111. }