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#include <exception>
32#include <compare>
33
34hi_export_module(hikogui.geometry : transform);
35
36hi_export namespace hi { inline namespace v1 {
37
38template<typename T>
39struct transform2 : public std::false_type {};
40template<typename T>
41struct transform3 : public std::false_type {};
42
43// clang-format off
44template<> struct transform2<matrix2> : public std::true_type {};
45template<> struct transform3<matrix3> : public std::true_type {};
46template<> struct transform2<translate2> : public std::true_type {};
47template<> struct transform3<translate3> : public std::true_type {};
48template<> struct transform2<rotate2> : public std::true_type {};
49template<> struct transform3<rotate3> : public std::true_type {};
50template<> struct transform2<scale2> : public std::true_type {};
51template<> struct transform3<scale3> : public std::true_type {};
52template<> struct transform3<perspective> : public std::true_type {};
53// clang-format on
54
55template<typename T>
56constexpr bool transform2_v = transform2<T>::value;
57template<typename T>
58constexpr bool transform3_v = transform3<T>::value;
59
60template<typename T>
61concept transformer2 = transform2_v<T>;
62template<typename T>
63concept transformer3 = transform3_v<T>;
64template<typename T>
66
69[[nodiscard]] constexpr matrix2 operator*(matrix2 const& lhs, matrix2 const& rhs) noexcept
70{
71 return matrix2{lhs * get<0>(rhs), lhs * get<1>(rhs), lhs * get<2>(rhs), lhs * get<3>(rhs)};
72}
73
76[[nodiscard]] constexpr matrix3 operator*(matrix3 const& lhs, matrix3 const& rhs) noexcept
77{
78 return matrix3{lhs * get<0>(rhs), lhs * get<1>(rhs), lhs * get<2>(rhs), lhs * get<3>(rhs)};
79}
80
81[[nodiscard]] constexpr matrix2 operator*(translate2 const& lhs, matrix2 const& rhs) noexcept
82{
83 return matrix2{get<0>(rhs), get<1>(rhs), get<2>(rhs), get<3>(rhs) + f32x4{lhs}};
84}
85
86[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, matrix3 const& rhs) noexcept
87{
88 return matrix3{get<0>(rhs), get<1>(rhs), get<2>(rhs), get<3>(rhs) + f32x4{lhs}};
89}
90
91[[nodiscard]] constexpr translate2 operator*(translate2 const& lhs, translate2 const& rhs) noexcept
92{
93 return translate2{f32x4{lhs} + f32x4{rhs}};
94}
95
96[[nodiscard]] constexpr translate3 operator*(translate3 const& lhs, translate3 const& rhs) noexcept
97{
98 return translate3{f32x4{lhs} + f32x4{rhs}};
99}
100
101[[nodiscard]] constexpr matrix2 operator*(translate2 const& lhs, scale2 const& rhs) noexcept
102{
103 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
104 return matrix2{f32x4{rhs}.x000(), f32x4{rhs}._0y00(), f32x4{rhs}._00z0(), f32x4{lhs}.xyz1()};
105}
106
107[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, scale3 const& rhs) noexcept
108{
109 return matrix3{f32x4{rhs}.x000(), f32x4{rhs}._0y00(), f32x4{rhs}._00z0(), f32x4{lhs}.xyz1()};
110}
111
112[[nodiscard]] constexpr matrix2 operator*(translate2 const& lhs, rotate2 const& rhs) noexcept
113{
114 return lhs * matrix2(rhs);
115}
116
117[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, rotate3 const& rhs) noexcept
118{
119 return lhs * matrix3(rhs);
120}
121
122[[nodiscard]] constexpr matrix2 operator*(scale2 const& lhs, translate2 const& rhs) noexcept
123{
124 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
125 return matrix2{f32x4{lhs}.x000(), f32x4{lhs}._0y00(), f32x4{lhs}._00z0(), f32x4{lhs} * f32x4{rhs}.xyz1()};
126}
127
128[[nodiscard]] constexpr matrix3 operator*(scale3 const& lhs, translate3 const& rhs) noexcept
129{
130 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
131 return matrix3{f32x4{lhs}.x000(), f32x4{lhs}._0y00(), f32x4{lhs}._00z0(), f32x4{lhs} * f32x4{rhs}.xyz1()};
132}
133
134[[nodiscard]] constexpr scale2 operator*(scale2 const& lhs, scale2 const& rhs) noexcept
135{
136 return scale2{f32x4{lhs} * f32x4{rhs}};
137}
138
139[[nodiscard]] constexpr scale3 operator*(scale3 const& lhs, scale3 const& rhs) noexcept
140{
141 return scale3{f32x4{lhs} * f32x4{rhs}};
142}
143
144/******************* Shape operations ******************/
145
151[[nodiscard]] inline float operator*(matrix2 const& lhs, float const& rhs) noexcept
152{
153 // As if _col0 * rhs.xxxx() in operator*(f32x4 rhs)
154 auto const abs_scale = hypot<0b0011>(get<0>(lhs) * f32x4::broadcast(rhs)).x();
155
156 // We want to keep the sign of the original scaler, even if the matrix has rotation.
157 return std::copysign(abs_scale, rhs);
158}
159
165[[nodiscard]] inline float operator*(matrix3 const &lhs, float const& rhs) noexcept
166{
167 // As if _col0 * rhs.xxxx() in operator*(f32x4 rhs)
168 auto const abs_scale = hypot<0b0111>(get<0>(lhs) * f32x4::broadcast(rhs)).x();
169
170 // We want to keep the sign of the original scaler, even if the matrix has rotation.
171 return std::copysign(abs_scale, rhs);
172}
173
174[[nodiscard]] constexpr float operator*(translate2 const&, float const& rhs) noexcept
175{
176 return rhs;
177}
178
179[[nodiscard]] constexpr float operator*(translate3 const&, float const& rhs) noexcept
180{
181 return rhs;
182}
183
184[[nodiscard]] constexpr float operator*(scale2 const& lhs, float const& rhs) noexcept
185{
186 return lhs.x() * rhs;
187}
188
189[[nodiscard]] constexpr float operator*(scale3 const& lhs, float const& rhs) noexcept
190{
191 return lhs.x() * rhs;
192}
193
194[[nodiscard]] constexpr float operator*(rotate2 const&, float const& rhs) noexcept
195{
196 return rhs;
197}
198
199[[nodiscard]] constexpr float operator*(rotate3 const&, float const& rhs) noexcept
200{
201 return rhs;
202}
203
211[[nodiscard]] constexpr vector2 operator*(matrix2 const& lhs, vector2 const& rhs) noexcept
212{
213 return vector2{get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy()};
214}
215
216[[nodiscard]] constexpr vector2 operator*(translate2 const&, vector2 const& rhs) noexcept
217{
218 return rhs;
219}
220
221[[nodiscard]] constexpr vector2 operator*(translate3 const&, vector2 const& rhs) noexcept
222{
223 return rhs;
224}
225
226[[nodiscard]] constexpr vector2 operator*(scale2 const& lhs, vector2 const& rhs) noexcept
227{
228 return vector2{f32x4{lhs} * f32x4{rhs}};
229}
230
231[[nodiscard]] constexpr vector2 operator*(scale3 const& lhs, vector2 const& rhs) noexcept
232{
233 return vector2{f32x4{lhs} * f32x4{rhs}};
234}
235
243[[nodiscard]] constexpr vector3 operator*(matrix3 const& lhs, vector3 const& rhs) noexcept
244{
245 return vector3{get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy() + get<2>(lhs) * f32x4{rhs}.zzzz()};
246}
247
248[[nodiscard]] constexpr vector3 operator*(translate3 const&, vector3 const& rhs) noexcept
249{
250 return rhs;
251}
252
253[[nodiscard]] constexpr vector3 operator*(scale3 const& lhs, vector3 const& rhs) noexcept
254{
255 return vector3{f32x4{lhs} * f32x4{rhs}};
256}
257
263[[nodiscard]] constexpr point2 operator*(matrix2 const& lhs, point2 const& rhs) noexcept
264{
265 return point2{get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy() + get<3>(lhs)};
266}
267
268[[nodiscard]] constexpr point2 operator*(translate2 const& lhs, point2 const& rhs) noexcept
269{
270 return point2{f32x4{lhs} + f32x4{rhs}};
271}
272
273[[nodiscard]] constexpr point2 operator*(scale2 const& lhs, point2 const& rhs) noexcept
274{
275 return point2{f32x4{lhs} * f32x4{rhs}};
276}
277
278[[nodiscard]] constexpr point2 operator*(scale3 const& lhs, point2 const& rhs) noexcept
279{
280 return point2{f32x4{lhs} * f32x4{rhs}};
281}
282
288[[nodiscard]] constexpr point3 operator*(matrix3 const& lhs, point3 const& rhs) noexcept
289{
290 return point3{
291 get<0>(lhs) * f32x4{rhs}.xxxx() + get<1>(lhs) * f32x4{rhs}.yyyy() + get<2>(lhs) * f32x4{rhs}.zzzz() +
292 get<3>(lhs) * f32x4{rhs}.wwww()};
293}
294
295[[nodiscard]] constexpr point3 operator*(translate3 const& lhs, point3 const& rhs) noexcept
296{
297 return point3{f32x4{lhs} + f32x4{rhs}};
298}
299
300[[nodiscard]] constexpr point3 operator*(scale3 const& lhs, point3 const& rhs) noexcept
301{
302 return point3{f32x4{lhs} * f32x4{rhs}};
303}
304
305[[nodiscard]] constexpr extent2 operator*(transformer2 auto const& lhs, extent2 const& rhs) noexcept
306{
307 return extent2{lhs *vector2{rhs}};
308}
309
310[[nodiscard]] constexpr extent3 operator*(transformer3 auto const& lhs, std::convertible_to<extent3> auto const& rhs) noexcept
311{
312 return extent3{lhs *vector3{rhs}};
313}
314
315[[nodiscard]] constexpr aarectangle operator*(translate2 const& lhs, aarectangle const& rhs) noexcept
316{
317 return aarectangle{lhs * get<0>(rhs), lhs * get<3>(rhs)};
318}
319
322[[nodiscard]] constexpr aarectangle operator*(scale2 const& lhs, aarectangle const& rhs) noexcept
323{
324 return aarectangle{lhs * get<0>(rhs), lhs * get<3>(rhs)};
325}
326
336[[nodiscard]] constexpr rectangle operator*(transformer auto const& lhs, aarectangle const& rhs) noexcept
337{
338 auto const rhs_ = rectangle{rhs};
339 return rectangle{lhs * rhs_.origin, lhs * rhs_.right, lhs * rhs_.up};
340}
341
348[[deprecated("Use full_mul() or fast_mul() instead.")]] [[nodiscard]] constexpr rectangle
349operator*(matrix2 const& lhs, aarectangle const& rhs) noexcept
350{
351 auto const rhs_ = rectangle{rhs};
352 return rectangle{lhs * rhs_.origin, lhs * rhs_.right, lhs * rhs_.up};
353}
354
361[[nodiscard]] constexpr rectangle full_mul(matrix2 const& lhs, aarectangle const& rhs) noexcept
362{
363 auto const rhs_ = rectangle{rhs};
364 return rectangle{lhs * rhs_.origin, lhs * rhs_.right, lhs * rhs_.up};
365}
366
373[[nodiscard]] constexpr aarectangle fast_mul(matrix2 const& lhs, aarectangle const& rhs) noexcept
374{
375 return aarectangle{lhs * get<0>(rhs), lhs * get<3>(rhs)};
376}
377
384[[nodiscard]] constexpr rectangle operator*(transformer auto const& lhs, rectangle const& rhs) noexcept
385{
386 return rectangle{lhs * rhs.origin, lhs * rhs.right, lhs * rhs.up};
387}
388
394[[nodiscard]] constexpr quad operator*(transformer auto const& lhs, quad const& rhs) noexcept
395{
396 return quad{lhs * rhs.p0, lhs * rhs.p1, lhs * rhs.p2, lhs * rhs.p3};
397}
398
404[[nodiscard]] constexpr circle operator*(transformer auto const& lhs, circle const& rhs) noexcept
405{
406 return circle{lhs * midpoint(rhs), lhs * rhs.radius()};
407}
408
414[[nodiscard]] constexpr line_segment operator*(transformer auto const& lhs, line_segment const& rhs) noexcept
415{
416 return line_segment{lhs * rhs.origin(), lhs * rhs.direction()};
417}
418
424[[nodiscard]] constexpr corner_radii operator*(matrix3 const& lhs, corner_radii const& rhs) noexcept
425{
426 return {lhs * get<0>(rhs), lhs * get<1>(rhs), lhs * get<2>(rhs), lhs * get<3>(rhs)};
427}
428
435template<typename Lhs, transformer Rhs>
436constexpr Lhs& operator*=(Lhs& lhs, Rhs const& rhs) noexcept
437 requires requires(Lhs& a, Rhs const& b) { a = b * a; }
438{
439 return lhs = rhs * lhs;
440}
441
442[[nodiscard]] constexpr aarectangle fit(aarectangle const& bounds, aarectangle const& rectangle) noexcept
443{
444 auto const resized_rectangle = aarectangle{
445 rectangle.left(),
446 rectangle.bottom(),
447 std::min(rectangle.width(), bounds.width()),
448 std::min(rectangle.height(), bounds.height())};
449
450 auto const translate_from_p0 = max(vector2{}, get<0>(bounds) - get<0>(resized_rectangle));
451 auto const translate_from_p3 = min(vector2{}, get<3>(bounds) - get<3>(resized_rectangle));
452 return translate2{translate_from_p0 + translate_from_p3} * resized_rectangle;
453}
454
463[[nodiscard]] constexpr quad scale_from_center(quad const& lhs, scale2 const& rhs) noexcept
464{
465 auto const top_extra = (lhs.top() * rhs.x() - lhs.top()) * 0.5f;
466 auto const bottom_extra = (lhs.bottom() * rhs.x() - lhs.bottom()) * 0.5f;
467 auto const left_extra = (lhs.left() * rhs.y() - lhs.left()) * 0.5f;
468 auto const right_extra = (lhs.right() * rhs.y() - lhs.right()) * 0.5f;
469
470 return {
471 lhs.p0 - bottom_extra - left_extra,
472 lhs.p1 + bottom_extra - right_extra,
473 lhs.p2 - top_extra + left_extra,
474 lhs.p3 + top_extra + right_extra};
475}
476
477}} // 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.
The HikoGUI namespace.
Definition array_generic.hpp:20
constexpr aarectangle fast_mul(matrix2 const &lhs, aarectangle const &rhs) noexcept
Transform an axis-aligned rectangle without rotation by the matrix.
Definition transform.hpp:373
constexpr rectangle full_mul(matrix2 const &lhs, aarectangle const &rhs) noexcept
Transform an axis-aligned rectangle without rotation by the matrix.
Definition transform.hpp:361
constexpr Lhs & operator*=(Lhs &lhs, Rhs const &rhs) noexcept
Inplace geometric translation.
Definition transform.hpp:436
constexpr matrix2 operator*(matrix2 const &lhs, matrix2 const &rhs) noexcept
Matrix/Matrix multiplication.
Definition transform.hpp:69
constexpr quad scale_from_center(quad const &lhs, scale2 const &rhs) noexcept
scale the quad.
Definition transform.hpp:463
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition simd_intf.hpp:18
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:33
A type defining a 2D circle.
Definition circle.hpp:23
The 4 radii of the corners of a quad or rectangle.
Definition corner_radii.hpp:26
Line segment.
Definition line_segment.hpp:26
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix2.hpp:39
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix3.hpp:36
Perspective transform.
Definition perspective.hpp:21
A rectangle / parallelogram in 3D space.
Definition rectangle.hpp:25
Definition rotate2.hpp:17
Definition rotate3.hpp:17
Definition scale2.hpp:18
Definition scale3.hpp:19
Definition transform.hpp:39
Definition transform.hpp:41
Definition translate2.hpp:18
Definition translate3.hpp:22
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector2.hpp:27
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector3.hpp:26
Definition transform.hpp:61
Definition transform.hpp:63
Definition transform.hpp:65
T copysign(T... args)
T min(T... args)
T transform(T... args)