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 "vector3.hpp"
9#include "point3.hpp"
10#include "extent3.hpp"
11#include "aarectangle.hpp"
12#include "rectangle.hpp"
13#include "../macros.hpp"
14#include <tuple>
15#include <exception>
16#include <compare>
17
18hi_export_module(hikogui.geometry : quad);
19
20hi_export namespace hi::inline v1 {
21
22class quad {
23public:
28
29 constexpr quad() noexcept : p0(), p1(), p2(), p3() {}
30
31 constexpr quad(point3 p0, point3 p1, point3 p2, point3 p3) noexcept : p0(p0), p1(p1), p2(p2), p3(p3) {}
32
33 constexpr quad(quad const &) noexcept = default;
34 constexpr quad(quad &&) noexcept = default;
35 constexpr quad &operator=(quad const &) noexcept = default;
36 constexpr quad &operator=(quad &&) noexcept = default;
37
38 constexpr quad(aarectangle const &rhs) noexcept
39 {
40 auto const tmp = f32x4{rhs};
41 p0 = point3{tmp.xy01()};
42 p1 = point3{tmp.zy01()};
43 p2 = point3{tmp.xw01()};
44 p3 = point3{tmp.zw01()};
45 }
46
47 constexpr quad(rectangle const &rhs) noexcept : p0(get<0>(rhs)), p1(get<1>(rhs)), p2(get<2>(rhs)), p3(get<3>(rhs)) {}
48
51 [[nodiscard]] constexpr vector3 bottom() const noexcept
52 {
53 return p1 - p0;
54 }
55
58 [[nodiscard]] constexpr vector3 top() const noexcept
59 {
60 return p3 - p2;
61 }
62
65 [[nodiscard]] constexpr vector3 left() const noexcept
66 {
67 return p2 - p0;
68 }
69
72 [[nodiscard]] constexpr vector3 right() const noexcept
73 {
74 return p3 - p1;
75 }
76
81 [[nodiscard]] constexpr f32x4 edge_hypots() const noexcept
82 {
83 auto const[x, y, z, zeros] = transpose(f32x4{bottom()}, f32x4{left()}, f32x4{top()}, f32x4{right()});
84 return sqrt(x * x + y * y + z * z);
85 }
86
87 [[nodiscard]] constexpr point3 &operator[](std::size_t index) noexcept
88 {
89 switch (index) {
90 case 0: return p0;
91 case 1: return p1;
92 case 2: return p2;
93 case 3: return p3;
94 default: hi_no_default();
95 }
96 }
97
98 [[nodiscard]] constexpr point3 const &operator[](std::size_t index) const noexcept
99 {
100 switch (index) {
101 case 0: return p0;
102 case 1: return p1;
103 case 2: return p2;
104 case 3: return p3;
105 default: hi_no_default();
106 }
107 }
108
109 template<std::size_t I>
110 [[nodiscard]] constexpr friend point3 const &get(quad const &rhs) noexcept
111 {
112 static_assert(I < 4, "Index out of range.");
113
114 if constexpr (I == 0) {
115 return rhs.p0;
116 } else if constexpr (I == 1) {
117 return rhs.p1;
118 } else if constexpr (I == 2) {
119 return rhs.p2;
120 } else {
121 return rhs.p3;
122 }
123 }
124
125 template<std::size_t I>
126 [[nodiscard]] constexpr friend point3 &get(quad &rhs) noexcept
127 {
128 static_assert(I < 4, "Index out of range.");
129
130 if constexpr (I == 0) {
131 return rhs.p0;
132 } else if constexpr (I == 1) {
133 return rhs.p1;
134 } else if constexpr (I == 2) {
135 return rhs.p2;
136 } else {
137 return rhs.p3;
138 }
139 }
140
149 [[nodiscard]] friend constexpr std::pair<quad, f32x4> expand_and_edge_hypots(quad const &lhs, f32x4 const &rhs) noexcept
150 {
151 auto const t = f32x4{lhs.top()};
152 auto const l = f32x4{lhs.left()};
153 auto const b = f32x4{lhs.bottom()};
154 auto const r = f32x4{lhs.right()};
155
156 auto const[x, y, z, ones] = transpose(t, l, b, r);
157 auto const square_lengths = x * x + y * y + z * z;
158 auto const inv_lengths = rsqrt(square_lengths);
159 auto const norm_t = t * inv_lengths.xxxx();
160 auto const norm_l = l * inv_lengths.yyyy();
161 auto const norm_b = b * inv_lengths.zzzz();
162 auto const norm_r = r * inv_lengths.wwww();
163
164 auto const extra_width = rhs.xxxx();
165 auto const extra_height = rhs.yyyy();
166
167 auto const top_extra = vector3{norm_t * extra_width};
168 auto const left_extra = vector3{norm_l * extra_height};
169 auto const bottom_extra = vector3{norm_b * extra_width};
170 auto const right_extra = vector3{norm_r * extra_height};
171
172 auto const lengths = rcp(inv_lengths);
173
174 auto const rhs_times_2 = rhs + rhs;
175
176 return {
177 quad{
178 lhs.p0 - bottom_extra - left_extra,
179 lhs.p1 + bottom_extra - right_extra,
180 lhs.p2 - top_extra + left_extra,
181 lhs.p3 + top_extra + right_extra},
182 lengths + rhs_times_2.xyxy()};
183 }
184
193 [[nodiscard]] friend constexpr std::pair<quad, f32x4> expand_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
194 {
195 return expand_and_edge_hypots(lhs, f32x4{rhs});
196 }
197
206 [[nodiscard]] friend constexpr std::pair<quad, f32x4> shrink_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
207 {
208 return expand_and_edge_hypots(lhs, -f32x4{rhs});
209 }
210
219 [[nodiscard]] friend constexpr quad operator+(quad const &lhs, extent2 const &rhs) noexcept
220 {
221 auto const[expanded_quad, new_lengths] = expand_and_edge_hypots(lhs, rhs);
222 return expanded_quad;
223 }
224
225 [[nodiscard]] friend constexpr quad operator+(quad const &lhs, float rhs) noexcept
226 {
227 return lhs + extent2{rhs, rhs};
228 }
229
238 [[nodiscard]] friend constexpr quad operator-(quad const &lhs, extent2 const &rhs) noexcept
239 {
240 auto const[expanded_quad, new_lengths] = shrink_and_edge_hypots(lhs, rhs);
241 return expanded_quad;
242 }
243
244 [[nodiscard]] friend constexpr quad operator-(quad const &lhs, float rhs) noexcept
245 {
246 return lhs - extent2{rhs, rhs};
247 }
248
249 [[nodiscard]] friend constexpr aarectangle bounding_rectangle(quad const &rhs) noexcept
250 {
251 auto min_p = rhs.p0;
252 auto max_p = rhs.p0;
253
254 min_p = min(min_p, rhs.p1);
255 max_p = max(max_p, rhs.p1);
256 min_p = min(min_p, rhs.p2);
257 max_p = max(max_p, rhs.p2);
258 min_p = min(min_p, rhs.p3);
259 max_p = max(max_p, rhs.p3);
260 return aarectangle{point2{min_p}, point2{max_p}};
261 }
262
263 constexpr quad &operator+=(extent2 const &rhs) noexcept
264 {
265 return *this = *this + rhs;
266 }
267
268 [[nodiscard]] friend constexpr bool operator==(quad const &lhs, quad const &rhs) noexcept = default;
269};
270
271} // namespace hi::inline v1
Defined the geo::extent, extent2 and extent3 types.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
A high-level geometric point Part of the high-level vec, point, mat and color types.
Definition point3.hpp:29
Definition quad.hpp:22
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:149
point3 p3
Right-top.
Definition quad.hpp:27
constexpr vector3 right() const noexcept
The vector from right-bottom to right-top.
Definition quad.hpp:72
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:206
point3 p1
Right-bottom.
Definition quad.hpp:25
friend constexpr quad operator+(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:219
constexpr vector3 left() const noexcept
The vector from left-bottom to left-top.
Definition quad.hpp:65
friend constexpr quad operator-(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:238
point3 p0
Left-bottom.
Definition quad.hpp:24
constexpr vector3 bottom() const noexcept
The vector from left-bottom to right-bottom.
Definition quad.hpp:51
constexpr vector3 top() const noexcept
The vector from left-top to right-top.
Definition quad.hpp:58
point3 p2
Left-top.
Definition quad.hpp:26
constexpr f32x4 edge_hypots() const noexcept
Return the length of each edge.
Definition quad.hpp:81
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:193