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