Last active
January 20, 2024 17:22
-
-
Save comefrombottom/c8e5d113dd17c8125bfd450c0095a281 to your computer and use it in GitHub Desktop.
格子上のLineが通るIndexを順に返すイテレータ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# include <Siv3D.hpp> | |
void dragVec2(Vec2& v, bool& dragging, double r = 5) { | |
if (v.asCircle(r).leftClicked())dragging = true; | |
if (MouseL.up()) { | |
if (KeySpace.pressed()) { | |
constexpr Point step{ 10,10 }; | |
v = Floor(v / step + Vec2{0.5, 0.5})* step; | |
} | |
dragging = false; | |
} | |
if (dragging) { | |
v += Cursor::DeltaF(); | |
} | |
} | |
class GridWalker{ | |
Vec2 offset; | |
Vec2 size; | |
Line line; | |
Point beginIndex; | |
Point endIndex; | |
public: | |
class Iterator | |
{ | |
public: | |
using iterator_concept = std::forward_iterator_tag; | |
using value_type = Point; | |
[[nodiscard]] | |
constexpr Iterator() = default; | |
[[nodiscard]] | |
constexpr Iterator(const Vec2& offset, const Vec2& size, const Line& line,const Point& index, const Point& endIndex) noexcept | |
:offset(offset),size(size),lineBegin(line.begin),lineVector(line.vector()),index(index),endIndex(endIndex) {} | |
constexpr Iterator& operator ++() noexcept { | |
const Point subIndex = endIndex - index; | |
if (subIndex.x > 0) { | |
if (subIndex.y > 0) { | |
const Vec2 p = offset + size * (index + Point{ 1, 1 }); | |
const double cross = (p - lineBegin).cross(lineVector); | |
if (cross > 0) { | |
index += Point{ 0, 1 }; | |
} | |
else if (cross < 0) { | |
index += Point{ 1, 0 }; | |
} | |
else { | |
index += Point{ 1, 1 }; | |
} | |
} | |
else if (subIndex.y < 0) { | |
const Vec2 p = offset + size * (index + Point{ 1, 0 }); | |
const double cross = (p - lineBegin).cross(lineVector); | |
if (cross >= 0) { | |
index += Point{ 1, 0 }; | |
} | |
else { | |
index += Point{ 0, -1 }; | |
} | |
} | |
else { | |
index += Point{ 1, 0 }; | |
} | |
} | |
else if (subIndex.x < 0) { | |
if (subIndex.y > 0) { | |
const Vec2 p = offset + size * (index + Point{ 0, 1 }); | |
const double cross = (p - lineBegin).cross(lineVector); | |
if (cross > 0) { | |
index += Point{ -1, 0 }; | |
} | |
else { | |
index += Point{ 0, 1 }; | |
} | |
} | |
else if (subIndex.y < 0) { | |
const Vec2 p = offset + size * (index + Point{ 0, 0 }); | |
const double cross = (p - lineBegin).cross(lineVector); | |
if (cross > 0) { | |
index += Point{ 0, -1 }; | |
} | |
else if (cross < 0) { | |
index += Point{ -1, 0 }; | |
} | |
else { | |
index += Point{ -1, -1 }; | |
} | |
} | |
else { | |
index += Point{ -1, 0 }; | |
} | |
} | |
else { | |
if (subIndex.y > 0) { | |
index += Point{ 0, 1 }; | |
} | |
else if (subIndex.y < 0) { | |
index += Point{ 0, -1 }; | |
} | |
else { | |
} | |
} | |
return *this; | |
} | |
constexpr Iterator operator ++(int) noexcept | |
{ | |
Iterator tmp = *this; | |
++(*this); | |
return tmp; | |
} | |
[[nodiscard]] | |
constexpr const Point& operator *() const noexcept { | |
return index; | |
} | |
[[nodiscard]] | |
constexpr const Point* operator ->() const noexcept { | |
return &index; | |
} | |
[[nodiscard]] | |
constexpr bool operator ==(const Iterator& r) const noexcept { | |
return index == r.index; | |
} | |
[[nodiscard]] | |
constexpr bool operator !=(const Iterator& r) const noexcept { | |
return index != r.index; | |
} | |
private: | |
Vec2 offset; | |
Vec2 size; | |
Vec2 lineBegin; | |
Vec2 lineVector; | |
Point index; | |
Point endIndex; | |
}; | |
using iterator = Iterator; | |
[[nodiscard]] | |
GridWalker(const Vec2& offset, const Vec2& size, const Line& line) :offset(offset), size(size), line(line) { | |
beginIndex = Floor((line.begin - offset) / size).asPoint(); | |
endIndex = Floor((line.end - offset) / size).asPoint(); | |
const Vec2 v= line.vector(); | |
endIndex = *(++Iterator(offset, size, line, endIndex, endIndex + (v.isZero() ? Point{1, 0} : Sign(line.vector()).asPoint()))); | |
} | |
[[nodiscard]] | |
constexpr iterator begin() const noexcept { | |
return Iterator(offset, size, line, beginIndex, endIndex); | |
} | |
[[nodiscard]] | |
constexpr iterator end() const noexcept { | |
return Iterator(offset, size, line, endIndex, endIndex); | |
} | |
}; | |
void Main() | |
{ | |
FontAsset::Register(U"index", 20, Typeface::Medium); | |
Vec2 offset{ 10,10 }; | |
Vec2 size{ 100,100 }; | |
Vec2 sizeDecider{ offset + size }; | |
bool offset_dragging = false; | |
bool sizeDecider_dragging = false; | |
Line line{ 100,100,300,300 }; | |
bool begin_dragging = false; | |
bool end_dragging = false; | |
while (System::Update()) | |
{ | |
//drawGrid | |
Point ulI = Ceil((Vec2{ 0,0 } - offset)/size).asPoint(); | |
Point brI = Floor((Scene::Size() - offset)/size).asPoint(); | |
for (auto x_i : Range(ulI.x, brI.x)) { | |
Line{ offset.x + size.x * x_i,0,Arg::direction(0,Scene::Height()) }.draw(); | |
} | |
for (auto y_i : Range(ulI.y, brI.y)) { | |
Line{ 0,offset.y + size.y * y_i,Arg::direction(Scene::Width(),0) }.draw(); | |
} | |
//drawDragPoint | |
offset.asCircle(5).draw(); | |
sizeDecider.asCircle(5).draw(); | |
//drawGridWalker | |
for (auto [ i,p] : Indexed(GridWalker(offset, size, line))) { | |
RectF{offset+ size * p, size }.draw(Palette::Orange.withAlpha(64)); | |
FontAsset(U"index")(i).drawAt(offset + size * p + size / 2); | |
} | |
//drawEnd | |
Point endIndex = *GridWalker(offset, size, line).end(); | |
RectF{ offset + size * endIndex, size }.draw(Palette::Purple.withAlpha(64)); | |
FontAsset(U"index")(U"end").drawAt(offset + size * endIndex + size / 2); | |
//drawDragLine | |
line.drawArrow(1, { 5,5 }, Palette::Red); | |
line.begin.asCircle(5).draw(Palette::Red); | |
dragVec2(offset, offset_dragging); | |
dragVec2(sizeDecider, sizeDecider_dragging); | |
dragVec2(line.begin, begin_dragging); | |
dragVec2(line.end, end_dragging); | |
size = sizeDecider - offset; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment