1 // -*- C++ -*-
2 /* GG is a GUI for OpenGL.
3    Copyright (C) 2003-2008 T. Zachary Laine
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public License
7    as published by the Free Software Foundation; either version 2.1
8    of the License, or (at your option) any later version.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA
19 
20    If you do not wish to comply with the terms of the LGPL please
21    contact the author as other terms are available for a fee.
22 
23    Zach Laine
24    whatwasthataddress@gmail.com */
25 
26 /** \file PtRect.h \brief Contains the utility classes Pt and Rect. */
27 
28 #ifndef _GG_PtRect_h_
29 #define _GG_PtRect_h_
30 
31 #include <GG/Base.h>
32 #include <GG/StrongTypedef.h>
33 #include <boost/functional/hash.hpp>
34 
35 
36 namespace GG {
37 
38 /** \class GG::X
39     \brief The x-coordinate value type.
40 
41     X has an underlying value type of int.  \see GG_STRONG_INTEGRAL_TYPEDEF */
42 GG_STRONG_INTEGRAL_TYPEDEF(X, int);
43 
44 /** \class GG::Y
45     \brief The y-coordinate value type.
46 
47     Y has an underlying value type of int.  \see GG_STRONG_INTEGRAL_TYPEDEF */
48 GG_STRONG_INTEGRAL_TYPEDEF(Y, int);
49 
50 // some useful coordinate constants
51 extern GG_API const X X0;
52 extern GG_API const X X1;
53 extern GG_API const Y Y0;
54 extern GG_API const Y Y1;
55 
56 /** \brief A GG screen coordinate class. */
57 struct GG_API Pt
58 {
59     /** \name Structors */ ///@{
60     Pt();
61 
62     Pt(X x_, Y y_);     ///< Ctor that creates a Pt ( \a _x , \a y ).
63     Pt(X_d x_, Y y_);   ///< Ctor that creates a Pt ( \a _x , \a y ).
64     Pt(X x_, Y_d y_);   ///< Ctor that creates a Pt ( \a _x , \a y ).
65     Pt(X_d x_, Y_d y_); ///< Ctor that creates a Pt ( \a _x , \a y ).
66     //@}
67 
68     /** \name Accessors */ ///@{
69     /** Returns true if x < \a rhs.x or returns true if x == \a rhs.x and y
70         <\a rhs.y.  This is useful for sorting Pts in STL containers and
71         algorithms. */
LessPt72     bool Less(const Pt& rhs) const
73         { return x < rhs.x ? true : (x == rhs.x ? (y < rhs.y ? true : false) : false); }
74     //@}
75 
76     /** \name Mutators */ ///@{
77     void  operator+=(const Pt& rhs)     { x += rhs.x; y += rhs.y; }     ///< Adds \a rhs to Pt.
78     void  operator-=(const Pt& rhs)     { x -= rhs.x; y -= rhs.y; }     ///< Subtracts \a rhs from Pt.
79     Pt    operator-() const             { return Pt(-x, -y); }          ///< Negates Pt.
80     Pt    operator/=(const double rhs)  { return Pt(x / rhs, y / rhs); }///< Devides components of Pt by \a rhs
81     Pt    operator*=(const double rhs)  { return Pt(x * rhs, y * rhs); }///< Devides components of Pt by \a rhs
82     //@}
83 
84     X x; ///< The x component.
85     Y y; ///< The y component.
86 };
87 
88 GG_API std::ostream& operator<<(std::ostream& os, const Pt& pt);
89 
90 
91 /** \brief A GG rectangle class.
92 
93     This is essentially just two points that bound the rectangle. */
94 struct GG_API Rect
95 {
96     /** \name Structors */ ///@{
97     Rect();
98 
99     Rect(const Pt& pt1, const Pt& pt2);    ///< ctor that constructs a Rect from two corners; any two opposing corners will do
100     Rect(X x1, Y y1, X x2, Y y2);  ///< ctor that constructs a Rect from its left, upper, right, and bottom boundaries
101     //@}
102 
103     /** \name Accessors */ ///@{
LeftRect104     X   Left() const        { return ul.x; }            ///< returns the left boundary of the Rect
RightRect105     X   Right() const       { return lr.x; }            ///< returns the right boundary of the Rect
TopRect106     Y   Top() const         { return ul.y; }            ///< returns the top boundary of the Rect
BottomRect107     Y   Bottom() const      { return lr.y; }            ///< returns the bottom boundary of the Rect
UpperLeftRect108     Pt  UpperLeft() const   { return ul; }              ///< returns the upper-left corner of the Rect
LowerRightRect109     Pt  LowerRight() const  { return lr; }              ///< returns the lower-right corner of the Rect
WidthRect110     X   Width() const       { return lr.x - ul.x; }     ///< returns the width of the Rect
HeightRect111     Y   Height() const      { return lr.y - ul.y; }     ///< returns the height of the Rect
MidXRect112     X   MidX() const        { return (lr.x + ul.x)/2; } ///< returns the horizontal mid-point of the Rect
MidYRect113     Y   MidY() const        { return (lr.y + ul.y)/2; } ///< returns the vertical mid-point of the Rect
114 
115 
116     bool  Contains(const Pt& pt) const; ///< returns true iff \a pt falls inside the Rect
117     //@}
118 
119     /** \name Mutators */ ///@{
120     void operator+=(const Pt& pt)      { ul += pt; lr += pt; } ///< shifts the Rect by adding \a pt to each corner
121     void operator-=(const Pt& pt)      { ul -= pt; lr -= pt; } ///< shifts the Rect by subtracting \a pt from each corner
122     //@}
123 
124     Pt ul; ///< the upper-left corner of the Rect
125     Pt lr; ///< the lower-right corner of the Rect
126 };
127 
128 GG_API inline bool operator==(const Pt& lhs, const Pt& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } ///< returns true if \a lhs is identical to \a rhs
129 GG_API inline bool operator!=(const Pt& lhs, const Pt& rhs) { return !(lhs == rhs); }                    ///< returns true if \a lhs differs from \a rhs
130 GG_API inline bool operator<(const Pt& lhs, const Pt& rhs)  { return lhs.x < rhs.x && lhs.y < rhs.y; }   ///< returns true if \a lhs.x and \a lhs.y are both less than the corresponding components of \a rhs
131 GG_API inline bool operator>(const Pt& lhs, const Pt& rhs)  { return lhs.x > rhs.x && lhs.y > rhs.y; }   ///< returns true if \a lhs.x and \a lhs.y are both greater than the corresponding components of \a rhs
132 GG_API inline bool operator<=(const Pt& lhs, const Pt& rhs) { return lhs.x <= rhs.x && lhs.y <= rhs.y; } ///< returns true if \a lhs.x and \a lhs.y are both less than or equal to the corresponding components of \a rhs
133 GG_API inline bool operator>=(const Pt& lhs, const Pt& rhs) { return lhs.x >= rhs.x && lhs.y >= rhs.y; } ///< returns true if \a lhs.x and \a lhs.y are both greater than or equal to the corresponding components of \a rhs
134 GG_API inline Pt   operator+(const Pt& lhs, const Pt& rhs)  { return Pt(lhs.x + rhs.x, lhs.y + rhs.y); } ///< returns the vector sum of \a lhs and \a rhs
135 GG_API inline Pt   operator-(const Pt& lhs, const Pt& rhs)  { return Pt(lhs.x - rhs.x, lhs.y - rhs.y); } ///< returns the vector difference of \a lhs and \a rhs
136 GG_API inline Pt   operator*(const Pt& lhs, double rhs)     { return Pt(lhs.x * rhs, lhs.y * rhs); }     ///< returns the vector with components multiplied by \a rhs
137 GG_API inline Pt   operator/(const Pt& lhs, double rhs)     { return Pt(lhs.x / rhs, lhs.y / rhs); }     ///< returns the vector with components divided by \a rhs
138 
139 GG_API std::ostream& operator<<(std::ostream& os, const Pt& pt); ///< Pt stream-output operator for debug output
140 
141 /** returns true if \a lhs is identical to \a rhs */
142 GG_API inline bool operator==(const Rect& lhs, const Rect& rhs) { return lhs.ul.x == rhs.ul.x && lhs.lr.x == rhs.lr.x && lhs.ul.y == rhs.ul.y && lhs.lr.y == rhs.lr.y; }
143 
144 /** returns true if \a lhs differs from \a rhs */
145 GG_API inline bool operator!=(const Rect& lhs, const Rect& rhs) { return !(lhs == rhs); }
146 
147 GG_API inline Rect operator+(const Rect& rect, const Pt& pt) { return Rect(rect.ul + pt, rect.lr + pt); } ///< returns \a rect shifted by adding \a pt to each corner
148 GG_API inline Rect operator-(const Rect& rect, const Pt& pt) { return Rect(rect.ul - pt, rect.lr - pt); } ///< returns \a rect shifted by subtracting \a pt from each corner
149 GG_API inline Rect operator+(const Pt& pt, const Rect& rect) { return rect + pt; } ///< returns \a rect shifted by adding \a pt to each corner
150 GG_API inline Rect operator-(const Pt& pt, const Rect& rect) { return rect - pt; } ///< returns \a rect shifted by subtracting \a pt from each corner
151 
152 GG_API std::ostream& operator<<(std::ostream& os, const Rect& rect); ///< Rect stream-output operator for debug output
153 
154     // Hash functions
155     // Replace with C++11 equilvalent when converted to C++11
hash_value(X const & x)156     GG_API inline std::size_t hash_value(X const& x) { return boost::hash<int>()(Value(x)); }
hash_value(Y const & y)157     GG_API inline std::size_t hash_value(Y const& y) { return boost::hash<int>()(Value(y)); }
hash_value(Pt const & pt)158     GG_API inline std::size_t hash_value(Pt const& pt) {
159         std::size_t seed(0);
160         boost::hash_combine(seed, pt.x);
161         boost::hash_combine(seed, pt.y);
162         return seed;
163     }
hash_value(Rect const & r)164     GG_API inline std::size_t hash_value(Rect const& r) {
165         std::size_t seed(0);
166         boost::hash_combine(seed, r.ul);
167         boost::hash_combine(seed, r.lr);
168         return seed;
169     }
170 
171 } // namepace GG
172 
173 #endif
174