32 glm::tvec2<T> p1 = { 0,0 };
33 glm::tvec2<T> p2 = { 0,0 };
35 using tvec = glm::tvec2<T>;
38 constexpr trec2()
noexcept =
default;
39 constexpr trec2(tvec a, tvec b) noexcept : p1(a), p2(b) {}
40 explicit constexpr trec2(span<tvec const> points)
noexcept
42 *
this = trec2::exclusive();
43 for (
auto& p : points)
47 template <GHPL_TYPENAME(std::same_as<tvec>)... ARGS>
48 explicit constexpr trec2(bounding_box_for_t, ARGS&&... args)
noexcept
50 *
this = trec2::exclusive();
51 (this->include(std::forward<ARGS>(args)), ...);
54 constexpr explicit trec2(tvec a) noexcept : p1(), p2(a) {}
55 constexpr trec2(T x1, T y1, T x2, T y2) noexcept : p1(x1, y1), p2(x2, y2) {}
56 constexpr trec2(
const trec2&)
noexcept =
default;
57 constexpr trec2(trec2&&)
noexcept =
default;
59 constexpr explicit trec2(
const trec2<U>& other) noexcept : p1(glm::tvec2<U>(other.p1)), p2(glm::tvec2<U>(other.p2)) {}
61 constexpr explicit trec2(trec2<U>&& other) noexcept : p1(glm::tvec2<U>(other.p1)), p2(glm::tvec2<U>(other.p2)) {}
63 constexpr trec2& operator=(
const trec2&)
noexcept =
default;
64 constexpr trec2& operator=(trec2&&)
noexcept =
default;
66 static constexpr trec2 from_points(span<tvec const> points)
noexcept {
return trec2{ points }; }
67 template <GHPL_TYPENAME(std::same_as<tvec>)... ARGS>
68 static constexpr trec2 from_points(ARGS&&... args)
noexcept {
return trec2(bounding_box_for, std::forward<ARGS>(args)...); }
69 static constexpr trec2 from_size(tvec s)
noexcept {
return { tvec{}, s }; };
70 static constexpr trec2 from_size(tvec p, tvec s)
noexcept {
return { p, p + s }; };
71 static constexpr trec2 from_size(T x, T y, T w, T h)
noexcept {
return { x, y, x + w, y + h }; };
72 static constexpr trec2 from_center_and_size(tvec p, tvec s)
noexcept {
return { p - s / T(2), p + s / T(2) }; };
73 static constexpr trec2 from_center_and_size(T x, T y, T w, T h)
noexcept {
return { x - w / T(2), y - h / T(2), x + w / T(2), y + h / T(2) }; };
74 static constexpr trec2 from_center_and_half_size(tvec p, tvec s)
noexcept {
return { p - s, p + s }; };
75 static constexpr trec2 from_center_and_half_size(T x, T y, T w, T h)
noexcept {
return { x - w, y - h, x + w, y + h }; };
77 static constexpr trec2 invalid()
noexcept {
return { T{1}, T{1}, T{-1}, T{-1} }; };
78 static constexpr trec2 exclusive()
noexcept
80 if constexpr (std::numeric_limits<T>::has_infinity)
81 return { std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity() };
83 return { std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest() };
86 static constexpr trec2 inclusive()
noexcept
88 if constexpr (std::numeric_limits<T>::has_infinity)
89 return { -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity() };
91 return { std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() };
94 constexpr trec2 operator+(tvec
op)
const noexcept {
return { p1 +
op, p2 +
op }; }
95 constexpr trec2& operator+=(tvec
op)
noexcept { p1 +=
op; p2 +=
op;
return *
this; };
96 constexpr trec2 operator-(tvec
op)
const noexcept {
return { p1 -
op, p2 -
op }; }
97 constexpr trec2& operator-=(tvec
op)
noexcept { p1 -=
op; p2 -=
op;
return *
this; };
98 constexpr trec2 operator*(T
op)
const noexcept {
return { p1 *
op, p2 *
op }; }
99 constexpr trec2 operator/(T
op)
const noexcept {
return { p1 /
op, p2 /
op }; }
100 constexpr trec2 operator*(tvec
op)
const noexcept {
return { p1 *
op, p2 *
op }; }
101 constexpr trec2 operator/(tvec
op)
const noexcept {
return { p1 /
op, p2 /
op }; }
103 constexpr bool operator==(trec2
const& other)
const noexcept {
return p1 == other.p1 && p2 == other.p2; }
112 case 1:
return right_top();
114 case 3:
return left_bottom();
119#ifdef __cpp_explicit_this_parameter
121 template <
typename U> values_t(U&& left, U&& top, U&& right, U&& bottom) -> values_t<U>;
122 template <
typename SELF>
123 constexpr auto values(
this SELF&& self)
noexcept
126 std::forward_like<SELF>(self.p1.x),
127 std::forward_like<SELF>(self.p1.y),
128 std::forward_like<SELF>(self.p2.x),
129 std::forward_like<SELF>(self.p2.y)
134 constexpr tvec size() const noexcept {
return p2 - p1; }
135 constexpr tvec position() const noexcept {
return p1; }
136 constexpr trec2& set_position(tvec pos)
noexcept { p2 += pos - p1; p1 = pos;
return *
this; }
137 constexpr trec2& set_position(T x, T y)
noexcept { p2.x += x - p1.x; p2.y += y - p1.y; p1 = { x, y };
return *
this; }
138 constexpr trec2& set_x(T x)
noexcept { p2.x += x - p1.x; p1.x = x;
return *
this; }
139 constexpr trec2& set_y(T y)
noexcept { p2.y += y - p1.y; p1.y = y;
return *
this; }
140 constexpr trec2& set_size(tvec size)
noexcept { p2 = p1 + size;
return *
this; }
141 constexpr trec2& set_size(T w, T h)
noexcept { p2.x = p1.x + w; p2.y = p1.y + h;
return *
this; }
143 constexpr trec2& grow(T by)
noexcept { p1.x -= by; p1.y -= by; p2.x += by; p2.y += by;
return *
this; }
144 constexpr trec2& shrink(T by)
noexcept {
return grow(-by); }
145 constexpr trec2& grow(tvec by)
noexcept { p1 -= by; p2 += by;
return *
this; }
146 constexpr trec2& shrink(tvec by)
noexcept {
return grow(-by); }
147 constexpr trec2 grown(T by)
const noexcept {
auto copy = *
this; copy.p1.x -= by; copy.p1.y -= by; copy.p2.x += by; copy.p2.y += by;
return copy; }
148 constexpr trec2 shrunk(T by)
const noexcept {
return grown(-by); }
149 constexpr trec2 grown(tvec by)
const noexcept {
auto copy = *
this; copy.p1 -= by; copy.p2 += by;
return copy; }
150 constexpr trec2 shrunk(tvec by)
const noexcept {
return grown(-by); }
151 constexpr trec2& grow(T left, T top, T right, T bottom)
noexcept { p1.x -= left; p1.y -= top; p2.x += right; p2.y += bottom;
return *
this; }
152 constexpr trec2& shrink(T left, T top, T right, T bottom)
noexcept {
return grow(-left, -top, -right, -bottom); }
153 constexpr trec2 grown(T left, T top, T right, T bottom)
const noexcept {
auto copy = *
this; copy.p1.x -= left; copy.p1.y -= top; copy.p2.x += right; copy.p2.y += bottom;
return copy; }
154 constexpr trec2 shrunk(T left, T top, T right, T bottom)
const noexcept {
return grown(-left, -top, -right, -bottom); }
156 constexpr trec2 at_position(tvec pos)
const noexcept {
auto copy = *
this; copy.set_position(pos);
return copy; }
157 constexpr trec2 at_position(T x, T y)
const noexcept {
auto copy = *
this; copy.set_position(x, y);
return copy; }
158 constexpr trec2 sized(tvec size)
const noexcept {
auto copy = *
this; copy.set_size(size);
return copy; }
159 constexpr trec2 sized(T w, T h)
const noexcept {
auto copy = *
this; copy.set_size(w, h);
return copy; }
160 constexpr trec2 translated(tvec op)
const noexcept {
return *
this + op; }
161 constexpr trec2 translated(T x, T y)
const noexcept {
return *
this + tvec{ x, y }; }
162 constexpr trec2 scaled(tvec op)
const noexcept {
return *
this * op; }
163 constexpr trec2 scaled(T x, T y)
const noexcept {
return *
this * tvec{ x, y }; }
164 constexpr trec2 scaled(T s)
const noexcept {
return *
this * s; }
165 constexpr T width() const noexcept {
return p2.x - p1.x; };
166 constexpr T height() const noexcept {
return p2.y - p1.y; };
167 constexpr trec2& set_width(T w)
noexcept { p2.x = p1.x + w;
return *
this; };
168 constexpr trec2& set_height(T h)
noexcept { p2.y = p1.y + h;
return *
this; };
169 constexpr T x() const noexcept {
return p1.x; }
170 constexpr T y() const noexcept {
return p1.y; }
171 constexpr T left() const noexcept {
return p1.x; }
172 constexpr T top() const noexcept {
return p1.y; }
173 constexpr T right() const noexcept {
return p2.x; }
174 constexpr T bottom() const noexcept {
return p2.y; }
175 constexpr tvec left_top() const noexcept {
return p1; }
176 constexpr tvec left_bottom() const noexcept {
return { p1.x, p2.y }; }
177 constexpr tvec right_top() const noexcept {
return { p2.x, p1.y }; }
178 constexpr tvec right_bottom() const noexcept {
return p2; }
179 constexpr tvec half_size() const noexcept {
return (p2 - p1) / T{ 2 }; }
180 constexpr tvec center() const noexcept {
return p1 + half_size(); }
181 constexpr tvec centroid() const noexcept {
return center(); }
182 constexpr trec2& set_center(tvec pos)
noexcept {
const auto hw = half_size(); p1 = pos - hw; p2 = pos + hw;
return *
this; }
183 constexpr trec2 at_center(tvec pos)
const noexcept {
auto copy = *
this; copy.set_center(pos);
return copy; }
185 constexpr trec2 local() const noexcept {
return { tvec{}, size() }; }
186 constexpr trec2 relative_to(trec2
const& other)
const noexcept {
return { p1 - other.position(), p2 - other.position() }; }
188 constexpr trec2 to_global(trec2
const& parent_rect)
const noexcept {
return { p1 + parent_rect.position(), p2 + parent_rect.position() }; }
190 constexpr glm::vec2 to_rect_space(tvec world_space)
const noexcept {
return glm::vec2{ world_space - p1 } / glm::vec2{ size() }; }
191 constexpr tvec to_world_space(glm::vec2 rect_space)
const noexcept {
return tvec{ rect_space * glm::vec2{ size() } } + p1; }
193 constexpr trec2& include(tvec pt)
noexcept { this->p1 = glm::min(this->p1, pt); this->p2 = glm::max(this->p2, pt);
return *
this; };
194 constexpr trec2& include(trec2
const& rec)
noexcept {
return this->include(rec.p1).include(rec.p2); };
196 constexpr trec2 including(tvec pt)
const noexcept {
return { glm::min(this->p1, pt), glm::max(this->p2, pt) }; };
197 constexpr trec2 including(trec2
const& rec)
const noexcept {
return this->include(rec.p1).include(rec.p2); };
199 constexpr bool intersects(trec2
const& other)
const noexcept
201 return (left() <= other.right() && other.left() <= right() && top() <= other.bottom() && other.top() <= bottom());
204 constexpr trec2 intersection(trec2
const& other)
const noexcept
206 auto x1 = std::max(std::min(p1.x, p2.x), std::min(other.p1.x, other.p2.x));
207 auto y1 = std::max(std::min(p1.y, p2.y), std::min(other.p1.y, other.p2.y));
208 auto x2 = std::min(std::max(p1.x, p2.x), std::max(other.p1.x, other.p2.x));
209 auto y2 = std::min(std::max(p1.y, p2.y), std::max(other.p1.y, other.p2.y));
210 return { x1,y1,x2,y2 };
213 constexpr trec2 clipped_to(trec2
const& other)
const noexcept
215 return intersection(other);
218 constexpr trec2 constrained_to(trec2
const& other)
const noexcept;
222 constexpr bool contains(glm::vec<2, T>
const& other)
const noexcept
224 return other.x >= p1.x && other.y >= p1.y && other.x < p2.x && other.y < p2.y;
228 constexpr bool contains(trec2
const& other)
const noexcept
230 return other.p1.x >= p1.x && other.p1.y >= p1.y && other.p2.x <= p2.x && other.p2.y <= p2.y;
233 constexpr bool is_valid() const noexcept
235 return p1.x <= p2.x && p1.y <= p2.y;
238 constexpr trec2 valid() const noexcept
241 if (copy.p1.x > copy.p2.x) std::swap(copy.p1.x, copy.p2.x);
242 if (copy.p1.y > copy.p2.y) std::swap(copy.p1.y, copy.p2.y);
246 constexpr trec2& make_valid() noexcept
248 if (p1.x > p2.x) std::swap(p1.x, p2.x);
249 if (p1.y > p2.y) std::swap(p1.y, p2.y);
253 constexpr std::pair<trec2, trec2> split_vertical(T top_height)
const noexcept
256 top_height = this->height() + top_height;
257 return { trec2::from_size(this->p1, {this->width(), top_height}), trec2::from_size(this->p1 + tvec{0, top_height}, {this->width(), this->height() - top_height}) };
260 constexpr std::pair<trec2, trec2> split_horizontal(T left_width)
const noexcept
263 left_width = this->width() + left_width;
264 return { trec2::from_size(this->p1, {left_width, this->height()}), trec2::from_size(this->p1 + tvec{left_width, 0}, {this->width() - left_width, this->height()}) };
267 constexpr std::array<tvec, 4> split_on(tvec split_center)
const noexcept;
268 constexpr std::array<tvec, 4> split_on(trec2
const& removed_portion)
const noexcept;
270 constexpr trec2 lerp(trec2
const& other,
float factor)
const noexcept;
272 constexpr T calculate_area() const noexcept {
return width() * height(); }
274 constexpr T edge_length() const noexcept {
return (width() + height()) * 2; }
276 constexpr glm::vec2 edge_point_alpha(
double edge_progress)
const
278 edge_progress = glm::fract(edge_progress);
279 const auto w = width();
280 const auto h = height();
281 const auto el = (w + h) * 2;
282 const auto d =
static_cast<T
>(edge_progress * el);
284 return glm::mix(this->left_top(), this->right_top(), d / w);
286 return glm::mix(this->right_top(), this->right_bottom(), (d - w) / h);
287 else if (d < w + h + w)
288 return glm::mix(this->right_bottom(), this->left_bottom(), (d - (w + h)) / w);
290 return glm::mix(this->left_bottom(), this->left_top(), (d - (w + h + w)) / h);
293 constexpr glm::vec2 point_alpha(glm::vec2 alpha)
const
295 return glm::vec2{ this->p1 } + alpha * glm::vec2{ this->size() };
298 constexpr glm::vec2 edge_point(
double edge_pos)
const
300 const auto w = width();
301 const auto h = height();
302 edge_pos = fmod(edge_pos, (w + h) * 2);
304 return glm::mix(this->left_top(), this->right_top(), edge_pos / w);
305 else if (edge_pos < w + h)
306 return glm::mix(this->right_top(), this->right_bottom(), (edge_pos - w) / h);
307 else if (edge_pos < w + h + w)
308 return glm::mix(this->right_bottom(), this->left_bottom(), (edge_pos - (w + h)) / w);
310 return glm::mix(this->left_bottom(), this->left_top(), (edge_pos - (w + h + w)) / h);
313 constexpr trec2 bounding_box() const noexcept
318 constexpr glm::vec2 closest_point_to(glm::vec2 pt)
const
320 const auto d = (pt - p1) / size();
321 const auto c = glm::clamp(d, glm::vec2{ 0 }, glm::vec2{ 1 });
322 return p1 + c * size();
325 template <
typename FUNC>
326 GHPL_REQUIRES(std::is_invocable_v<FUNC, tvec>&& std::is_integral_v<T>)
327 constexpr void for_each_pixel(FUNC&& func)
const
329 for (T y = p1.y; y < p2.y; ++y)
330 for (T x = p1.x; x < p2.x; ++x)
334 template <
typename FUNC>
335 constexpr void for_each_edge(FUNC&& func)
const
337 func(left_top(), right_top());
338 func(right_top(), right_bottom());
339 func(right_bottom(), left_bottom());
340 func(left_bottom(), left_top());
343 template <
typename FUNC>
344 constexpr void for_each_vertex(FUNC&& func)
const
348 func(right_bottom());
352 constexpr size_t vertex_count() const noexcept {
return 4; }
353 constexpr size_t edge_count() const noexcept {
return 4; }
355 auto edge(
size_t index)
const -> std::optional<std::pair<glm::tvec2<T>, glm::tvec2<T>>>
359 case 0:
return std::make_pair(left_top(), right_top());
360 case 1:
return std::make_pair(right_top(), right_bottom());
361 case 2:
return std::make_pair(right_bottom(), left_bottom());
362 case 3:
return std::make_pair(left_bottom(), left_top());
367 auto vertex(
size_t index)
const -> std::optional<tvec>
371 case 0:
return left_top();
372 case 1:
return right_top();
373 case 2:
return right_bottom();
374 case 3:
return left_bottom();