ApprOrthogonalPlane3.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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/ApprQuery.h>
  9. #include <Mathematics/SymmetricEigensolver3x3.h>
  10. #include <Mathematics/Vector3.h>
  11. // Least-squares fit of a plane to (x,y,z) data by using distance measurements
  12. // orthogonal to the proposed plane. The return value is 'true' if and only if
  13. // the fit is unique (always successful, 'true' when a minimum eigenvalue is
  14. // unique). The mParameters value is (P,N) = (origin,normal). The error for
  15. // S = (x0,y0,z0) is (S-P)^T*(I - N*N^T)*(S-P).
  16. namespace WwiseGTE
  17. {
  18. template <typename Real>
  19. class ApprOrthogonalPlane3 : public ApprQuery<Real, Vector3<Real>>
  20. {
  21. public:
  22. // Initialize the model parameters to zero.
  23. ApprOrthogonalPlane3()
  24. {
  25. mParameters.first = Vector3<Real>::Zero();
  26. mParameters.second = Vector3<Real>::Zero();
  27. }
  28. // Basic fitting algorithm. See ApprQuery.h for the various Fit(...)
  29. // functions that you can call.
  30. virtual bool FitIndexed(
  31. size_t numPoints, Vector3<Real> const* points,
  32. size_t numIndices, int const* indices) override
  33. {
  34. if (this->ValidIndices(numPoints, points, numIndices, indices))
  35. {
  36. // Compute the mean of the points.
  37. Vector3<Real> mean = Vector3<Real>::Zero();
  38. int const* currentIndex = indices;
  39. for (size_t i = 0; i < numIndices; ++i)
  40. {
  41. mean += points[*currentIndex++];
  42. }
  43. Real invSize = (Real)1 / (Real)numIndices;
  44. mean *= invSize;
  45. if (std::isfinite(mean[0]) && std::isfinite(mean[1]))
  46. {
  47. // Compute the covariance matrix of the points.
  48. Real covar00 = (Real)0, covar01 = (Real)0, covar02 = (Real)0;
  49. Real covar11 = (Real)0, covar12 = (Real)0, covar22 = (Real)0;
  50. currentIndex = indices;
  51. for (size_t i = 0; i < numIndices; ++i)
  52. {
  53. Vector3<Real> diff = points[*currentIndex++] - mean;
  54. covar00 += diff[0] * diff[0];
  55. covar01 += diff[0] * diff[1];
  56. covar02 += diff[0] * diff[2];
  57. covar11 += diff[1] * diff[1];
  58. covar12 += diff[1] * diff[2];
  59. covar22 += diff[2] * diff[2];
  60. }
  61. covar00 *= invSize;
  62. covar01 *= invSize;
  63. covar02 *= invSize;
  64. covar11 *= invSize;
  65. covar12 *= invSize;
  66. covar22 *= invSize;
  67. // Solve the eigensystem.
  68. SymmetricEigensolver3x3<Real> es;
  69. std::array<Real, 3> eval;
  70. std::array<std::array<Real, 3>, 3> evec;
  71. es(covar00, covar01, covar02, covar11, covar12, covar22,
  72. false, +1, eval, evec);
  73. // The plane normal is the eigenvector in the direction of
  74. // smallest variance of the points.
  75. mParameters.first = mean;
  76. mParameters.second = evec[0];
  77. // The fitted plane is unique when the minimum eigenvalue
  78. // has multiplicity 1.
  79. return eval[0] < eval[1];
  80. }
  81. }
  82. mParameters.first = Vector3<Real>::Zero();
  83. mParameters.second = Vector3<Real>::Zero();
  84. return false;
  85. }
  86. // Get the parameters for the best fit.
  87. std::pair<Vector3<Real>, Vector3<Real>> const& GetParameters() const
  88. {
  89. return mParameters;
  90. }
  91. virtual size_t GetMinimumRequired() const override
  92. {
  93. return 3;
  94. }
  95. virtual Real Error(Vector3<Real> const& point) const override
  96. {
  97. Vector3<Real> diff = point - mParameters.first;
  98. Real sqrlen = Dot(diff, diff);
  99. Real dot = Dot(diff, mParameters.second);
  100. Real error = std::fabs(sqrlen - dot * dot);
  101. return error;
  102. }
  103. virtual void CopyParameters(ApprQuery<Real, Vector3<Real>> const* input) override
  104. {
  105. auto source = dynamic_cast<ApprOrthogonalPlane3<Real> const*>(input);
  106. if (source)
  107. {
  108. *this = *source;
  109. }
  110. }
  111. private:
  112. std::pair<Vector3<Real>, Vector3<Real>> mParameters;
  113. };
  114. }