|
|
|
|
@ -5,35 +5,74 @@
|
|
|
|
|
#include "point.hpp" |
|
|
|
|
#include "rectangle.hpp" |
|
|
|
|
|
|
|
|
|
namespace devilution { |
|
|
|
|
namespace devilution { |
|
|
|
|
|
|
|
|
|
class PointsInRectangleRange { |
|
|
|
|
class PointsInRectangleIteratorBase { |
|
|
|
|
public: |
|
|
|
|
using const_iterator = class PointsInRectangleIterator { |
|
|
|
|
public: |
|
|
|
|
using iterator_category = std::random_access_iterator_tag; |
|
|
|
|
using difference_type = int; |
|
|
|
|
using value_type = Point; |
|
|
|
|
using pointer = void; |
|
|
|
|
using reference = value_type; |
|
|
|
|
using iterator_category = std::random_access_iterator_tag; |
|
|
|
|
using difference_type = int; |
|
|
|
|
using value_type = Point; |
|
|
|
|
using pointer = void; |
|
|
|
|
using reference = value_type; |
|
|
|
|
|
|
|
|
|
PointsInRectangleIterator() = default; |
|
|
|
|
protected: |
|
|
|
|
PointsInRectangleIteratorBase(Point origin, int majorDimension, int majorIndex, int minorIndex) |
|
|
|
|
: origin(origin) |
|
|
|
|
, majorDimension(majorDimension) |
|
|
|
|
, majorIndex(majorIndex) |
|
|
|
|
, minorIndex(minorIndex) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PointsInRectangleIterator(Point origin, int majorDimension, int majorIndex, int minorIndex) |
|
|
|
|
: origin(origin) |
|
|
|
|
, majorDimension(majorDimension) |
|
|
|
|
, majorIndex(majorIndex) |
|
|
|
|
, minorIndex(minorIndex) |
|
|
|
|
{ |
|
|
|
|
explicit PointsInRectangleIteratorBase(Point origin, int majorDimension, int index = 0) |
|
|
|
|
: PointsInRectangleIteratorBase(origin, majorDimension, index / majorDimension, index % majorDimension) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Increment() |
|
|
|
|
{ |
|
|
|
|
++minorIndex; |
|
|
|
|
if (minorIndex >= majorDimension) { |
|
|
|
|
++majorIndex; |
|
|
|
|
minorIndex -= majorDimension; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
explicit PointsInRectangleIterator(Point origin, int majorDimension, int index = 0) |
|
|
|
|
: PointsInRectangleIterator(origin, majorDimension, index / majorDimension, index % majorDimension) |
|
|
|
|
{ |
|
|
|
|
void Decrement() |
|
|
|
|
{ |
|
|
|
|
if (minorIndex <= 0) { |
|
|
|
|
--majorIndex; |
|
|
|
|
minorIndex += majorDimension; |
|
|
|
|
} |
|
|
|
|
--minorIndex; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Offset(difference_type delta) |
|
|
|
|
{ |
|
|
|
|
majorIndex += (minorIndex + delta) / majorDimension; |
|
|
|
|
minorIndex = (minorIndex + delta) % majorDimension; |
|
|
|
|
if (minorIndex < 0) { |
|
|
|
|
minorIndex += majorDimension; |
|
|
|
|
--majorIndex; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Point origin; |
|
|
|
|
|
|
|
|
|
int majorDimension; |
|
|
|
|
|
|
|
|
|
int majorIndex; |
|
|
|
|
int minorIndex; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class PointsInRectangleRange { |
|
|
|
|
public: |
|
|
|
|
using const_iterator = class PointsInRectangleIterator : public PointsInRectangleIteratorBase { |
|
|
|
|
public: |
|
|
|
|
PointsInRectangleIterator() = default; |
|
|
|
|
|
|
|
|
|
PointsInRectangleIterator(Rectangle region, int index = 0) |
|
|
|
|
: PointsInRectangleIterator(region.position, region.size.width, index) |
|
|
|
|
: PointsInRectangleIteratorBase(region.position, region.size.width, index) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -141,45 +180,178 @@ public:
|
|
|
|
|
{ |
|
|
|
|
return **(this + offset); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
PointsInRectangleRange(Rectangle region) |
|
|
|
|
: region(region) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] const_iterator cbegin() const |
|
|
|
|
{ |
|
|
|
|
return region; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] const_iterator begin() const |
|
|
|
|
{ |
|
|
|
|
return cbegin(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] const_iterator cend() const |
|
|
|
|
{ |
|
|
|
|
return { region, region.size.width * region.size.height }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] const_iterator end() const |
|
|
|
|
{ |
|
|
|
|
return cend(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto crbegin() const |
|
|
|
|
{ |
|
|
|
|
// explicit type needed for older GCC versions
|
|
|
|
|
return std::reverse_iterator<const_iterator>(cend()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto rbegin() const |
|
|
|
|
{ |
|
|
|
|
return crbegin(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto crend() const |
|
|
|
|
{ |
|
|
|
|
// explicit type needed for older GCC versions
|
|
|
|
|
return std::reverse_iterator<const_iterator>(cbegin()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[[nodiscard]] auto rend() const |
|
|
|
|
{ |
|
|
|
|
return crend(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
Rectangle region; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class PointsInRectangleRangeColMajor { |
|
|
|
|
public: |
|
|
|
|
using const_iterator = class PointsInRectangleIteratorColMajor : public PointsInRectangleIteratorBase { |
|
|
|
|
public: |
|
|
|
|
PointsInRectangleIteratorColMajor() = default; |
|
|
|
|
|
|
|
|
|
PointsInRectangleIteratorColMajor(Rectangle region, int index = 0) |
|
|
|
|
: PointsInRectangleIteratorBase(region.position, region.size.height, index) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
void Increment() |
|
|
|
|
value_type operator*() const |
|
|
|
|
{ |
|
|
|
|
++minorIndex; |
|
|
|
|
if (minorIndex >= majorDimension) { |
|
|
|
|
++majorIndex; |
|
|
|
|
minorIndex -= majorDimension; |
|
|
|
|
} |
|
|
|
|
// Col-major iteration e.g. {0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, ...
|
|
|
|
|
return origin + Displacement { majorIndex, minorIndex }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Decrement() |
|
|
|
|
// Equality comparable concepts
|
|
|
|
|
bool operator==(const PointsInRectangleIteratorColMajor &rhs) const |
|
|
|
|
{ |
|
|
|
|
if (minorIndex <= 0) { |
|
|
|
|
--majorIndex; |
|
|
|
|
minorIndex += majorDimension; |
|
|
|
|
} |
|
|
|
|
--minorIndex; |
|
|
|
|
return this->majorIndex == rhs.majorIndex && this->minorIndex == rhs.minorIndex; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Offset(difference_type delta) |
|
|
|
|
bool operator!=(const PointsInRectangleIteratorColMajor &rhs) const |
|
|
|
|
{ |
|
|
|
|
majorIndex += (minorIndex + delta) / majorDimension; |
|
|
|
|
minorIndex = (minorIndex + delta) % majorDimension; |
|
|
|
|
if (minorIndex < 0) { |
|
|
|
|
minorIndex += majorDimension; |
|
|
|
|
--majorIndex; |
|
|
|
|
} |
|
|
|
|
return !(*this == rhs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Point origin; |
|
|
|
|
// Partially ordered concepts
|
|
|
|
|
bool operator>=(const PointsInRectangleIteratorColMajor &rhs) const |
|
|
|
|
{ |
|
|
|
|
return this->majorIndex > rhs.majorIndex || (this->majorIndex == rhs.majorIndex && this->minorIndex >= rhs.minorIndex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool operator<(const PointsInRectangleIteratorColMajor &rhs) const |
|
|
|
|
{ |
|
|
|
|
return !(*this >= rhs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int majorDimension; |
|
|
|
|
bool operator<=(const PointsInRectangleIteratorColMajor &rhs) const |
|
|
|
|
{ |
|
|
|
|
return this->majorIndex < rhs.majorIndex || (this->majorIndex == rhs.majorIndex && this->minorIndex <= rhs.minorIndex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int majorIndex; |
|
|
|
|
int minorIndex; |
|
|
|
|
bool operator>(const PointsInRectangleIteratorColMajor &rhs) const |
|
|
|
|
{ |
|
|
|
|
return !(*this <= rhs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
difference_type operator-(const PointsInRectangleIteratorColMajor &rhs) const |
|
|
|
|
{ |
|
|
|
|
return (this->majorIndex - rhs.majorIndex) * majorDimension + (this->minorIndex - rhs.minorIndex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Forward concepts
|
|
|
|
|
PointsInRectangleIteratorColMajor &operator++() |
|
|
|
|
{ |
|
|
|
|
Increment(); |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PointsInRectangleIteratorColMajor operator++(int) |
|
|
|
|
{ |
|
|
|
|
auto copy = *this; |
|
|
|
|
++(*this); |
|
|
|
|
return copy; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Bidirectional concepts
|
|
|
|
|
PointsInRectangleIteratorColMajor &operator--() |
|
|
|
|
{ |
|
|
|
|
Decrement(); |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PointsInRectangleIteratorColMajor operator--(int) |
|
|
|
|
{ |
|
|
|
|
auto copy = *this; |
|
|
|
|
--(*this); |
|
|
|
|
return copy; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Random access concepts
|
|
|
|
|
PointsInRectangleIteratorColMajor operator+(difference_type delta) const |
|
|
|
|
{ |
|
|
|
|
auto copy = *this; |
|
|
|
|
return copy += delta; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PointsInRectangleIteratorColMajor &operator+=(difference_type delta) |
|
|
|
|
{ |
|
|
|
|
Offset(delta); |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
friend PointsInRectangleIteratorColMajor operator+(difference_type delta, const PointsInRectangleIteratorColMajor &it) |
|
|
|
|
{ |
|
|
|
|
return it + delta; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PointsInRectangleIteratorColMajor &operator-=(difference_type delta) |
|
|
|
|
{ |
|
|
|
|
return *this += -delta; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PointsInRectangleIteratorColMajor operator-(difference_type delta) const |
|
|
|
|
{ |
|
|
|
|
auto copy = *this; |
|
|
|
|
return copy -= delta; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
value_type operator[](difference_type offset) const |
|
|
|
|
{ |
|
|
|
|
return **(this + offset); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
PointsInRectangleRange(Rectangle region) |
|
|
|
|
// gcc6 needs a defined constructor?
|
|
|
|
|
PointsInRectangleRangeColMajor(Rectangle region) |
|
|
|
|
: region(region) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|