roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
box.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4
5#include "roo_logging.h"
6
7namespace roo_display {
8
9/// Axis-aligned integer rectangle.
10///
11/// Coordinates are inclusive: width is `xMax - xMin + 1`.
12class Box {
13 public:
14 /// Result of clipping a box to a clip region.
15 enum class ClipResult { kEmpty = 0, kReduced, kUnchanged };
16
17 [[deprecated("Use `Box::ClipResult::kEmpty` instead.")]]
19 [[deprecated("Use `Box::ClipResult::kReduced` instead.")]]
21 [[deprecated("Use `Box::ClipResult::kUnchanged` instead.")]]
23
24 /// Return the intersection of two boxes (may be empty).
25 inline static Box Intersect(const Box& a, const Box& b) {
26 int16_t xMin = std::max(a.xMin(), b.xMin());
27 int16_t yMin = std::max(a.yMin(), b.yMin());
28 int16_t xMax = std::min(a.xMax(), b.xMax());
29 int16_t yMax = std::min(a.yMax(), b.yMax());
30 return Box(xMin, yMin, xMax, yMax);
31 }
32
33 /// Return the smallest box that contains both input boxes.
34 inline static Box Extent(const Box& a, const Box& b) {
35 int16_t xMin = std::min(a.xMin(), b.xMin());
36 int16_t yMin = std::min(a.yMin(), b.yMin());
37 int16_t xMax = std::max(a.xMax(), b.xMax());
38 int16_t yMax = std::max(a.yMax(), b.yMax());
39 return Box(xMin, yMin, xMax, yMax);
40 }
41
42 /// Construct a box from inclusive coordinates.
43 ///
44 /// If `xMax < xMin` or `yMax < yMin`, the box is made empty.
46 : xMin_(xMin),
47 yMin_(yMin),
48 xMax_(xMax >= xMin ? xMax : xMin - 1),
49 yMax_(yMax >= yMin ? yMax : yMin - 1) {}
50
51 Box(const Box&) = default;
52 Box(Box&&) = default;
53 Box() = default;
54
55 Box& operator=(const Box&) = default;
56 Box& operator=(Box&&) = default;
57
58 /// Return a large sentinel box used for unbounded extents.
59 inline static Box MaximumBox() { return Box(-16384, -16384, 16383, 16383); }
60
61 /// Return whether the box is empty.
62 bool empty() const { return xMax_ < xMin_ || yMax_ < yMin_; }
63
64 /// Minimum x (inclusive).
65 int16_t xMin() const { return xMin_; }
66
67 /// Minimum y (inclusive).
68 int16_t yMin() const { return yMin_; }
69
70 /// Maximum x (inclusive).
71 int16_t xMax() const { return xMax_; }
72
73 /// Maximum y (inclusive).
74 int16_t yMax() const { return yMax_; }
75
76 /// Width in pixels (inclusive coordinates).
77 int16_t width() const { return xMax_ - xMin_ + 1; }
78
79 /// Height in pixels (inclusive coordinates).
80 int16_t height() const { return yMax_ - yMin_ + 1; }
81
82 /// Area in pixels.
83 int32_t area() const { return width() * height(); }
84
85 /// Return whether the point (x, y) lies within the box.
86 bool contains(int16_t x, int16_t y) const {
87 return (x >= xMin_ && x <= xMax_ && y >= yMin_ && y <= yMax_);
88 }
89
90 /// Return whether this box fully contains the other box.
91 bool contains(const Box& other) const {
92 return (other.xMin() >= xMin_ && other.xMax() <= xMax_ &&
93 other.yMin() >= yMin_ && other.yMax() <= yMax_);
94 }
95
96 /// Return whether this box intersects the other box.
97 bool intersects(const Box& other) const {
98 return other.xMin() <= xMax_ && other.xMax() >= xMin_ &&
99 other.yMin() <= yMax_ && other.yMax() >= yMin_;
100 }
101
102 /// Clip this box to the given clip box.
103 ///
104 /// @return Clip result indicating whether the box was reduced or emptied.
105 ClipResult clip(const Box& clip_box) {
107 if (xMin_ < clip_box.xMin()) {
108 xMin_ = clip_box.xMin();
110 }
111 if (xMax_ > clip_box.xMax()) {
112 xMax_ = clip_box.xMax();
114 }
115 if (yMin_ < clip_box.yMin()) {
116 yMin_ = clip_box.yMin();
118 }
119 if (yMax_ > clip_box.yMax()) {
120 yMax_ = clip_box.yMax();
122 }
123 return empty() ? ClipResult::kEmpty : result;
124 }
125
126 /// Return a translated copy of this box.
127 Box translate(int16_t x_offset, int16_t y_offset) const {
128 return Box(xMin_ + x_offset, yMin_ + y_offset, xMax_ + x_offset,
129 yMax_ + y_offset);
130 }
131
132 /// Return a scaled copy of this box.
133 Box scale(int16_t x_scale, int16_t y_scale) const {
134 return Box(xMin_ * x_scale, yMin_ * y_scale, xMax_ * x_scale,
135 yMax_ * y_scale);
136 }
137
138 /// Return a copy with x and y axes swapped.
139 Box swapXY() const { return Box(yMin_, xMin_, yMax_, xMax_); }
140
141 /// Return a copy mirrored across the Y-axis.
142 Box flipX() const { return Box(-xMax_, yMin_, -xMin_, yMax_); }
143
144 /// Return a copy mirrored across the X-axis.
145 Box flipY() const { return Box(xMin_, -yMax_, xMax_, -yMin_); }
146
147 /// Return a copy rotated 180 degrees around the origin.
148 Box rotateUpsideDown() const { return Box(-xMax_, -yMax_, -xMin_, -yMin_); }
149
150 /// Return a copy rotated 90 degrees clockwise around the origin.
151 Box rotateRight() const { return Box(-yMax_, xMin_, -yMin_, xMax_); }
152
153 /// Return a copy rotated 90 degrees counter-clockwise around the origin.
154 Box rotateLeft() const { return Box(yMin_, -xMax_, yMax_, -xMin_); }
155
156 /// Return the minimal box containing this box and the given point.
158 int16_t x_min = std::min(xMin(), x);
159 int16_t y_min = std::min(yMin(), y);
160 int16_t x_max = std::max(xMax(), x);
161 int16_t y_max = std::max(yMax(), y);
162 return Box(x_min, y_min, x_max, y_max);
163 }
164
165 private:
166 int16_t xMin_, yMin_, xMax_, yMax_;
167};
168
169/// Equality operator for boxes.
170inline bool operator==(const Box& a, const Box& b) {
171 return a.xMin() == b.xMin() && a.yMin() == b.yMin() && a.xMax() == b.xMax() &&
172 a.yMax() == b.yMax();
173}
174
175/// Inequality operator for boxes.
176inline bool operator!=(const Box& a, const Box& b) { return !(a == b); }
177
178/// Logging operator for boxes.
179roo_logging::Stream& operator<<(roo_logging::Stream& os, const Box& box);
180
181/// Logging operator for box clip results.
182roo_logging::Stream& operator<<(roo_logging::Stream& os,
183 Box::ClipResult clip_result);
184
185} // namespace roo_display
186
187#if defined(__linux__) || defined(__linux) || defined(linux)
188
189// Unit testing support.
190
191#include <ostream>
192
193namespace roo_display {
194inline std::ostream& operator<<(std::ostream& os, const roo_display::Box& box) {
195 os << "[" << box.xMin() << ", " << box.yMin() << ", " << box.xMax() << ", "
196 << box.yMax() << "]";
197 return os;
198}
199} // namespace roo_display
200#endif // defined(__linux__)
Axis-aligned integer rectangle.
Definition box.h:12
Box rotateRight() const
Return a copy rotated 90 degrees clockwise around the origin.
Definition box.h:151
int16_t width() const
Width in pixels (inclusive coordinates).
Definition box.h:77
Box rotateUpsideDown() const
Return a copy rotated 180 degrees around the origin.
Definition box.h:148
static constexpr ClipResult CLIP_RESULT_EMPTY
Definition box.h:18
ClipResult
Result of clipping a box to a clip region.
Definition box.h:15
int16_t xMin() const
Minimum x (inclusive).
Definition box.h:65
static constexpr ClipResult CLIP_RESULT_UNCHANGED
Definition box.h:22
int16_t xMax() const
Maximum x (inclusive).
Definition box.h:71
bool empty() const
Return whether the box is empty.
Definition box.h:62
static Box MaximumBox()
Return a large sentinel box used for unbounded extents.
Definition box.h:59
int16_t height() const
Height in pixels (inclusive coordinates).
Definition box.h:80
Box & operator=(Box &&)=default
Box scale(int16_t x_scale, int16_t y_scale) const
Return a scaled copy of this box.
Definition box.h:133
Box translate(int16_t x_offset, int16_t y_offset) const
Return a translated copy of this box.
Definition box.h:127
bool contains(int16_t x, int16_t y) const
Return whether the point (x, y) lies within the box.
Definition box.h:86
Box & operator=(const Box &)=default
Box extend(int16_t x, int16_t y)
Return the minimal box containing this box and the given point.
Definition box.h:157
constexpr Box(int16_t xMin, int16_t yMin, int16_t xMax, int16_t yMax)
Construct a box from inclusive coordinates.
Definition box.h:45
ClipResult clip(const Box &clip_box)
Clip this box to the given clip box.
Definition box.h:105
int16_t yMax() const
Maximum y (inclusive).
Definition box.h:74
Box(const Box &)=default
static constexpr ClipResult CLIP_RESULT_REDUCED
Definition box.h:20
Box flipX() const
Return a copy mirrored across the Y-axis.
Definition box.h:142
Box swapXY() const
Return a copy with x and y axes swapped.
Definition box.h:139
bool intersects(const Box &other) const
Return whether this box intersects the other box.
Definition box.h:97
Box rotateLeft() const
Return a copy rotated 90 degrees counter-clockwise around the origin.
Definition box.h:154
int32_t area() const
Area in pixels.
Definition box.h:83
static Box Extent(const Box &a, const Box &b)
Return the smallest box that contains both input boxes.
Definition box.h:34
bool contains(const Box &other) const
Return whether this box fully contains the other box.
Definition box.h:91
static Box Intersect(const Box &a, const Box &b)
Return the intersection of two boxes (may be empty).
Definition box.h:25
Box(Box &&)=default
Box flipY() const
Return a copy mirrored across the X-axis.
Definition box.h:145
int16_t yMin() const
Minimum y (inclusive).
Definition box.h:68
Defines 140 opaque HTML named colors.
constexpr bool operator==(const Color &a, const Color &b)
Equality operator for colors.
Definition color.h:99
constexpr bool operator!=(const Color &a, const Color &b)
Inequality operator for colors.
Definition color.h:104
roo_logging::Stream & operator<<(roo_logging::Stream &os, BlendingMode mode)
Definition blending.cpp:54