123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- #pragma once
- #include <Mathematics/IntrAlignedBox2AlignedBox2.h>
- #include <Mathematics/EdgeKey.h>
- #include <set>
- #include <vector>
- namespace WwiseGTE
- {
- template <typename Real>
- class RectangleManager
- {
- public:
-
- RectangleManager(std::vector<AlignedBox2<Real>>& rectangles)
- :
- mRectangles(rectangles)
- {
- Initialize();
- }
-
-
- RectangleManager() = delete;
- RectangleManager(RectangleManager const&) = delete;
- RectangleManager& operator=(RectangleManager const&) = delete;
-
-
-
-
-
- void Initialize()
- {
-
- int intrSize = static_cast<int>(mRectangles.size()), endpSize = 2 * intrSize;
- mXEndpoints.resize(endpSize);
- mYEndpoints.resize(endpSize);
- for (int i = 0, j = 0; i < intrSize; ++i)
- {
- mXEndpoints[j].type = 0;
- mXEndpoints[j].value = mRectangles[i].min[0];
- mXEndpoints[j].index = i;
- mYEndpoints[j].type = 0;
- mYEndpoints[j].value = mRectangles[i].min[1];
- mYEndpoints[j].index = i;
- ++j;
- mXEndpoints[j].type = 1;
- mXEndpoints[j].value = mRectangles[i].max[0];
- mXEndpoints[j].index = i;
- mYEndpoints[j].type = 1;
- mYEndpoints[j].value = mRectangles[i].max[1];
- mYEndpoints[j].index = i;
- ++j;
- }
-
- std::sort(mXEndpoints.begin(), mXEndpoints.end());
- std::sort(mYEndpoints.begin(), mYEndpoints.end());
-
- mXLookup.resize(endpSize);
- mYLookup.resize(endpSize);
- for (int j = 0; j < endpSize; ++j)
- {
- mXLookup[2 * mXEndpoints[j].index + mXEndpoints[j].type] = j;
- mYLookup[2 * mYEndpoints[j].index + mYEndpoints[j].type] = j;
- }
-
- std::set<int> active;
-
-
- mOverlap.clear();
-
-
- for (int i = 0; i < endpSize; ++i)
- {
- Endpoint& endpoint = mXEndpoints[i];
- int index = endpoint.index;
- if (endpoint.type == 0)
- {
-
-
-
- for (auto activeIndex : active)
- {
-
-
- AlignedBox2<Real> const& r0 = mRectangles[activeIndex];
- AlignedBox2<Real> const& r1 = mRectangles[index];
- if (r0.max[1] >= r1.min[1] && r0.min[1] <= r1.max[1])
- {
- if (activeIndex < index)
- {
- mOverlap.insert(EdgeKey<false>(activeIndex, index));
- }
- else
- {
- mOverlap.insert(EdgeKey<false>(index, activeIndex));
- }
- }
- }
- active.insert(index);
- }
- else
- {
- active.erase(index);
- }
- }
- }
-
-
-
-
-
- void SetRectangle(int i, AlignedBox2<Real> const& rectangle)
- {
- mRectangles[i] = rectangle;
- mXEndpoints[mXLookup[2 * i]].value = rectangle.min[0];
- mXEndpoints[mXLookup[2 * i + 1]].value = rectangle.max[0];
- mYEndpoints[mYLookup[2 * i]].value = rectangle.min[1];
- mYEndpoints[mYLookup[2 * i + 1]].value = rectangle.max[1];
- }
- inline void GetRectangle(int i, AlignedBox2<Real>& rectangle) const
- {
- rectangle = mRectangles[i];
- }
-
-
-
- void Update()
- {
- InsertionSort(mXEndpoints, mXLookup);
- InsertionSort(mYEndpoints, mYLookup);
- }
-
-
-
- inline std::set<EdgeKey<false>> const& GetOverlap() const
- {
- return mOverlap;
- }
- private:
- class Endpoint
- {
- public:
- Real value;
- int type;
- int index;
-
- bool operator<(Endpoint const& endpoint) const
- {
- if (value < endpoint.value)
- {
- return true;
- }
- if (value > endpoint.value)
- {
- return false;
- }
- return type < endpoint.type;
- }
- };
- void InsertionSort(std::vector<Endpoint>& endpoint, std::vector<int>& lookup)
- {
-
-
-
-
- TIQuery<Real, AlignedBox2<Real>, AlignedBox2<Real>> query;
- int endpSize = static_cast<int>(endpoint.size());
- for (int j = 1; j < endpSize; ++j)
- {
- Endpoint key = endpoint[j];
- int i = j - 1;
- while (i >= 0 && key < endpoint[i])
- {
- Endpoint e0 = endpoint[i];
- Endpoint e1 = endpoint[i + 1];
-
- if (e0.type == 0)
- {
- if (e1.type == 1)
- {
-
-
-
-
-
-
-
-
-
-
- mOverlap.erase(EdgeKey<false>(e0.index, e1.index));
- }
- }
- else
- {
- if (e1.type == 0)
- {
-
-
-
-
-
-
- if (query(mRectangles[e0.index], mRectangles[e1.index]).intersect)
- {
- mOverlap.insert(EdgeKey<false>(e0.index, e1.index));
- }
- }
- }
-
- endpoint[i] = e1;
- endpoint[i + 1] = e0;
- lookup[2 * e1.index + e1.type] = i;
- lookup[2 * e0.index + e0.type] = i + 1;
- --i;
- }
- endpoint[i + 1] = key;
- lookup[2 * key.index + key.type] = i + 1;
- }
- }
- std::vector<AlignedBox2<Real>>& mRectangles;
- std::vector<Endpoint> mXEndpoints, mYEndpoints;
- std::set<EdgeKey<false>> mOverlap;
-
-
-
-
-
-
-
-
-
-
- std::vector<int> mXLookup, mYLookup;
- };
- }
|