neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
geometrical.hpp
Go to the documentation of this file.
1// geometrical.hpp
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2015, 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
23#include <array>
24#include <type_traits>
25#include <ostream>
26#include <optional>
30
31namespace neogfx
32{
37
38 typedef int32_t coordinate_i32;
39 typedef int32_t dimension_i32;
40 typedef int32_t coordinate_delta_i32;
41
42 typedef uint32_t coordinate_u32;
43 typedef uint32_t dimension_u32;
44 typedef uint32_t coordinate_delta_u32;
45
46 typedef vec2 xy;
47 typedef vec3 xyz;
48
55
56 template <logical_coordinate_system>
57 struct is_gui
58 {
59 static constexpr bool value = false;
60 };
61 template <>
63 {
64 static constexpr bool value = true;
65 };
66 template <logical_coordinate_system>
67 struct is_game
68 {
69 static constexpr bool value = false;
70 };
71 template <>
73 {
74 static constexpr bool value = true;
75 };
76
78
80 {
82
85 bool is_gui_orientation() const
86 {
87 return bottomLeft.y > topRight.y;
88 }
90 {
91 return !is_gui_orientation();
92 }
93 friend bool operator==(const logical_coordinates& lhs, const logical_coordinates& rhs)
94 {
95 return lhs.bottomLeft == rhs.bottomLeft && lhs.topRight == rhs.topRight;
96 }
97 friend bool operator!=(const logical_coordinates& lhs, const logical_coordinates& rhs)
98 {
99 return !(lhs == rhs);
100 }
101 };
102
104
105 // Primarily for 2D use so 3D support limited
106 template <typename CoordinateType>
108 {
109 typedef basic_delta<CoordinateType> self_type;
110 // types
111 public:
112 typedef self_type abstract_type; // todo: abstract type
113 typedef CoordinateType coordinate_type;
114 // construction
115 public:
116 constexpr basic_delta() : dx{}, dy{}, dz{} {}
118 constexpr explicit basic_delta(coordinate_type aSquareDelta) : dx{ aSquareDelta }, dy{ aSquareDelta }, dz{} {}
119 template <typename CoordinateType2>
121 dx{ static_cast<CoordinateType>(other.dx) }, dy{ static_cast<CoordinateType>(other.dy) }, dz{ static_cast<CoordinateType>(other.dz) } {}
122 // operations
123 public:
126 auto operator<=>(const basic_delta&) const = default;
127 basic_delta& operator+=(coordinate_type s) { dx +=s; dy += s; return *this; }
128 basic_delta& operator-=(coordinate_type s) { dx -=s; dy -= s; return *this; }
129 basic_delta& operator*=(coordinate_type s) { dx *=s; dy *= s; return *this; }
130 basic_delta& operator/=(coordinate_type s) { dx /=s; dy /= s; return *this; }
131 basic_delta& operator+=(const basic_delta& other) { dx += other.dx; dy += other.dy; dz += other.dz; return *this; }
132 basic_delta& operator-=(const basic_delta& other) { dx -= other.dx; dy -= other.dy; dz -= other.dz; return *this; }
133 basic_delta& operator*=(const basic_delta& other) { dx *= other.dx; dy *= other.dy; dz *= other.dz; return *this; }
134 basic_delta& operator/=(const basic_delta& other) { dx /= other.dx; dy /= other.dy; if (other.dz != static_cast<coordinate_type>(0.0)) dz /= other.dz; return *this; }
135 basic_delta operator-() const { return basic_delta{ -dx, -dy, -dz }; }
136 basic_delta abs() const { return basic_delta{ std::abs(dx), std::abs(dy), std::abs(dz) }; }
137 basic_delta ceil() const { return basic_delta{ std::ceil(dx), std::ceil(dy), std::ceil(dz) }; }
138 basic_delta floor() const { return basic_delta{ std::floor(dx), std::floor(dy), std::floor(dz) }; }
139 basic_delta round() const { return basic_delta{ std::round(dx), std::round(dy), std::round(dz) }; }
140 basic_delta min(const basic_delta& other) const { return basic_delta{ std::min(dx, other.dx), std::min(dy, other.dy), std::min(dz, other.dz) }; }
141 basic_delta max(const basic_delta& other) const { return basic_delta{ std::max(dx, other.dx), std::max(dy, other.dy), std::max(dz, other.dz) }; }
144 coordinate_type magnitude() const { return std::sqrt(dx * dx + dy * dy + dz * dz); }
145 public:
146 template <typename T>
148 {
149 return *this;
150 }
151 // attributes
152 public:
156 };
157
159
160 template <typename CoordinateType>
162 {
164 ret += s;
165 return ret;
166 }
167
168 template <typename CoordinateType>
170 {
172 ret -= s;
173 return ret;
174 }
175
176 template <typename CoordinateType>
178 {
180 ret *= s;
181 return ret;
182 }
183
184 template <typename CoordinateType>
186 {
188 ret /= s;
189 return ret;
190 }
191
192 template <typename CoordinateType>
194 {
196 ret += right;
197 return ret;
198 }
199
200 template <typename CoordinateType>
202 {
204 ret -= right;
205 return ret;
206 }
207
208 template <typename CoordinateType>
210 {
212 ret *= right;
213 return ret;
214 }
215
216 template <typename CoordinateType>
218 {
220 ret /= right;
221 return ret;
222 }
223
224 template <typename CoordinateType>
225 inline bool nearly_equal(basic_delta<CoordinateType> const& lhs, basic_delta<CoordinateType> const& rhs, scalar epsilon = 0.00001)
226 {
227 return nearly_equal(lhs.dx, rhs.dx, epsilon) && nearly_equal(lhs.dy, rhs.dy, epsilon);
228 }
229
230 struct bad_size : std::logic_error { bad_size() : std::logic_error{ "neogfx::bad_size" } {} };
231
232 // Primarily for 2D use so 3D support limited
233 template <typename CoordinateType>
235 {
237 // types
238 public:
239 typedef self_type abstract_type; // todo: abstract type
240 typedef CoordinateType coordinate_type;
241 typedef CoordinateType dimension_type;
243 // construction
244 public:
245 constexpr basic_size() : cx{}, cy{}, cz{} {}
246 template <typename Scalar>
247 constexpr basic_size(const basic_vector<Scalar, 2>& other) : cx{ static_cast<dimension_type>(other.x) }, cy{ static_cast<dimension_type>(other.y) }, cz{} {}
248 template <typename Scalar>
249 constexpr basic_size(const basic_vector<Scalar, 3>& other) : cx{ static_cast<dimension_type>(other.x) }, cy{ static_cast<dimension_type>(other.y) }, cz{ static_cast<dimension_type>(other.z) } {}
251 constexpr explicit basic_size(dimension_type aSquareDimension) : cx{ aSquareDimension }, cy{ aSquareDimension }, cz{} {}
252 template <typename CoordinateType2>
253 constexpr basic_size(const basic_size<CoordinateType2>& other) :
254 cx{ static_cast<CoordinateType>(other.cx) }, cy{ static_cast<CoordinateType>(other.cy) }, cz{ static_cast<CoordinateType>(other.cz) } {}
255 constexpr basic_size(const basic_delta<CoordinateType>& other) : cx{ other.dx }, cy{ other.dy }, cz{ other.dz } {}
256 // operations
257 public:
258 basic_vector<dimension_type, 2> to_vec2() const { throw_on_bad_size(*this); return basic_vector<dimension_type, 2>{ cx, cy }; }
259 basic_vector<dimension_type, 3> to_vec3() const { throw_on_bad_size(*this); return basic_vector<dimension_type, 3>{ cx, cy, cz }; }
262 delta_type to_delta() const { return delta_type(cx, cy, cz); }
263 bool empty() const { return cx == 0 || cy == 0; }
264 auto operator<=>(const basic_size&) const = default;
265 basic_size operator-() const { throw_on_bad_size(*this); return basic_size{ -cx, -cy, -cz }; }
266 basic_size& operator+=(const basic_size& other) { throw_on_bad_size(other); cx += other.cx; cy += other.cy; cz += other.cz; return *this; }
267 basic_size& operator+=(const basic_delta<CoordinateType>& other) { throw_on_bad_size(other); cx += other.dx; cy += other.dy; cz += other.dz; return *this; }
268 basic_size& operator+=(dimension_type amount) { throw_on_bad_size(basic_size{ amount }); cx += amount; cy += amount; return *this; }
269 basic_size& operator-=(const basic_size& other) { throw_on_bad_size(other); cx -= other.cx; cy -= other.cy; cz -= other.cz; return *this; }
270 basic_size& operator-=(const basic_delta<CoordinateType>& other) { throw_on_bad_size(other); cx -= other.dx; cy -= other.dy; cz -= other.dz; return *this; }
271 basic_size& operator-=(dimension_type amount) { throw_on_bad_size(basic_size{ amount }); cx -= amount; cy -= amount; return *this; }
272 basic_size& operator*=(const basic_size& other) { throw_on_bad_size(other); cx *= other.cx; cy *= other.cy; cz *= other.cz; return *this; }
273 basic_size& operator*=(dimension_type amount) { throw_on_bad_size(basic_size{ amount }); cx *= amount; cy *= amount; return *this; }
274 basic_size& operator/=(const basic_size& other) { throw_on_bad_size(other); cx /= other.cx; cy /= other.cy; if (other.cz != static_cast<dimension_type>(0.0)) cz /= other.cz; return *this; }
275 basic_size& operator/=(dimension_type amount) { throw_on_bad_size(basic_size{ amount }); cx /= amount; cy /= amount; return *this; }
276 basic_size ceil() const { return basic_size{ !cx_inf() ? std::ceil(cx) : cx, !cy_inf() ? std::ceil(cy) : cy, !cz_inf() ? std::ceil(cz) : cz }; }
277 basic_size floor() const { return basic_size{ !cx_inf() ? std::floor(cx) : cx, !cy_inf() ? std::floor(cy) : cy, !cz_inf() ? std::floor(cz) : cz }; }
278 basic_size round() const { return basic_size{ !cx_inf() ? std::round(cx) : cx, !cy_inf() ? std::round(cy) : cy, !cz_inf() ? std::round(cz) : cz }; }
279 basic_size min(const basic_size& other) const { return basic_size{ std::min(cx, other.cx), std::min(cy, other.cy), std::min(cz, other.cz) }; }
280 basic_size max(const basic_size& other) const { return basic_size{ std::max(cx, other.cx), std::max(cy, other.cy), std::max(cz, other.cz) }; }
281 bool less_than(const basic_size& other) const { return cx < other.cx && cy < other.cy; };
282 bool less_than_or_equal(const basic_size& other) const { return cx <= other.cx && cy <= other.cy; };
283 bool greater_than(const basic_size& other) const { return cy > other.cy && cy > other.cy; };
284 bool greater_than_or_equal(const basic_size& other) const { return cy >= other.cy && cy >= other.cy; };
285 dimension_type magnitude() const { throw_on_bad_size(*this); return std::sqrt(cx * cx + cy * cy); }
286 basic_size with_cx(dimension_type d) const { return basic_size{ d, cy, cz }; }
287 basic_size with_cy(dimension_type d) const { return basic_size{ cx, d, cz }; }
288 basic_size with_cz(dimension_type d) const { return basic_size{ cx, cy, d }; }
289 basic_size aspect_ratio() const { return cx >= cy ? basic_size{ 1.0, cy / cx, cz } : basic_size{ cx / cy, 1.0, cz }; }
290 basic_size with_aspect_ratio_min(const basic_size& aspectRatio) const { return basic_size{ std::min(cx, cy) } * aspectRatio; };
291 basic_size with_aspect_ratio_max(const basic_size& aspectRatio) const { return basic_size{ std::max(cx, cy) } * aspectRatio; };
292 public:
293 template <typename T>
295 {
296 return *this;
297 }
298 public:
299 bool cx_inf() const { return cx == max_dimension(); }
300 bool cy_inf() const { return cy == max_dimension(); }
301 bool cz_inf() const { return cz == max_dimension(); }
302 private:
303 void throw_on_bad_size(const basic_size& rhs) const { if ((rhs.cx != 0.0 && cx_inf()) && (rhs.cy != 0.0 && cy_inf()) && (rhs.cz != 0.0 && cz_inf())) throw bad_size(); }
304 // helpers
305 public:
306 static constexpr dimension_type max_dimension() { return std::numeric_limits<dimension_type>::infinity(); }
307 static constexpr basic_size max_size() { return basic_size{ max_dimension(), max_dimension() }; }
308 // attributes
309 public:
313 };
314
316
317 template <typename CoordinateType>
319 {
321 ret += right;
322 return ret;
323 }
324
325 template <typename CoordinateType>
327 {
329 ret -= right;
330 return ret;
331 }
332
333 template <typename CoordinateType>
335 {
337 ret *= right;
338 return ret;
339 }
340
341 template <typename CoordinateType>
343 {
345 ret /= right;
346 return ret;
347 }
348
349 template <typename CoordinateType>
351 {
353 ret += right;
354 return ret;
355 }
356
357 template <typename CoordinateType>
359 {
361 ret -= right;
362 return ret;
363 }
364
365 template <typename CoordinateType>
367 {
369 ret *= right;
370 return ret;
371 }
372
373 template <typename CoordinateType>
375 {
377 ret /= right;
378 return ret;
379 }
380
381 template <typename CoordinateType>
382 inline bool nearly_equal(basic_size<CoordinateType> const& lhs, basic_size<CoordinateType> const& rhs, scalar epsilon = 0.00001)
383 {
384 return nearly_equal(lhs.cx, rhs.cx, epsilon) && nearly_equal(lhs.cy, rhs.cy, epsilon);
385 }
386
387 // Primarily for 2D use so 3D support limited
388 template <typename CoordinateType>
390 {
391 typedef basic_point<CoordinateType> self_type;
392 // types
393 public:
394 typedef self_type abstract_type; // todo: abstract type
395 typedef CoordinateType coordinate_type;
396 // construction
397 public:
398 constexpr basic_point() : x{}, y{}, z{} {}
399 template <typename Scalar>
400 constexpr basic_point(const basic_vector<Scalar, 2>& other) :
401 x{ static_cast<coordinate_type>(other.x) },
402 y{ static_cast<coordinate_type>(other.y) },
403 z{} {}
404 template <typename Scalar>
405 constexpr basic_point(const basic_vector<Scalar, 3>& other) :
406 x{ static_cast<coordinate_type>(other.x) },
407 y{ static_cast<coordinate_type>(other.y) },
408 z{} {}
409 constexpr basic_point(CoordinateType x, CoordinateType y, CoordinateType z = {}) :
410 x{ x }, y{ y }, z{ z } {}
411 template <typename CoordinateType2>
413 x{ static_cast<CoordinateType>(other.x) },
414 y{ static_cast<CoordinateType>(other.y) },
415 z{ static_cast<CoordinateType>(other.z) } {}
416 constexpr basic_point(const basic_delta<CoordinateType>& other) :
417 x{ other.dx }, y{ other.dy }, z{} {}
418 constexpr basic_point(const basic_size<CoordinateType>& other) :
419 x{ other.cx }, y{ other.cy }, z{} {}
420 // operations
421 public:
426 explicit operator basic_delta<coordinate_type>() const { return to_delta(); }
427 explicit operator basic_size<coordinate_type>() const { return to_size(); }
428 auto operator<=>(const basic_point&) const = default;
429 basic_point& operator+=(const basic_point& other) { x += other.x; y += other.y; z += other.z; return *this; }
430 basic_point& operator-=(const basic_point& other) { x -= other.x; y -= other.y; z -= other.z; return *this; }
431 basic_point& operator*=(const basic_point& other) { x *= other.x; y *= other.y; z *= other.z; return *this; }
432 basic_point& operator/=(const basic_point& other) { x /= other.x; y /= other.y; if (other.z != static_cast<coordinate_type>(0.0)) z /= other.z; return *this; }
433 basic_point& operator+=(coordinate_type amount) { x += amount; y += amount; return *this; }
434 basic_point& operator-=(coordinate_type amount) { x -= amount; y -= amount; return *this; }
435 basic_point& operator*=(coordinate_type amount) { x *= amount; y *= amount; return *this; }
436 basic_point& operator/=(coordinate_type amount) { x /= amount; y /= amount; return *this; }
437 basic_point& operator+=(const basic_delta<coordinate_type>& other) { x += static_cast<coordinate_type>(other.dx); y += static_cast<coordinate_type>(other.dy); z += static_cast<coordinate_type>(other.dz); return *this; }
438 basic_point& operator-=(const basic_delta<coordinate_type>& other) { x -= static_cast<coordinate_type>(other.dx); y -= static_cast<coordinate_type>(other.dy); z -= static_cast<coordinate_type>(other.dz); return *this; }
439 basic_point& operator+=(const basic_size<coordinate_type>& other) { x += static_cast<coordinate_type>(other.cx); y += static_cast<coordinate_type>(other.cy); z += static_cast<coordinate_type>(other.cz); return *this; }
440 basic_point& operator-=(const basic_size<coordinate_type>& other) { x -= static_cast<coordinate_type>(other.cx); y -= static_cast<coordinate_type>(other.cy); z -= static_cast<coordinate_type>(other.cz); return *this; }
441 basic_point operator-() const { return basic_point{ -x, -y, -z }; }
442 basic_point abs() const { return basic_point{ std::abs(x), std::abs(y), std::abs(z) }; }
443 basic_point ceil() const { return basic_point{ std::ceil(x), std::ceil(y), std::ceil(z) }; }
444 basic_point floor() const { return basic_point{ std::floor(x), std::floor(y), std::floor(z) }; }
445 basic_point round() const { return basic_point{ std::round(x), std::round(y), std::round(z) }; }
446 basic_point min(const basic_point& other) const { return basic_point{ std::min(x, other.x), std::min(y, other.y), std::min(z, other.z) }; }
447 basic_point max(const basic_point& other) const { return basic_point{ std::max(x, other.x), std::max(y, other.y), std::max(z, other.z) }; }
448 basic_point min_max(const basic_point& other) const { return basic_point{ std::min(x, other.x), std::max(y, other.y), other.z }; }
449 basic_point max_min(const basic_point& other) const { return basic_point{ std::max(x, other.x), std::min(y, other.y), other.z }; }
450 basic_point mid(const basic_point& other) const { return basic_point{ (x + other.x) / static_cast<coordinate_type>(2.0), (y + other.y) / static_cast<coordinate_type>(2.0), (z + other.z) / static_cast<coordinate_type>(2.0) }; }
451 basic_point with_x(coordinate_type x0) const { return basic_point{ x0, y, z }; }
452 basic_point with_y(coordinate_type y0) const { return basic_point{ x, y0, z }; }
453 basic_point with_z(coordinate_type z0) const { return basic_point{ x, y, z0 }; }
454 coordinate_type magnitude() const { return std::sqrt(x * x + y * y + z * z); }
455 template <typename T>
457 {
458 return *this;
459 }
460 // attributes
461 public:
465 };
466
468
469 template <typename CoordinateType>
471 {
473 ret += right;
474 return ret;
475 }
476
477 template <typename CoordinateType>
479 {
481 ret -= right;
482 return ret;
483 }
484
485 template <typename CoordinateType>
487 {
489 ret *= right;
490 return ret;
491 }
492
493 template <typename CoordinateType>
495 {
497 ret /= right;
498 return ret;
499 }
500
501 template <typename CoordinateType>
503 {
505 ret += amount;
506 return ret;
507 }
508
509 template <typename CoordinateType>
511 {
513 ret -= amount;
514 return ret;
515 }
516
517 template <typename CoordinateType>
519 {
521 ret *= amount;
522 return ret;
523 }
524
525 template <typename CoordinateType>
527 {
529 ret /= amount;
530 return ret;
531 }
532
533 template <typename CoordinateType>
535 {
537 ret += right;
538 return ret;
539 }
540
541 template <typename CoordinateType>
543 {
545 ret -= right;
546 return ret;
547 }
548
549 template <typename CoordinateType>
551 {
553 ret *= right;
554 return ret;
555 }
556
557 template <typename CoordinateType>
559 {
561 ret /= right;
562 return basic_delta<CoordinateType>(ret.x, ret.y);
563 }
564
565 template <typename CoordinateType>
567 {
569 ret += right;
570 return ret;
571 }
572
573 template <typename CoordinateType>
575 {
577 ret -= right;
578 return ret;
579 }
580
581 template <typename CoordinateType>
583 {
585 ret *= right;
586 return ret;
587 }
588
589 template <typename CoordinateType>
591 {
593 ret /= right;
594 return ret;
595 }
596
597 template <typename CoordinateType>
599 {
601 ret += basic_size<CoordinateType>{ right.x, right.y };
602 return ret;
603 }
604
605 template <typename CoordinateType>
607 {
609 ret -= basic_size<CoordinateType>{ right.x, right.y };
610 return ret;
611 }
612
613 template <typename CoordinateType>
615 {
617 ret *= basic_size<CoordinateType>{ right.x, right.y };
618 return ret;
619 }
620
621 template <typename CoordinateType>
623 {
625 ret /= basic_size<CoordinateType>{ right.x, right.y };
626 return ret;
627 }
628
629 template <typename CoordinateType>
630 inline bool nearly_equal(basic_point<CoordinateType> const& lhs, basic_point<CoordinateType> const& rhs, scalar epsilon = 0.00001)
631 {
632 return nearly_equal(lhs.x, rhs.x, epsilon) && nearly_equal(lhs.y, rhs.y, epsilon);
633 }
634
635 template <typename DimensionType>
637 {
638 typedef basic_box_areas<DimensionType> self_type;
639 // types
640 public:
641 typedef self_type abstract_type; // todo: abstract type
642 typedef DimensionType dimension_type;
646 // construction
647 public:
649 basic_box_areas(dimension_type all) : left(all), top(all), right(all), bottom(all) {}
651 basic_box_areas(dimension_type leftRight, dimension_type topBottom) : left(leftRight), top(topBottom), right(leftRight), bottom(topBottom) {}
652 basic_box_areas(const size_type& aDimensions) : basic_box_areas{ aDimensions.cx, aDimensions.cy } {};
653 basic_box_areas(const point_type& aTopLeft, const point_type& aBottomRight) : left(aTopLeft.x), top(aTopLeft.y), right(aBottomRight.x), bottom(aBottomRight.y) {}
654 template <typename DimensionType2>
656 left(static_cast<dimension_type>(other.left)), top(static_cast<dimension_type>(other.top)), right(static_cast<dimension_type>(other.right)), bottom(static_cast<dimension_type>(other.bottom)) {}
657 // operations
658 public:
659 auto operator<=>(const self_type&) const = default;
660 self_type operator-() const { return self_type{ -left, -top, -right, -bottom }; }
661 self_type& operator+=(const self_type& other) { left += other.left; top += other.top; right += other.right; bottom += other.bottom; return *this; }
662 self_type& operator+=(dimension_type amount) { left += amount; top += amount; right += amount; bottom += amount; return *this; }
663 self_type& operator-=(const self_type& other) { left -= other.left; top -= other.top; right -= other.right; bottom -= other.bottom; return *this; }
664 self_type& operator-=(dimension_type amount) { left -= amount; top -= amount; right -= amount; bottom -= amount; return *this; }
665 self_type& operator*=(const self_type& other) { left *= other.left; top *= other.top; right *= other.right; bottom *= other.bottom; return *this; }
666 self_type& operator*=(dimension_type amount) { left *= amount; top *= amount; right *= amount; bottom *= amount; return *this; }
667 self_type& operator/=(const self_type& other) { left /= other.left; top /= other.top; right /= other.right; bottom /= other.bottom; return *this; }
668 self_type& operator/=(dimension_type amount) { left /= amount; top /= amount; right /= amount; bottom /= amount; return *this; }
669 public:
670 self_type with_left(dimension_type d) const { return self_type{ d, top, right, bottom }; }
671 self_type with_top(dimension_type d) const { return self_type{ left, d, right, bottom }; }
672 self_type with_right(dimension_type d) const { return self_type{ left, top, d, bottom }; }
673 self_type with_bottom(dimension_type d) const { return self_type{ left, top, right, d }; }
674 public:
675 point_type top_left() const { return point_type{ left, top }; }
677 size_type size() const { return size_type{ left + right, top + bottom }; }
678 public:
679 self_type ceil() const { return self_type{ std::ceil(left), std::ceil(top), std::ceil(right), std::ceil(bottom) }; }
680 self_type floor() const { return self_type{ std::floor(left), std::floor(top), std::floor(right), std::floor(bottom) }; }
681 self_type round() const { return self_type{ std::round(left), std::round(top), std::round(right), std::round(bottom) }; }
682 // attributes
683 public:
688 };
689
691
692 template <typename DimensionType>
694 {
696 ret += right;
697 return ret;
698 }
699
700 template <typename DimensionType>
702 {
704 ret -= right;
705 return ret;
706 }
707
708 template <typename DimensionType>
710 {
712 ret *= right;
713 return ret;
714 }
715
716 template <typename DimensionType>
718 {
720 ret /= right;
721 return ret;
722 }
723
724 template <typename DimensionType>
726 {
728 ret += right;
729 return ret;
730 }
731
732 template <typename DimensionType>
734 {
736 ret -= right;
737 return ret;
738 }
739
740 template <typename DimensionType>
742 {
744 ret *= right;
745 return ret;
746 }
747
748 template <typename DimensionType>
750 {
752 ret /= right;
753 return ret;
754 }
755
756 // Primarily for 2D use so 3D support limited
757 template <typename CoordinateType, logical_coordinate_system CoordinateSystem = logical_coordinate_system::AutomaticGui>
759 public basic_point<CoordinateType>,
760 public basic_size<CoordinateType>
761 {
763 // types
764 public:
765 typedef self_type abstract_type; // todo: abstract type
766 typedef CoordinateType coordinate_type;
768 private:
772 typedef basic_box_areas<dimension_type> padding_type;
773 public:
774 using point_type::x;
775 using point_type::y;
776 using point_type::z;
777 using size_type::cx;
778 using size_type::cy;
779 using size_type::cz;
780 // constants
781 public:
782 static constexpr bool gui = is_gui<CoordinateSystem>::value;
783 static constexpr bool game = is_game<CoordinateSystem>::value;
784 static constexpr coordinate_type zero = constants::zero<coordinate_type>;
785 static constexpr coordinate_type one = constants::one<coordinate_type>;
786 static constexpr coordinate_type two = constants::two<coordinate_type>;
787 static constexpr coordinate_type default_epsilon = static_cast<coordinate_type>(0.00001);
788 // construction
789 public:
791 basic_rect(const point_type& coordinates, const size_type& dimensions) : point_type{ coordinates }, size_type{ dimensions } {}
792 basic_rect(const point_type& leftCorner, const point_type& rightCorner) : basic_rect{ leftCorner.x, leftCorner.y, rightCorner.x, rightCorner.y } {}
793 explicit basic_rect(const point_type& coordinates) : point_type{ coordinates }, size_type{} {}
794 explicit basic_rect(const size_type& dimensions) : point_type{}, size_type{ dimensions } {}
796 basic_rect(const aabb_2d& aBoundingBox) : basic_rect{ aBoundingBox.min.x, aBoundingBox.min.y, aBoundingBox.max.x, aBoundingBox.max.y } {}
797 basic_rect(const basic_box_areas<coordinate_type>& aBoxAreas) : basic_rect{ aBoxAreas.top_left(), aBoxAreas.bottom_right() } {}
798 public:
799 template <typename CoordinateType2, logical_coordinate_system CoordinateSystem2>
801 // assignment
802 public:
803 template <typename CoordinateType2, logical_coordinate_system CoordinateSystem2>
804 self_type& operator=(const basic_rect<CoordinateType2, CoordinateSystem2>& other) { static_cast<point_type&>(*this) = other; static_cast<size_type&>(*this) = other; epsilon = other.epsilon; return *this; }
805 self_type& operator=(const point_type& coordinates) { static_cast<point_type&>(*this) = coordinates; return *this; }
806 self_type& operator=(const size_type& dimensions) { static_cast<size_type&>(*this) = dimensions; return *this; }
807 // operations
808 public:
810 {
811 if constexpr (gui)
812 return basic_vector<basic_vector<coordinate_type, 2>, 4>(top_left().to_vector(), top_right().to_vector(), bottom_right().to_vector(), bottom_left().to_vector());
813 else
814 return basic_vector<basic_vector<coordinate_type, 2>, 4>(bottom_left().to_vector(), bottom_right().to_vector(), top_right().to_vector(), top_left().to_vector());
815 }
816 const point_type& position() const { return *this; }
817 point_type& position() { return *this; }
818 const size_type& extents() const { return *this; }
819 size_type& extents() { return *this; }
820 coordinate_type left() const { return x; }
821 coordinate_type top() const { if constexpr (gui) return y; else return (y + cy) - epsilon.cy; }
822 coordinate_type right() const { return (x + cx) - epsilon.cx; }
823 coordinate_type bottom() const { if constexpr (gui) return (y + cy) - epsilon.cy; else return y; }
824 point_type top_left() const { return point_type(left(), top(), z); }
825 point_type top_right() const { return point_type(right(), top(), z); }
826 point_type bottom_left() const { return point_type(left(), bottom(), z); }
827 point_type bottom_right() const { return point_type(right(), bottom(), z); }
828 dimension_type width() const { return cx; }
829 dimension_type height() const { return cy; }
830 bool operator==(const basic_rect& other) const { return x == other.x && y == other.y && cx == other.cx && cy == other.cy; }
831 bool operator!=(const basic_rect& other) const { return !operator==(other); }
832 self_type& operator*=(const self_type& other) { position() *= other.position(); extents() *= other.extents(); return *this; }
833 self_type& operator*=(const size_type& size) { position() *= size; extents() *= size; return *this; }
834 self_type& operator*=(dimension_type value) { position() *= value; extents() *= value; return *this; }
835 self_type& operator/=(const basic_rect& other) { position() /= other.position(); extents() /= other.extents(); return *this; }
836 self_type& operator/=(const size_type& size) { position() /= size; extents() /= size; return *this; }
837 self_type& operator/=(dimension_type value) { position() /= value; extents() /= value; return *this; }
838 bool contains_x(const point_type& point) const { return point.x >= left() && point.x < right(); }
839 bool contains_y(const point_type& point) const { if constexpr (gui) return point.y >= top() && point.y < bottom(); else return point.y >= bottom() && point.y < top(); }
840 bool contains(const point_type& point) const { return contains_x(point) && contains_y(point); }
841 bool contains(const self_type& other) const
842 {
843 if constexpr (gui)
844 return other.left() >= left() && other.right() <= right() && other.top() >= top() && other.bottom() <= bottom();
845 else
846 return other.left() >= left() && other.right() <= right() && other.bottom() >= bottom() && other.top() <= top();
847 }
849 {
850 if constexpr (gui)
851 return point_type{ left() + static_cast<coordinate_type>(width()) / two, top() + static_cast<coordinate_type>(height()) / two };
852 else
853 return point_type{ left() + static_cast<coordinate_type>(width()) / two, bottom() + static_cast<coordinate_type>(height()) / two };
854 }
855 self_type& translate(const point_type& aOffset) { x += aOffset.x; y += aOffset.y; return *this; }
856 self_type translated(const point_type& aOffset) const { self_type result = *this; result.x += aOffset.x; result.y += aOffset.y; return result; }
857 self_type& indent(const point_type& aOffset) { x += aOffset.x; y += aOffset.y; cx -= aOffset.x; cy -= aOffset.y; return *this; }
858 self_type& inflate(const delta_type& delta) { x -= delta.dx; y -= delta.dy; cx += delta.dx * two; cy += delta.dy * two; return *this; }
863 template <typename... Args>
864 self_type inflated(Args&&... aArgs) const
865 {
866 auto result = *this;
867 result.inflate(std::forward<Args>(aArgs)...);
868 return result;
869 }
875 template <typename... Args>
876 self_type deflated(Args&&... aArgs) const
877 {
878 auto result = *this;
879 result.deflate(std::forward<Args>(aArgs)...);
880 return result;
881 }
882 template <typename... T>
883 friend self_type inflate_rect(const self_type& aRect, T&&... aAmount)
884 {
885 auto result = aRect;
886 result.inflate(std::forward<T>(aAmount)...);
887 return result;
888 }
889 template <typename... T>
890 friend self_type deflate_rect(const self_type& aRect, T&&... aAmount)
891 {
892 auto result = aRect;
893 result.deflate(std::forward<T>(aAmount)...);
894 return result;
895 }
896 self_type intersection(const self_type& other) const
897 {
898 if constexpr (gui)
899 {
900 self_type candidate{ top_left().max(other.top_left()), bottom_right().min(other.bottom_right()) };
901 if (contains(candidate.center()) && other.contains(candidate.center()))
902 return candidate;
903 else
904 return basic_rect{};
905 }
906 else
907 {
908 self_type candidate{ bottom_left().max(other.bottom_left()), top_right().min(other.top_right()) };
909 if (contains(candidate.center()) && other.contains(candidate.center()))
910 return candidate;
911 else
912 return basic_rect{};
913 }
914 }
915 bool intersects(const self_type& aOther) const
916 {
917 auto const& test = intersection(aOther);
918 return test != basic_rect{};
919 }
921 {
922 *this = centered_on(other);
923 return *this;
924 }
925 self_type centered_on(const self_type other) const
926 {
927 auto result = *this;
928 result.position() += (other.center() - center());
929 return result;
930 }
932 {
933 *this = combined(other);
934 return *this;
935 }
936 self_type combined(const self_type& other) const
937 {
938 if constexpr (gui)
939 return self_type{ top_left().min(other.top_left()), bottom_right().max(other.bottom_right()) };
940 else
941 return self_type{ bottom_left().min(other.bottom_left()), top_right().max(other.top_right()) };
942 }
944 {
945 auto result = *this;
946 result.position().x = p.x;
947 result.position().y = p.y;
948 return result;
949 }
951 {
952 auto result = *this;
953 result.position().x = c;
954 return result;
955 }
957 {
958 auto result = *this;
959 result.position().y = c;
960 return result;
961 }
963 {
964 auto result = *this;
965 result.extents().cx = e.cx;
966 result.extents().cy = e.cy;
967 return result;
968 }
970 {
971 auto result = *this;
972 result.extents().cx = d;
973 return result;
974 }
976 {
977 auto result = *this;
978 result.extents().cy = d;
979 return result;
980 }
982 {
983 return self_type{ point_type{ -extents() / two }, extents() };
984 }
989 {
990 self_type result = *this;
991 result.epsilon = aEpsilon;
992 return result;
993 }
995 {
996 if constexpr (gui)
997 return aabb_2d{ top_left().to_vec2(), bottom_right().to_vec2() };
998 else
999 return aabb_2d{ bottom_left().to_vec2(), top_right().to_vec2() };
1000 }
1006 {
1008 }
1009 public:
1010 template <typename T>
1011 std::enable_if_t<!std::is_same_v<T, coordinate_type>, basic_rect<T, CoordinateSystem>> as() const
1012 {
1013 return basic_rect<T, CoordinateSystem>{ *this };
1014 }
1015 template <typename T>
1016 std::enable_if_t<std::is_same_v<T, coordinate_type>, self_type const&> as() const
1017 {
1018 return *this;
1019 }
1020 public:
1022 };
1023
1026 typedef gui_rect rect;
1027
1028 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1035
1036 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1043
1044 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1051
1052 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1059
1060 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1067
1068 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1075
1076 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1078 {
1080 ret.basic_point<CoordinateType>::operator+=(right);
1081 return ret;
1082 }
1083
1084 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1086 {
1088 ret.basic_size<CoordinateType>::operator+=(right);
1089 return ret;
1090 }
1091
1092 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1094 {
1096 ret.basic_size<CoordinateType>::operator+=(right);
1097 return ret;
1098 }
1099
1100 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1102 {
1104 ret.basic_point<CoordinateType>::operator-=(right);
1105 return ret;
1106 }
1107
1108 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1110 {
1112 ret.basic_size<CoordinateType>::operator-=(right);
1113 return ret;
1114 }
1115
1116 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1118 {
1120 ret.basic_size<CoordinateType>::operator-=(right);
1121 return ret;
1122 }
1123
1124 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1126 {
1127 return std::forward_as_tuple(left.position(), left.extents()) < std::forward_as_tuple(right.position(), right.extents());
1128 }
1129
1130 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1132 {
1133 return left.position() == right.position() && left.extents() == right.extents();
1134 }
1135
1136 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1138 {
1139 return left < right || left == right;
1140 }
1141
1142 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1144 {
1145 return right < left;
1146 }
1147
1148 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1150 {
1151 return right < left || left == right;
1152 }
1153
1154 template <typename CoordinateType, logical_coordinate_system CoordinateSystem>
1156 {
1157 return nearly_equal(lhs.position(), rhs.position(), epsilon) && nearly_equal(lhs.extents(), rhs.extents(), epsilon);
1158 }
1159
1160 template <typename CoordinateType>
1162 {
1163 // types
1164 private:
1165 typedef CoordinateType coordinate_type;
1168 typedef basic_line<coordinate_type> line;
1169 // construction
1170 public:
1171 basic_line(const point_type& a, const point_type& b) : a(a), b(b), d(b - a), m(d.dx != 0 ? d.dy / d.dx : 0), c(a.y - m * a.x) {}
1172 template <typename CoordinateType2>
1174 a(static_cast<point_type>(other.a)), b(static_cast<point_type>(other.b)), d(b - a), m(d.dx != 0 ? d.dy / d.dx : 0), c(a.y - m * a.x) {}
1175 // operations
1176 public:
1177 bool operator==(const basic_line& other) const { return (a == other.a && b == other.b) || (a == other.b & b == other.a); }
1178 bool operator!=(const basic_line& other) const { return !operator==(other); }
1180 {
1181 if (a == this->a)
1182 return *this;
1183 else
1184 return basic_line(this->b, this->a);
1185 }
1186 coordinate_type delta_x() const { return d.dx; }
1187 coordinate_type delta_y() const { return d.dy; }
1188 bool is_vertex(const point_type& v) const { return v == a || v == b; }
1190 {
1191 return p.x >= std::min(a.x, b.x) && p.x <= std::max(a.x, b.x) &&
1192 p.y >= std::min(a.y, b.y) && p.y <= std::max(a.y, b.y);
1193 }
1194 bool intersection(const line& other, point& pointOfIntersection) const
1195 {
1196 if (d.dx == 0 || other.d.dx == 0)
1197 {
1198 if (d.dx == other.d.dx)
1199 return false;
1200 else if (d.dx == 0)
1201 {
1202 pointOfIntersection.x = a.x;
1203 pointOfIntersection.y = other.m * a.x + other.c;
1204 }
1205 else // (other.d.dx == 0)
1206 {
1207 pointOfIntersection.x = other.a.x;
1208 pointOfIntersection.y = m * other.a.x + c;
1209 }
1210 }
1211 else if (d.dy == 0 || other.d.dy == 0)
1212 {
1213 if (d.dy == other.d.dy)
1214 return false;
1215 else if (d.dy == 0)
1216 {
1217 pointOfIntersection.y = a.y;
1218 pointOfIntersection.x = (a.y - other.c) / other.m;
1219 }
1220 else // (other.d.dy == 0)
1221 {
1222 pointOfIntersection.y = other.a.y;
1223 pointOfIntersection.x = (other.a.y - c) / m;
1224 }
1225 }
1226 else
1227 {
1228 if (m == other.m)
1229 return false;
1230 pointOfIntersection.x = (other.c - c) / (m - other.m);
1231 pointOfIntersection.y = pointOfIntersection.x * m + c;
1232 }
1233 return within_bounding_rect(pointOfIntersection) && other.within_bounding_rect(pointOfIntersection);
1234 }
1235 // attributes
1236 public:
1239 private:
1240 delta_type d;
1241 coordinate_type m;
1242 coordinate_type c;
1243 };
1244
1246
1251
1256
1257 template <typename DimensionType>
1259
1260 template <typename DimensionType>
1262
1263 template <typename DimensionType>
1265
1269
1287
1288 template <typename T>
1289 inline basic_point<T> operator*(basic_matrix<T, 3, 3> const& aTransformation, basic_point<T> const& aPoint)
1290 {
1291 return aTransformation * aPoint.to_vec3();
1292 }
1293
1294 template <typename T>
1295 inline basic_size<T> operator*(basic_matrix<T, 3, 3> const& aTransformation, basic_size<T> const& aSize)
1296 {
1297 if (aSize == basic_size<T>::max_size())
1298 return aSize;
1299 return inf_multiply(aTransformation, aSize.to_vec3_inf());
1300 }
1301
1302 template <typename T>
1303 inline basic_rect<T> operator*(basic_matrix<T, 3, 3> const& aTransformation, basic_rect<T> const& aRect)
1304 {
1305 return basic_rect<T>{ basic_point<T>{ aTransformation* aRect.top_left().to_vec3() }, basic_point<T>{ aTransformation * aRect.bottom_right().to_vec3() } };
1306 }
1307
1308 template <typename T>
1309 inline basic_box_areas<T> operator*(basic_matrix<T, 3, 3> const& aTransformation, basic_box_areas<T> const& aBoxAreas)
1310 {
1311 return basic_box_areas<T>{ basic_point<T>{ aTransformation * aBoxAreas.top_left().to_vec3() }, basic_point<T>{ aTransformation * aBoxAreas.bottom_right().to_vec3() } };
1312 }
1313
1314 inline point mix(const point& aLhs, const point& aRhs, double aMixValue)
1315 {
1316 return point{ mix(aLhs.x, aRhs.x, aMixValue), mix(aLhs.y, aRhs.y, aMixValue) };
1317 }
1318
1319 inline vec2 mix(const vec2& aLhs, const vec2& aRhs, double aMixValue)
1320 {
1321 return vec2{ mix(aLhs.x, aRhs.x, aMixValue), mix(aLhs.y, aRhs.y, aMixValue) };
1322 }
1323
1324 inline vec3 mix(const vec3& aLhs, const vec3& aRhs, double aMixValue)
1325 {
1326 return vec3{ mix(aLhs.x, aRhs.x, aMixValue), mix(aLhs.y, aRhs.y, aMixValue), mix(aLhs.z, aRhs.z, aMixValue) };
1327 }
1328
1329 template <typename Elem, typename Traits, typename T>
1330 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const basic_point<T>& aPoint)
1331 {
1332 aStream << "(" << aPoint.x << ", " << aPoint.y << ")";
1333 return aStream;
1334 }
1335
1336 template <typename Elem, typename Traits, typename T>
1337 inline std::basic_istream<Elem, Traits>& operator>>(std::basic_istream<Elem, Traits>& aStream, basic_point<T>& aPoint)
1338 {
1339 auto previousImbued = aStream.getloc();
1340 if (typeid(std::use_facet<std::ctype<char>>(previousImbued)) != typeid(neolib::comma_as_whitespace))
1341 aStream.imbue(std::locale{ previousImbued, new neolib::comma_as_whitespace{} });
1342 char ignore;
1343 aStream >> ignore >> aPoint.x >> aPoint.y >> ignore;
1344 aStream.imbue(previousImbued);
1345 return aStream;
1346 }
1347
1348 template <typename Elem, typename Traits, typename T>
1349 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const basic_size<T>& aSize)
1350 {
1351 aStream << "{" << aSize.cx << ", " << aSize.cy << "}";
1352 return aStream;
1353 }
1354
1355 template <typename Elem, typename Traits, typename T>
1356 inline std::basic_istream<Elem, Traits>& operator>>(std::basic_istream<Elem, Traits>& aStream, basic_size<T>& aSize)
1357 {
1358 auto previousImbued = aStream.getloc();
1359 if (typeid(std::use_facet<std::ctype<char>>(previousImbued)) != typeid(neolib::comma_as_whitespace))
1360 aStream.imbue(std::locale{ previousImbued, new neolib::comma_as_whitespace{} });
1361 char ignore;
1362 aStream >> ignore >> aSize.cx >> aSize.cy >> ignore;
1363 aStream.imbue(previousImbued);
1364 return aStream;
1365 }
1366
1367 template <typename Elem, typename Traits, typename T>
1368 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const basic_delta<T>& aDelta)
1369 {
1370 aStream << "{dx: " << aDelta.dx << ", dy: " << aDelta.dy << "}";
1371 return aStream;
1372 }
1373
1374 template <typename Elem, typename Traits, typename T>
1375 inline std::basic_istream<Elem, Traits>& operator>>(std::basic_istream<Elem, Traits>& aStream, basic_delta<T>& aDelta)
1376 {
1377 auto previousImbued = aStream.getloc();
1378 if (typeid(std::use_facet<std::ctype<char>>(previousImbued)) != typeid(neolib::comma_as_whitespace))
1379 aStream.imbue(std::locale{ previousImbued, new neolib::comma_as_whitespace{} });
1380 std::string ignore;
1381 aStream >> ignore >> aDelta.dx >> ignore >> aDelta.dy >> ignore;
1382 aStream.imbue(previousImbued);
1383 return aStream;
1384 }
1385
1386 template <typename Elem, typename Traits, typename T>
1387 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const basic_rect<T>& aRect)
1388 {
1389 aStream << "[" << aRect.top_left() << " -> " << aRect.bottom_right() << ", " << aRect.extents() << "]";
1390 return aStream;
1391 }
1392
1393 template <typename Elem, typename Traits, typename T>
1394 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const basic_box_areas<T>& aBoxAreas)
1395 {
1396 aStream << "[" << aBoxAreas.top_left() << " -> " << aBoxAreas.bottom_right() << ", " << aBoxAreas.size() << "]";
1397 return aStream;
1398 }
1399
1400 template <typename Elem, typename Traits, typename T>
1401 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const neolib::optional<basic_point<T>>& aPoint)
1402 {
1403 if (aPoint)
1404 return aStream << *aPoint;
1405 aStream << "(nullopt)";
1406 return aStream;
1407 }
1408
1409 template <typename Elem, typename Traits, typename T>
1410 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const neolib::optional<basic_size<T>>& aSize)
1411 {
1412 if (aSize)
1413 return aStream << *aSize;
1414 aStream << "(nullopt)";
1415 return aStream;
1416 }
1417
1418 template <typename Elem, typename Traits, typename T>
1419 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const neolib::optional<basic_delta<T>>& aDelta)
1420 {
1421 if (aDelta)
1422 return aStream << *aDelta;
1423 aStream << "(nullopt)";
1424 return aStream;
1425 }
1426
1427 template <typename Elem, typename Traits, typename T>
1428 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const neolib::optional<basic_rect<T>>& aBoxAreas)
1429 {
1430 if (aBoxAreas)
1431 return aStream << *aBoxAreas;
1432 aStream << "(nullopt)";
1433 return aStream;
1434 }
1435
1436 template <typename Elem, typename Traits, typename T>
1437 inline std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& aStream, const neolib::optional<basic_box_areas<T>>& aRect)
1438 {
1439 if (aRect)
1440 return aStream << *aRect;
1441 aStream << "(nullopt)";
1442 return aStream;
1443 }
1444}
1445
1450
1451namespace std
1452{
1453 template <> struct hash<neogfx::rect>
1454 {
1455 size_t operator()(const neogfx::rect& aRect) const
1456 {
1457 return std::hash<neogfx::rect::coordinate_type>()(aRect.x) ^
1458 std::hash<neogfx::rect::coordinate_type>()(aRect.y) ^
1459 std::hash<neogfx::rect::coordinate_type>()(aRect.cx) ^
1460 std::hash<neogfx::rect::coordinate_type>()(aRect.cy);
1461 }
1462 };
1463}
basic_box_areas(dimension_type all)
dimension_type coordinate_type
self_type with_top(dimension_type d) const
basic_box_areas(const basic_box_areas< DimensionType2 > &other)
basic_box_areas(dimension_type leftRight, dimension_type topBottom)
self_type ceil() const
self_type floor() const
self_type & operator/=(dimension_type amount)
self_type & operator+=(dimension_type amount)
self_type with_right(dimension_type d) const
self_type & operator-=(const self_type &other)
basic_size< dimension_type > size_type
self_type & operator+=(const self_type &other)
size_type size() const
basic_box_areas(const point_type &aTopLeft, const point_type &aBottomRight)
self_type & operator-=(dimension_type amount)
self_type & operator*=(dimension_type amount)
self_type round() const
auto operator<=>(const self_type &) const =default
self_type operator-() const
DimensionType dimension_type
self_type & operator*=(const self_type &other)
self_type with_left(dimension_type d) const
self_type with_bottom(dimension_type d) const
basic_box_areas(const size_type &aDimensions)
basic_box_areas(dimension_type left, dimension_type top, dimension_type right, dimension_type bottom)
point_type top_left() const
self_type & operator/=(const self_type &other)
basic_point< coordinate_type > point_type
point_type bottom_right() const
basic_delta min(const basic_delta &other) const
basic_delta< T > as() const
coordinate_type dy
constexpr basic_delta()
basic_delta operator-() const
basic_delta & operator+=(const basic_delta &other)
basic_delta & operator/=(coordinate_type s)
constexpr basic_delta(coordinate_type dx, coordinate_type dy, coordinate_type dz={})
basic_delta & operator-=(const basic_delta &other)
auto operator<=>(const basic_delta &) const =default
basic_delta floor() const
constexpr basic_delta(const basic_delta< CoordinateType2 > &other)
constexpr basic_delta(coordinate_type aSquareDelta)
basic_delta & operator/=(const basic_delta &other)
basic_delta with_dy(coordinate_type dy) const
basic_delta with_dx(coordinate_type dx) const
basic_delta round() const
coordinate_type dx
CoordinateType coordinate_type
basic_delta & operator-=(coordinate_type s)
basic_vector< coordinate_type, 3 > to_vec3() const
basic_delta ceil() const
coordinate_type magnitude() const
basic_delta abs() const
basic_delta & operator*=(const basic_delta &other)
coordinate_type dz
basic_vector< coordinate_type, 2 > to_vec2() const
basic_delta max(const basic_delta &other) const
basic_delta & operator*=(coordinate_type s)
basic_delta & operator+=(coordinate_type s)
coordinate_type delta_x() const
bool operator==(const basic_line &other) const
basic_line from(const point_type &a) const
basic_line(const point_type &a, const point_type &b)
bool operator!=(const basic_line &other) const
bool within_bounding_rect(const point_type &p) const
bool intersection(const line &other, point &pointOfIntersection) const
coordinate_type delta_y() const
bool is_vertex(const point_type &v) const
basic_line(const basic_line< CoordinateType2 > &other)
constexpr basic_point(const basic_size< CoordinateType > &other)
basic_point mid(const basic_point &other) const
basic_point round() const
basic_point< T > as() const
basic_delta< coordinate_type > to_delta() const
basic_point & operator-=(const basic_size< coordinate_type > &other)
coordinate_type x
basic_point & operator/=(coordinate_type amount)
basic_point & operator/=(const basic_point &other)
basic_point min_max(const basic_point &other) const
basic_point & operator*=(const basic_point &other)
basic_point min(const basic_point &other) const
constexpr basic_point(const basic_point< CoordinateType2 > &other)
basic_point & operator+=(const basic_point &other)
constexpr basic_point()
basic_vector< coordinate_type, 2 > to_vec2() const
coordinate_type z
basic_point max_min(const basic_point &other) const
constexpr basic_point(const basic_delta< CoordinateType > &other)
basic_point & operator*=(coordinate_type amount)
basic_point & operator+=(coordinate_type amount)
basic_point abs() const
constexpr basic_point(const basic_vector< Scalar, 3 > &other)
coordinate_type magnitude() const
basic_point with_z(coordinate_type z0) const
basic_point ceil() const
constexpr basic_point(const basic_vector< Scalar, 2 > &other)
basic_point floor() const
basic_point operator-() const
basic_point & operator+=(const basic_delta< coordinate_type > &other)
constexpr basic_point(CoordinateType x, CoordinateType y, CoordinateType z={})
basic_point with_y(coordinate_type y0) const
basic_point & operator-=(coordinate_type amount)
auto operator<=>(const basic_point &) const =default
coordinate_type y
basic_point & operator-=(const basic_delta< coordinate_type > &other)
basic_point & operator+=(const basic_size< coordinate_type > &other)
basic_point max(const basic_point &other) const
CoordinateType coordinate_type
basic_vector< coordinate_type, 3 > to_vec3() const
basic_size< coordinate_type > to_size() const
basic_point & operator-=(const basic_point &other)
basic_point with_x(coordinate_type x0) const
basic_rect(const point_type &leftCorner, const point_type &rightCorner)
point_type top_left() const
bool operator!=(const basic_rect &other) const
coordinate_type dimension_type
self_type with_x(coordinate_type c) const
self_type floor() const
point_type top_right() const
self_type & deflate(coordinate_type dx, coordinate_type dy)
basic_rect(const size_type &dimensions)
bool contains_x(const point_type &point) const
self_type & operator/=(const basic_rect &other)
CoordinateType coordinate_type
self_type & operator=(const basic_rect< CoordinateType2, CoordinateSystem2 > &other)
self_type ceil() const
point_type & position()
self_type & inflate(coordinate_type dx, coordinate_type dy)
self_type & operator/=(dimension_type value)
self_type & operator*=(const size_type &size)
self_type & operator*=(const self_type &other)
friend self_type deflate_rect(const self_type &aRect, T &&... aAmount)
point_type bottom_left() const
self_type & deflate(const delta_type &delta)
basic_vector< coordinate_type, 4 > to_vec4() const
dimension_type height() const
bool contains_y(const point_type &point) const
self_type round() const
self_type & inflate(const size_type &size)
self_type with_cx(dimension_type d) const
coordinate_type bottom() const
dimension_type width() const
static constexpr coordinate_type one
aabb_2d to_aabb_2d() const
self_type & operator*=(dimension_type value)
static constexpr coordinate_type default_epsilon
self_type & operator/=(const size_type &size)
self_type intersection(const self_type &other) const
bool contains(const self_type &other) const
self_type & operator=(const point_type &coordinates)
self_type with_position(const point_type &p) const
self_type & center_on(const self_type &other)
basic_vector< basic_vector< coordinate_type, 2 >, 4 > to_vector() const
self_type centered_on(const self_type other) const
const point_type & position() const
self_type with_cy(dimension_type d) const
self_type with_y(coordinate_type c) const
self_type with_epsilon(const size_type &aEpsilon=default_epsilon) const
static constexpr bool gui
self_type inflated(Args &&... aArgs) const
self_type & translate(const point_type &aOffset)
self_type & inflate(const padding_type &padding)
point_type bottom_right() const
basic_rect(const point_type &coordinates)
self_type deflated(Args &&... aArgs) const
basic_rect(const basic_box_areas< coordinate_type > &aBoxAreas)
point_type center() const
self_type & operator=(const size_type &dimensions)
basic_rect(const point_type &coordinates, const size_type &dimensions)
friend self_type inflate_rect(const self_type &aRect, T &&... aAmount)
coordinate_type right() const
coordinate_type top() const
bool contains(const point_type &point) const
self_type combined(const self_type &other) const
bool operator==(const basic_rect &other) const
self_type & deflate(const padding_type &padding)
self_type & deflate(const size_type &size)
self_type & deflate(coordinate_type left, coordinate_type top, coordinate_type right, coordinate_type bottom)
self_type translated(const point_type &aOffset) const
self_type with_centered_origin() const
std::enable_if_t< std::is_same_v< T, coordinate_type >, self_type const & > as() const
std::enable_if_t<!std::is_same_v< T, coordinate_type >, basic_rect< T, CoordinateSystem > > as() const
basic_rect(coordinate_type x0, coordinate_type y0, coordinate_type x1, coordinate_type y1)
const size_type & extents() const
coordinate_type left() const
size_type & extents()
basic_rect(const basic_rect< CoordinateType2, CoordinateSystem2 > &other)
self_type & inflate(const delta_type &delta)
self_type with_extents(const size_type &e) const
self_type & indent(const point_type &aOffset)
basic_rect(const aabb_2d &aBoundingBox)
self_type & combine(const self_type &other)
static constexpr bool game
static constexpr coordinate_type zero
bool intersects(const self_type &aOther) const
static constexpr coordinate_type two
self_type & inflate(coordinate_type left, coordinate_type top, coordinate_type right, coordinate_type bottom)
CoordinateType coordinate_type
delta_type to_delta() const
constexpr basic_size(const basic_vector< Scalar, 3 > &other)
basic_size max(const basic_size &other) const
basic_size with_cy(dimension_type d) const
basic_size & operator*=(dimension_type amount)
basic_size & operator-=(const basic_size &other)
static constexpr dimension_type max_dimension()
basic_size aspect_ratio() const
basic_size & operator+=(const basic_size &other)
basic_size operator-() const
basic_size with_cz(dimension_type d) const
basic_size & operator+=(const basic_delta< CoordinateType > &other)
bool cz_inf() const
basic_size with_cx(dimension_type d) const
bool greater_than(const basic_size &other) const
basic_size & operator/=(const basic_size &other)
basic_size ceil() const
constexpr basic_size(const basic_delta< CoordinateType > &other)
basic_vector< dimension_type, 3 > to_vec3() const
constexpr basic_size(const basic_size< CoordinateType2 > &other)
basic_size min(const basic_size &other) const
basic_size & operator-=(const basic_delta< CoordinateType > &other)
constexpr basic_size(const basic_vector< Scalar, 2 > &other)
bool less_than_or_equal(const basic_size &other) const
CoordinateType dimension_type
bool cy_inf() const
bool less_than(const basic_size &other) const
basic_size & operator+=(dimension_type amount)
bool cx_inf() const
auto operator<=>(const basic_size &) const =default
constexpr basic_size()
basic_size & operator/=(dimension_type amount)
basic_vector< dimension_type, 3 > to_vec3_inf() const
dimension_type cz
bool greater_than_or_equal(const basic_size &other) const
basic_delta< dimension_type > delta_type
constexpr basic_size(dimension_type cx, dimension_type cy, dimension_type cz={})
basic_vector< dimension_type, 2 > to_vec2_inf() const
basic_size round() const
static constexpr basic_size max_size()
basic_vector< dimension_type, 2 > to_vec2() const
basic_size with_aspect_ratio_max(const basic_size &aspectRatio) const
dimension_type cy
dimension_type magnitude() const
constexpr basic_size(dimension_type aSquareDimension)
basic_size floor() const
dimension_type cx
basic_size & operator*=(const basic_size &other)
basic_size with_aspect_ratio_min(const basic_size &aspectRatio) const
basic_size< T > as() const
basic_size & operator-=(dimension_type amount)
#define define_setting_type(T)
optional< vector2 > optional_vector2
int32_t coordinate_delta_i32
optional< rect > optional_rect
basic_rect< uint32_t > rect_u32
std::basic_ostream< Elem, Traits > & operator<<(std::basic_ostream< Elem, Traits > &aStream, const basic_point< T > &aPoint)
basic_box_areas< double > box_areas
uint32_t coordinate_delta_u32
logical_coordinate_system
int32_t coordinate_i32
uint32_t dimension_u32
basic_margin< dimension > margin
optional< margin > optional_margin
optional< rect_u32 > optional_rect_u32
optional< delta_u32 > optional_delta_u32
T inf_multiply(T lhs, T rhs)
Definition numerical.hpp:72
basic_delta< CoordinateType > operator/(const basic_delta< CoordinateType > &left, CoordinateType s)
optional< point > optional_point
point mix(const point &aLhs, const point &aRhs, double aMixValue)
bool operator<=(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
default_geometry_value_type dimension
std::basic_istream< Elem, Traits > & operator>>(std::basic_istream< Elem, Traits > &aStream, basic_point< T > &aPoint)
uint32_t coordinate_u32
basic_delta< coordinate > delta
optional< padding > optional_padding
basic_padding< dimension > padding
int32_t dimension_i32
default_geometry_value_type coordinate
basic_point< int32_t > point_i32
bool operator<(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
default_geometry_value_type coordinate_delta
basic_delta< CoordinateType > operator-(const basic_delta< CoordinateType > &left, CoordinateType s)
optional< vector4 > optional_vector4
optional< vector3 > optional_vector3
basic_size< uint32_t > size_u32
basic_rect< coordinate, logical_coordinate_system::AutomaticGui > gui_rect
neolib::optional< logical_coordinates > optional_logical_coordinates
basic_size< int32_t > size_i32
bool operator>=(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
gui_rect rect
optional< size_u32 > optional_size_u32
basic_point< uint32_t > point_u32
optional< delta > optional_delta
bool operator==(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
optional< dimension > optional_dimension
bool operator>(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
basic_line< coordinate > line
bool nearly_equal(basic_delta< CoordinateType > const &lhs, basic_delta< CoordinateType > const &rhs, scalar epsilon=0.00001)
scalar default_geometry_value_type
basic_rect< int32_t > rect_i32
optional< logical_coordinate_system > optional_logical_coordinate_system
optional< size > optional_size
optional< border > optional_border
optional< point_u32 > optional_point_u32
basic_point< coordinate > point
basic_border< dimension > border
optional< angle > optional_angle
basic_delta< CoordinateType > operator*(const basic_delta< CoordinateType > &left, CoordinateType s)
basic_delta< int32_t > delta_i32
basic_rect< coordinate, logical_coordinate_system::AutomaticGame > game_rect
basic_delta< uint32_t > delta_u32
optional< vector1 > optional_vector1
basic_size< coordinate > size
basic_delta< CoordinateType > operator+(const basic_delta< CoordinateType > &left, CoordinateType s)
std::array< vec3, 4 > quad
double scalar
Definition numerical.hpp:63
Definition plf_hive.h:79
static constexpr bool value
static constexpr bool value
logical_coordinates abstract_type
friend bool operator!=(const logical_coordinates &lhs, const logical_coordinates &rhs)
friend bool operator==(const logical_coordinates &lhs, const logical_coordinates &rhs)