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 "../rapid/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 [[nodiscard]] constexpr explicit operator bool () const noexcept
52 {
53 if constexpr (D == 2) {
54 return _v.x() != 0.0f or _v.y() != 0.0f;
55 } else if constexpr (D == 3) {
56 return _v.x() != 0.0f or _v.y() != 0.0f or _v.z() != 0.0f;
57 } else {
58 tt_no_default();
59 }
60 }
61
62 template<int E>
63 [[nodiscard]] constexpr explicit operator vector<E>() const noexcept requires(E >= D)
64 {
65 tt_axiom(is_valid());
66 return vector<E>{static_cast<f32x4>(*this)};
67 }
68
71 [[nodiscard]] constexpr extent() noexcept : _v(0.0f, 0.0f, 0.0f, 0.0f)
72 {
73 tt_axiom(is_valid());
74 }
75
80 [[nodiscard]] constexpr extent(float width, float height) noexcept requires(D == 2) : _v(width, height, 0.0f, 0.0f)
81 {
82 tt_axiom(is_valid());
83 }
84
90 [[nodiscard]] constexpr extent(float width, float height, float depth = 0.0f) noexcept requires(D == 3) :
91 _v(width, height, depth, 0.0f)
92 {
93 tt_axiom(is_valid());
94 }
95
96 [[nodiscard]] static constexpr extent infinity() noexcept requires(D == 2)
97 {
99 }
100
101 [[nodiscard]] static constexpr extent infinity() noexcept requires(D == 3)
102 {
103 return extent{
107 }
108
109 [[nodiscard]] static constexpr extent large() noexcept requires(D == 2)
110 {
111 return extent{32767.0f, 32767.0f};
112 }
113
114 [[nodiscard]] static constexpr extent large() noexcept requires(D == 3)
115 {
116 return extent{32767.0f, 32767.0f, 32767.0f};
117 }
118
119 [[nodiscard]] static constexpr extent nan() noexcept requires(D == 2)
120 {
121 auto r = extent{};
124 return r;
125 }
126
127 [[nodiscard]] static constexpr extent nan() noexcept requires(D == 3)
128 {
129 auto r = extent{};
133 return r;
134 }
135
142 [[nodiscard]] constexpr float &width() noexcept
143 {
144 return _v.x();
145 }
146
153 [[nodiscard]] constexpr float &height() noexcept
154 {
155 return _v.y();
156 }
157
164 [[nodiscard]] constexpr float &depth() noexcept requires(D == 3)
165 {
166 return _v.z();
167 }
168
175 [[nodiscard]] constexpr float const &width() const noexcept
176 {
177 return _v.x();
178 }
179
186 [[nodiscard]] constexpr float const &height() const noexcept
187 {
188 return _v.y();
189 }
190
197 [[nodiscard]] constexpr float const &depth() const noexcept requires(D == 3)
198 {
199 return _v.z();
200 }
201
202 [[nodiscard]] constexpr vector<D> right() const noexcept
203 {
204 return vector<D>{_v.x000()};
205 }
206
207 [[nodiscard]] constexpr vector<D> up() const noexcept
208 {
209 return vector<D>{_v._0y00()};
210 }
211
212 constexpr extent &operator+=(extent const &rhs) noexcept
213 {
214 return *this = *this + rhs;
215 }
216
222 [[nodiscard]] constexpr friend extent operator+(extent const &lhs, extent const &rhs) noexcept
223 {
224 tt_axiom(lhs.is_valid() && rhs.is_valid());
225 return extent{lhs._v + rhs._v};
226 }
227
233 [[nodiscard]] constexpr friend extent operator-(extent const &lhs, extent const &rhs) noexcept
234 {
235 tt_axiom(lhs.is_valid() && rhs.is_valid());
236 return extent{lhs._v - rhs._v};
237 }
238
244 [[nodiscard]] constexpr friend extent operator*(extent const &lhs, float const &rhs) noexcept
245 {
246 tt_axiom(lhs.is_valid());
247 return extent{lhs._v * rhs};
248 }
249
250 template<int E>
251 [[nodiscard]] constexpr friend auto operator+(extent const &lhs, vector<E> const &rhs) noexcept
252 {
253 tt_axiom(lhs.is_valid());
254 tt_axiom(rhs.is_valid());
255
256 return extent<std::max(D, E)>{static_cast<f32x4>(lhs) + static_cast<f32x4>(rhs)};
257 }
258
259 template<int E>
260 [[nodiscard]] constexpr friend auto operator+(vector<E> const &lhs, extent const &rhs) noexcept
261 {
262 tt_axiom(lhs.is_valid());
263 tt_axiom(rhs.is_valid());
264
265 return vector<std::max(D, E)>{static_cast<f32x4>(lhs) + static_cast<f32x4>(rhs)};
266 }
267
273 [[nodiscard]] constexpr friend extent operator+(extent const &lhs, float const &rhs) noexcept
274 {
275 tt_axiom(lhs.is_valid());
276
277 auto r = extent{};
278 for (size_t i = 0; i != D; ++i) {
279 r._v[i] = lhs._v[i] + rhs;
280 }
281
282 return r;
283 }
284
290 [[nodiscard]] constexpr friend extent operator*(float const &lhs, extent const &rhs) noexcept
291 {
292 tt_axiom(rhs.is_valid());
293 return extent{lhs * rhs._v};
294 }
295
301 [[nodiscard]] constexpr friend bool operator==(extent const &lhs, extent const &rhs) noexcept
302 {
303 tt_axiom(lhs.is_valid() && rhs.is_valid());
304 return lhs._v == rhs._v;
305 }
306
309 [[nodiscard]] constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept requires(D == 2)
310 {
311 return lhs.width() < rhs.width() && lhs.height() < rhs.height();
312 }
313
316 [[nodiscard]] constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
317 {
318 return lhs.width() < rhs.width() && lhs.height() < rhs.height() && lhs.depth() < rhs.depth();
319 }
320
323 [[nodiscard]] constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept requires(D == 2)
324 {
325 return lhs.width() <= rhs.width() && lhs.height() <= rhs.height();
326 }
327
330 [[nodiscard]] constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
331 {
332 return lhs.width() <= rhs.width() && lhs.height() <= rhs.height() && lhs.depth() <= rhs.depth();
333 }
334
337 [[nodiscard]] constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept requires(D == 2)
338 {
339 return lhs.width() > rhs.width() && lhs.height() > rhs.height();
340 }
341
344 [[nodiscard]] constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
345 {
346 return lhs.width() > rhs.width() && lhs.height() > rhs.height() && lhs.depth() > rhs.depth();
347 }
348
351 [[nodiscard]] constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept requires(D == 2)
352 {
353 return lhs.width() >= rhs.width() && lhs.height() >= rhs.height();
354 }
355
358 [[nodiscard]] constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept requires(D == 3)
359 {
360 return lhs.width() >= rhs.width() && lhs.height() >= rhs.height() && lhs.depth() >= rhs.depth();
361 }
362
367 [[nodiscard]] constexpr friend float squared_hypot(extent const &rhs) noexcept
368 {
369 tt_axiom(rhs.is_valid());
370 return squared_hypot<element_mask>(rhs._v);
371 }
372
377 [[nodiscard]] constexpr friend float hypot(extent const &rhs) noexcept
378 {
379 tt_axiom(rhs.is_valid());
380 return hypot<element_mask>(rhs._v);
381 }
382
387 [[nodiscard]] constexpr friend float rcp_hypot(extent const &rhs) noexcept
388 {
389 tt_axiom(rhs.is_valid());
390 return rcp_hypot<element_mask>(rhs._v);
391 }
392
397 [[nodiscard]] constexpr friend extent normalize(extent const &rhs) noexcept
398 {
399 tt_axiom(rhs.is_valid());
400 return extent{normalize<element_mask>(rhs._v)};
401 }
402
403 [[nodiscard]] constexpr friend extent ceil(extent const &rhs) noexcept
404 {
405 tt_axiom(rhs.is_valid());
406 return extent{ceil(static_cast<f32x4>(rhs))};
407 }
408
409 [[nodiscard]] constexpr friend extent floor(extent const &rhs) noexcept
410 {
411 tt_axiom(rhs.is_valid());
412 return extent{floor(static_cast<f32x4>(rhs))};
413 }
414
415 [[nodiscard]] constexpr friend extent min(extent const &lhs, extent const &rhs) noexcept
416 {
417 return extent{min(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
418 }
419
420 [[nodiscard]] constexpr friend extent max(extent const &lhs, extent const &rhs) noexcept
421 {
422 return extent{max(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
423 }
424
425 [[nodiscard]] constexpr friend extent clamp(extent const &value, extent const &min, extent const &max) noexcept
426 {
427 return extent{clamp(static_cast<f32x4>(value), static_cast<f32x4>(min), static_cast<f32x4>(max))};
428 }
429
434 [[nodiscard]] constexpr bool is_valid() const noexcept
435 {
436 return _v.x() >= 0.0f && _v.y() >= 0.0f && _v.z() >= 0.0f && _v.w() == 0.0f && (D == 3 || _v.z() == 0.0f);
437 }
438
439 [[nodiscard]] friend std::string to_string(extent const &rhs) noexcept
440 {
441 if constexpr (D == 2) {
442 return std::format("[{}, {}]", rhs._v.x(), rhs._v.y());
443 } else if constexpr (D == 3) {
444 return std::format("[{}, {}, {}]", rhs._v.x(), rhs._v.y(), rhs._v.z());
445 } else {
446 tt_static_no_default();
447 }
448 }
449
450 friend std::ostream &operator<<(std::ostream &lhs, extent const &rhs) noexcept
451 {
452 return lhs << to_string(rhs);
453 }
454
455private:
456 f32x4 _v;
457
458 static constexpr size_t element_mask = (1_uz << D) - 1;
459};
460
461} // namespace geo
462
463using extent2 = geo::extent<2>;
464using extent3 = geo::extent<3>;
465
466} // namespace tt
467
468namespace std {
469
470template<typename CharT>
471struct formatter<tt::geo::extent<2>, CharT> {
472 auto parse(auto &pc)
473 {
474 return pc.end();
475 }
476
477 auto format(tt::geo::extent<2> const &t, auto &fc)
478 {
479 return std::vformat_to(fc.out(), "[{}, {}]", std::make_format_args(t.width(), t.height()));
480 }
481};
482
483template<typename CharT>
484struct formatter<tt::geo::extent<3>, CharT> : formatter<float, CharT> {
485 auto parse(auto &pc)
486 {
487 return pc.end();
488 }
489
490 auto format(tt::geo::extent<3> const &t, auto &fc)
491 {
492 return std::vformat_to(fc.out(), "[{}, {}, {}]", std::make_format_args(t.width(), t.height(), t.depth()));
493 }
494};
495
496} // namespace std
STL namespace.
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:186
constexpr float const & width() const noexcept
Access the x-as-width element from the extent.
Definition extent.hpp:175
constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:337
constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:309
constexpr float & width() noexcept
Access the x-as-width element from the extent.
Definition extent.hpp:142
constexpr friend bool operator<(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:316
constexpr friend extent operator*(float const &lhs, extent const &rhs) noexcept
Scale the extent by a scaler.
Definition extent.hpp:290
constexpr bool is_valid() const noexcept
Check if the extent is valid.
Definition extent.hpp:434
constexpr friend float squared_hypot(extent const &rhs) noexcept
Get the squared length of the extent.
Definition extent.hpp:367
constexpr friend extent operator-(extent const &lhs, extent const &rhs) noexcept
Subtract two extents from each other.
Definition extent.hpp:233
constexpr friend extent operator*(extent const &lhs, float const &rhs) noexcept
Scale the extent by a scaler.
Definition extent.hpp:244
constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:323
constexpr friend float rcp_hypot(extent const &rhs) noexcept
Get the length of the extent.
Definition extent.hpp:387
constexpr friend bool operator<=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:330
constexpr friend extent normalize(extent const &rhs) noexcept
Normalize a extent to a unit extent.
Definition extent.hpp:397
constexpr extent(float width, float height, float depth=0.0f) noexcept
Construct a 3D extent from x, y and z elements.
Definition extent.hpp:90
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:80
constexpr float & depth() noexcept
Access the z-as-depth element from the extent.
Definition extent.hpp:164
constexpr friend float hypot(extent const &rhs) noexcept
Get the length of the extent.
Definition extent.hpp:377
constexpr friend extent operator+(extent const &lhs, float const &rhs) noexcept
Add a scaler to the extent.
Definition extent.hpp:273
constexpr float const & depth() const noexcept
Access the z-as-depth element from the extent.
Definition extent.hpp:197
constexpr friend bool operator>(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:344
constexpr float & height() noexcept
Access the y-as-height element from the extent.
Definition extent.hpp:153
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:301
constexpr extent() noexcept
Construct a empty extent / zero length.
Definition extent.hpp:71
constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:351
constexpr friend extent operator+(extent const &lhs, extent const &rhs) noexcept
Add two extents from each other.
Definition extent.hpp:222
constexpr friend bool operator>=(extent const &lhs, extent const &rhs) noexcept
Compare the size of the extents.
Definition extent.hpp:358
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:20
T infinity(T... args)
T max(T... args)
T signaling_NaN(T... args)