11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
18PROMEKI_NAMESPACE_BEGIN
42template <
typename T>
class Rect {
48 Rect(
const Point<T, 2> &pos,
const Size2DTemplate<T> &size) : _pos(pos), _size(size) {}
51 Rect(T x, T y, T width, T height) : _pos(x, y), _size(width, height) {}
54 T x()
const {
return _pos.x(); }
57 T y()
const {
return _pos.y(); }
60 T width()
const {
return _size.width(); }
63 T height()
const {
return _size.height(); }
66 void setX(T val) { _pos.setX(val); }
69 void setY(T val) { _pos.setY(val); }
72 void setWidth(T val) { _size.setWidth(val); }
75 void setHeight(T val) { _size.setHeight(val); }
78 Point<T, 2> topLeft()
const {
return _pos; }
81 Point<T, 2> topRight()
const {
return Point<T, 2>(x() + width(), y()); }
84 Point<T, 2> bottomLeft()
const {
return Point<T, 2>(x(), y() + height()); }
87 Point<T, 2> bottomRight()
const {
return Point<T, 2>(x() + width(), y() + height()); }
90 Point<T, 2> center()
const {
return Point<T, 2>(x() + width() / 2, y() + height() / 2); }
93 const Point<T, 2> &pos()
const {
return _pos; }
96 const Size2DTemplate<T> &size()
const {
return _size; }
99 void setPos(
const Point<T, 2> &p) { _pos = p; }
102 void setSize(
const Size2DTemplate<T> &s) { _size = s; }
105 bool isValid()
const {
return _size.isValid(); }
108 bool isEmpty()
const {
return !isValid(); }
111 bool contains(
const Point<T, 2> &p)
const {
112 return p.x() >= x() && p.x() < x() + width() && p.y() >= y() && p.y() < y() + height();
116 bool contains(
const Rect &r)
const {
117 return r.x() >= x() && r.x() + r.width() <= x() + width() && r.y() >= y() &&
118 r.y() + r.height() <= y() + height();
122 bool intersects(
const Rect &r)
const {
123 return x() < r.x() + r.width() && x() + width() > r.x() && y() < r.y() + r.height() &&
124 y() + height() > r.y();
128 Rect intersected(
const Rect &r)
const {
129 T ix = std::max(x(), r.x());
130 T iy = std::max(y(), r.y());
131 T ix2 = std::min(x() + width(), r.x() + r.width());
132 T iy2 = std::min(y() + height(), r.y() + r.height());
133 if (ix2 <= ix || iy2 <= iy)
return Rect();
134 return Rect(ix, iy, ix2 - ix, iy2 - iy);
138 Rect united(
const Rect &r)
const {
139 if (isEmpty())
return r;
140 if (r.isEmpty())
return *
this;
141 T ux = std::min(x(), r.x());
142 T uy = std::min(y(), r.y());
143 T ux2 = std::max(x() + width(), r.x() + r.width());
144 T uy2 = std::max(y() + height(), r.y() + r.height());
145 return Rect(ux, uy, ux2 - ux, uy2 - uy);
149 Rect adjusted(T dx1, T dy1, T dx2, T dy2)
const {
150 return Rect(x() + dx1, y() + dy1, width() + dx2 - dx1, height() + dy2 - dy1);
154 Rect translated(T dx, T dy)
const {
return Rect(x() + dx, y() + dy, width(), height()); }
157 bool operator==(
const Rect &other)
const {
158 return _pos == other._pos && _size.width() == other._size.width() &&
159 _size.height() == other._size.height();
163 bool operator!=(
const Rect &other)
const {
return !(*
this == other); }
167 Size2DTemplate<T> _size;
171using Rect2Di32 = Rect<int32_t>;
173using Rect2Df = Rect<float>;
175using Rect2Dd = Rect<double>;