HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
point.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 "vector.hpp"
8#include "extent.hpp"
9#include "../SIMD/module.hpp"
10#include "../utility/module.hpp"
11#include <format>
12
13namespace hi::inline v1 {
14namespace geo {
15
23template<typename T, int D>
24class point {
25public:
26 using value_type = T;
27 using array_type = simd<value_type, 4>;
28
29 static_assert(D == 2 || D == 3, "Only 2D or 3D points are supported");
30
31 constexpr point(point const&) noexcept = default;
32 constexpr point(point&&) noexcept = default;
33 constexpr point& operator=(point const&) noexcept = default;
34 constexpr point& operator=(point&&) noexcept = default;
35
38 template<int E>
39 requires(E < D)
40 [[nodiscard]] constexpr point(point<value_type, E> const& other) noexcept : _v(static_cast<array_type>(other))
41 {
42 hi_axiom(holds_invariant());
43 }
44
47 [[nodiscard]] constexpr point(point<value_type, 2> const& other, value_type z) noexcept
48 requires(D == 3)
49 : _v(static_cast<array_type>(other))
50 {
51 _v.z() = z;
52 hi_axiom(holds_invariant());
53 }
54
58 template<int E>
59 requires(E > D)
60 [[nodiscard]] constexpr explicit point(point<value_type, E> const& other) noexcept : _v(static_cast<array_type>(other))
61 {
62 for (std::size_t i = D; i != E; ++i) {
63 _v[i] = value_type{0};
64 }
65 hi_axiom(holds_invariant());
66 }
67
70 [[nodiscard]] constexpr explicit operator array_type() const noexcept
71 {
72 hi_axiom(holds_invariant());
73 return _v;
74 }
75
78 [[nodiscard]] constexpr explicit point(array_type const& other) noexcept : _v(other)
79 {
80 hi_axiom(holds_invariant());
81 }
82
85 [[nodiscard]] constexpr point() noexcept : _v(value_type{0}, value_type{0}, value_type{0}, value_type{1}) {}
86
91 [[nodiscard]] constexpr point(value_type x, value_type y) noexcept
92 requires(D == 2)
93 : _v(x, y, value_type{0}, value_type{1})
94 {
95 }
96
102 [[nodiscard]] constexpr point(value_type x, value_type y, value_type z = value_type{0}) noexcept
103 requires(D == 3)
104 : _v(x, y, z, value_type{1})
105 {
106 }
107
111 [[nodiscard]] constexpr value_type& x() noexcept
112 {
113 return _v.x();
114 }
115
119 [[nodiscard]] constexpr value_type& y() noexcept
120 {
121 return _v.y();
122 }
123
127 [[nodiscard]] constexpr value_type& z() noexcept
128 requires(D == 3)
129 {
130 return _v.z();
131 }
132
136 [[nodiscard]] constexpr value_type x() const noexcept
137 {
138 return _v.x();
139 }
140
144 [[nodiscard]] constexpr value_type y() const noexcept
145 {
146 return _v.y();
147 }
148
152 [[nodiscard]] constexpr value_type z() const noexcept
153 requires(D == 3)
154 {
155 return _v.z();
156 }
157
158 template<int E>
159 requires(E <= D)
160 constexpr point& operator+=(vector<value_type, E> const& rhs) noexcept
161 {
162 hi_axiom(holds_invariant() && rhs.holds_invariant());
163 _v = _v + static_cast<array_type>(rhs);
164 return *this;
165 }
166
167 template<int E>
168 requires(E <= D)
169 constexpr point& operator-=(vector<value_type, E> const& rhs) noexcept
170 {
171 hi_axiom(holds_invariant() && rhs.holds_invariant());
172 _v = _v - static_cast<array_type>(rhs);
173 return *this;
174 }
175
181 template<int E>
182 [[nodiscard]] constexpr friend auto operator+(point const& lhs, vector<value_type, E> const& rhs) noexcept
183 {
184 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
185 return point<value_type, std::max(D, E)>{lhs._v + static_cast<array_type>(rhs)};
186 }
187
193 template<int E>
194 [[nodiscard]] constexpr friend auto operator+(vector<value_type, E> const& rhs, point const& lhs) noexcept
195 {
196 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
197 return point<value_type, std::max(D, E)>{lhs._v + static_cast<array_type>(rhs)};
198 }
199
205 template<int E>
206 [[nodiscard]] constexpr friend auto operator-(point const& lhs, vector<value_type, E> const& rhs) noexcept
207 {
208 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
209 return point<value_type, std::max(D, E)>{lhs._v - static_cast<array_type>(rhs)};
210 }
211
217 [[nodiscard]] constexpr friend vector<value_type, D> operator-(point const& lhs, point const& rhs) noexcept
218 {
219 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
220 return vector<value_type, D>{lhs._v - rhs._v};
221 }
222
228 [[nodiscard]] constexpr friend bool operator==(point const& lhs, point const& rhs) noexcept
229 {
230 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
231 return equal(lhs._v, rhs._v);
232 }
233
234 template<int E>
235 [[nodiscard]] friend constexpr auto midpoint(point const& lhs, point<value_type, E> const& rhs) noexcept
236 {
237 return point<value_type, std::max(D, E)>{midpoint(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
238 }
239
240 template<int E>
241 [[nodiscard]] friend constexpr auto reflect(point const& lhs, point<value_type, E> const& rhs) noexcept
242 {
243 return point<value_type, std::max(D, E)>{reflect_point(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
244 }
245
251 template<int E>
252 [[nodiscard]] friend constexpr auto min(point const& lhs, point<value_type, E> const& rhs) noexcept
253 {
254 return point<value_type, std::max(D, E)>{min(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
255 }
256
262 template<int E>
263 [[nodiscard]] friend constexpr auto max(point const& lhs, point<value_type, E> const& rhs) noexcept
264 {
265 return point<value_type, std::max(D, E)>{max(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
266 }
267
270 [[nodiscard]] friend constexpr point round(point const& rhs) noexcept
271 requires std::is_same_v<value_type, float>
272 {
273 return point{round(static_cast<array_type>(rhs))};
274 }
275
278 [[nodiscard]] friend constexpr point ceil(point const& rhs) noexcept
279 requires std::is_same_v<value_type, float>
280 {
281 return point{ceil(static_cast<array_type>(rhs))};
282 }
283
286 [[nodiscard]] friend constexpr point floor(point const& rhs) noexcept
287 requires std::is_same_v<value_type, float>
288 {
289 return point{floor(static_cast<array_type>(rhs))};
290 }
291
294 [[nodiscard]] friend constexpr point ceil(point const& lhs, extent<value_type, D> rhs) noexcept
295 requires std::is_same_v<value_type, float>
296 {
297 hilet rhs_ = array_type{rhs}.xy11();
298 return point{ceil(array_type{lhs} / rhs_) * rhs_};
299 }
300
303 [[nodiscard]] friend constexpr point ceil(point const& lhs, extent<value_type, D> rhs) noexcept
304 requires std::is_same_v<value_type, int>
305 {
306 hilet rhs_ = array_type{rhs}.xy11();
307 hilet lhs_ = array_type{lhs};
308 return point{(lhs_ + (rhs_ - 1)) / rhs_ * rhs_};
309 }
310
313 [[nodiscard]] friend constexpr point floor(point const& lhs, extent<value_type, D> rhs) noexcept
314 requires std::is_same_v<value_type, float>
315 {
316 hilet rhs_ = array_type{rhs}.xy11();
317 return point{floor(array_type{lhs} / rhs_) * rhs_};
318 }
319
322 [[nodiscard]] friend constexpr point floor(point const& lhs, extent<value_type, D> rhs) noexcept
323 requires std::is_same_v<value_type, int>
324 {
325 hilet rhs_ = array_type{rhs}.xy11();
326 hilet lhs_ = array_type{lhs};
327 return point{lhs_ / rhs_ * rhs_};
328 }
329
330 [[nodiscard]] friend constexpr value_type distance(point const& lhs, point const& rhs) noexcept
331 {
332 return hypot(rhs - lhs);
333 }
334
338 [[nodiscard]] constexpr bool holds_invariant() const noexcept
339 {
340 return _v.w() != value_type{0} && (D == 3 || _v.z() == value_type{0});
341 }
342
343 [[nodiscard]] friend std::string to_string(point const& rhs) noexcept
344 {
345 if constexpr (D == 2) {
346 return std::format("<{}, {}>", rhs._v.x(), rhs._v.y());
347 } else if constexpr (D == 3) {
348 return std::format("<{}, {}, {}>", rhs._v.x(), rhs._v.y(), rhs._v.z());
349 } else {
351 }
352 }
353
354 friend std::ostream& operator<<(std::ostream& lhs, point const& rhs) noexcept
355 {
356 return lhs << to_string(rhs);
357 }
358
359private:
360 array_type _v;
361};
362
363} // namespace geo
364
365using point2 = geo::point<float, 2>;
366using point3 = geo::point<float, 3>;
367using point2i = geo::point<int, 2>;
368using point3i = geo::point<int, 3>;
369
370template<>
371[[nodiscard]] constexpr point2 narrow_cast(point2i const& rhs) noexcept
372{
373 return {narrow_cast<float>(rhs.x()), narrow_cast<float>(rhs.y())};
374}
375
376} // namespace hi::inline v1
377
378template<typename CharT>
379struct std::formatter<hi::geo::point<float, 2>, CharT> {
380 auto parse(auto& pc)
381 {
382 return pc.end();
383 }
384
385 auto format(hi::geo::point<float, 2> const& t, auto& fc)
386 {
387 return std::vformat_to(fc.out(), "<{}, {}>", std::make_format_args(t.x(), t.y()));
388 }
389};
390
391template<typename CharT>
392struct std::formatter<hi::geo::point<float, 3>, CharT> {
393 auto parse(auto& pc)
394 {
395 return pc.end();
396 }
397
398 auto format(hi::geo::point<float, 3> const& t, auto& fc)
399 {
400 return std::vformat_to(fc.out(), "<{}, {}, {}>", std::make_format_args(t.x(), t.y(), t.z()));
401 }
402};
403
404template<typename CharT>
405struct std::formatter<hi::geo::point<int, 2>, CharT> {
406 auto parse(auto& pc)
407 {
408 return pc.end();
409 }
410
411 auto format(hi::geo::point<int, 2> const& t, auto& fc)
412 {
413 return std::vformat_to(fc.out(), "<{}, {}>", std::make_format_args(t.x(), t.y()));
414 }
415};
416
417template<typename CharT>
418struct std::formatter<hi::geo::point<int, 3>, CharT> {
419 auto parse(auto& pc)
420 {
421 return pc.end();
422 }
423
424 auto format(hi::geo::point<int, 3> const& t, auto& fc)
425 {
426 return std::vformat_to(fc.out(), "<{}, {}, {}>", std::make_format_args(t.x(), t.y(), t.z()));
427 }
428};
Defined the geo::extent, extent2 and extent3 types.
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:308
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:238
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
A high-level geometric point Part of the high-level vec, point, mat and color types.
Definition point.hpp:24
friend constexpr point ceil(point const &rhs) noexcept
Round the coordinates of a point toward the right-top.
Definition point.hpp:278
constexpr value_type & y() noexcept
Access the y element from the point.
Definition point.hpp:119
constexpr value_type x() const noexcept
Access the x element from the point.
Definition point.hpp:136
constexpr point() noexcept
Construct a point at the origin of the coordinate system.
Definition point.hpp:85
friend constexpr auto max(point const &lhs, point< value_type, E > const &rhs) noexcept
Mix the two points and get the highest value of each element.
Definition point.hpp:263
constexpr friend auto operator-(point const &lhs, vector< value_type, E > const &rhs) noexcept
Move a point backward along the vector.
Definition point.hpp:206
constexpr point(value_type x, value_type y) noexcept
Construct a 2D point from x and y elements.
Definition point.hpp:91
constexpr friend vector< value_type, D > operator-(point const &lhs, point const &rhs) noexcept
Find the vector between two points.
Definition point.hpp:217
constexpr point(point< value_type, E > const &other) noexcept
Construct a point from a lower dimension point.
Definition point.hpp:40
constexpr point(point< value_type, E > const &other) noexcept
Construct a point from a higher dimension point.
Definition point.hpp:60
friend constexpr point floor(point const &lhs, extent< value_type, D > rhs) noexcept
Round the coordinates of a point toward the left-bottom with the given granularity.
Definition point.hpp:322
friend constexpr point ceil(point const &lhs, extent< value_type, D > rhs) noexcept
Round the coordinates of a point toward the top-right with the given granularity.
Definition point.hpp:294
friend constexpr auto min(point const &lhs, point< value_type, E > const &rhs) noexcept
Mix the two points and get the lowest value of each element.
Definition point.hpp:252
constexpr friend auto operator+(point const &lhs, vector< value_type, E > const &rhs) noexcept
Move a point along a vector.
Definition point.hpp:182
constexpr value_type y() const noexcept
Access the y element from the point.
Definition point.hpp:144
constexpr value_type z() const noexcept
Access the z element from the point.
Definition point.hpp:152
friend constexpr point floor(point const &lhs, extent< value_type, D > rhs) noexcept
Round the coordinates of a point toward the left-bottom with the given granularity.
Definition point.hpp:313
friend constexpr point ceil(point const &lhs, extent< value_type, D > rhs) noexcept
Round the coordinates of a point toward the top-right with the given granularity.
Definition point.hpp:303
constexpr point(array_type const &other) noexcept
Construct a point from a array_type-simd.
Definition point.hpp:78
friend constexpr point floor(point const &rhs) noexcept
Round the coordinates of a point toward the left-bottom.
Definition point.hpp:286
constexpr value_type & x() noexcept
Access the x element from the point.
Definition point.hpp:111
constexpr bool holds_invariant() const noexcept
Check if the point is valid.
Definition point.hpp:338
constexpr friend bool operator==(point const &lhs, point const &rhs) noexcept
Compare if two points are equal.
Definition point.hpp:228
constexpr point(value_type x, value_type y, value_type z=value_type{0}) noexcept
Construct a 3D point from x, y and z elements.
Definition point.hpp:102
friend constexpr point round(point const &rhs) noexcept
Round the coordinates of a point toward nearest integer.
Definition point.hpp:270
constexpr point(point< value_type, 2 > const &other, value_type z) noexcept
Construct a point from a lower dimension point.
Definition point.hpp:47
constexpr value_type & z() noexcept
Access the z element from the point.
Definition point.hpp:127
constexpr friend auto operator+(vector< value_type, E > const &rhs, point const &lhs) noexcept
Move a point along a vector.
Definition point.hpp:194
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:21
T max(T... args)
T to_string(T... args)