summaryrefslogtreecommitdiffhomepage
path: root/src/rotation.inl
blob: 4ddf1153e468c1a24e682eed4301dcd32c270350 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#pragma once
#include "compat/assert.hpp"
#include "rotation.hpp"
#include <Corrade/Containers/PairStl.h>
#include <Corrade/Containers/TripleStl.h>
#include <Magnum/Magnum.h>
#include <Magnum/Math/Vector2.h>

namespace floormat {

constexpr Triple<Vector2b, Vector2ub, Vector2ub> rotation_symmetry(rotation r)
{
    constexpr Pair<rotation, Triple<Vector2b, Vector2ub, Vector2ub>> 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<typename T> using Vec2 = Math::Vector2<T>;

template<typename T>
constexpr Vec2<T> rotate_point(Vec2<T> 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<T>(m_offset0);
    auto offset_n = Vec2<T>(offset0_[i_offset0[0]], offset0_[i_offset0[1]]);
    auto [m_offset1, i_offset1, i_size1] = rotation_symmetry(r_new);
    return Vec2<T>{offset_n[i_offset1[0]], offset_n[i_offset1[1]]}*Vec2<T>{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<Vector2b, Vector2ub> 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