TGX 1.0.3
A tiny 2D/3D graphics library optimized for 32 bits microcontrollers.
Loading...
Searching...
No Matches
Box2.h
Go to the documentation of this file.
1
5//
6// Copyright 2020 Arvind Singh
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Lesser General Public
10// License as published by the Free Software Foundation; either
11//version 2.1 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
16// Lesser General Public License for more details.
17//
18// You should have received a copy of the GNU Lesser General Public
19// License along with this library; If not, see <http://www.gnu.org/licenses/>.
20
21#ifndef _TGX_BOX2_H_
22#define _TGX_BOX2_H_
23
24// only C++, no plain C
25#ifdef __cplusplus
26
27
28#include "Misc.h"
29#include "Vec2.h"
30
31#include <type_traits>
32#include <stdint.h>
33
34namespace tgx
35{
36
37
38 // Forward declaration
39
40 template<typename T> struct Box2;
41
42
43 // Specializations
44
45 typedef Box2<int> iBox2;
46
48
50
51
52
73 enum Anchor
74 {
75 CENTER = 0,
76 LEFT = 1,
77 RIGHT = 2,
78 TOP = 4,
79 BOTTOM = 8,
80 BASELINE = 16,
90 };
91
92
94 inline constexpr Anchor operator|(Anchor a1, Anchor a2) { return ((Anchor)((int)a1 | (int)a2)); }
95
97 inline Anchor& operator|=(Anchor& a1, Anchor a2) { a1 = a1 | a2; return a1; }
98
100 inline constexpr Anchor operator&(Anchor a1, Anchor a2) { return ((Anchor)((int)a1 & (int)a2)); }
101
103 inline Anchor& operator&=(Anchor& a1, Anchor a2) { a1 = a1 & a2; return a1; }
104
105
106
109 {
110 SPLIT_LEFT = Anchor::LEFT,
111 SPLIT_RIGHT = Anchor::RIGHT,
112 SPLIT_TOP = Anchor::TOP,
113 SPLIT_BOTTOM = Anchor::BOTTOM,
114 SPLIT_TOPLEFT = Anchor::TOPLEFT,
115 SPLIT_TOPRIGHT = Anchor::TOPRIGHT,
116 SPLIT_BOTTOMLEFT = Anchor::BOTTOMLEFT,
117 SPLIT_BOTTOMRIGHT = Anchor::BOTTOMRIGHT
118 };
119
120
122 inline constexpr BoxSplit operator|(BoxSplit a1, BoxSplit a2) { return ((BoxSplit)((int)a1 | (int)a2)); }
123
125 inline BoxSplit& operator|=(BoxSplit& a1, BoxSplit a2) { a1 = a1 | a2; return a1; }
126
128 inline constexpr BoxSplit operator&(BoxSplit a1, BoxSplit a2) { return ((BoxSplit)((int)a1 & (int)a2)); }
129
131 inline BoxSplit& operator&=(BoxSplit& a1, BoxSplit a2) { a1 = a1 & a2; return a1; }
132
133
134
135
150 template<typename T> struct Box2
151 {
152
153 // mtools extension (if available).
154 #if (MTOOLS_TGX_EXTENSIONS)
155 #include <mtools/extensions/tgx/tgx_ext_Box2.inl>
156 #endif
157
158
159 // box dimension: [minX, maxX] x [minY, maxY]
160
165
166
170 constexpr Box2()
171 {
172 }
173
174
178 constexpr Box2(const T minx, const T maxx, const T miny, const T maxy) : minX(minx), maxX(maxx), minY(miny), maxY(maxy)
179 {
180 }
181
182
186 constexpr Box2(const Vec2<T>& P) : minX(P.x), maxX(P.x), minY(P.y), maxY(P.y)
187 {
188 }
189
190
194 Box2(const Box2<T>& B) = default;
195
196
200 Box2<T>& operator=(const Box2<T>& B) = default;
201
202
206 template<typename U>
207 explicit operator Box2<U>() { return Box2<U>((U)minX, (U)maxX, (U)minY, (U)maxY); }
208
209
213 operator Box2<typename DefaultFPType<T>::fptype>() { return Box2<typename DefaultFPType<T>::fptype>((typename DefaultFPType<T>::fptype)minX, (typename DefaultFPType<T>::fptype)maxX, (typename DefaultFPType<T>::fptype)minY, (typename DefaultFPType<T>::fptype)maxY); }
214
215
219 constexpr inline bool isEmpty() const { return ((maxX < minX) || (maxY < minY)); }
220
221
225 void empty()
226 {
227 minX = (T)1;
228 maxX = (T)0;
229 minY = (T)1;
230 maxY = (T)0;
231 }
232
233
242 inline T lx() const
243 {
244 if (std::is_integral<T>::value) // compiler optimize this away.
245 {
246 return (maxX - minX + 1); // for integer, return the number of points
247 }
248 else
249 {
250 return (maxX - minX); // for floating point type, return maxX - minX.
251 }
252 }
253
254
263 inline T ly() const
264 {
265 if (std::is_integral<T>::value) // compiler optimize this away.
266 {
267 return (maxY - minY + 1); // for integer, return the number of points
268 }
269 else
270 {
271 return (maxY - minY); // for floating point type, return maxX - minX.
272 }
273 }
274
275
283 inline bool equals(const Box2<T>& B) const
284 {
285 if (isEmpty()) { return B.isEmpty(); }
286 return ((minX == B.minX) && (maxX == B.maxX) && (minY == B.minY) && (maxY == B.maxY));
287 }
288
289
297 inline bool operator==(const Box2<T>& B) const
298 {
299 return equals(B);
300 }
301
302
306 inline bool contains(const Vec2<T>& v) const
307 {
308 return(((minX <= v.x) && (v.x <= maxX)) && ((minY <= v.y) && (v.y <= maxY)));
309 }
310
311
319 inline bool contains(const Box2<T>& B) const
320 {
321 if (isEmpty()) return false;
322 if (B.isEmpty()) return true;
323 return ((minX <= B.minX) && (maxX >= B.maxX) && (minY <= B.minY) && (maxY >= B.maxY));
324 }
325
326
336 inline bool operator>=(const Box2<T>& B) const
337 {
338 return contains(B);
339 }
340
341
351 inline bool operator<=(const Box2<T>& B) const
352 {
353 return B.contains(*this);
354 }
355
356
364 inline bool operator>(const Box2<T>& B) const
365 {
366 return ((contains(B)) && (!equals(B)));
367 }
368
369
377 inline bool operator<(const Box2<T>& B) const
378 {
379 return ((B.contains(*this)) && (!B.equals(*this)));
380 }
381
382
386 inline Box2<T> operator&(const Box2<T>& B) const
387 {
388 Box2<T> R;
389 if (isEmpty())
390 {
391 R = *this;
392 }
393 else if (B.isEmpty())
394 {
395 R = B;
396 }
397 else
398 {
399 R.minX = max(minX, B.minX);
400 R.maxX = min(maxX, B.maxX);
401 R.minY = max(minY, B.minY);
402 R.maxY = min(maxY, B.maxY);
403 }
404 return R;
405 }
406
407
411 inline void operator&=(const Box2<T>& B)
412 {
413 (*this) = ((*this) & B);
414 }
415
416
420 inline Box2<T> operator|(const Box2<T>& B) const
421 {
422 Box2<T> R;
423 if (isEmpty())
424 {
425 R = B;
426 }
427 else if (B.isEmpty())
428 {
429 R = (*this);
430 }
431 else
432 {
433 R.minX = min(minX, B.minX);
434 R.maxX = max(maxX, B.maxX);
435 R.minY = min(minY, B.minY);
436 R.maxY = max(maxY, B.maxY);
437 }
438 return R;
439 }
440
441
445 inline void operator|=(const Box2<T>& B)
446 {
447 *this = (*this) | B;
448 }
449
450
454 inline Box2<T> operator|(const Vec2<T>& v) const
455 {
456 Box2<T> R;
457 if (isEmpty())
458 {
459 R.minX = R.maxX = v.x;
460 R.minY = R.maxY = v.y;
461 }
462 else
463 {
464 R.minX = min(minX, v.x);
465 R.maxX = max(maxX, v.x);
466 R.minY = min(minY, v.y);
467 R.maxY = max(maxY, v.y);
468 }
469 return R;
470 }
471
472
476 inline void operator|=(const Vec2<T>& v)
477 {
478 (*this) = (*this) | v;
479 }
480
481
485 inline void operator+=(const Vec2<T> & V)
486 {
487 minX += V.x;
488 maxX += V.x;
489 minY += V.y;
490 maxY += V.y;
491 }
492
493
497 inline Box2<T> operator+(const Vec2<T> & V) const
498 {
499 return Box2<T>(minX + V.x, maxX + V.x, minY + V.y, maxY + V.y);
500 }
501
502
506 inline void operator-=(const Vec2<T> & V)
507 {
508 minX -= V.x;
509 maxX -= V.x;
510 minY -= V.y;
511 maxY -= V.y;
512 }
513
514
518 inline Box2<T> operator-(const Vec2<T> & V) const
519 {
520 return Box2<T>(minX - V.x, maxX - V.x, minY - V.y, maxY - V.y);
521 }
522
523
531 inline void split(BoxSplit part)
532 {
533 *this = getSplit(part);
534 }
535
536
545 {
546 const T midX = (minX + maxX)/2;
547 const T midY = (minY + maxY)/2;
548 switch (part)
549 {
550 case SPLIT_TOP: { return Box2<T>(minX, maxX, midY, maxY); }
551 case SPLIT_BOTTOM: { return Box2<T>(minX, maxX, minY, midY); }
552 case SPLIT_LEFT: { return Box2<T>(minX, midX, minY, maxY); }
553 case SPLIT_RIGHT: { return Box2<T>(midX, maxX, minY, maxY); }
554 case SPLIT_TOPLEFT: { return Box2<T>(minX, midX, midY, maxY); }
555 case SPLIT_TOPRIGHT: { return Box2<T>(midX, maxX, midY, maxY); }
556 case SPLIT_BOTTOMLEFT: { return Box2<T>(minX, midX, minY, midY); }
557 case SPLIT_BOTTOMRIGHT: { return Box2<T>(midX, maxX, minY, midY); }
558 }
559 return *this;
560 }
561
562
568 Vec2<T> getAnchor(Anchor anchor_pos) const
569 {
570 anchor_pos &= (CENTER | LEFT | RIGHT | TOP | BOTTOM); // remove baseline flag
571 switch (anchor_pos)
572 {
573 case TOPLEFT: return Vec2<T>(minX, minY);
574 case TOPRIGHT: return Vec2<T>(maxX, minY);
575 case BOTTOMLEFT: return Vec2<T>(minX, maxY);
576 case BOTTOMRIGHT: return Vec2<T>(maxX, maxY);
577 case CENTER: return Vec2<T>((minX + maxX) / 2, (minY + maxY) / 2);
578 case CENTERLEFT: return Vec2<T>(minX, (minY + maxY) / 2);
579 case CENTERRIGHT: return Vec2<T>(maxX, (minY + maxY) / 2);
580 case CENTERTOP: return Vec2<T>((minX + maxX) / 2, minY);
581 case CENTERBOTTOM: return Vec2<T>((minX + maxX) / 2, maxY);
582 default: break;
583 }
584 return Vec2<T>((minX + maxX) / 2, (minY + maxY) / 2); // unknown pos returns center.
585 }
586
587
592 {
593 return Vec2<T>((minX + maxX) / 2, (minY + maxY) / 2);
594 }
595
596
605 template<typename Tfloat = DefaultFPType<T> > inline Tfloat ratio() const
606 {
607 if (isEmpty()) return (Tfloat)(-1);
608 return ((Tfloat)(lx())) / ((Tfloat)(ly()));
609 }
610
611
617 void zoomOut()
618 {
619 const T u = lx() / 10;
620 minX -= u;
621 maxX += u;
622 const T v = ly() / 10;
623 minY -= v;
624 maxY += v;
625 }
626
627
633 void zoomIn()
634 {
635 const T u = lx() / 8;
636 minX += u;
637 maxX -= u;
638 const T v = ly() / 8;
639 minY += v;
640 maxY -= v;
641 }
642
643
649 void left()
650 {
651 const T u = lx() / 10;
652 minX -= u;
653 maxX -= u;
654 }
655
656
662 void right()
663 {
664 const T u = lx() / 10;
665 minX += u;
666 maxX += u;
667 }
668
669
675 void up()
676 {
677 const T v = ly() / 10;
678 minY -= v;
679 maxY -= v;
680 }
681
682
688 void down()
689 {
690 const T v = ly() / 10;
691 minY += v;
692 maxY += v;
693 }
694
695
702
703
710
711
712 };
713
714
715
716
717
718 template<typename T> Box2<T> Box2<T>::getEnclosedWithSameRatioAs(const Box2<T> & B) const
719 {
720 Box2<T> C;
721 if (ratio() < B.ratio())
722 {
723 C.minX = 0;
724 C.maxX = maxX - minX;
725 T ll = (T)(lx() / B.ratio());
726 C.minY = (ly() - ll) / 2;
727 C.maxY = C.minY + ll - (std::is_integral<T>::value ? 1 : 0);
728 }
729 else
730 {
731 C.minY = 0;
732 C.maxY = maxY - minY;
733 T ll = (T)(ly() * B.ratio());
734 C.minX = (lx() - ll) / 2;
735 C.maxX = C.minX + ll - (std::is_integral<T>::value ? 1 : 0);
736 }
737 return C;
738 }
739
740
741 template<typename T> Box2<T> Box2<T>::getEnclosingWithSameRatioAs(const Box2<T> & B) const
742 {
743 Box2<T> C;
744 if (ratio() > B.ratio())
745 {
746 C.minX = 0;
747 C.maxX = maxX - minX;
748 T ll = (T)(lx() / B.ratio());
749 C.minY = (ly() - ll) / 2;
750 C.maxY = C.minY + ll - (std::is_integral<T>::value ? 1 : 0);
751 }
752 else
753 {
754 C.minY = 0;
755 C.maxY = maxY - minY;
756 T ll = (T)(ly() * B.ratio());
757 C.minX = (lx() - ll) / 2;
758 C.maxX = C.minX + ll - (std::is_integral<T>::value ? 1 : 0);
759 }
760 return C;
761 }
762
763
764}
765
766
767#endif
768
769#endif
770
Anchor & operator|=(Anchor &a1, Anchor a2)
Enable bitwise |= operator for enum Anchor.
Definition: Box2.h:97
constexpr Anchor operator|(Anchor a1, Anchor a2)
Enable bitwise | operator for enum Anchor.
Definition: Box2.h:94
constexpr Anchor operator&(Anchor a1, Anchor a2)
Enable bitwise & operator for enum Anchor.
Definition: Box2.h:100
BoxSplit
Splitting of a box in half and quarters.
Definition: Box2.h:109
@ SPLIT_RIGHT
right half
Definition: Box2.h:111
@ SPLIT_BOTTOMRIGHT
bottom right quarter
Definition: Box2.h:117
@ SPLIT_BOTTOM
bottom half
Definition: Box2.h:113
@ SPLIT_TOPRIGHT
top right quarter
Definition: Box2.h:115
@ SPLIT_BOTTOMLEFT
bottom left quarter
Definition: Box2.h:116
@ SPLIT_LEFT
left half
Definition: Box2.h:110
@ SPLIT_TOPLEFT
top left quarter
Definition: Box2.h:114
@ SPLIT_TOP
top half
Definition: Box2.h:112
Anchor & operator&=(Anchor &a1, Anchor a2)
Enable bitwise &= operator for enum Anchor.
Definition: Box2.h:103
Anchor
Define the placement of an anchor point inside a box.
Definition: Box2.h:74
@ BASELINE
Baseline height (vertical alignement). only makes sense with a font (when drawing text),...
Definition: Box2.h:80
@ BOTTOMRIGHT
Bottom-right corner.
Definition: Box2.h:84
@ CENTERRIGHT
center point on the right side
Definition: Box2.h:86
@ TOPLEFT
Top-left corner.
Definition: Box2.h:81
@ TOPRIGHT
Top-right corner.
Definition: Box2.h:82
@ CENTERLEFT
center point on the left side
Definition: Box2.h:85
@ BOTTOM
Bottom side (vertical alignement)
Definition: Box2.h:79
@ CENTER
Center (vertical/horizontal alignement). This is the default placement if not specitified.
Definition: Box2.h:75
@ RIGHT
Right side (horizontal alignement)
Definition: Box2.h:77
@ CENTERBOTTOM
center point on the bottom side
Definition: Box2.h:88
@ BOTTOMLEFT
bottom-left corner
Definition: Box2.h:83
@ CENTERTOP
center point on the top side
Definition: Box2.h:87
@ DEFAULT_TEXT_ANCHOR
Default location for text anchoring.
Definition: Box2.h:89
@ TOP
Top side (vertical alignement)
Definition: Box2.h:78
@ LEFT
Left side (horizontal alignement)
Definition: Box2.h:76
Utility/miscellaneous functions used throughout the library.
TGX_INLINE T min(const T &a, const T &b)
Don't know why but faster than fminf() for floats.
Definition: Misc.h:180
TGX_INLINE T max(const T &a, const T &b)
Don't know why but much faster than fmaxf() for floats.
Definition: Misc.h:184
2D vector.
Generic 2D Box [specializations iBox2 , fBox2, dBox2].
Definition: Box2.h:151
bool equals(const Box2< T > &B) const
Return true if the boxes are equal.
Definition: Box2.h:283
Box2(const Box2< T > &B)=default
default copy constructor.
Box2< T > operator&(const Box2< T > &B) const
Return the intersection of this box and B.
Definition: Box2.h:386
T maxY
max vertical (Y) value (inclusive)
Definition: Box2.h:164
constexpr Box2()
default constructor: the box content is undefined.
Definition: Box2.h:170
void split(BoxSplit part)
Split the box in half or quarter.
Definition: Box2.h:531
bool operator==(const Box2< T > &B) const
Return true if the boxes are equal.
Definition: Box2.h:297
constexpr Box2(const T minx, const T maxx, const T miny, const T maxy)
Constructor with explicit dimensions.
Definition: Box2.h:178
Box2< T > operator+(const Vec2< T > &V) const
Return this box translated by vector v.
Definition: Box2.h:497
void operator-=(const Vec2< T > &V)
Translate the box by a given vector (substracted)
Definition: Box2.h:506
void left()
Move the box to the left by 1/10th of its width.
Definition: Box2.h:649
Box2< T > getSplit(BoxSplit part) const
Return the box splitted in half or quater.
Definition: Box2.h:544
void down()
Move the box down by 1/10th of its height.
Definition: Box2.h:688
Vec2< T > getAnchor(Anchor anchor_pos) const
Return the position of an anchor point inside this box.
Definition: Box2.h:568
void up()
Move the box up by 1/10th of its height.
Definition: Box2.h:675
Box2< T > operator-(const Vec2< T > &V) const
Return this box translated by v (substracted).
Definition: Box2.h:518
bool operator>(const Box2< T > &B) const
Return true if B is strictly included in this box (i.e.
Definition: Box2.h:364
T ly() const
Return the box height.
Definition: Box2.h:263
Tfloat ratio() const
Return the aspect ratio of the box lx()/ly().
Definition: Box2.h:605
bool operator<(const Box2< T > &B) const
Return true if this box is strictly included inside B (i.e.
Definition: Box2.h:377
Box2< T > getEnclosedWithSameRatioAs(const Box2< T > &B) const
Return the largest box with the same ratio() as box B that is centered and enclosed inside this box.
Definition: Box2.h:718
bool operator>=(const Box2< T > &B) const
Return true if B is included in this box.
Definition: Box2.h:336
bool operator<=(const Box2< T > &B) const
Return true if this box is included in B.
Definition: Box2.h:351
void zoomOut()
Zoom outside the box (ie increase its size by 1/10th).
Definition: Box2.h:617
T maxX
max horizontal (X) value (inclusive)
Definition: Box2.h:162
void empty()
Make the box empty.
Definition: Box2.h:225
constexpr bool isEmpty() const
Return true if the box is empty.
Definition: Box2.h:219
T lx() const
Return the box width.
Definition: Box2.h:242
T minX
min horizontal (X) value (inclusive)
Definition: Box2.h:161
Vec2< T > center() const
Return the position of the box center as a 2 dimensional vector.
Definition: Box2.h:591
bool contains(const Vec2< T > &v) const
Return true if the box contains the point v.
Definition: Box2.h:306
Box2< T > operator|(const Vec2< T > &v) const
Return the smallest box containing this box and point v.
Definition: Box2.h:454
Box2< T > operator|(const Box2< T > &B) const
Return the smallest box containing both this box and B.
Definition: Box2.h:420
void operator|=(const Vec2< T > &v)
Enlarge this box in order to contain point v.
Definition: Box2.h:476
Box2< T > getEnclosingWithSameRatioAs(const Box2< T > &B) const
Return the smallest box with the same ratio() as box B that contains this box in its center.
Definition: Box2.h:741
bool contains(const Box2< T > &B) const
Return true if B is included in this box.
Definition: Box2.h:319
void right()
Move the box to the right by 1/10th of its width.
Definition: Box2.h:662
void operator+=(const Vec2< T > &V)
Translate this box by a given vector.
Definition: Box2.h:485
Box2< T > & operator=(const Box2< T > &B)=default
default assignement operator.
void zoomIn()
Zoom inside the box (ie decrease its size by 1/8th).
Definition: Box2.h:633
void operator|=(const Box2< T > &B)
Enlarge this box in order to contain B.
Definition: Box2.h:445
T minY
min vertical (Y) value (inclusive)
Definition: Box2.h:163
constexpr Box2(const Vec2< T > &P)
Construct a box representing a single point.
Definition: Box2.h:186
void operator&=(const Box2< T > &B)
Intersect this box with box B.
Definition: Box2.h:411
Generic 2D vector [specializations iVec2, fVec2, dVec2].
Definition: Vec2.h:64
T x
'x' coordinate (first dimension)
Definition: Vec2.h:72
T y
'y' coordinate (second dimension)
Definition: Vec2.h:73