]> git.lizzy.rs Git - irrlicht.git/blob - include/rect.h
Bump revision
[irrlicht.git] / include / rect.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __IRR_RECT_H_INCLUDED__\r
6 #define __IRR_RECT_H_INCLUDED__\r
7 \r
8 #include "irrTypes.h"\r
9 #include "dimension2d.h"\r
10 #include "position2d.h"\r
11 \r
12 namespace irr\r
13 {\r
14 namespace core\r
15 {\r
16 \r
17         //! Rectangle template.\r
18         /** Mostly used by 2D GUI elements and for 2D drawing methods.\r
19         It has 2 positions instead of position and dimension and a fast\r
20         method for collision detection with other rectangles and points.\r
21 \r
22         Coordinates are (0,0) for top-left corner, and increasing to the right\r
23         and to the bottom.\r
24         */\r
25         template <class T>\r
26         class rect\r
27         {\r
28         public:\r
29 \r
30                 //! Default constructor creating empty rectangle at (0,0)\r
31                 rect() : UpperLeftCorner(0,0), LowerRightCorner(0,0) {}\r
32 \r
33                 //! Constructor with two corners\r
34                 rect(T x, T y, T x2, T y2)\r
35                         : UpperLeftCorner(x,y), LowerRightCorner(x2,y2) {}\r
36 \r
37                 //! Constructor with two corners\r
38                 rect(const position2d<T>& upperLeft, const position2d<T>& lowerRight)\r
39                         : UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {}\r
40 \r
41                 //! Constructor with upper left corner and dimension\r
42                 template <class U>\r
43                 rect(const position2d<T>& pos, const dimension2d<U>& size)\r
44                         : UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height) {}\r
45 \r
46                 //! Constructor with upper left at 0,0 and lower right using dimension\r
47                 template <class U>\r
48                 explicit rect(const dimension2d<U>& size)\r
49                         : UpperLeftCorner(0,0), LowerRightCorner(size.Width, size.Height) {}\r
50 \r
51                 //! move right by given numbers\r
52                 rect<T> operator+(const position2d<T>& pos) const\r
53                 {\r
54                         rect<T> ret(*this);\r
55                         return ret+=pos;\r
56                 }\r
57 \r
58                 //! move right by given numbers\r
59                 rect<T>& operator+=(const position2d<T>& pos)\r
60                 {\r
61                         UpperLeftCorner += pos;\r
62                         LowerRightCorner += pos;\r
63                         return *this;\r
64                 }\r
65 \r
66                 //! move left by given numbers\r
67                 rect<T> operator-(const position2d<T>& pos) const\r
68                 {\r
69                         rect<T> ret(*this);\r
70                         return ret-=pos;\r
71                 }\r
72 \r
73                 //! move left by given numbers\r
74                 rect<T>& operator-=(const position2d<T>& pos)\r
75                 {\r
76                         UpperLeftCorner -= pos;\r
77                         LowerRightCorner -= pos;\r
78                         return *this;\r
79                 }\r
80 \r
81                 //! equality operator\r
82                 bool operator==(const rect<T>& other) const\r
83                 {\r
84                         return (UpperLeftCorner == other.UpperLeftCorner &&\r
85                                 LowerRightCorner == other.LowerRightCorner);\r
86                 }\r
87 \r
88                 //! inequality operator\r
89                 bool operator!=(const rect<T>& other) const\r
90                 {\r
91                         return (UpperLeftCorner != other.UpperLeftCorner ||\r
92                                 LowerRightCorner != other.LowerRightCorner);\r
93                 }\r
94 \r
95                 //! compares size of rectangles\r
96                 bool operator<(const rect<T>& other) const\r
97                 {\r
98                         return getArea() < other.getArea();\r
99                 }\r
100 \r
101                 //! Returns size of rectangle\r
102                 T getArea() const\r
103                 {\r
104                         return getWidth() * getHeight();\r
105                 }\r
106 \r
107                 //! Returns if a 2d point is within this rectangle.\r
108                 /** \param pos Position to test if it lies within this rectangle.\r
109                 \return True if the position is within the rectangle, false if not. */\r
110                 bool isPointInside(const position2d<T>& pos) const\r
111                 {\r
112                         return (UpperLeftCorner.X <= pos.X &&\r
113                                 UpperLeftCorner.Y <= pos.Y &&\r
114                                 LowerRightCorner.X >= pos.X &&\r
115                                 LowerRightCorner.Y >= pos.Y);\r
116                 }\r
117 \r
118                 //! Check if the rectangle collides with another rectangle.\r
119                 /** \param other Rectangle to test collision with\r
120                 \return True if the rectangles collide. */\r
121                 bool isRectCollided(const rect<T>& other) const\r
122                 {\r
123                         return (LowerRightCorner.Y > other.UpperLeftCorner.Y &&\r
124                                 UpperLeftCorner.Y < other.LowerRightCorner.Y &&\r
125                                 LowerRightCorner.X > other.UpperLeftCorner.X &&\r
126                                 UpperLeftCorner.X < other.LowerRightCorner.X);\r
127                 }\r
128 \r
129                 //! Clips this rectangle with another one.\r
130                 /** \param other Rectangle to clip with */\r
131                 void clipAgainst(const rect<T>& other)\r
132                 {\r
133                         if (other.LowerRightCorner.X < LowerRightCorner.X)\r
134                                 LowerRightCorner.X = other.LowerRightCorner.X;\r
135                         if (other.LowerRightCorner.Y < LowerRightCorner.Y)\r
136                                 LowerRightCorner.Y = other.LowerRightCorner.Y;\r
137 \r
138                         if (other.UpperLeftCorner.X > LowerRightCorner.X)\r
139                                 LowerRightCorner.X = other.UpperLeftCorner.X;\r
140                         if (other.UpperLeftCorner.Y > LowerRightCorner.Y)\r
141                                 LowerRightCorner.Y = other.UpperLeftCorner.Y;\r
142 \r
143                         if (other.LowerRightCorner.X < UpperLeftCorner.X)\r
144                                 UpperLeftCorner.X = other.LowerRightCorner.X;\r
145                         if (other.LowerRightCorner.Y < UpperLeftCorner.Y)\r
146                                 UpperLeftCorner.Y = other.LowerRightCorner.Y;\r
147 \r
148                         if (other.UpperLeftCorner.X > UpperLeftCorner.X)\r
149                                 UpperLeftCorner.X = other.UpperLeftCorner.X;\r
150                         if (other.UpperLeftCorner.Y > UpperLeftCorner.Y)\r
151                                 UpperLeftCorner.Y = other.UpperLeftCorner.Y;\r
152                 }\r
153 \r
154                 //! Moves this rectangle to fit inside another one.\r
155                 /** \return True on success, false if not possible */\r
156                 bool constrainTo(const rect<T>& other)\r
157                 {\r
158                         if (other.getWidth() < getWidth() || other.getHeight() < getHeight())\r
159                                 return false;\r
160 \r
161                         T diff = other.LowerRightCorner.X - LowerRightCorner.X;\r
162                         if (diff < 0)\r
163                         {\r
164                                 LowerRightCorner.X += diff;\r
165                                 UpperLeftCorner.X  += diff;\r
166                         }\r
167 \r
168                         diff = other.LowerRightCorner.Y - LowerRightCorner.Y;\r
169                         if (diff < 0)\r
170                         {\r
171                                 LowerRightCorner.Y += diff;\r
172                                 UpperLeftCorner.Y  += diff;\r
173                         }\r
174 \r
175                         diff = UpperLeftCorner.X - other.UpperLeftCorner.X;\r
176                         if (diff < 0)\r
177                         {\r
178                                 UpperLeftCorner.X  -= diff;\r
179                                 LowerRightCorner.X -= diff;\r
180                         }\r
181 \r
182                         diff = UpperLeftCorner.Y - other.UpperLeftCorner.Y;\r
183                         if (diff < 0)\r
184                         {\r
185                                 UpperLeftCorner.Y  -= diff;\r
186                                 LowerRightCorner.Y -= diff;\r
187                         }\r
188 \r
189                         return true;\r
190                 }\r
191 \r
192                 //! Get width of rectangle.\r
193                 T getWidth() const\r
194                 {\r
195                         return LowerRightCorner.X - UpperLeftCorner.X;\r
196                 }\r
197 \r
198                 //! Get height of rectangle.\r
199                 T getHeight() const\r
200                 {\r
201                         return LowerRightCorner.Y - UpperLeftCorner.Y;\r
202                 }\r
203 \r
204                 //! If the lower right corner of the rect is smaller then the upper left, the points are swapped.\r
205                 void repair()\r
206                 {\r
207                         if (LowerRightCorner.X < UpperLeftCorner.X)\r
208                         {\r
209                                 T t = LowerRightCorner.X;\r
210                                 LowerRightCorner.X = UpperLeftCorner.X;\r
211                                 UpperLeftCorner.X = t;\r
212                         }\r
213 \r
214                         if (LowerRightCorner.Y < UpperLeftCorner.Y)\r
215                         {\r
216                                 T t = LowerRightCorner.Y;\r
217                                 LowerRightCorner.Y = UpperLeftCorner.Y;\r
218                                 UpperLeftCorner.Y = t;\r
219                         }\r
220                 }\r
221 \r
222                 //! Returns if the rect is valid to draw.\r
223                 /** It would be invalid if the UpperLeftCorner is lower or more\r
224                 right than the LowerRightCorner. */\r
225                 bool isValid() const\r
226                 {\r
227                         return ((LowerRightCorner.X >= UpperLeftCorner.X) &&\r
228                                 (LowerRightCorner.Y >= UpperLeftCorner.Y));\r
229                 }\r
230 \r
231                 //! Get the center of the rectangle\r
232                 position2d<T> getCenter() const\r
233                 {\r
234                         return position2d<T>(\r
235                                         (UpperLeftCorner.X + LowerRightCorner.X) / 2,\r
236                                         (UpperLeftCorner.Y + LowerRightCorner.Y) / 2);\r
237                 }\r
238 \r
239                 //! Get the dimensions of the rectangle\r
240                 dimension2d<T> getSize() const\r
241                 {\r
242                         return dimension2d<T>(getWidth(), getHeight());\r
243                 }\r
244 \r
245 \r
246                 //! Adds a point to the rectangle\r
247                 /** Causes the rectangle to grow bigger if point is outside of\r
248                 the box\r
249                 \param p Point to add to the box. */\r
250                 void addInternalPoint(const position2d<T>& p)\r
251                 {\r
252                         addInternalPoint(p.X, p.Y);\r
253                 }\r
254 \r
255                 //! Adds a point to the bounding rectangle\r
256                 /** Causes the rectangle to grow bigger if point is outside of\r
257                 the box\r
258                 \param x X-Coordinate of the point to add to this box.\r
259                 \param y Y-Coordinate of the point to add to this box. */\r
260                 void addInternalPoint(T x, T y)\r
261                 {\r
262                         if (x>LowerRightCorner.X)\r
263                                 LowerRightCorner.X = x;\r
264                         if (y>LowerRightCorner.Y)\r
265                                 LowerRightCorner.Y = y;\r
266 \r
267                         if (x<UpperLeftCorner.X)\r
268                                 UpperLeftCorner.X = x;\r
269                         if (y<UpperLeftCorner.Y)\r
270                                 UpperLeftCorner.Y = y;\r
271                 }\r
272 \r
273                 //! Upper left corner\r
274                 position2d<T> UpperLeftCorner;\r
275                 //! Lower right corner\r
276                 position2d<T> LowerRightCorner;\r
277         };\r
278 \r
279         //! Rectangle with float values\r
280         typedef rect<f32> rectf;\r
281         //! Rectangle with int values\r
282         typedef rect<s32> recti;\r
283 \r
284 } // end namespace core\r
285 } // end namespace irr\r
286 \r
287 #endif\r
288 \r