HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
extent.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 "vector.hpp"
8#include "numeric_array.hpp"
9
10namespace tt {
11namespace geo {
12
19template<int D>
20class extent {
21public:
22 static_assert(D == 2 || D == 3, "Only 2D or 3D extents are supported");
23
24 constexpr extent(extent const &) noexcept = default;
25 constexpr extent(extent &&) noexcept = default;
26 constexpr extent &operator=(extent const &) noexcept = default;
27 constexpr extent &operator=(extent &&) noexcept = default;
28
31 template<int E>
32 requires(E < D) [[nodiscard]] constexpr extent(extent<E> const &other) noexcept : _v(static_cast<f32x4>(other))
33 {
34 tt_axiom(is_valid());
35 }
36
39 [[nodiscard]] constexpr explicit operator f32x4() const noexcept
40 {
41 return _v;
42 }
43
46 [[nodiscard]] constexpr explicit extent(f32x4 const &other) noexcept : _v(other)
47 {
48 tt_axiom(is_valid());
49 }
50
51 template<int E>
52 [[nodiscard]] constexpr explicit operator vector<E>() const noexcept requires(E >= D)
53 {
54 tt_axiom(is_valid());
55 return vector<E>{static_cast<f32x4>(*this)};
56 }
57
60 [[nodiscard]] constexpr extent() noexcept : _v(0.0f, 0.0f, 0.0f, 0.0f)
61 {
62 tt_axiom(is_valid());
63 }
64
69 [[nodiscard]] constexpr extent(float width, float height) noexcept requires(D == 2) : _v(width, height, 0.0f, 0.0f)
70 {
71 tt_axiom(is_valid());
72 }
73
79 [[nodiscard]] constexpr extent(float width, float height, float depth = 0.0f) noexcept requires(D == 3) :
80 _v(width, height, depth, 0.0f)
81 {
82 tt_axiom(is_valid());
83 }
84
91 [[nodiscard]] constexpr float &width() noexcept
92 {
93 return _v.x();
94 }
95
102 [[nodiscard]] constexpr float &height() noexcept
103 {
104 return _v.y();
105 }
106
113 [[nodiscard]] constexpr float &depth() noexcept requires(D == 3)
114 {
115 return _v.z();
116 }
117
124 [[nodiscard]] constexpr float const &width() const noexcept
125 {
126 return _v.x();
127 }
128
135 [[nodiscard]] constexpr float const &height() const noexcept
136 {
137 return _v.y();
138 }
139
146 [[nodiscard]] constexpr float const &depth() const noexcept requires(D == 3)
147 {
148 return _v.z();
149 }
150
151 [[nodiscard]] constexpr vector<D> right() const noexcept
152 {
153 return vector<D>{_v.x000()};
154 }
155
156 [[nodiscard]] constexpr vector<D> up() const noexcept
157 {
158 return vector<D>{_v._0y00()};
159 }
160
166 [[nodiscard]] constexpr friend extent operator+(extent const &lhs, extent const &rhs) noexcept
167 {
168 tt_axiom(lhs.is_valid() && rhs.is_valid());
169 return extent{lhs._v + rhs._v};
170 }
171
177 [[nodiscard]] constexpr friend extent operator-(extent const &lhs, extent const &rhs) noexcept
178 {
179 tt_axiom(lhs.is_valid() && rhs.is_valid());
180 return extent{lhs._v - rhs._v};
181 }
182
188 [[nodiscard]] constexpr friend extent operator*(extent const &lhs, float const &rhs) noexcept
189 {
190 tt_axiom(lhs.is_valid());
191 return extent{lhs._v * rhs};
192 }
193
194 template<int E>
195 [[nodiscard]] constexpr friend auto operator+(extent const &lhs, vector<E> const &rhs) noexcept
196 {
197 tt_axiom(lhs.is_valid());
198 tt_axiom(rhs.is_valid());
199
200 return extent<std::max(D, E)>{static_cast<f32x4>(lhs) + static_cast<f32x4>(rhs)};
201 }
202
203 template<int E>
204 [[nodiscard]] constexpr friend auto operator+(vector<E> const &lhs, extent const &rhs) noexcept
205 {
206 tt_axiom(lhs.is_valid());
207 tt_axiom(rhs.is_valid());
208
209 return vector<std::max(D, E)>{static_cast<f32x4>(lhs) + static_cast<f32x4>(rhs)};
210 }
211
217 [[nodiscard]] constexpr friend extent operator+(extent const &lhs, float const &rhs) noexcept
218 {
219 tt_axiom(lhs.is_valid());
220
221 auto r = extent{};
222 for (size_t i = 0; i != D; ++i) {
223 r._v[i] = lhs._v[i] + rhs;
224 }
225
226 return r;
227 }
228
234 [[nodiscard]] constexpr friend extent operator*(float const &lhs, extent const &rhs) noexcept
235 {
236 tt_axiom(rhs.is_valid());
237 return extent{lhs * rhs._v};
238 }
239
245 [[nodiscard]] constexpr friend bool operator==(extent const &lhs, extent const &rhs) noexcept
246 {
247 tt_axiom(lhs.is_valid() && rhs.is_valid());
248 return lhs._v == rhs._v;
249 }
250
253 [[nodiscard]] constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept requires (D == 2)
254 {
255 return lhs.width() < rhs.width() && lhs.height() < rhs.height();
256 }
257
260 [[nodiscard]] constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
261 {
262 return lhs.width() < rhs.width() && lhs.height() < rhs.height() && lhs.depth() < rhs.depth();
263 }
264
267 [[nodiscard]] constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept requires(D == 2)
268 {
269 return lhs.width() <= rhs.width() && lhs.height() <= rhs.height();
270 }
271
274 [[nodiscard]] constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
275 {
276 return lhs.width() <= rhs.width() && lhs.height() <= rhs.height() && lhs.depth() <= rhs.depth();
277 }
278
281 [[nodiscard]] constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept requires(D == 2)
282 {
283 return lhs.width() > rhs.width() && lhs.height() > rhs.height();
284 }
285
288 [[nodiscard]] constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
289 {
290 return lhs.width() > rhs.width() && lhs.height() > rhs.height() && lhs.depth() > rhs.depth();
291 }
292
295 [[nodiscard]] constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept requires(D == 2)
296 {
297 return lhs.width() >= rhs.width() && lhs.height() >= rhs.height();
298 }
299
302 [[nodiscard]] constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
303 {
304 return lhs.width() >= rhs.width() && lhs.height() >= rhs.height() && lhs.depth() >= rhs.depth();
305 }
306
311 [[nodiscard]] constexpr friend float squared_hypot(extent const &rhs) noexcept
312 {
313 tt_axiom(rhs.is_valid());
314 return squared_hypot<element_mask>(rhs._v);
315 }
316
321 [[nodiscard]] constexpr friend float hypot(extent const &rhs) noexcept
322 {
323 tt_axiom(rhs.is_valid());
324 return hypot<element_mask>(rhs._v);
325 }
326
331 [[nodiscard]] constexpr friend float rcp_hypot(extent const &rhs) noexcept
332 {
333 tt_axiom(rhs.is_valid());
334 return rcp_hypot<element_mask>(rhs._v);
335 }
336
341 [[nodiscard]] constexpr friend extent normalize(extent const &rhs) noexcept
342 {
343 tt_axiom(rhs.is_valid());
344 return extent{normalize<element_mask>(rhs._v)};
345 }
346
347 [[nodiscard]] constexpr friend extent ceil(extent const &rhs) noexcept
348 {
349 tt_axiom(rhs.is_valid());
350 return extent{ceil(static_cast<f32x4>(rhs))};
351 }
352
353 [[nodiscard]] constexpr friend extent floor(extent const &rhs) noexcept
354 {
355 tt_axiom(rhs.is_valid());
356 return extent{floor(static_cast<f32x4>(rhs))};
357 }
358
363 [[nodiscard]] constexpr bool is_valid() const noexcept
364 {
365 return _v.x() >= 0.0f && _v.y() >= 0.0f && _v.z() >= 0.0f && _v.w() == 0.0f && (D == 3 || _v.z() == 0.0f);
366 }
367
368 [[nodiscard]] friend std::string to_string(extent const &rhs) noexcept
369 {
370 if constexpr (D == 2) {
371 return fmt::format("[{}, {}]", rhs._v.x(), rhs._v.y());
372 } else if constexpr (D == 3) {
373 return fmt::format("[{}, {}, {}]", rhs._v.x(), rhs._v.y(), rhs._v.z());
374 } else {
375 tt_static_no_default();
376 }
377 }
378
379 friend std::ostream &operator<<(std::ostream &lhs, extent const &rhs) noexcept
380 {
381 return lhs << to_string(rhs);
382 }
383
384private:
385 f32x4 _v;
386
387 static constexpr size_t element_mask = (1_uz << D) - 1;
388};
389
390}
391
392using extent2 = geo::extent<2>;
393using extent3 = geo::extent<3>;
394
395} // namespace tt
A high-level geometric extent.
Definition extent.hpp:20
constexpr float const & height() const noexcept
Access the y-as-height element from the extent.
Definition extent.hpp:135
constexpr float const & width() const noexcept
Access the x-as-width element from the extent.
Definition extent.hpp:124
constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:281
constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:253
constexpr float & width() noexcept
Access the x-as-width element from the extent.
Definition extent.hpp:91
constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:260
constexpr friend extent operator*(float const &lhs, extent const &rhs) noexcept
Scale the extent by a scaler.
Definition extent.hpp:234
constexpr bool is_valid() const noexcept
Check if the extent is valid.
Definition extent.hpp:363
constexpr friend float squared_hypot(extent const &rhs) noexcept
Get the squared length of the extent.
Definition extent.hpp:311
constexpr friend extent operator-(extent const &lhs, extent const &rhs) noexcept
Subtract two extents from each other.
Definition extent.hpp:177
constexpr friend extent operator*(extent const &lhs, float const &rhs) noexcept
Scale the extent by a scaler.
Definition extent.hpp:188
constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:267
constexpr friend float rcp_hypot(extent const &rhs) noexcept
Get the length of the extent.
Definition extent.hpp:331
constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:274
constexpr friend extent normalize(extent const &rhs) noexcept
Normalize a extent to a unit extent.
Definition extent.hpp:341
constexpr extent(float width, float height, float depth=0.0f) noexcept
Construct a 3D extent from x, y and z elements.
Definition extent.hpp:79
constexpr extent(extent< E > const &other) noexcept
Construct a extent from a lower dimension extent.
Definition extent.hpp:32
constexpr extent(float width, float height) noexcept
Construct a 2D extent from x and y elements.
Definition extent.hpp:69
constexpr float & depth() noexcept
Access the z-as-depth element from the extent.
Definition extent.hpp:113
constexpr friend float hypot(extent const &rhs) noexcept
Get the length of the extent.
Definition extent.hpp:321
constexpr friend extent operator+(extent const &lhs, float const &rhs) noexcept
Add a scaler to the extent.
Definition extent.hpp:217
constexpr float const & depth() const noexcept
Access the z-as-depth element from the extent.
Definition extent.hpp:146
constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:288
constexpr float & height() noexcept
Access the y-as-height element from the extent.
Definition extent.hpp:102
constexpr extent(f32x4 const &other) noexcept
Construct a extent from a f32x4-numeric_array.
Definition extent.hpp:46
constexpr friend bool operator==(extent const &lhs, extent const &rhs) noexcept
Compare if two extents are equal.
Definition extent.hpp:245
constexpr extent() noexcept
Construct a empty extent / zero length.
Definition extent.hpp:60
constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:295
constexpr friend extent operator+(extent const &lhs, extent const &rhs) noexcept
Add two extents from each other.
Definition extent.hpp:166
constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:302
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:20
T max(T... args)