HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
quad.hpp
1// Copyright Take Vos 2021-2022.
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
6#pragma once
7
8#include "vector.hpp"
9#include "point.hpp"
10#include "extent.hpp"
11#include "axis_aligned_rectangle.hpp"
12#include "rectangle.hpp"
13#include <tuple>
14
15namespace hi::inline v1 {
16
17class quad {
18public:
23
24 constexpr quad() noexcept : p0(), p1(), p2(), p3() {}
25
26 constexpr quad(point3 p0, point3 p1, point3 p2, point3 p3) noexcept : p0(p0), p1(p1), p2(p2), p3(p3) {}
27
28 constexpr quad(quad const &) noexcept = default;
29 constexpr quad(quad &&) noexcept = default;
30 constexpr quad &operator=(quad const &) noexcept = default;
31 constexpr quad &operator=(quad &&) noexcept = default;
32
33 constexpr quad(aarectangle const &rhs) noexcept
34 {
35 hilet tmp = f32x4{rhs};
36 p0 = point3{tmp.xy01()};
37 p1 = point3{tmp.zy01()};
38 p2 = point3{tmp.xw01()};
39 p3 = point3{tmp.zw01()};
40 }
41
42 constexpr quad(rectangle const &rhs) noexcept : p0(get<0>(rhs)), p1(get<1>(rhs)), p2(get<2>(rhs)), p3(get<3>(rhs)) {}
43
46 [[nodiscard]] constexpr vector3 bottom() const noexcept
47 {
48 return p1 - p0;
49 }
50
53 [[nodiscard]] constexpr vector3 top() const noexcept
54 {
55 return p3 - p2;
56 }
57
60 [[nodiscard]] constexpr vector3 left() const noexcept
61 {
62 return p2 - p0;
63 }
64
67 [[nodiscard]] constexpr vector3 right() const noexcept
68 {
69 return p3 - p1;
70 }
71
76 [[nodiscard]] constexpr f32x4 edge_hypots() const noexcept
77 {
78 hilet[x, y, z, zeros] = transpose(f32x4{bottom()}, f32x4{left()}, f32x4{top()}, f32x4{right()});
79 return sqrt(x * x + y * y + z * z);
80 }
81
82 [[nodiscard]] constexpr point3 &operator[](std::size_t index) noexcept
83 {
84 switch (index) {
85 case 0: return p0;
86 case 1: return p1;
87 case 2: return p2;
88 case 3: return p3;
89 default: hi_no_default();
90 }
91 }
92
93 [[nodiscard]] constexpr point3 const &operator[](std::size_t index) const noexcept
94 {
95 switch (index) {
96 case 0: return p0;
97 case 1: return p1;
98 case 2: return p2;
99 case 3: return p3;
100 default: hi_no_default();
101 }
102 }
103
104 template<std::size_t I>
105 [[nodiscard]] constexpr friend point3 const &get(quad const &rhs) noexcept
106 {
107 static_assert(I < 4, "Index out of range.");
108
109 if constexpr (I == 0) {
110 return rhs.p0;
111 } else if constexpr (I == 1) {
112 return rhs.p1;
113 } else if constexpr (I == 2) {
114 return rhs.p2;
115 } else {
116 return rhs.p3;
117 }
118 }
119
120 template<std::size_t I>
121 [[nodiscard]] constexpr friend point3 &get(quad &rhs) noexcept
122 {
123 static_assert(I < 4, "Index out of range.");
124
125 if constexpr (I == 0) {
126 return rhs.p0;
127 } else if constexpr (I == 1) {
128 return rhs.p1;
129 } else if constexpr (I == 2) {
130 return rhs.p2;
131 } else {
132 return rhs.p3;
133 }
134 }
135
144 [[nodiscard]] friend constexpr std::pair<quad, f32x4> expand_and_edge_hypots(quad const &lhs, f32x4 const &rhs) noexcept
145 {
146 hilet t = f32x4{lhs.top()};
147 hilet l = f32x4{lhs.left()};
148 hilet b = f32x4{lhs.bottom()};
149 hilet r = f32x4{lhs.right()};
150
151 hilet[x, y, z, ones] = transpose(t, l, b, r);
152 hilet square_lengths = x * x + y * y + z * z;
153 hilet inv_lengths = rcp_sqrt(square_lengths);
154 hilet norm_t = t * inv_lengths.xxxx();
155 hilet norm_l = l * inv_lengths.yyyy();
156 hilet norm_b = b * inv_lengths.zzzz();
157 hilet norm_r = r * inv_lengths.wwww();
158
159 hilet width = rhs.xxxx();
160 hilet height = rhs.yyyy();
161
162 hilet top_extra = vector3{norm_t * width};
163 hilet left_extra = vector3{norm_l * height};
164 hilet bottom_extra = vector3{norm_b * width};
165 hilet right_extra = vector3{norm_r * height};
166
167 hilet lengths = rcp(inv_lengths);
168
169 hilet rhs_times_2 = rhs + rhs;
170
171 return {
172 quad{
173 lhs.p0 - bottom_extra - left_extra,
174 lhs.p1 + bottom_extra - right_extra,
175 lhs.p2 - top_extra + left_extra,
176 lhs.p3 + top_extra + right_extra},
177 lengths + rhs_times_2.xyxy()};
178 }
179
188 [[nodiscard]] friend constexpr std::pair<quad, f32x4> expand_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
189 {
190 return expand_and_edge_hypots(lhs, f32x4{rhs});
191 }
192
201 [[nodiscard]] friend constexpr std::pair<quad, f32x4> shrink_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
202 {
203 return expand_and_edge_hypots(lhs, -f32x4{rhs});
204 }
205
214 [[nodiscard]] friend constexpr quad operator+(quad const &lhs, extent2 const &rhs) noexcept
215 {
216 hilet[expanded_quad, new_lengths] = expand_and_edge_hypots(lhs, rhs);
217 return expanded_quad;
218 }
219
220 [[nodiscard]] friend constexpr quad operator+(quad const &lhs, float rhs) noexcept
221 {
222 return lhs + extent2{rhs, rhs};
223 }
224
233 [[nodiscard]] friend constexpr quad operator-(quad const &lhs, extent2 const &rhs) noexcept
234 {
235 hilet[expanded_quad, new_lengths] = shrink_and_edge_hypots(lhs, rhs);
236 return expanded_quad;
237 }
238
239 [[nodiscard]] friend constexpr quad operator-(quad const &lhs, float rhs) noexcept
240 {
241 return lhs - extent2{rhs, rhs};
242 }
243
244 [[nodiscard]] friend constexpr aarectangle bounding_rectangle(quad const &rhs) noexcept
245 {
246 auto min_p = rhs.p0;
247 auto max_p = rhs.p0;
248
249 min_p = min(min_p, rhs.p1);
250 max_p = max(max_p, rhs.p1);
251 min_p = min(min_p, rhs.p2);
252 max_p = max(max_p, rhs.p2);
253 min_p = min(min_p, rhs.p3);
254 max_p = max(max_p, rhs.p3);
255 return aarectangle{point2{min_p}, point2{max_p}};
256 }
257
258 constexpr quad &operator+=(extent2 const &rhs) noexcept
259 {
260 return *this = *this + rhs;
261 }
262
263 [[nodiscard]] friend constexpr bool operator==(quad const &lhs, quad const &rhs) noexcept = default;
264};
265
266} // namespace hi::inline v1
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
@ bottom
Align to the bottom.
@ top
Align to the top.
Definition quad.hpp:17
friend constexpr std::pair< quad, f32x4 > expand_and_edge_hypots(quad const &lhs, f32x4 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:144
point3 p3
Right-top.
Definition quad.hpp:22
constexpr vector3 right() const noexcept
The vector from right-bottom to right-top.
Definition quad.hpp:67
friend constexpr std::pair< quad, f32x4 > shrink_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
Subtract a border from the quad.
Definition quad.hpp:201
point3 p1
Right-bottom.
Definition quad.hpp:20
friend constexpr quad operator+(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:214
constexpr vector3 left() const noexcept
The vector from left-bottom to left-top.
Definition quad.hpp:60
friend constexpr quad operator-(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:233
point3 p0
Left-bottom.
Definition quad.hpp:19
constexpr vector3 bottom() const noexcept
The vector from left-bottom to right-bottom.
Definition quad.hpp:46
constexpr vector3 top() const noexcept
The vector from left-top to right-top.
Definition quad.hpp:53
point3 p2
Left-top.
Definition quad.hpp:21
constexpr f32x4 edge_hypots() const noexcept
Return the length of each edge.
Definition quad.hpp:76
friend constexpr std::pair< quad, f32x4 > expand_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:188
T max(T... args)
T min(T... args)