1 /******************************************************************************
2  *  Warmux is a convivial mass murder game.
3  *  Copyright (C) 2001-2011 Warmux Team.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program 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
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18  ******************************************************************************
19  * Rectangle.h: Standard C++ Rectangle template
20  ******************************************************************************
21  * 2005/09/21:  Jean-Christophe Duberga (jcduberga@gmx.de)
22  *              Initial version
23  *****************************************************************************/
24 
25 #ifndef WARMUX_RECTANGLE_H
26 #define WARMUX_RECTANGLE_H
27 
28 #include <cmath>
29 #include <WARMUX_error.h>
30 #include <WARMUX_types.h>
31 #include <WARMUX_vector2.h>
32 
33 /**
34  * This template handle rectangles.
35  *
36  * @param T Type for position and size of the Rectangle
37  */
38 template<class T> class rectangle
39 {
40   protected:
41     /** Position of the rectangle. */
42     Vector2<T> position;
43     /** Size of the rectangle. */
44     Vector2<T> size;
45 
46   public:
47     /**
48      * Default constructor
49      */
rectangle()50     inline rectangle():
51                   position(0, 0),
52                   size(0, 0)
53                 { }
54 
~rectangle()55                 virtual ~rectangle() {};
56 
57     /**
58      * Constructor for building a new rectangle.
59      *
60      * @param x Position among the x axe.
61      * @param y Position among the y axe.
62      * @param width Width of the new rectangle.
63      * @param height Height of the new rectangle.
64      */
rectangle(T x,T y,T width,T height)65     inline rectangle(T x, T y, T width, T height):
66                   position(x, y),
67                   size(width, height)
68                 { }
69 
70     /**
71      * Constructor for building a new rectangle with the position and size specified.
72      *
73      * @param thePosition Position of the new rectangle.
74      * @param theSize Size of the new rectangle.
75      */
rectangle(Vector2<T> thePosition,Vector2<T> theSize)76     inline rectangle(Vector2<T> thePosition, Vector2<T> theSize):
77       position(thePosition),
78                         size(theSize)
79                 {}
80 
81     /**
82      * Set the position of the rectangle.
83      *
84      * @param x New X position.
85      * @param y New Y position.
86      */
SetPosition(T x,T y)87     inline void SetPosition(T x, T y){
88       position.SetValues(x, y);
89     }
90 
91     /**
92      * Change the position of the rectangle.
93      *
94      * @param newPos The new position of the rectangle.
95      */
SetPosition(const Vector2<T> & newPos)96     inline void SetPosition(const Vector2<T> &newPos){
97       position = newPos;
98     }
99 
100     /**
101      * Change the x position of the rectangle.
102      *
103      * @param x New X position.
104      */
SetPositionX(T x)105     inline void SetPositionX(T x){
106       position.x = x;
107     }
108 
109     /**
110      * Change the y position of the rectangle.
111      *
112      * @param y New Y position.
113      */
SetPositionY(T y)114     inline void SetPositionY(T y){
115       position.y = y;
116     }
117 
118     /**
119      * Set the size of the rectangle.
120      *
121      * @param sizeX new size among the x axe.
122      * @param sizeY new size among the y axe.
123      */
SetSize(T sizeX,T sizeY)124     inline void SetSize(T sizeX, T sizeY){
125       size.SetValues(sizeX, sizeY);
126     }
127 
128     /**
129      * Change the X size of the rectangle.
130      *
131      * @param x New size among x axe.
132      */
SetSizeX(T sizeX)133     inline void SetSizeX(T sizeX){
134       size.x = sizeX;
135     }
136 
137     /**
138      * Change the Y size of the rectangle.
139      *
140      * @param y New size among y axe.
141      */
SetSizeY(T sizeY)142     inline void SetSizeY(T sizeY){
143       size.y = sizeY;
144     }
145 
SetSize(Vector2<T> newSize)146     inline void SetSize(Vector2<T> newSize){
147       size = newSize;
148     }
149 
GetRectangle()150     inline rectangle<T> GetRectangle() const{
151       return *this;
152     }
153 
154     /**
155      * Return the position of the rectangle.
156      */
GetPosition()157     inline Vector2<T> GetPosition() const{
158       return position;
159     }
160 
GetPositionX()161     inline T GetPositionX() const{
162       return position.x;
163     }
164 
GetPositionY()165     inline T GetPositionY() const{
166       return position.y;
167     }
168 
169     /**
170      * Return the size of the rectangle.
171      */
GetSize()172     inline Vector2<T> GetSize() const{
173       return size;
174     }
175 
GetSizeX()176     inline T GetSizeX() const{
177       return size.x;
178     }
179 
GetSizeY()180     inline T GetSizeY() const{
181       return size.y;
182     }
183 
184     /**
185      * Clip the current rectangle using an other rectangle.
186      *
187      * @param cr The rectangle used for clipping
188      */
Clip(const rectangle & cr)189     void Clip(const rectangle &cr) {
190       if( IsSizeZero() || cr.IsSizeZero() ) {
191         size.x = 0;
192         size.y = 0;
193         return;
194       }
195 
196       Vector2<T> r1BR = GetBottomRightPoint();
197       Vector2<T> r2BR = cr.GetBottomRightPoint();
198       Vector2<T> r1TL = GetTopLeftPoint();
199       Vector2<T> r2TL = cr.GetTopLeftPoint();
200 
201       if (r1BR.x < r2TL.x || r1BR.y < r2TL.y ||
202           r2BR.x < r1TL.x || r2BR.y < r1TL.y ) {
203         size.x = 0;
204         size.y = 0;
205         return;
206       }
207 
208       position.x = std::max(r1TL.x, r2TL.x);
209       position.y = std::max(r1TL.y, r2TL.y);
210       size.x     = std::min(r1BR.x, r2BR.x) - position.x + 1;
211       size.y     = std::min(r1BR.y, r2BR.y) - position.y + 1;
212     }
213 
214     /**
215      * Return true if the point p is contained in the rectangle.
216      *
217      * @param p Point used to perform the check.
218      */
Contains(const Vector2<T> p)219     inline bool Contains( const Vector2<T> p ) const{
220       if( IsSizeZero() )
221         return false;
222 
223       return p >= GetTopLeftPoint() &&
224         p <= GetBottomRightPoint();
225     }
226 
227     /**
228      * Return true if r2 is contained in the current rectangle.
229      *
230      * @param r2 The rectangle for witch the check if performed.
231      */
Contains(const rectangle<T> & r2)232     inline bool Contains( const rectangle<T> &r2 ) const{
233       if( r2.IsSizeZero() )
234         return false;
235 
236       return Contains( r2.GetTopLeftPoint() ) &&
237         Contains( r2.GetBottomRightPoint() );
238     }
239 
240     /**
241      * Return true if there is an intersection between the current rectangle
242      * and the r2 rectangle.
243      *
244      * @param r2 The second rectangle.
245      */
Intersect(const rectangle<T> & r2)246     inline bool Intersect( const rectangle<T> &r2 ) const{
247       if( IsSizeZero() || r2.IsSizeZero() )
248         return false;
249 
250       Vector2<T> r1BR = GetBottomRightPoint();
251       Vector2<T> r2BR = r2.GetBottomRightPoint();
252       Vector2<T> r1TL = GetTopLeftPoint();
253       Vector2<T> r2TL = r2.GetTopLeftPoint();
254 
255       if( r1BR.x < r2TL.x || r1BR.y < r2TL.y ||
256            r2BR.x < r1TL.x || r2BR.y < r1TL.y )
257         return false;
258 
259       return true;
260     }
261 
262     /**
263      * Return the point in the top left corner of the rectangle.
264      *
265      * If the rectangle has a size of zero, this point doesn't exist,
266      * so the program crash with a failled ASSERTion.
267      */
GetTopLeftPoint()268     inline Vector2<T> GetTopLeftPoint() const{
269       ASSERT( !IsSizeZero() );
270       return position;
271     }
272 
273     /**
274      * Return the point in the top right corner of the rectangle.
275      *
276      * If the rectangle has a size of zero, this point doesn't exist,
277      * so the program crash with a failled ASSERTion.
278      */
GetTopRightPoint()279     inline Vector2<T> GetTopRightPoint() const{
280       ASSERT( !IsSizeZero() );
281       Vector2<T> r = position;
282 
283       r.x += size.x - 1;
284 
285       return r;
286     }
287 
288     /**
289      * Return the point in the bottom left corner of the rectangle.
290      *
291      * If the rectangle has a size of zero, this point doesn't exist,
292      * so the program crash with a failled ASSERTion.
293      */
GetBottomLeftPoint()294     inline Vector2<T> GetBottomLeftPoint() const{
295       ASSERT( !IsSizeZero() );
296       Vector2<T> r = position;
297 
298       r.y += size.y - 1;
299 
300       return r;
301     }
302 
303     /**
304      * Return the point in the top left corner of the rectangle.
305      *
306      * If the rectangle has a size of zero, this point doesn't exist,
307      * so the program crash with a failled ASSERTion. */
GetBottomRightPoint()308     inline Vector2<T> GetBottomRightPoint() const{
309       ASSERT( !IsSizeZero() );
310       return position + size - 1;
311     }
312 
313     /**
314      * Return true if the rectangle has a size of zero.
315      */
IsSizeZero()316     inline bool IsSizeZero() const{
317       return size.IsXNull() || size.IsYNull();
318     }
319 
320     inline bool operator==(const rectangle<T> &p2) const{
321       return size==p2.size && position==p2.position;
322     }
323 };
324 
325 typedef rectangle<int>    Rectanglei;
326 typedef rectangle<Double>  Rectanglef;
327 typedef rectangle<Double> Rectangled;
328 #endif // _RECTANGLE_H
329