src/misc/rect.hpp
author KUDr
Mon, 26 Mar 2007 22:15:38 +0000
branchcpp_gui
changeset 6303 84c215fc8eb8
parent 6301 e0251f797d59
permissions -rw-r--r--
(svn r9486) [cpp_gui] -Sync with trunk (r9100:9476)
/* $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*/