HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
translate.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "matrix.hpp"
8#include "identity.hpp"
9
10namespace tt {
11namespace geo {
12
13template<int D>
14class translate {
15public:
16 static_assert(D == 2 || D == 3, "Only 2D or 3D translation-matrices are supported");
17
18 constexpr translate(translate const &) noexcept = default;
19 constexpr translate(translate &&) noexcept = default;
20 constexpr translate &operator=(translate const &) noexcept = default;
21 constexpr translate &operator=(translate &&) noexcept = default;
22
23 [[nodiscard]] constexpr operator matrix<D>() const noexcept
24 {
25 tt_axiom(is_valid());
26 ttlet ones = f32x4::broadcast(1.0);
27 return matrix<D>{ones.x000(), ones._0y00(), ones._00z0(), ones._000w() + _v};
28 }
29
30 [[nodiscard]] constexpr translate() noexcept : _v() {}
31
32 [[nodiscard]] constexpr translate(identity const &) noexcept : translate() {}
33
34 [[nodiscard]] constexpr explicit operator f32x4() const noexcept
35 {
36 tt_axiom(is_valid());
37 return _v;
38 }
39
40 [[nodiscard]] constexpr explicit translate(f32x4 const &other) noexcept : _v(other)
41 {
42 tt_axiom(is_valid());
43 }
44
45 [[nodiscard]] constexpr explicit translate(aarect const &other) noexcept : _v(other.p0().xy00())
46 {
47 tt_axiom(is_valid());
48 }
49
50 template<int E>
51 requires(E < D) [[nodiscard]] constexpr translate(translate<E> const &other) noexcept : _v(static_cast<f32x4>(other))
52 {
53 tt_axiom(is_valid());
54 }
55
56 template<int E>
57 requires(E <= D) [[nodiscard]] constexpr explicit translate(vector<E> const &other) noexcept : _v(static_cast<f32x4>(other))
58 {
59 tt_axiom(is_valid());
60 }
61
62 [[nodiscard]] constexpr translate(float x, float y) noexcept requires(D == 2) : _v(x, y, 0.0, 0.0) {}
63
64 [[nodiscard]] constexpr translate(float x, float y, float z = 0.0) noexcept requires(D == 3) : _v(x, y, z, 0.0) {}
65
72 [[nodiscard]] constexpr static translate align(aarect src_rectangle, aarect dst_rectangle, alignment alignment) noexcept
73 {
74 auto x = 0.0f;
75 if (alignment == horizontal_alignment::left) {
76 x = dst_rectangle.p0().x();
77
78 } else if (alignment == horizontal_alignment::right) {
79 x = dst_rectangle.p3().x() - src_rectangle.width();
80
81 } else if (alignment == horizontal_alignment::center) {
82 x = (dst_rectangle.p0().x() + (dst_rectangle.width() * 0.5f)) - (src_rectangle.width() * 0.5f);
83
84 } else {
85 tt_no_default();
86 }
87
88 auto y = 0.0f;
89 if (alignment == vertical_alignment::bottom) {
90 y = dst_rectangle.p0().y();
91
92 } else if (alignment == vertical_alignment::top) {
93 y = dst_rectangle.p3().y() - src_rectangle.height();
94
95 } else if (alignment == vertical_alignment::middle) {
96 y = (dst_rectangle.p0().y() + (dst_rectangle.height() * 0.5f)) - (src_rectangle.height() * 0.5f);
97
98 } else {
99 tt_no_default();
100 }
101
102 return translate{x - src_rectangle.x(), y - src_rectangle.y()};
103 }
104
105 template<int E>
106 [[nodiscard]] constexpr vector<E> operator*(vector<E> const &rhs) const noexcept
107 {
108 // Vectors are not translated.
109 tt_axiom(is_valid() && rhs.is_valid());
110 return rhs;
111 }
112
113 [[nodiscard]] constexpr f32x4 operator*(f32x4 const &rhs) const noexcept
114 {
115 return rhs + _v * f32x4::broadcast(rhs.w());
116 }
117
118 template<int E>
119 [[nodiscard]] constexpr point<std::max(D, E)> operator*(point<E> const &rhs) const noexcept
120 {
121 tt_axiom(is_valid() && rhs.is_valid());
122 return point<std::max(D, E)>{_v + static_cast<f32x4>(rhs)};
123 }
124
125 [[nodiscard]] constexpr aarect operator*(aarect const &rhs) const noexcept requires(D == 2)
126 {
127 return aarect::p0p3(_v + rhs.p0(), _v + rhs.p3());
128 }
129
130 [[nodiscard]] constexpr rect operator*(rect const &rhs) const noexcept
131 {
132 return rect{_v + rhs.corner<0>(), _v + rhs.corner<1>(), _v + rhs.corner<2>(), _v + rhs.corner<3>()};
133 }
134
135 [[nodiscard]] constexpr translate operator*(identity const &) const noexcept
136 {
137 tt_axiom(is_valid());
138 return *this;
139 }
140
141 template<int E>
142 [[nodiscard]] constexpr auto operator*(matrix<E> const &rhs) const noexcept
143 {
144 tt_axiom(is_valid() && rhs.is_valid());
145 return matrix<std::max(D, E)>{get<0>(rhs), get<1>(rhs), get<2>(rhs), get<3>(rhs) + _v};
146 }
147
148 template<int E>
149 [[nodiscard]] constexpr auto operator*(translate<E> const &rhs) const noexcept
150 {
151 tt_axiom(is_valid() && rhs.is_valid());
152 return translate<std::max(D, E)>{_v + static_cast<f32x4>(rhs)};
153 }
154
155 template<int E>
156 [[nodiscard]] constexpr bool operator==(translate<E> const &rhs) const noexcept
157 {
158 tt_axiom(is_valid() && rhs.is_valid());
159 return {_v == static_cast<f32x4>(rhs)};
160 }
161
162 [[nodiscard]] constexpr translate operator~() const noexcept
163 {
164 return translate{-_v};
165 }
166
167 [[nodiscard]] constexpr bool is_valid() const noexcept
168 {
169 return _v.w() == 0.0f && (D == 3 || _v.z() == 0.0f);
170 }
171
172private:
173 f32x4 _v;
174};
175
176} // namespace geo
177
178using translate2 = geo::translate<2>;
179using translate3 = geo::translate<3>;
180
181} // namespace tt
static axis_aligned_rectangle p0p3(numeric_array< float, 4 > const &v) noexcept
Create axis_aligned_rectangle from packed p0p3 coordinates.
Definition aarect.hpp:86
Definition identity.hpp:11
Definition matrix.hpp:18
Definition translate.hpp:14
static constexpr translate align(aarect src_rectangle, aarect dst_rectangle, alignment alignment) noexcept
Align a rectangle within another rectangle.
Definition translate.hpp:72
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:20
T max(T... args)