123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- // David Eberly, Geometric Tools, Redmond WA 98052
- // Copyright (c) 1998-2020
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
- // Version: 4.0.2019.08.13
- #pragma once
- #include <vector>
- namespace WwiseGTE
- {
- // Compute Boolean operations of disjoint sets of half-open intervals of
- // the form [xmin,xmax) with xmin < xmax.
- template <typename Scalar>
- class DisjointIntervals
- {
- public:
- // Construction and destruction. The non-default constructor requires
- // that xmin < xmax.
- DisjointIntervals()
- {
- }
- DisjointIntervals(Scalar const& xmin, Scalar const& xmax)
- {
- if (xmin < xmax)
- {
- mEndpoints = { xmin, xmax };
- mEndpoints[0] = xmin;
- mEndpoints[1] = xmax;
- }
- }
- ~DisjointIntervals()
- {
- }
- // Copy operations.
- DisjointIntervals(DisjointIntervals const& other)
- :
- mEndpoints(other.mEndpoints)
- {
- }
- DisjointIntervals& operator=(DisjointIntervals const& other)
- {
- mEndpoints = other.mEndpoints;
- return *this;
- }
- // Move operations.
- DisjointIntervals(DisjointIntervals&& other)
- :
- mEndpoints(std::move(other.mEndpoints))
- {
- }
- DisjointIntervals& operator=(DisjointIntervals&& other)
- {
- mEndpoints = std::move(other.mEndpoints);
- return *this;
- }
- // The number of intervals in the set.
- inline int GetNumIntervals() const
- {
- return static_cast<int>(mEndpoints.size() / 2);
- }
- // The i-th interval is [xmin,xmax). The values xmin and xmax are
- // valid only when 0 <= i < GetNumIntervals().
- bool GetInterval(int i, Scalar& xmin, Scalar& xmax) const
- {
- int index = 2 * i;
- if (0 <= index && index < static_cast<int>(mEndpoints.size()))
- {
- xmin = mEndpoints[index];
- xmax = mEndpoints[++index];
- return true;
- }
- xmin = (Scalar)0;
- xmax = (Scalar)0;
- return false;
- }
- // Make this set empty.
- inline void Clear()
- {
- mEndpoints.clear();
- }
- // Insert [xmin,xmax) into the set. This is a Boolean 'union'
- // operation. The operation is successful only when xmin < xmax.
- bool Insert(Scalar const& xmin, Scalar const& xmax)
- {
- if (xmin < xmax)
- {
- DisjointIntervals input(xmin, xmax);
- DisjointIntervals output = *this | input;
- mEndpoints = std::move(output.mEndpoints);
- return true;
- }
- return false;
- }
- // Remove [xmin,xmax) from the set. This is a Boolean 'difference'
- // operation. The operation is successful only when xmin < xmax.
- bool Remove(Scalar const& xmin, Scalar const& xmax)
- {
- if (xmin < xmax)
- {
- DisjointIntervals input(xmin, xmax);
- DisjointIntervals output = std::move(*this - input);
- mEndpoints = std::move(output.mEndpoints);
- return true;
- }
- return false;
- }
- // Get the union of the interval sets, input0 union input1.
- friend DisjointIntervals operator|(DisjointIntervals const& input0, DisjointIntervals const& input1)
- {
- DisjointIntervals output;
- size_t const numEndpoints0 = input0.mEndpoints.size();
- size_t const numEndpoints1 = input1.mEndpoints.size();
- size_t i0 = 0, i1 = 0;
- int parity0 = 0, parity1 = 0;
- while (i0 < numEndpoints0 && i1 < numEndpoints1)
- {
- Scalar const& value0 = input0.mEndpoints[i0];
- Scalar const& value1 = input1.mEndpoints[i1];
- if (value0 < value1)
- {
- if (parity0 == 0)
- {
- parity0 = 1;
- if (parity1 == 0)
- {
- output.mEndpoints.push_back(value0);
- }
- }
- else
- {
- if (parity1 == 0)
- {
- output.mEndpoints.push_back(value0);
- }
- parity0 = 0;
- }
- ++i0;
- }
- else if (value1 < value0)
- {
- if (parity1 == 0)
- {
- parity1 = 1;
- if (parity0 == 0)
- {
- output.mEndpoints.push_back(value1);
- }
- }
- else
- {
- if (parity0 == 0)
- {
- output.mEndpoints.push_back(value1);
- }
- parity1 = 0;
- }
- ++i1;
- }
- else // value0 == value1
- {
- if (parity0 == parity1)
- {
- output.mEndpoints.push_back(value0);
- }
- parity0 ^= 1;
- parity1 ^= 1;
- ++i0;
- ++i1;
- }
- }
- while (i0 < numEndpoints0)
- {
- output.mEndpoints.push_back(input0.mEndpoints[i0]);
- ++i0;
- }
- while (i1 < numEndpoints1)
- {
- output.mEndpoints.push_back(input1.mEndpoints[i1]);
- ++i1;
- }
- return output;
- }
- // Get the intersection of the interval sets, input0 intersect is1.
- friend DisjointIntervals operator&(DisjointIntervals const& input0, DisjointIntervals const& input1)
- {
- DisjointIntervals output;
- size_t const numEndpoints0 = input0.mEndpoints.size();
- size_t const numEndpoints1 = input1.mEndpoints.size();
- size_t i0 = 0, i1 = 0;
- int parity0 = 0, parity1 = 0;
- while (i0 < numEndpoints0 && i1 < numEndpoints1)
- {
- Scalar const& value0 = input0.mEndpoints[i0];
- Scalar const& value1 = input1.mEndpoints[i1];
- if (value0 < value1)
- {
- if (parity0 == 0)
- {
- parity0 = 1;
- if (parity1 == 1)
- {
- output.mEndpoints.push_back(value0);
- }
- }
- else
- {
- if (parity1 == 1)
- {
- output.mEndpoints.push_back(value0);
- }
- parity0 = 0;
- }
- ++i0;
- }
- else if (value1 < value0)
- {
- if (parity1 == 0)
- {
- parity1 = 1;
- if (parity0 == 1)
- {
- output.mEndpoints.push_back(value1);
- }
- }
- else
- {
- if (parity0 == 1)
- {
- output.mEndpoints.push_back(value1);
- }
- parity1 = 0;
- }
- ++i1;
- }
- else // value0 == value1
- {
- if (parity0 == parity1)
- {
- output.mEndpoints.push_back(value0);
- }
- parity0 ^= 1;
- parity1 ^= 1;
- ++i0;
- ++i1;
- }
- }
- return output;
- }
- // Get the differences of the interval sets, input0 minus input1.
- friend DisjointIntervals operator-(DisjointIntervals const& input0, DisjointIntervals const& input1)
- {
- DisjointIntervals output;
- size_t const numEndpoints0 = input0.mEndpoints.size();
- size_t const numEndpoints1 = input1.mEndpoints.size();
- size_t i0 = 0, i1 = 0;
- int parity0 = 0, parity1 = 1;
- while (i0 < numEndpoints0 && i1 < numEndpoints1)
- {
- Scalar const& value0 = input0.mEndpoints[i0];
- Scalar const& value1 = input1.mEndpoints[i1];
- if (value0 < value1)
- {
- if (parity0 == 0)
- {
- parity0 = 1;
- if (parity1 == 1)
- {
- output.mEndpoints.push_back(value0);
- }
- }
- else
- {
- if (parity1 == 1)
- {
- output.mEndpoints.push_back(value0);
- }
- parity0 = 0;
- }
- ++i0;
- }
- else if (value1 < value0)
- {
- if (parity1 == 0)
- {
- parity1 = 1;
- if (parity0 == 1)
- {
- output.mEndpoints.push_back(value1);
- }
- }
- else
- {
- if (parity0 == 1)
- {
- output.mEndpoints.push_back(value1);
- }
- parity1 = 0;
- }
- ++i1;
- }
- else // value0 == value1
- {
- if (parity0 == parity1)
- {
- output.mEndpoints.push_back(value0);
- }
- parity0 ^= 1;
- parity1 ^= 1;
- ++i0;
- ++i1;
- }
- }
- while (i0 < numEndpoints0)
- {
- output.mEndpoints.push_back(input0.mEndpoints[i0]);
- ++i0;
- }
- return output;
- }
- // Get the exclusive or of the interval sets, input0 xor input1 =
- // (input0 minus input1) or (input1 minus input0).
- friend DisjointIntervals operator^(DisjointIntervals const& input0, DisjointIntervals const& input1)
- {
- DisjointIntervals output;
- size_t const numEndpoints0 = input0.mEndpoints.size();
- size_t const numEndpoints1 = input1.mEndpoints.size();
- size_t i0 = 0, i1 = 0;
- while (i0 < numEndpoints0 && i1 < numEndpoints1)
- {
- Scalar const& value0 = input0.mEndpoints[i0];
- Scalar const& value1 = input1.mEndpoints[i1];
- if (value0 < value1)
- {
- output.mEndpoints.push_back(value0);
- ++i0;
- }
- else if (value1 < value0)
- {
- output.mEndpoints.push_back(value1);
- ++i1;
- }
- else // value0 == value1
- {
- ++i0;
- ++i1;
- }
- }
- while (i0 < numEndpoints0)
- {
- output.mEndpoints.push_back(input0.mEndpoints[i0]);
- ++i0;
- }
- while (i1 < numEndpoints1)
- {
- output.mEndpoints.push_back(input1.mEndpoints[i1]);
- ++i1;
- }
- return output;
- }
- private:
- // The array of endpoints has an even number of elements. The i-th
- // interval is [mEndPoints[2*i],mEndPoints[2*i+1]).
- std::vector<Scalar> mEndpoints;
- };
- }
|