123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- #pragma once
- #include <Mathematics/ContOrientedBox2.h>
- #include <Mathematics/DistPointHyperellipsoid.h>
- #include <Mathematics/Matrix2x2.h>
- #include <Mathematics/MinimizeN.h>
- namespace WwiseGTE
- {
- template <typename Real>
- class ApprEllipse2
- {
- public:
- Real operator()(int numPoints, Vector2<Real> const* points,
- Vector2<Real>& center, Matrix2x2<Real>& rotate, Real diagonal[2]) const
- {
-
-
-
- std::function<Real(Real const*)> energy =
- [numPoints, points](Real const* input)
- {
- return Energy(numPoints, points, input);
- };
- MinimizeN<Real> minimizer(5, energy, 8, 8, 32);
-
-
- OrientedBox2<Real> box;
- GetContainer(numPoints, points, box);
- center = box.center;
- for (int i = 0; i < 2; ++i)
- {
- rotate.SetRow(i, box.axis[i]);
- diagonal[i] = box.extent[i];
- }
- Real angle = std::atan2(rotate(0, 1), rotate(0, 0));
- Real e0 =
- diagonal[0] * std::fabs(rotate(0, 0)) +
- diagonal[1] * std::fabs(rotate(1, 0));
- Real e1 =
- diagonal[0] * std::fabs(rotate(0, 1)) +
- diagonal[1] * std::fabs(rotate(1, 1));
- Real v0[5] =
- {
- (Real)0.5 * diagonal[0],
- (Real)0.5 * diagonal[1],
- center[0] - e0,
- center[1] - e1,
- -(Real)GTE_C_PI
- };
- Real v1[5] =
- {
- (Real)2 * diagonal[0],
- (Real)2 * diagonal[1],
- center[0] + e0,
- center[1] + e1,
- (Real)GTE_C_PI
- };
- Real vInitial[5] =
- {
- diagonal[0],
- diagonal[1],
- center[0],
- center[1],
- angle
- };
- Real vMin[5], error;
- minimizer.GetMinimum(v0, v1, vInitial, vMin, error);
- diagonal[0] = vMin[0];
- diagonal[1] = vMin[1];
- center[0] = vMin[2];
- center[1] = vMin[3];
- MakeRotation(-vMin[4], rotate);
- return error;
- }
- private:
- static Real Energy(int numPoints, Vector2<Real> const* points, Real const* input)
- {
-
- Matrix2x2<Real> rotate;
- MakeRotation(-input[4], rotate);
- Ellipse2<Real> ellipse(Vector2<Real>::Zero(), { Vector2<Real>::Unit(0),
- Vector2<Real>::Unit(1) }, { input[0], input[1] });
-
-
- DCPQuery<Real, Vector2<Real>, Ellipse2<Real>> peQuery;
- Real energy = (Real)0;
- for (int i = 0; i < numPoints; ++i)
- {
- Vector2<Real> diff = points[i] - Vector2<Real>{ input[2], input[3] };
- Vector2<Real> prod = rotate * diff;
- Real dist = peQuery(prod, ellipse).distance;
- energy += dist;
- }
- return energy;
- }
- };
- }
|