HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
transform.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 "matrix2.hpp"
8#include "matrix3.hpp"
9#include "translate2.hpp"
10#include "translate3.hpp"
11#include "rotate2.hpp"
12#include "rotate3.hpp"
13#include "scale2.hpp"
14#include "scale3.hpp"
15#include "perspective.hpp"
16#include "vector2.hpp"
17#include "vector3.hpp"
18#include "point2.hpp"
19#include "point3.hpp"
20#include "extent2.hpp"
21#include "extent3.hpp"
22#include "aarectangle.hpp"
23#include "rectangle.hpp"
24#include "quad.hpp"
25#include "circle.hpp"
26#include "corner_radii.hpp"
27#include "line_segment.hpp"
28#include "../macros.hpp"
29#include <type_traits>
30#include <functional>
31
32namespace hi { inline namespace v1 {
33
34template<typename T>
35struct transform2 : public std::false_type {};
36template<typename T>
37struct transform3 : public std::false_type {};
38
39// clang-format off
40template<> struct transform2<matrix2> : public std::true_type {};
41template<> struct transform3<matrix3> : public std::true_type {};
42template<> struct transform2<translate2> : public std::true_type {};
43template<> struct transform3<translate3> : public std::true_type {};
44template<> struct transform2<rotate2> : public std::true_type {};
45template<> struct transform3<rotate3> : public std::true_type {};
46template<> struct transform2<scale2> : public std::true_type {};
47template<> struct transform3<scale3> : public std::true_type {};
48template<> struct transform3<perspective> : public std::true_type {};
49// clang-format on
50
51template<typename T>
52constexpr bool transform2_v = transform2<T>::value;
53template<typename T>
54constexpr bool transform3_v = transform3<T>::value;
55
56template<typename T>
58template<typename T>
60template<typename T>
62
65[[nodiscard]] constexpr matrix2 operator*(matrix2 const& lhs, matrix2 const& rhs) noexcept
66{
67 return matrix2{lhs * get<0>(rhs), lhs * get<1>(rhs), lhs * get<2>(rhs), lhs * get<3>(rhs)};
68}
69
72[[nodiscard]] constexpr matrix3 operator*(matrix3 const& lhs, matrix3 const& rhs) noexcept
73{
74 return matrix3{lhs * get<0>(rhs), lhs * get<1>(rhs), lhs * get<2>(rhs), lhs * get<3>(rhs)};
75}
76
77[[nodiscard]] constexpr matrix2 operator*(translate2 const& lhs, matrix2 const& rhs) noexcept
78{
79 return matrix2{get<0>(rhs), get<1>(rhs), get<2>(rhs), get<3>(rhs) + f32x4{lhs}};
80}
81
82[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, matrix3 const& rhs) noexcept
83{
84 return matrix3{get<0>(rhs), get<1>(rhs), get<2>(rhs), get<3>(rhs) + f32x4{lhs}};
85}
86
87[[nodiscard]] constexpr translate2 operator*(translate2 const& lhs, translate2 const& rhs) noexcept
88{
89 return translate2{f32x4{lhs} + f32x4{rhs}};
90}
91
92[[nodiscard]] constexpr translate3 operator*(translate3 const& lhs, translate3 const& rhs) noexcept
93{
94 return translate3{f32x4{lhs} + f32x4{rhs}};
95}
96
97[[nodiscard]] constexpr matrix2 operator*(translate2 const& lhs, scale2 const& rhs) noexcept
98{
99 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
100 return matrix2{f32x4{rhs}.x000(), f32x4{rhs}._0y00(), f32x4{rhs}._00z0(), f32x4{lhs}.xyz1()};
101}
102
103[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, scale3 const& rhs) noexcept
104{
105 return matrix3{f32x4{rhs}.x000(), f32x4{rhs}._0y00(), f32x4{rhs}._00z0(), f32x4{lhs}.xyz1()};
106}
107
108[[nodiscard]] constexpr matrix2 operator*(translate2 const& lhs, rotate2 const& rhs) noexcept
109{
110 return lhs * matrix2(rhs);
111}
112
113[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, rotate3 const& rhs) noexcept
114{
115 return lhs * matrix3(rhs);
116}
117
118[[nodiscard]] constexpr matrix2 operator*(scale2 const& lhs, translate2 const& rhs) noexcept
119{
120 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
121 return matrix2{f32x4{lhs}.x000(), f32x4{lhs}._0y00(), f32x4{lhs}._00z0(), f32x4{lhs} * f32x4{rhs}.xyz1()};
122}
123
124[[nodiscard]] constexpr matrix3 operator*(scale3 const& lhs, translate3 const& rhs) noexcept
125{
126 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
127 return matrix3{f32x4{lhs}.x000(), f32x4{lhs}._0y00(), f32x4{lhs}._00z0(), f32x4{lhs} * f32x4{rhs}.xyz1()};
128}
129
130[[nodiscard]] constexpr scale2 operator*(scale2 const& lhs, scale2 const& rhs) noexcept
131{
132 return scale2{f32x4{lhs} * f32x4{rhs}};
133}
134
135[[nodiscard]] constexpr scale3 operator*(scale3 const& lhs, scale3 const& rhs) noexcept
136{
137 return scale3{f32x4{lhs} * f32x4{rhs}};
138}
139
140/******************* Shape operations ******************/
141
147[[nodiscard]] inline float operator*(matrix2 const& lhs, float const& rhs) noexcept
148{
149 // As if _col0 * rhs.xxxx() in operator*(f32x4 rhs)
150 hilet abs_scale = hypot<0b0011>(get<0>(lhs) * f32x4::broadcast(rhs));
151
152 // We want to keep the sign of the original scaler, even if the matrix has rotation.
153 return std::copysign(abs_scale, rhs);
154}
155
161[[nodiscard]] inline float operator*(matrix3 const &lhs, float const& rhs) noexcept
162{
163 // As if _col0 * rhs.xxxx() in operator*(f32x4 rhs)
164 hilet abs_scale = hypot<0b0111>(get<0>(lhs) * f32x4::broadcast(rhs));
165
166 // We want to keep the sign of the original scaler, even if the matrix has rotation.
167 return std::copysign(abs_scale, rhs);
168}
169
170[[nodiscard]] constexpr float operator*(translate2 const&, float const& rhs) noexcept
171{
172 return rhs;
173}
174
175[[nodiscard]] constexpr float operator*(translate3 const&, float const& rhs) noexcept
176{
177 return rhs;
178}
179
180[[nodiscard]] constexpr float operator*(scale2 const& lhs, float const& rhs) noexcept
181{
182 return lhs.x() * rhs;
183}
184
185[[nodiscard]] constexpr float operator*(scale3 const& lhs, float const& rhs) noexcept
186{
187 return lhs.x() * rhs;
188}
189
190[[nodiscard]] constexpr float operator*(rotate2 const&, float const& rhs) noexcept
191{
192 return rhs;
193}
194
195[[nodiscard]] constexpr float operator*(rotate3 const&, float const& rhs) noexcept
196{
197 return rhs;
198}
199
207[[nodiscard]] constexpr vector2 operator*(matrix2 const& lhs, vector2 const& rhs) noexcept
208{
209 return vector2{get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy()};
210}
211
212[[nodiscard]] constexpr vector2 operator*(translate2 const&, vector2 const& rhs) noexcept
213{
214 return rhs;
215}
216
217[[nodiscard]] constexpr vector2 operator*(translate3 const&, vector2 const& rhs) noexcept
218{
219 return rhs;
220}
221
222[[nodiscard]] constexpr vector2 operator*(scale2 const& lhs, vector2 const& rhs) noexcept
223{
224 return vector2{f32x4{lhs} * f32x4{rhs}};
225}
226
227[[nodiscard]] constexpr vector2 operator*(scale3 const& lhs, vector2 const& rhs) noexcept
228{
229 return vector2{f32x4{lhs} * f32x4{rhs}};
230}
231
239[[nodiscard]] constexpr vector3 operator*(matrix3 const& lhs, vector3 const& rhs) noexcept
240{
241 return vector3{get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy() + get<2>(lhs) * f32x4{rhs}.zzzz()};
242}
243
244[[nodiscard]] constexpr vector3 operator*(translate3 const&, vector3 const& rhs) noexcept
245{
246 return rhs;
247}
248
249[[nodiscard]] constexpr vector3 operator*(scale3 const& lhs, vector3 const& rhs) noexcept
250{
251 return vector3{f32x4{lhs} * f32x4{rhs}};
252}
253
259[[nodiscard]] constexpr point2 operator*(matrix2 const& lhs, point2 const& rhs) noexcept
260{
261 return point2{get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy() + get<3>(lhs)};
262}
263
264[[nodiscard]] constexpr point2 operator*(translate2 const& lhs, point2 const& rhs) noexcept
265{
266 return point2{f32x4{lhs} + f32x4{rhs}};
267}
268
269[[nodiscard]] constexpr point2 operator*(scale2 const& lhs, point2 const& rhs) noexcept
270{
271 return point2{f32x4{lhs} * f32x4{rhs}};
272}
273
274[[nodiscard]] constexpr point2 operator*(scale3 const& lhs, point2 const& rhs) noexcept
275{
276 return point2{f32x4{lhs} * f32x4{rhs}};
277}
278
284[[nodiscard]] constexpr point3 operator*(matrix3 const& lhs, point3 const& rhs) noexcept
285{
286 return point3{
287 get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy() + get<2>(lhs) * f32x4{rhs}.zzzz() +
288 get<3>(lhs) * f32x4{rhs}.wwww()};
289}
290
291[[nodiscard]] constexpr point3 operator*(translate3 const& lhs, point3 const& rhs) noexcept
292{
293 return point3{f32x4{lhs} + f32x4{rhs}};
294}
295
296[[nodiscard]] constexpr point3 operator*(scale3 const& lhs, point3 const& rhs) noexcept
297{
298 return point3{f32x4{lhs} * f32x4{rhs}};
299}
300
301[[nodiscard]] constexpr extent2 operator*(transformer2 auto const& lhs, extent2 const& rhs) noexcept
302{
303 return extent2{lhs *vector2{rhs}};
304}
305
306[[nodiscard]] constexpr extent3 operator*(transformer3 auto const& lhs, std::convertible_to<extent3> auto const& rhs) noexcept
307{
308 return extent3{lhs *vector3{rhs}};
309}
310
311[[nodiscard]] constexpr aarectangle operator*(translate2 const& lhs, aarectangle const& rhs) noexcept
312{
313 return aarectangle{lhs * get<0>(rhs), lhs * get<3>(rhs)};
314}
315
318[[nodiscard]] constexpr aarectangle operator*(scale2 const& lhs, aarectangle const& rhs) noexcept
319{
320 return aarectangle{lhs * get<0>(rhs), lhs * get<3>(rhs)};
321}
322
332[[nodiscard]] constexpr rectangle operator*(transformer auto const& lhs, aarectangle const& rhs) noexcept
333{
334 hilet rhs_ = rectangle{rhs};
335 return rectangle{lhs * rhs_.origin, lhs * rhs_.right, lhs * rhs_.up};
336}
337
344[[deprecated("Use full_mul() or fast_mul() instead.")]] [[nodiscard]] constexpr rectangle
345operator*(matrix2 const& lhs, aarectangle const& rhs) noexcept
346{
347 hilet rhs_ = rectangle{rhs};
348 return rectangle{lhs * rhs_.origin, lhs * rhs_.right, lhs * rhs_.up};
349}
350
357[[nodiscard]] constexpr rectangle full_mul(matrix2 const& lhs, aarectangle const& rhs) noexcept
358{
359 hilet rhs_ = rectangle{rhs};
360 return rectangle{lhs * rhs_.origin, lhs * rhs_.right, lhs * rhs_.up};
361}
362
369[[nodiscard]] constexpr aarectangle fast_mul(matrix2 const& lhs, aarectangle const& rhs) noexcept
370{
371 return aarectangle{lhs * get<0>(rhs), lhs * get<3>(rhs)};
372}
373
380[[nodiscard]] constexpr rectangle operator*(transformer auto const& lhs, rectangle const& rhs) noexcept
381{
382 return rectangle{lhs * rhs.origin, lhs * rhs.right, lhs * rhs.up};
383}
384
390[[nodiscard]] constexpr quad operator*(transformer auto const& lhs, quad const& rhs) noexcept
391{
392 return quad{lhs * rhs.p0, lhs * rhs.p1, lhs * rhs.p2, lhs * rhs.p3};
393}
394
400[[nodiscard]] constexpr circle operator*(transformer auto const& lhs, circle const& rhs) noexcept
401{
402 return circle{lhs * midpoint(rhs), lhs * rhs.radius()};
403}
404
410[[nodiscard]] constexpr line_segment operator*(transformer auto const& lhs, line_segment const& rhs) noexcept
411{
412 return line_segment{lhs * rhs.origin(), lhs * rhs.direction()};
413}
414
420[[nodiscard]] constexpr corner_radii operator*(matrix3 const& lhs, corner_radii const& rhs) noexcept
421{
422 return {lhs * get<0>(rhs), lhs * get<1>(rhs), lhs * get<2>(rhs), lhs * get<3>(rhs)};
423}
424
431template<typename Lhs, transformer Rhs>
432constexpr Lhs& operator*=(Lhs& lhs, Rhs const& rhs) noexcept
433 requires requires(Lhs& a, Rhs const& b) { a = b * a; }
434{
435 return lhs = rhs * lhs;
436}
437
438[[nodiscard]] constexpr aarectangle fit(aarectangle const& bounds, aarectangle const& rectangle) noexcept
439{
440 hilet resized_rectangle = aarectangle{
441 rectangle.left(),
442 rectangle.bottom(),
443 std::min(rectangle.width(), bounds.width()),
444 std::min(rectangle.height(), bounds.height())};
445
446 hilet translate_from_p0 = max(vector2{}, get<0>(bounds) - get<0>(resized_rectangle));
447 hilet translate_from_p3 = min(vector2{}, get<3>(bounds) - get<3>(resized_rectangle));
449}
450
459[[nodiscard]] constexpr quad scale_from_center(quad const& lhs, scale2 const& rhs) noexcept
460{
461 hilet top_extra = (lhs.top() * rhs.x() - lhs.top()) * 0.5f;
462 hilet bottom_extra = (lhs.bottom() * rhs.x() - lhs.bottom()) * 0.5f;
463 hilet left_extra = (lhs.left() * rhs.y() - lhs.left()) * 0.5f;
464 hilet right_extra = (lhs.right() * rhs.y() - lhs.right()) * 0.5f;
465
466 return {
467 lhs.p0 - bottom_extra - left_extra,
468 lhs.p1 + bottom_extra - right_extra,
469 lhs.p2 - top_extra + left_extra,
470 lhs.p3 + top_extra + right_extra};
471}
472
473}} // namespace hi::v1
Defined the corner_radii type.
Defined the geo::extent, extent2 and extent3 types.
Defines line_segment.
Defined the circle type.
Defined the geo::extent, extent2 and extent3 types.
@ rectangle
The gui_event has rectangle data.
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
constexpr aarectangle fast_mul(matrix2 const &lhs, aarectangle const &rhs) noexcept
Transform an axis-aligned rectangle without rotation by the matrix.
Definition transform.hpp:369
constexpr rectangle full_mul(matrix2 const &lhs, aarectangle const &rhs) noexcept
Transform an axis-aligned rectangle without rotation by the matrix.
Definition transform.hpp:357
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
constexpr Lhs & operator*=(Lhs &lhs, Rhs const &rhs) noexcept
Inplace geometric translation.
Definition transform.hpp:432
constexpr quad scale_from_center(quad const &lhs, scale2 const &rhs) noexcept
scale the quad.
Definition transform.hpp:459
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:29
A type defining a 2D circle.
Definition circle.hpp:19
The 4 radii of the corners of a quad or rectangle.
Definition corner_radii.hpp:19
Line segment.
Definition line_segment.hpp:21
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix2.hpp:27
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix3.hpp:30
Perspective transform.
Definition perspective.hpp:18
A rectangle / parallelogram in 3D space.
Definition rectangle.hpp:21
Definition rotate2.hpp:10
Definition rotate3.hpp:12
Definition scale2.hpp:13
Definition scale3.hpp:14
Definition transform.hpp:35
Definition transform.hpp:37
Definition translate2.hpp:14
Definition translate3.hpp:18
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector2.hpp:19
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector3.hpp:20
Definition transform.hpp:57
Definition transform.hpp:59
Definition transform.hpp:61
T copysign(T... args)
T max(T... args)
T min(T... args)