123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- #pragma once
- #include <Mathematics/Logger.h>
- #include <Mathematics/PrimalQuery2.h>
- #include <Mathematics/Line.h>
- #include <vector>
- namespace WwiseGTE
- {
- template <typename InputType, typename ComputeType>
- class ConvexHull2
- {
- public:
-
-
- ConvexHull2()
- :
- mEpsilon((InputType)0),
- mDimension(0),
- mLine(Vector2<InputType>::Zero(), Vector2<InputType>::Zero()),
- mNumPoints(0),
- mNumUniquePoints(0),
- mPoints(nullptr)
- {
- }
-
-
-
-
-
-
- bool operator()(int numPoints, Vector2<InputType> const* points, InputType epsilon)
- {
- mEpsilon = std::max(epsilon, (InputType)0);
- mDimension = 0;
- mLine.origin = Vector2<InputType>::Zero();
- mLine.direction = Vector2<InputType>::Zero();
- mNumPoints = numPoints;
- mNumUniquePoints = 0;
- mPoints = points;
- mMerged.clear();
- mHull.clear();
- int i, j;
- if (mNumPoints < 3)
- {
-
- return false;
- }
- IntrinsicsVector2<InputType> info(mNumPoints, mPoints, mEpsilon);
- if (info.dimension == 0)
- {
-
- return false;
- }
- if (info.dimension == 1)
- {
-
- mDimension = 1;
- mLine = Line2<InputType>(info.origin, info.direction[0]);
- return false;
- }
- mDimension = 2;
-
- mComputePoints.resize(mNumPoints);
- mQuery.Set(mNumPoints, &mComputePoints[0]);
- for (i = 0; i < mNumPoints; ++i)
- {
- for (j = 0; j < 2; ++j)
- {
- mComputePoints[i][j] = points[i][j];
- }
- }
-
- mHull.resize(mNumPoints);
- for (i = 0; i < mNumPoints; ++i)
- {
- mHull[i] = i;
- }
- std::sort(mHull.begin(), mHull.end(),
- [points](int i0, int i1)
- {
- if (points[i0][0] < points[i1][0])
- {
- return true;
- }
- if (points[i0][0] > points[i1][0])
- {
- return false;
- }
- return points[i0][1] < points[i1][1];
- }
- );
-
- auto newEnd = std::unique(mHull.begin(), mHull.end(),
- [points](int i0, int i1)
- {
- return points[i0] == points[i1];
- }
- );
- mHull.erase(newEnd, mHull.end());
- mNumUniquePoints = static_cast<int>(mHull.size());
-
-
- mMerged.resize(mNumUniquePoints);
- int i0 = 0, i1 = mNumUniquePoints - 1;
- GetHull(i0, i1);
- mHull.resize(i1 - i0 + 1);
- return true;
- }
-
-
-
-
- inline InputType GetEpsilon() const
- {
- return mEpsilon;
- }
- inline int GetDimension() const
- {
- return mDimension;
- }
- inline Line2<InputType> const& GetLine() const
- {
- return mLine;
- }
-
- inline int GetNumPoints() const
- {
- return mNumPoints;
- }
- inline int GetNumUniquePoints() const
- {
- return mNumUniquePoints;
- }
- inline Vector2<InputType> const* GetPoints() const
- {
- return mPoints;
- }
- inline PrimalQuery2<ComputeType> const& GetQuery() const
- {
- return mQuery;
- }
-
-
- inline std::vector<int> const& GetHull() const
- {
- return mHull;
- }
- private:
-
- void GetHull(int& i0, int& i1)
- {
- int numVertices = i1 - i0 + 1;
- if (numVertices > 1)
- {
-
- int mid = (i0 + i1) / 2;
-
- int j0 = i0, j1 = mid, j2 = mid + 1, j3 = i1;
- GetHull(j0, j1);
- GetHull(j2, j3);
-
- Merge(j0, j1, j2, j3, i0, i1);
- }
-
- }
- void Merge(int j0, int j1, int j2, int j3, int& i0, int& i1)
- {
-
-
-
-
- int size0 = j1 - j0 + 1;
- int size1 = j3 - j2 + 1;
- int i;
- Vector2<ComputeType> p;
-
- Vector2<ComputeType> pmax0 = mComputePoints[mHull[j0]];
- int imax0 = j0;
- for (i = j0 + 1; i <= j1; ++i)
- {
- p = mComputePoints[mHull[i]];
- if (pmax0 < p)
- {
- pmax0 = p;
- imax0 = i;
- }
- }
-
- Vector2<ComputeType> pmin1 = mComputePoints[mHull[j2]];
- int imin1 = j2;
- for (i = j2 + 1; i <= j3; ++i)
- {
- p = mComputePoints[mHull[i]];
- if (p < pmin1)
- {
- pmin1 = p;
- imin1 = i;
- }
- }
-
-
- int iLL = imax0, iLR = imin1;
- GetTangent(j0, j1, j2, j3, iLL, iLR);
-
-
- int iUL = imax0, iUR = imin1;
- GetTangent(j2, j3, j0, j1, iUR, iUL);
-
- int k;
- int numMerged = 0;
- i = iUL;
- for (k = 0; k < size0; ++k)
- {
- mMerged[numMerged++] = mHull[i];
- if (i == iLL)
- {
- break;
- }
- i = (i < j1 ? i + 1 : j0);
- }
- LogAssert(k < size0, "Unexpected condition.");
- i = iLR;
- for (k = 0; k < size1; ++k)
- {
- mMerged[numMerged++] = mHull[i];
- if (i == iUR)
- {
- break;
- }
- i = (i < j3 ? i + 1 : j2);
- }
- LogAssert(k < size1, "Unexpected condition.");
- int next = j0;
- for (k = 0; k < numMerged; ++k)
- {
- mHull[next] = mMerged[k];
- ++next;
- }
- i0 = j0;
- i1 = next - 1;
- }
- void GetTangent(int j0, int j1, int j2, int j3, int& i0, int& i1)
- {
-
-
-
-
- int size0 = j1 - j0 + 1;
- int size1 = j3 - j2 + 1;
- int const imax = size0 + size1;
- int i, iLm1, iRp1;
- Vector2<ComputeType> L0, L1, R0, R1;
- for (i = 0; i < imax; i++)
- {
-
- L1 = mComputePoints[mHull[i0]];
- R0 = mComputePoints[mHull[i1]];
-
- if (size0 > 1)
- {
- iLm1 = (i0 > j0 ? i0 - 1 : j1);
- L0 = mComputePoints[mHull[iLm1]];
- auto order = mQuery.ToLineExtended(R0, L0, L1);
- if (order == PrimalQuery2<ComputeType>::ORDER_NEGATIVE
- || order == PrimalQuery2<ComputeType>::ORDER_COLLINEAR_RIGHT)
- {
- i0 = iLm1;
- continue;
- }
- }
-
- if (size1 > 1)
- {
- iRp1 = (i1 < j3 ? i1 + 1 : j2);
- R1 = mComputePoints[mHull[iRp1]];
- auto order = mQuery.ToLineExtended(L1, R0, R1);
- if (order == PrimalQuery2<ComputeType>::ORDER_NEGATIVE
- || order == PrimalQuery2<ComputeType>::ORDER_COLLINEAR_LEFT)
- {
- i1 = iRp1;
- continue;
- }
- }
-
- break;
- }
-
-
- #if defined(GTE_THROW_ON_CONVEXHULL2_INFINITE_LOOP)
- LogAssert(i < imax, "Unexpected condition.");
- #endif
- }
-
-
-
-
-
-
-
-
- InputType mEpsilon;
- int mDimension;
- Line2<InputType> mLine;
-
-
- std::vector<Vector2<ComputeType>> mComputePoints;
- PrimalQuery2<ComputeType> mQuery;
- int mNumPoints;
- int mNumUniquePoints;
- Vector2<InputType> const* mPoints;
- std::vector<int> mMerged, mHull;
- };
- }
|