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