Skip to content

Instantly share code, notes, and snippets.

@comefrombottom
Last active January 20, 2024 17:22
Show Gist options
  • Save comefrombottom/c8e5d113dd17c8125bfd450c0095a281 to your computer and use it in GitHub Desktop.
Save comefrombottom/c8e5d113dd17c8125bfd450c0095a281 to your computer and use it in GitHub Desktop.
格子上のLineが通るIndexを順に返すイテレータ
# 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