HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
translate.hpp
1// Copyright Take Vos 2021-2022.
2// Distributed under the Boost Software License, Version value_type{1}.
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#include "rotate.hpp"
10
11namespace hi::inline v1 {
12namespace geo {
13
14template<typename T, int D>
15class translate {
16public:
17 static_assert(D == 2 || D == 3, "Only 2D or 3D translation-matrices are supported");
18
19 using value_type = T;
21
22 constexpr translate(translate const&) noexcept = default;
23 constexpr translate(translate&&) noexcept = default;
24 constexpr translate& operator=(translate const&) noexcept = default;
25 constexpr translate& operator=(translate&&) noexcept = default;
26
27 [[nodiscard]] constexpr operator matrix<2>() const noexcept
28 requires std::is_same_v<value_type, float> and (D == 2)
29 {
30 hi_axiom(holds_invariant());
31 hilet ones = array_type::broadcast(value_type{1});
32 return matrix<2>{ones.x000(), ones._0y00(), ones._00z0(), ones._000w() + _v};
33 }
34
35 [[nodiscard]] constexpr operator matrix<3>() const noexcept
36 requires std::is_same_v<value_type, float>
37 {
38 hi_axiom(holds_invariant());
39 hilet ones = array_type::broadcast(value_type{1});
40 return matrix<3>{ones.x000(), ones._0y00(), ones._00z0(), ones._000w() + _v};
41 }
42
43 [[nodiscard]] constexpr translate() noexcept : _v() {}
44
45 [[nodiscard]] constexpr translate(identity const&) noexcept : translate() {}
46
47 [[nodiscard]] constexpr explicit operator array_type() const noexcept
48 {
49 hi_axiom(holds_invariant());
50 return _v;
51 }
52
53 [[nodiscard]] constexpr explicit translate(array_type const& other) noexcept : _v(other)
54 {
55 hi_axiom(holds_invariant());
56 }
57
58 [[nodiscard]] constexpr explicit translate(axis_aligned_rectangle<value_type> const& other) noexcept :
59 _v(static_cast<array_type>(get<0>(other)).xy00())
60 {
61 hi_axiom(holds_invariant());
62 }
63
64 [[nodiscard]] constexpr explicit translate(axis_aligned_rectangle<value_type> const& other, value_type z) noexcept
65 requires(D == 3)
66 : _v(static_cast<array_type>(get<0>(other)).xy00())
67 {
68 _v.z() = z;
69 hi_axiom(holds_invariant());
70 }
71
72 template<int E>
73 requires(E < D)
74 [[nodiscard]] constexpr translate(translate<value_type, E> const& other) noexcept : _v(static_cast<array_type>(other))
75 {
76 hi_axiom(holds_invariant());
77 }
78
79 template<int E>
80 requires(E < D)
81 [[nodiscard]] constexpr translate(translate<value_type, E> const& other, value_type z) noexcept :
82 _v(static_cast<array_type>(other))
83 {
84 _v.z() = z;
85 hi_axiom(holds_invariant());
86 }
87
88 template<int E>
89 requires(E <= D)
90 [[nodiscard]] constexpr explicit translate(vector<value_type, E> const& other) noexcept : _v(static_cast<array_type>(other))
91 {
92 hi_axiom(holds_invariant());
93 }
94
95 template<int E>
96 requires(E <= D)
97 [[nodiscard]] constexpr explicit translate(point<value_type, E> const& other) noexcept :
98 _v(static_cast<array_type>(other).xyz0())
99 {
100 hi_axiom(holds_invariant());
101 }
102
103 [[nodiscard]] constexpr translate(value_type x, value_type y) noexcept
104 requires(D == 2)
105 : _v(x, y, value_type{0}, value_type{0})
106 {
107 }
108
109 [[nodiscard]] constexpr translate(value_type x, value_type y, value_type z = value_type{0}) noexcept
110 requires(D == 3)
111 : _v(x, y, z, value_type{0})
112 {
113 }
114
115 [[nodiscard]] constexpr value_type x() const noexcept
116 {
117 return _v.x();
118 }
119
120 [[nodiscard]] constexpr value_type y() const noexcept requires(D >= 2)
121 {
122 return _v.y();
123 }
124
125 [[nodiscard]] constexpr value_type z() const noexcept requires(D >= 3)
126 {
127 return _v.z();
128 }
129
136 [[nodiscard]] constexpr static translate align(
137 axis_aligned_rectangle<value_type> src_rectangle,
138 axis_aligned_rectangle<value_type> dst_rectangle,
139 alignment alignment) noexcept
140 {
141 auto x = value_type{0};
142 if (alignment == horizontal_alignment::left) {
143 x = dst_rectangle.left();
144
145 } else if (alignment == horizontal_alignment::right) {
146 x = dst_rectangle.right() - src_rectangle.width();
147
148 } else if (alignment == horizontal_alignment::center) {
149 x = dst_rectangle.center() - src_rectangle.width() * 0.5f;
150
151 } else {
153 }
154
155 auto y = value_type{0};
156 if (alignment == vertical_alignment::bottom) {
157 y = dst_rectangle.bottom();
158
159 } else if (alignment == vertical_alignment::top) {
160 y = dst_rectangle.top() - src_rectangle.height();
161
162 } else if (alignment == vertical_alignment::middle) {
163 y = dst_rectangle.middle() - src_rectangle.height() * 0.5f;
164
165 } else {
167 }
168
169 return translate{x - src_rectangle.left(), y - src_rectangle.bottom()};
170 }
171
172 template<int E>
173 [[nodiscard]] constexpr vector<value_type, E> operator*(vector<value_type, E> const& rhs) const noexcept
174 {
175 // Vectors are not translated.
176 hi_axiom(holds_invariant() && rhs.holds_invariant());
177 return rhs;
178 }
179
180 template<int E>
181 [[nodiscard]] constexpr point<value_type, std::max(D, E)> operator*(point<value_type, E> const& rhs) const noexcept
182 {
183 hi_axiom(holds_invariant() && rhs.holds_invariant());
184 return point<value_type, std::max(D, E)>{_v + static_cast<array_type>(rhs)};
185 }
186
187 [[nodiscard]] constexpr axis_aligned_rectangle<value_type>
188 operator*(axis_aligned_rectangle<value_type> const& rhs) const noexcept
189 requires(D == 2)
190 {
191 return axis_aligned_rectangle<value_type>{*this * get<0>(rhs), *this * get<3>(rhs)};
192 }
193
194 [[nodiscard]] constexpr rectangle operator*(axis_aligned_rectangle<value_type> const& rhs) const noexcept
195 requires std::is_same_v<value_type, float> and (D == 3)
196 {
197 return *this * rectangle{rhs};
198 }
199
200 [[nodiscard]] constexpr rectangle operator*(rectangle const& rhs) const noexcept
201 requires std::is_same_v<value_type, float>
202 {
203 return rectangle{*this * rhs.origin, rhs.right, rhs.up};
204 }
205
206 [[nodiscard]] constexpr quad operator*(quad const& rhs) const noexcept
207 requires std::is_same_v<value_type, float>
208 {
209 return quad{*this * rhs.p0, *this * rhs.p1, *this * rhs.p2, *this * rhs.p3};
210 }
211
212 [[nodiscard]] constexpr circle operator*(circle const& rhs) const noexcept
213 requires std::is_same_v<value_type, float>
214 {
215 return circle{array_type{rhs} + _v};
216 }
217
218 [[nodiscard]] constexpr line_segment operator*(line_segment const& rhs) const noexcept
219 requires std::is_same_v<value_type, float>
220 {
221 return line_segment{*this * rhs.origin(), rhs.direction()};
222 }
223
224 [[nodiscard]] constexpr translate operator*(identity const&) const noexcept
225 {
226 hi_axiom(holds_invariant());
227 return *this;
228 }
229
230 template<int E>
231 [[nodiscard]] constexpr auto operator*(matrix<E> const& rhs) const noexcept
232 requires std::is_same_v<value_type, float>
233 {
234 hi_axiom(holds_invariant() && rhs.holds_invariant());
235 return matrix<std::max(D, E)>{get<0>(rhs), get<1>(rhs), get<2>(rhs), get<3>(rhs) + _v};
236 }
237
238 template<int E>
239 [[nodiscard]] constexpr auto operator*(rotate<E> const& rhs) const noexcept
240 requires std::is_same_v<value_type, float>
241 {
242 return *this * matrix<E>(rhs);
243 }
244
245 template<int E>
246 [[nodiscard]] constexpr auto operator*(translate<value_type, E> const& rhs) const noexcept
247 {
248 hi_axiom(holds_invariant() && rhs.holds_invariant());
249 return translate<value_type, std::max(D, E)>{_v + static_cast<array_type>(rhs)};
250 }
251
252 template<int E>
253 [[nodiscard]] constexpr bool operator==(translate<value_type, E> const& rhs) const noexcept
254 {
255 hi_axiom(holds_invariant() && rhs.holds_invariant());
256 return _v == static_cast<array_type>(rhs);
257 }
258
259 [[nodiscard]] constexpr translate operator~() const noexcept
260 {
261 return translate{-_v};
262 }
263
264 [[nodiscard]] constexpr bool holds_invariant() const noexcept
265 {
266 return _v.w() == value_type{0} && (D == 3 || _v.z() == value_type{0});
267 }
268
269 [[nodiscard]] friend constexpr translate round(translate const& rhs) noexcept
270 requires std::is_same_v<value_type, float>
271 {
272 return translate{round(rhs._v)};
273 }
274
275private:
276 array_type _v;
277};
278
279} // namespace geo
280
281using translate2 = geo::translate<float, 2>;
282using translate3 = geo::translate<float, 3>;
283using translate2i = geo::translate<int, 2>;
284using translate3i = geo::translate<int, 3>;
285
286constexpr translate3 translate_z(float z) noexcept
287{
288 return translate3{float{0}, float{0}, z};
289}
290
291constexpr translate3i translate_z(int z) noexcept
292{
293 return translate3i{int{0}, int{0}, z};
294}
295
296template<>
297[[nodiscard]] constexpr translate2 narrow_cast(translate2i const &rhs) noexcept
298{
299 return {narrow_cast<float>(rhs.x()), narrow_cast<float>(rhs.y())};
300}
301
302} // namespace hi::inline v1
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:148
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Defines identity type.
Defines geo::matrix, matrix2 and matrix3.
@ rectangle
The gui_event has rectangle data.
DOXYGEN BUG.
Definition algorithm.hpp:15
@ circle
<circle> Encircled form.
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:178
Horizontal/Vertical alignment combination.
Definition alignment.hpp:232
A high-level geometric point Part of the high-level vec, point, mat and color types.
Definition point.hpp:24
Definition translate.hpp:15
static constexpr translate align(axis_aligned_rectangle< value_type > src_rectangle, axis_aligned_rectangle< value_type > dst_rectangle, alignment alignment) noexcept
Align a rectangle within another rectangle.
Definition translate.hpp:136
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:21
T max(T... args)
T round(T... args)