Skip to content

Instantly share code, notes, and snippets.

@comefrombottom
Created December 20, 2023 09:13
Show Gist options
  • Save comefrombottom/697f41af89bbfbb92bf9feda08aac51f to your computer and use it in GitHub Desktop.
Save comefrombottom/697f41af89bbfbb92bf9feda08aac51f to your computer and use it in GitHub Desktop.
#pragma once
namespace s3d {
class Step3D
{
public:
class Iterator
{
public:
SIV3D_NODISCARD_CXX20
constexpr Iterator() noexcept
: m_countX{ 0 }
, m_countY{ 0 }
, m_startX{ 0 }
, m_startY{ 0 }
, m_step_counter{ 0, 0, 0 }
, m_counter{ 0, 0, 0 }
, m_step{ 0, 0, 0 } {}
SIV3D_NODISCARD_CXX20
constexpr Iterator(Point3D steps_count, Point3D start, Point3D step) noexcept
: m_countX{ steps_count.x }
, m_countY{ steps_count.y }
, m_startX{ start.x }
, m_startY{ start.y }
, m_step_counter{ steps_count }
, m_counter{ start }
, m_step{ step } {}
constexpr Iterator& operator ++() noexcept
{
if (m_step_counter.x == 1)
{
if (m_step_counter.y == 1)
{
m_step_counter.y = m_countY;
--m_step_counter.z;
m_counter.y = m_startY;
m_counter.z = m_counter.z + m_step.z;
}
else
{
--m_step_counter.y;
m_counter.y = m_counter.y + m_step.y;
}
m_step_counter.x = m_countX;
m_counter.x = m_startX;
}
else
{
--m_step_counter.x;
m_counter.x = m_counter.x + m_step.x;
}
return *this;
}
constexpr Iterator operator ++(int) noexcept {
Iterator it = *this;
++(*this);
return it;
}
[[nodiscard]]
constexpr const Point3D& operator *() const noexcept {
return m_counter;
}
[[nodiscard]]
constexpr const Point3D* operator ->() const noexcept {
return &m_counter;
}
[[nodiscard]]
constexpr bool operator ==(const Iterator& r) const noexcept {
return m_step_counter == r.m_step_counter;
}
[[nodiscard]]
constexpr bool operator !=(const Iterator& r) const noexcept {
return !(m_step_counter == r.m_step_counter);
}
private:
int32 m_countX;
int32 m_countY;
int32 m_startX;
int32 m_startY;
Point3D m_step_counter;
Point3D m_counter;
Point3D m_step;
};
using iterator = Iterator;
SIV3D_NODISCARD_CXX20
constexpr Step3D(Point3D start, Point3D step_count, Point3D step) noexcept
: m_start{ start }
, m_step_count{ step_count }
, m_step_length{ step }
, m_end_iterator{ { step_count.x, step_count.y, 0 }, Point3D{ 0, 0, 0 }, Point3D{ 0, 0, 0 } }
, m_start_iterator{ step_count, start, step } {}
[[nodiscard]]
constexpr iterator begin() const noexcept {
return m_start_iterator;
}
[[nodiscard]]
constexpr iterator end() const noexcept {
return m_end_iterator;
}
[[nodiscard]]
constexpr Point3D startValue() const noexcept {
return m_start;
}
[[nodiscard]]
constexpr Point3D count() const noexcept {
return m_step_count;
}
[[nodiscard]]
constexpr int32 num_elements() const noexcept {
return (m_step_count.x * m_step_count.y * m_step_count.z);
}
[[nodiscard]]
constexpr Point3D step() const noexcept {
return m_step_length;
}
[[nodiscard]]
constexpr bool isEmpty() const noexcept {
return ((m_step_count.x == 0)
|| (m_step_count.y == 0)
|| (m_step_count.z == 0));
}
/// @brief 範囲の値を配列に変換します。
/// @return 配列
[[nodiscard]]
Array<Point3D> asArray() const {
Array<Point3D> new_array;
if (isEmpty())
{
return new_array;
}
new_array.reserve(num_elements());
for (auto it = m_start_iterator; it != m_end_iterator; ++it)
{
new_array.push_back(*it);
}
return new_array;
}
private:
Point3D m_start;
Point3D m_step_count;
Point3D m_step_length;
iterator m_end_iterator;
iterator m_start_iterator;
};
inline constexpr auto step(const Point3D n) noexcept
{
return Step3D{ Point3D{ 0, 0, 0 }, n, Point3D{ 1, 1, 1 } };
}
inline constexpr auto step(const Point3D a, const Point3D n) noexcept
{
return Step3D{ a, n, Point3D{ 1, 1, 1 } };
}
inline constexpr auto step(const Point3D a, const Point3D n, const Point3D s) noexcept
{
return Step3D{ a, n, s };
}
inline constexpr auto step_backward(const Point3D n) noexcept
{
return Step3D{ Point3D{ (n.x - 1), (n.y - 1), (n.z - 1) }, n, Point3D{ -1, -1, -1 } };
}
inline constexpr auto Iota3D(const Point3D end) noexcept
{
return Step3D{ Point3D{ 0, 0, 0 }, end, Point3D{ 1, 1, 1 } };
}
inline constexpr auto Iota3D(const int32 xEnd, const int32 yEnd, const int32 zEnd) noexcept
{
return Iota3D(Point3D{ xEnd, yEnd, zEnd });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment