ContScribeCircle3Sphere3.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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/Circle3.h>
  9. #include <Mathematics/Hypersphere.h>
  10. #include <Mathematics/LinearSystem.h>
  11. namespace WwiseGTE
  12. {
  13. // All functions return 'true' if circle/sphere has been constructed,
  14. // 'false' otherwise (input points are linearly dependent).
  15. // Circle circumscribing a triangle in 3D.
  16. template <typename Real>
  17. bool Circumscribe(Vector3<Real> const& v0, Vector3<Real> const& v1,
  18. Vector3<Real> const& v2, Circle3<Real>& circle)
  19. {
  20. Vector3<Real> E02 = v0 - v2;
  21. Vector3<Real> E12 = v1 - v2;
  22. Real e02e02 = Dot(E02, E02);
  23. Real e02e12 = Dot(E02, E12);
  24. Real e12e12 = Dot(E12, E12);
  25. Real det = e02e02 * e12e12 - e02e12 * e02e12;
  26. if (det != (Real)0)
  27. {
  28. Real halfInvDet = (Real)0.5 / det;
  29. Real u0 = halfInvDet * e12e12 * (e02e02 - e02e12);
  30. Real u1 = halfInvDet * e02e02 * (e12e12 - e02e12);
  31. Vector3<Real> tmp = u0 * E02 + u1 * E12;
  32. circle.center = v2 + tmp;
  33. circle.normal = UnitCross(E02, E12);
  34. circle.radius = Length(tmp);
  35. return true;
  36. }
  37. return false;
  38. }
  39. // Sphere circumscribing a tetrahedron.
  40. template <typename Real>
  41. bool Circumscribe(Vector3<Real> const& v0, Vector3<Real> const& v1,
  42. Vector3<Real> const& v2, Vector3<Real> const& v3, Sphere3<Real>& sphere)
  43. {
  44. Vector3<Real> E10 = v1 - v0;
  45. Vector3<Real> E20 = v2 - v0;
  46. Vector3<Real> E30 = v3 - v0;
  47. Matrix3x3<Real> A;
  48. A.SetRow(0, E10);
  49. A.SetRow(1, E20);
  50. A.SetRow(2, E30);
  51. Vector3<Real> B{
  52. (Real)0.5 * Dot(E10, E10),
  53. (Real)0.5 * Dot(E20, E20),
  54. (Real)0.5 * Dot(E30, E30) };
  55. Vector3<Real> solution;
  56. if (LinearSystem<Real>::Solve(A, B, solution))
  57. {
  58. sphere.center = v0 + solution;
  59. sphere.radius = Length(solution);
  60. return true;
  61. }
  62. return false;
  63. }
  64. // Circle inscribing a triangle in 3D.
  65. template <typename Real>
  66. bool Inscribe(Vector3<Real> const& v0, Vector3<Real> const& v1,
  67. Vector3<Real> const& v2, Circle3<Real>& circle)
  68. {
  69. // Edges.
  70. Vector3<Real> E0 = v1 - v0;
  71. Vector3<Real> E1 = v2 - v1;
  72. Vector3<Real> E2 = v0 - v2;
  73. // Plane normal.
  74. circle.normal = Cross(E1, E0);
  75. // Edge normals within the plane.
  76. Vector3<Real> N0 = UnitCross(circle.normal, E0);
  77. Vector3<Real> N1 = UnitCross(circle.normal, E1);
  78. Vector3<Real> N2 = UnitCross(circle.normal, E2);
  79. Real a0 = Dot(N1, E0);
  80. if (a0 == (Real)0)
  81. {
  82. return false;
  83. }
  84. Real a1 = Dot(N2, E1);
  85. if (a1 == (Real)0)
  86. {
  87. return false;
  88. }
  89. Real a2 = Dot(N0, E2);
  90. if (a2 == (Real)0)
  91. {
  92. return false;
  93. }
  94. Real invA0 = (Real)1 / a0;
  95. Real invA1 = (Real)1 / a1;
  96. Real invA2 = (Real)1 / a2;
  97. circle.radius = (Real)1 / (invA0 + invA1 + invA2);
  98. circle.center = circle.radius * (invA0 * v0 + invA1 * v1 + invA2 * v2);
  99. Normalize(circle.normal);
  100. return true;
  101. }
  102. // Sphere inscribing tetrahedron.
  103. template <typename Real>
  104. bool Inscribe(Vector3<Real> const& v0, Vector3<Real> const& v1,
  105. Vector3<Real> const& v2, Vector3<Real> const& v3, Sphere3<Real>& sphere)
  106. {
  107. // Edges.
  108. Vector3<Real> E10 = v1 - v0;
  109. Vector3<Real> E20 = v2 - v0;
  110. Vector3<Real> E30 = v3 - v0;
  111. Vector3<Real> E21 = v2 - v1;
  112. Vector3<Real> E31 = v3 - v1;
  113. // Normals.
  114. Vector3<Real> N0 = Cross(E31, E21);
  115. Vector3<Real> N1 = Cross(E20, E30);
  116. Vector3<Real> N2 = Cross(E30, E10);
  117. Vector3<Real> N3 = Cross(E10, E20);
  118. // Normalize the normals.
  119. if (Normalize(N0) == (Real)0)
  120. {
  121. return false;
  122. }
  123. if (Normalize(N1) == (Real)0)
  124. {
  125. return false;
  126. }
  127. if (Normalize(N2) == (Real)0)
  128. {
  129. return false;
  130. }
  131. if (Normalize(N3) == (Real)0)
  132. {
  133. return false;
  134. }
  135. Matrix3x3<Real> A;
  136. A.SetRow(0, N1 - N0);
  137. A.SetRow(1, N2 - N0);
  138. A.SetRow(2, N3 - N0);
  139. Vector3<Real> B{ (Real)0, (Real)0, -Dot(N3, E30) };
  140. Vector3<Real> solution;
  141. if (LinearSystem<Real>::Solve(A, B, solution))
  142. {
  143. sphere.center = v3 + solution;
  144. sphere.radius = std::fabs(Dot(N0, solution));
  145. return true;
  146. }
  147. return false;
  148. }
  149. }