/* $Id$ */
#ifndef RECT_H
#define RECT_H
#include <limits>
/** Template based point without ctor/dtor (raw) for use in unions */
template <typename T> struct PointRawT {
T x, y;
PointRawT operator -() const
{
PointRawT pt = {-x, -y};
return pt;
}
};
/** Template based point */
template <typename T> struct PointT : public PointRawT<T> {
typedef PointRawT<T> PointRaw;
PointT(T x_a = 0, T y_a = 0)
{
PointRaw::x = x_a;
PointRaw::y = y_a;
}
template <typename Ta> PointT(const PointRawT<Ta> &src)
{
PointRaw::x = (T)src.x;
PointRaw::y = (T)src.y;
}
PointT& operator =(const PointRaw &src)
{
PointRaw::x = (T)src.x;
PointRaw::y = (T)src.y;
return *this;
}
bool operator ==(const PointRaw &other) const
{
return PointRaw::x == other.x && PointRaw::y == other.y;
}
bool operator !=(const PointRaw &other) const
{
return PointRaw::x != other.x || PointRaw::y != other.y;
}
PointT operator -() const
{
return PointT(-PointRaw::x, -PointRaw::y);
}
void DoMove(T dx, T dy)
{
PointRaw::x += dx;
PointRaw::y += dy;
}
template <typename T2> void DoMove(const PointRawT<T2> &offset)
{
DoMove((T)offset.x, (T)offset.y);
}
template <typename T2> PointT operator +(const PointRawT<T2> &offset) const
{
PointT pt(*this);
pt.DoMove(offset);
return pt;
}
template <typename T2> PointT operator -(const PointRawT<T2> &offset) const
{
PointT pt(*this);
pt.DoMove(-offset);
return pt;
}
PointT& operator +=(const PointRaw &offset)
{
DoMove(offset);
return *this;
}
PointT& operator -=(const PointRaw &offset)
{
DoMove(-offset);
return *this;
}
PointT operator *(T coef) const
{
return PointT(PointRaw::x * coef, PointRaw::y * coef);
}
PointT operator /(T coef) const
{
return PointT(PointRaw::x / coef, PointRaw::y / coef);
}
static const PointT& min()
{
static PointT val(std::numeric_limits<T>::min(), std::numeric_limits<T>::min());
return val;
}
static const PointT& zero()
{
static PointT val(0, 0);
return val;
}
static const PointT& one()
{
static PointT val(1, 1);
return val;
}
static const PointT& max()
{
static PointT val(std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
return val;
}
};
template <typename T> struct SizeT : public PointT<T> {
typedef PointT<T> Point;
typedef PointRawT<T> PointRaw;
SizeT(T x_a = 0, T y_a = 0)
: Point(x_a, y_a)
{}
template <typename Ta> SizeT(const PointRawT<Ta> &src)
: Point(src)
{}
SizeT operator -() const
{
return SizeT(-PointRaw::x, -PointRaw::y);
}
template <typename T2> SizeT operator +(const PointRawT<T2> &offset) const
{
SizeT pt(*this);
pt.DoMove(offset);
return pt;
}
template <typename T2> SizeT operator -(const PointRawT<T2> &offset) const
{
SizeT pt(*this);
pt.DoMove(-offset);
return pt;
}
SizeT& operator +=(const PointRaw &offset)
{
DoMove(offset);
return *this;
}
SizeT& operator -=(const PointRaw &offset)
{
DoMove(-offset);
return *this;
}
SizeT operator *(T coef) const
{
return SizeT(PointRaw::x * coef, PointRaw::y * coef);
}
SizeT operator /(T coef) const
{
return SizeT(PointRaw::x / coef, PointRaw::y / coef);
}
static const SizeT& min()
{
static SizeT val(std::numeric_limits<T>::min(), std::numeric_limits<T>::min());
return val;
}
static const SizeT& zero()
{
static SizeT val(0, 0);
return val;
}
static const SizeT& one()
{
static SizeT val(1, 1);
return val;
}
static const SizeT& max()
{
static SizeT val(std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
return val;
}
};
/** Template based rectangle */
template <typename T> struct RectT
{
typedef PointRawT<T> PointRaw;
PointT<T> top_left, bottom_right;
RectT(T left = 0, T top = 0, T right = 0, T bottom = 0)
: top_left(left, top), bottom_right(right, bottom)
{}
template <typename Ta> RectT(const PointT<Ta> &tl, const SizeT<Ta> &size)
: top_left(tl), bottom_right(tl + size - PointT<T>(1, 1))
{}
template <typename Ta> RectT(const PointT<Ta> &tl, const PointT<Ta> &br)
: top_left(tl), bottom_right(br)
{}
template <typename Ta> RectT(const RectT<Ta> &src)
: top_left(src.top_left), bottom_right(src.bottom_right)
{}
T Left() const
{
return top_left.x;
}
T Top() const
{
return top_left.y;
}
T Right() const
{
return bottom_right.x;
}
T Bottom() const
{
return bottom_right.y;
}
T Width() const
{
return bottom_right.x - top_left.x + 1;
}
T Height() const
{
return bottom_right.y - top_left.y + 1;
}
const PointT<T>& TopLeft() const
{
return top_left;
}
const PointT<T>& BottomRight() const
{
return bottom_right;
}
SizeT<T> Size() const
{
return SizeT<T>(bottom_right - top_left + PointT<T>(1, 1));
}
PointT<T> CenterPt() const
{
return (top_left + bottom_right + PointT<T>(1, 1)) / 2;
}
void SetLeft(T val)
{
top_left.x = val;
}
void SetTop(T val)
{
top_left.y = val;
}
void SetRight(T val)
{
bottom_right.x = val;
}
void SetBottom(T val)
{
bottom_right.y = val;
}
void SetWidth(T val)
{
bottom_right.x = top_left.x + val - 1;
}
void SetHeight(T val)
{
bottom_right.y = top_left.y + val - 1;
}
void SetTopLeft(const PointRaw &pt)
{
top_left = pt;
}
void SetBottomRight(const PointRaw &pt)
{
bottom_right = pt;
}
void SetSize(const PointRaw &pt)
{
bottom_right = top_left + pt - PointT<T>(1, 1);
}
bool PtInRect(const PointRaw &pt) const
{
return (top_left.x <= pt.x && pt.x <= bottom_right.x && top_left.y <= pt.y && pt.y <= bottom_right.y);
}
RectT& operator =(const RectT &src)
{
top_left = src.top_left;
bottom_right = src.bottom_right;
return *this;
}
void DoMove(T dx, T dy)
{
DoMove(PointT<T>(dx, dy));
}
void DoMove(const PointRaw &offset)
{
top_left.DoMove(offset);
bottom_right.DoMove(offset);
}
RectT operator +(const PointRaw &offset) const
{
RectT r(*this);
r.DoMove(offset);
return r;
}
RectT operator -(const PointRaw &offset) const
{
RectT r(*this);
r.DoMove(-offset);
return r;
}
RectT& operator +=(const PointRaw &offset)
{
DoMove(offset);
return *this;
}
RectT& operator -=(const PointRaw &offset)
{
DoMove(-offset);
return *this;
}
void DoUnion(const PointRawT<T> &pt)
{
if (pt.x < top_left.x) {
top_left.x = pt.x;
} else if (pt.x > bottom_right.x) {
bottom_right.x = pt.x;
}
if (pt.y < top_left.y) {
top_left.y = pt.y;
} else if (pt.y > bottom_right.y) {
bottom_right.y = pt.y;
}
}
void DoUnion(const RectT &rc)
{
if (rc.top_left.x < top_left.x) {
top_left.x = rc.top_left.x;
} else if (rc.bottom_right.x > bottom_right.x) {
bottom_right.x = rc.bottom_right.x;
}
if (rc.top_left.y < top_left.y) {
top_left.y = rc.top_left.y;
} else if (rc.bottom_right.y > bottom_right.y) {
bottom_right.y = rc.bottom_right.y;
}
}
};
typedef PointRawT<int16> PointRaw16;
typedef PointRawT<int32> PointRaw32;
typedef PointRawT<int> PointRaw;
typedef PointT<int16> Point16;
typedef PointT<int32> Point32;
typedef PointT<int> Point;
typedef SizeT<int16> Size16;
typedef SizeT<int32> Size32;
typedef SizeT<int> Size;
typedef RectT<int16> Rect16;
typedef RectT<int32> Rect32;
#endif /*RECT_H*/