summaryrefslogtreecommitdiffhomepage
path: root/src/hole.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-05-26 10:13:57 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-05-26 10:13:57 +0200
commit67bec06c00b10f57d0d4701a357f29efe7520e3b (patch)
tree37abbfe48ce0c833a8dd8bce54397e41fb732e7d /src/hole.cpp
parent38345b767464de5f070bdcf48acbc6aa43439f8a (diff)
w
Diffstat (limited to 'src/hole.cpp')
-rw-r--r--src/hole.cpp178
1 files changed, 151 insertions, 27 deletions
diff --git a/src/hole.cpp b/src/hole.cpp
index cdd409d7..aba4e7f3 100644
--- a/src/hole.cpp
+++ b/src/hole.cpp
@@ -1,52 +1,176 @@
#include "hole.hpp"
+#include "compat/array-size.hpp"
+#include "compat/iota.hpp"
+#include "compat/map.hpp"
//#include <mg/Functions.h>
+#ifdef __GNUG__
+#pragma GCC diagnostic ignored "-Wswitch-default"
+//#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
namespace floormat {
+namespace {
using bbox = cut_rectangle_result::bbox;
-namespace {
+enum shift : uint8_t { __ = 0, x0 = 1 << 0, x1 = 1 << 1, y0 = 1 << 2, y1 = 1 << 3, };
+enum class location : uint8_t { R0, R1, H0, H1, };
+
+struct coords
+{
+ location x0 : 2;
+ location x1 : 2;
+ location y0 : 2;
+ location y1 : 2;
+};
+
+struct element
+{
+ uint8_t size;
+ std::array<coords, 8> array;
+};
+
+constexpr element make_element(uint8_t s)
+{
+ switch (s)
+ {
+ using enum location;
+ case x0|x1|y0|y1: return element{1, {{ // 9.1
+ {R0, R1, R0, R1},
+ }}};
+ case __|__|__|__: return element{8, {{ // 14.1
+ {R0, H0, R0, H0},
+ {H0, H1, R0, H0},
+ {H1, R1, R0, H0},
+ {R0, H0, H0, H1},
+ {H1, R1, H0, H1},
+ {R0, H0, H1, R1},
+ {H0, H1, H0, R1},
+ {H1, R1, H1, R1},
+ }}};
+
+ case x0|x1|__|__: return element{2, {{ // 13.1
+ {R0, R1, R0, H0},
+ {R0, R1, H1, R1},
+ }}};
+ case __|__|y0|y1: return element{2, {{ // 13.2
+ {R0, H0, H1, R1},
+ {H1, R1, R0, R1},
+ }}};
+
+ case x0|x1|y0|__: return element{1, {{ // 12.1
+ {R0, R1, H1, R1},
+ }}};
+ case x0|x1|__|y1: return element{1, {{ // 12.2
+ {R0, R1, R0, H0},
+ }}};
+ case x0|__|y0|y1: return element{1, {{ // 12.3
+ {H1, R1, R0, R1},
+ }}};
+ case __|x1|y0|y1: return element{1, {{ // 12.4
+ {R0, H0, R0, R1},
+ }}};
+ case x0|__|__|__: return element{3, {{ // 10.1
+ {R0, R1, R0, H0},
+ {H1, R1, H0, H1},
+ {R0, R1, H1, R1},
+ }}};
+ case __|x1|__|__: return element{3, {{ // 10.2
+ {R0, R1, R0, H0},
+ {R0, H0, H0, H1},
+ {R0, R1, H1, R1},
+ }}};
+ case __|__|y0|__: return element{3, {{ // 10.3
+ {R0, H0, R0, R1},
+ {H0, H1, H0, R1},
+ {H1, R1, R0, R1},
+ }}};
+ case __|__|__|y1: return element{3, {{ // 10.4
+ {R0, H0, R0, R1},
+ {H0, H1, R0, H0},
+ {H1, R1, R0, R1},
+ }}};
+
+ case x0|__|y0|__: return element{2, {{ // 11.1
+ {H1, R1, R0, H1},
+ {R0, R1, H1, R1},
+ }}};
+ case __|x1|y0|__: return element{2, {{ // 11.2
+ {R0, H0, R0, H1},
+ {R0, R1, H1, R1},
+ }}};
+ case x0|__|__|y1: return element{2, {{ // 11.3
+ {R0, R1, R0, H0},
+ {H1, R1, H0, R1},
+ }}};
+ case __|x1|__|y1: return element{2, {{ // 11.4
+ {R0, R1, R0, H0},
+ {R0, H0, H0, H1},
+ }}};
+ }
+ fm_assert(false);
+}
+constexpr auto elements = map(make_element, iota_array<uint8_t, 16>);
+static_assert(array_size(elements) == 16);
} // namespace
-cut_rectangle_result cut_rectangle(cut_rectangle_result::bbox input, cut_rectangle_result::bbox hole)
+constexpr cut_rectangle_result cut_rectangle(bbox input, bbox hole)
{
- const auto ihalf = Vector2i{input.bbox_size/2};
- const auto istart = input.position - ihalf;
- const auto iend = input.position + Vector2i{input.bbox_size} - ihalf;
- const auto hhalf = Vector2i{hole.bbox_size/2};
- const auto hstart = hole.position - hhalf;
- const auto hend = hole.position + Vector2i{hole.bbox_size} - hhalf;
+ auto ihalf = Vector2i{input.bbox_size/2};
+ auto r0 = input.position - ihalf;
+ auto r1 = input.position + Vector2i{input.bbox_size} - ihalf;
- //std::atomic_signal_fence(std::memory_order::relaxed); // compiler-only barrier
+ auto hhalf = Vector2i{hole.bbox_size/2};
+ auto h0 = hole.position - hhalf;
+ auto h1 = hole.position + Vector2i{hole.bbox_size} - hhalf;
{
bool iempty = Vector2ui{input.bbox_size}.product() == 0;
bool hempty = Vector2ui{hole.bbox_size}.product() == 0;
- bool empty_before_x = hend.x() <= istart.x();
- bool empty_before_y = hend.y() <= istart.y();
- bool empty_after_x = hstart.x() >= iend.x();
- bool empty_after_y = hstart.y() >= iend.y();
- if (iempty | hempty | empty_before_x | empty_before_y | empty_after_x | empty_after_y)
- return {};
+ bool empty_before_x = h1.x() <= r0.x();
+ bool empty_after_x = h0.x() >= r1.x();
+ bool empty_before_y = h1.y() <= r0.y();
+ bool empty_after_y = h0.y() >= r1.y();
+
+ if (iempty | hempty | empty_before_x | empty_after_x | empty_before_y | empty_after_y) [[unlikely]]
+ return { 0, {} };
}
- const bool sx = hstart.x() <= istart.x();
- const bool ex = hend.x() >= iend.x();
- const bool sy = hstart.y() <= istart.y();
- const bool ey = hend.y() >= iend.y();
+ const bool sx = h0.x() <= r0.x();
+ const bool ex = h1.x() >= r1.x();
+ const bool sy = h0.y() <= r0.y();
+ const bool ey = h1.y() >= r1.y();
- enum : uint8_t { SX, EX, SY, EY };
- enum : uint8_t { startx = 1 << SX, endx = 1 << EX, starty = 1 << SY, endy = 1 << EY };
+ auto val = uint8_t(sx << 0 | ex << 1 | sy << 2 | ey << 3);
+ CORRADE_ASSUME(val < 16);
+ const auto elt = elements[val];
+ cut_rectangle_result res = {
+ .size = elt.size,
+ .array = {},
+ };
- constexpr auto mask = uint8_t(startx | endx | starty | endy);
- auto val = uint8_t(sx << SX | ex << EX | sy << SY | ey << EY);
- CORRADE_ASSUME((val & mask) == val);
- (void)val;
+ const Int xs[4] = { r0.x(), r1.x(), h0.x(), h1.x(), };
+ const Int ys[4] = { r0.y(), r1.y(), h0.y(), h1.y(), };
- return {};
-}
+ for (auto i = 0uz; i < elt.size; i++)
+ {
+ const auto e = elt.array[i];
+ const auto x0 = xs[(uint8_t)e.x0];
+ const auto x1 = xs[(uint8_t)e.x1];
+ const auto y0 = ys[(uint8_t)e.y0];
+ const auto y1 = ys[(uint8_t)e.y1];
+
+ res.array[i] = { {x0, y0}, {x1, y1}, };
+ }
+
+ fm_assert(false);
+ std::unreachable();
+
+ //return -1;
+}
} // namespace floormat