#pragma once #include "compat/assert.hpp" #include "rotation.hpp" #include #include #include #include namespace floormat { constexpr Triple rotation_symmetry(rotation r) { constexpr Pair> rotation_symmetries[] = { { rotation::N, { { 1, 1}, {0, 1}, {0, 1} } }, { rotation::E, { {-1, 1}, {1, 0}, {1, 0} } }, { rotation::S, { {-1, -1}, {0, 1}, {0, 1} } }, { rotation::W, { { 1, -1}, {1, 0}, {1, 0} } }, }; fm_assert(r < rotation_COUNT); auto idx = (size_t)r / 2; const auto& [r1, sym] = rotation_symmetries[idx]; return sym; } template using Vec2 = Math::Vector2; template constexpr Vec2 rotate_point(Vec2 rect, rotation r_old, rotation r_new) { fm_assert(r_old < rotation_COUNT && r_new < rotation_COUNT); auto [m_offset0, i_offset0, i_size0] = rotation_symmetry(r_old); auto offset0_ = rect * Vec2(m_offset0); auto offset_n = Vec2(offset0_[i_offset0[0]], offset0_[i_offset0[1]]); auto [m_offset1, i_offset1, i_size1] = rotation_symmetry(r_new); return Vec2{offset_n[i_offset1[0]], offset_n[i_offset1[1]]}*Vec2{m_offset1}; } constexpr Vector2ub rotate_size(Vector2ub size0, rotation r_old, rotation r_new) { fm_assert(r_old < rotation_COUNT && r_new < rotation_COUNT); auto [m_offset0, i_offset0, i_size0] = rotation_symmetry(r_old); auto size_n = Vector2ub(size0[i_size0[0]], size0[i_size0[1]]); //fm_debug_assert(r_old != rotation::N || offset_n == offset0 && size_n == size0); auto [m_offset1, i_offset1, i_size1] = rotation_symmetry(r_new); return Vector2ub{size_n[i_size1[0]], size_n[i_size1[1]]}; } constexpr Pair rotate_bbox(Vector2b offset0, Vector2ub size0, rotation r_old, rotation r_new) { return { rotate_point(offset0, r_old, r_new), rotate_size(size0, r_old, r_new), }; } } // namespace floormat