123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- #pragma once
- #include <Mathematics/Hypersphere.h>
- #include <Mathematics/Vector2.h>
- namespace WwiseGTE
- {
- template <typename Real>
- class ApprCircle2
- {
- public:
-
-
-
- bool FitUsingSquaredLengths(int numPoints, Vector2<Real> const* points, Circle2<Real>& circle)
- {
-
- Real const zero(0);
- Vector2<Real> A = { zero, zero };
- for (int i = 0; i < numPoints; ++i)
- {
- A += points[i];
- }
- Real invNumPoints = ((Real)1) / static_cast<Real>(numPoints);
- A *= invNumPoints;
-
-
- Real M00 = zero, M01 = zero, M11 = zero;
- Vector2<Real> R = { zero, zero };
- for (int i = 0; i < numPoints; ++i)
- {
- Vector2<Real> Y = points[i] - A;
- Real Y0Y0 = Y[0] * Y[0];
- Real Y0Y1 = Y[0] * Y[1];
- Real Y1Y1 = Y[1] * Y[1];
- M00 += Y0Y0;
- M01 += Y0Y1;
- M11 += Y1Y1;
- R += (Y0Y0 + Y1Y1) * Y;
- }
- R *= (Real)0.5;
-
- Real det = M00 * M11 - M01 * M01;
- if (det != zero)
- {
- circle.center[0] = A[0] + (M11 * R[0] - M01 * R[1]) / det;
- circle.center[1] = A[1] + (M00 * R[1] - M01 * R[0]) / det;
- Real rsqr = zero;
- for (int i = 0; i < numPoints; ++i)
- {
- Vector2<Real> delta = points[i] - circle.center;
- rsqr += Dot(delta, delta);
- }
- rsqr *= invNumPoints;
- circle.radius = std::sqrt(rsqr);
- return true;
- }
- else
- {
- circle.center = { zero, zero };
- circle.radius = zero;
- return false;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- unsigned int FitUsingLengths(int numPoints, Vector2<Real> const* points,
- unsigned int maxIterations, bool initialCenterIsAverage,
- Circle2<Real>& circle, Real epsilon = (Real)0)
- {
-
- Vector2<Real> average = points[0];
- for (int i = 1; i < numPoints; ++i)
- {
- average += points[i];
- }
- Real invNumPoints = ((Real)1) / static_cast<Real>(numPoints);
- average *= invNumPoints;
-
- if (initialCenterIsAverage)
- {
- circle.center = average;
- }
- Real epsilonSqr = epsilon * epsilon;
- unsigned int iteration;
- for (iteration = 0; iteration < maxIterations; ++iteration)
- {
-
- Vector2<Real> current = circle.center;
-
- Real lenAverage = (Real)0;
- Vector2<Real> derLenAverage = Vector2<Real>::Zero();
- for (int i = 0; i < numPoints; ++i)
- {
- Vector2<Real> diff = points[i] - circle.center;
- Real length = Length(diff);
- if (length > (Real)0)
- {
- lenAverage += length;
- Real invLength = ((Real)1) / length;
- derLenAverage -= invLength * diff;
- }
- }
- lenAverage *= invNumPoints;
- derLenAverage *= invNumPoints;
- circle.center = average + lenAverage * derLenAverage;
- circle.radius = lenAverage;
- Vector2<Real> diff = circle.center - current;
- Real diffSqrLen = Dot(diff, diff);
- if (diffSqrLen <= epsilonSqr)
- {
- break;
- }
- }
- return ++iteration;
- }
- };
- }
|