HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
rectangle.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#pragma once
6
7#include "../rapid/numeric_array.hpp"
8#include "axis_aligned_rectangle.hpp"
9#include "../alignment.hpp"
10#include <array>
11
12namespace hi::inline v1 {
13
20class rectangle {
21public:
22 point3 origin;
23 vector3 right;
24 vector3 up;
25
26 constexpr rectangle() noexcept : origin(), right(), up() {}
27 constexpr rectangle(rectangle const &rhs) noexcept = default;
28 constexpr rectangle &operator=(rectangle const &rhs) noexcept = default;
29 constexpr rectangle(rectangle &&rhs) noexcept = default;
30 constexpr rectangle &operator=(rectangle &&rhs) noexcept = default;
31
38 constexpr rectangle(point3 origin, vector3 right, vector3 up) noexcept : origin(origin), right(right), up(up) {}
39
47 constexpr rectangle(point3 origin, point3 right_bottom, point3 left_top, point3 right_top) noexcept :
48 rectangle(origin, right_bottom - origin, left_top - origin)
49 {
50 }
51
52 constexpr rectangle(aarectangle rhs) noexcept
53 {
54 hilet p0 = get<0>(rhs);
55 hilet p3 = get<3>(rhs);
56 hilet diagonal = static_cast<f32x4>(p3 - p0);
57
58 origin = p0;
59 right = vector3{diagonal.x000()};
60 up = vector3{diagonal._0y00()};
61 }
62
63 constexpr explicit rectangle(extent2 size) noexcept :
64 rectangle(point3{}, vector3{size.width(), 0.0f, 0.0f}, vector3{0.0f, size.height(), 0.0f})
65 {
66 }
67
68 constexpr rectangle &operator=(aarectangle rhs) noexcept
69 {
70 hilet p0 = get<0>(rhs);
71 hilet p3 = get<3>(rhs);
72 hilet diagonal = static_cast<f32x4>(p3 - p0);
73
74 origin = p0;
75 right = vector3{diagonal.x000()};
76 up = vector3{diagonal._0y00()};
77 return *this;
78 }
79
80 constexpr rectangle(point3 origin, extent2 extent) noexcept : rectangle(origin, extent.right(), extent.up()) {}
81
86 [[nodiscard]] constexpr explicit operator bool() const noexcept
87 {
88 // min() is smallest normal float.
89 return area() > std::numeric_limits<float>::min();
90 }
91
96 [[nodiscard]] constexpr bool is_rectangle() const noexcept
97 {
98 hilet dp = dot(right, up);
99 return -std::numeric_limits<float>::min() <= dp and dp <= std::numeric_limits<float>::min();
100 }
101
106 [[nodiscard]] constexpr bool is_axis_aligned() const noexcept
107 {
108 hilet should_be_zeroes = static_cast<f32x4>(right).yz00() | static_cast<f32x4>(up)._00xz();
109 return not should_be_zeroes;
110 }
111
114 [[nodiscard]] constexpr friend aarectangle bounding_rectangle(rectangle const &rhs) noexcept
115 {
116 auto left_bottom = f32x4::broadcast(std::numeric_limits<float>::max());
117 auto right_top = f32x4::broadcast(-std::numeric_limits<float>::max());
118
119 hilet p0 = rhs.origin;
120 left_bottom = min(left_bottom, static_cast<f32x4>(p0));
121 right_top = max(right_top, static_cast<f32x4>(p0));
122
123 hilet p1 = p0 + rhs.right;
124 left_bottom = min(left_bottom, static_cast<f32x4>(p1));
125 right_top = max(right_top, static_cast<f32x4>(p1));
126
127 hilet p2 = p0 + rhs.up;
128 left_bottom = min(left_bottom, static_cast<f32x4>(p2));
129 right_top = max(right_top, static_cast<f32x4>(p2));
130
131 hilet p3 = p2 + rhs.right;
132 left_bottom = min(left_bottom, static_cast<f32x4>(p3));
133 right_top = max(right_top, static_cast<f32x4>(p3));
134
135 return aarectangle{left_bottom.xy00() | right_top._00xy()};
136 }
137
140 [[nodiscard]] constexpr float width() const noexcept
141 {
142 return hypot(right);
143 }
144
147 [[nodiscard]] constexpr float height() const noexcept
148 {
149 return hypot(up);
150 }
151
154 [[nodiscard]] constexpr extent2 size() const noexcept
155 {
156 return {width(), height()};
157 }
158
159 [[nodiscard]] constexpr float area() const noexcept
160 {
161 return hypot(cross(right, up));
162 }
163
164 [[nodiscard]] constexpr point3 operator[](std::size_t i) const noexcept
165 {
166 switch (i) {
167 case 0: return get<0>(*this);
168 case 1: return get<1>(*this);
169 case 2: return get<2>(*this);
170 case 3: return get<3>(*this);
171 default: hi_no_default();
172 }
173 }
174
175 template<std::size_t I>
176 [[nodiscard]] friend constexpr point3 get(rectangle const &rhs) noexcept
177 {
178 static_assert(I < 4);
179 if constexpr (I == 0) {
180 return rhs.origin;
181 } else if constexpr (I == 1) {
182 return rhs.origin + rhs.right;
183 } else if constexpr (I == 2) {
184 return rhs.origin + rhs.up;
185 } else {
186 return rhs.origin + rhs.right + rhs.up;
187 }
188 }
189
203 [[nodiscard]] friend constexpr rectangle operator+(rectangle const &lhs, extent2 rhs) noexcept
204 {
205 hilet extra_right = normalize(lhs.right) * rhs.width();
206 hilet extra_up = normalize(lhs.up) * rhs.height();
207 hilet extra_diagonal = extra_right + extra_up;
208
209 return rectangle{lhs.origin - extra_diagonal, lhs.right + 2.0f * extra_right, lhs.up + 2.0f * extra_up};
210 }
211
225 [[nodiscard]] friend constexpr rectangle operator-(rectangle const &lhs, extent2 rhs) noexcept
226 {
227 hilet extra_right = normalize(lhs.right) * rhs.width();
228 hilet extra_up = normalize(lhs.up) * rhs.height();
229 hilet extra_diagonal = extra_right + extra_up;
230
231 return rectangle{lhs.origin + extra_diagonal, lhs.right - 2.0f * extra_right, lhs.up - 2.0f * extra_up};
232 }
233
247 [[nodiscard]] friend constexpr rectangle operator+(rectangle const &lhs, float rhs) noexcept
248 {
249 return lhs + extent2{rhs, rhs};
250 };
251
265 [[nodiscard]] friend constexpr rectangle operator-(rectangle const &lhs, float rhs) noexcept
266 {
267 return lhs - extent2{rhs, rhs};
268 }
269};
270
271} // namespace hi::inline v1
#define hi_no_default()
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:145
#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:15
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:20
A rectangle / parallelogram in 3D space.
Definition rectangle.hpp:20
constexpr bool is_axis_aligned() const noexcept
Check if this is an axis aligned rectangle.
Definition rectangle.hpp:106
friend constexpr rectangle operator-(rectangle const &lhs, float rhs) noexcept
Shrink the rectangle by subtracting an absolute distance from each side.
Definition rectangle.hpp:265
friend constexpr rectangle operator-(rectangle const &lhs, extent2 rhs) noexcept
Shrink the rectangle by subtracting an absolute distance from each side.
Definition rectangle.hpp:225
friend constexpr rectangle operator+(rectangle const &lhs, extent2 rhs) noexcept
Expand the rectangle by adding an absolute distance on each side.
Definition rectangle.hpp:203
constexpr friend aarectangle bounding_rectangle(rectangle const &rhs) noexcept
The axis-aligned bounding box around the rectangle.
Definition rectangle.hpp:114
friend constexpr rectangle operator+(rectangle const &lhs, float rhs) noexcept
Expand the rectangle by adding an absolute distance on each side.
Definition rectangle.hpp:247
constexpr rectangle(point3 origin, point3 right_bottom, point3 left_top, point3 right_top) noexcept
Create a rectangle from 4 corner points.
Definition rectangle.hpp:47
constexpr rectangle(point3 origin, vector3 right, vector3 up) noexcept
Create a rectangle from a corner point and two vectors.
Definition rectangle.hpp:38
constexpr extent2 size() const noexcept
The size, or length of the right and up vectors.
Definition rectangle.hpp:154
constexpr float height() const noexcept
The height, or length of the up vector.
Definition rectangle.hpp:147
constexpr bool is_rectangle() const noexcept
Check if this is a rectangle.
Definition rectangle.hpp:96
constexpr float width() const noexcept
The width, or length of the right vector.
Definition rectangle.hpp:140
T right(T... args)
T min(T... args)