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
5 #ifndef __IRR_RECT_H_INCLUDED__
\r
6 #define __IRR_RECT_H_INCLUDED__
\r
8 #include "irrTypes.h"
\r
9 #include "dimension2d.h"
\r
10 #include "position2d.h"
\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
22 Coordinates are (0,0) for top-left corner, and increasing to the right
\r
30 //! Default constructor creating empty rectangle at (0,0)
\r
31 rect() : UpperLeftCorner(0,0), LowerRightCorner(0,0) {}
\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
37 //! Constructor with two corners
\r
38 rect(const position2d<T>& upperLeft, const position2d<T>& lowerRight)
\r
39 : UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {}
\r
41 //! Constructor with upper left corner and dimension
\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
46 //! Constructor with upper left at 0,0 and lower right using dimension
\r
48 explicit rect(const dimension2d<U>& size)
\r
49 : UpperLeftCorner(0,0), LowerRightCorner(size.Width, size.Height) {}
\r
51 //! move right by given numbers
\r
52 rect<T> operator+(const position2d<T>& pos) const
\r
58 //! move right by given numbers
\r
59 rect<T>& operator+=(const position2d<T>& pos)
\r
61 UpperLeftCorner += pos;
\r
62 LowerRightCorner += pos;
\r
66 //! move left by given numbers
\r
67 rect<T> operator-(const position2d<T>& pos) const
\r
73 //! move left by given numbers
\r
74 rect<T>& operator-=(const position2d<T>& pos)
\r
76 UpperLeftCorner -= pos;
\r
77 LowerRightCorner -= pos;
\r
81 //! equality operator
\r
82 bool operator==(const rect<T>& other) const
\r
84 return (UpperLeftCorner == other.UpperLeftCorner &&
\r
85 LowerRightCorner == other.LowerRightCorner);
\r
88 //! inequality operator
\r
89 bool operator!=(const rect<T>& other) const
\r
91 return (UpperLeftCorner != other.UpperLeftCorner ||
\r
92 LowerRightCorner != other.LowerRightCorner);
\r
95 //! compares size of rectangles
\r
96 bool operator<(const rect<T>& other) const
\r
98 return getArea() < other.getArea();
\r
101 //! Returns size of rectangle
\r
104 return getWidth() * getHeight();
\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
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
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
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
129 //! Clips this rectangle with another one.
\r
130 /** \param other Rectangle to clip with */
\r
131 void clipAgainst(const rect<T>& other)
\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
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
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
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
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
158 if (other.getWidth() < getWidth() || other.getHeight() < getHeight())
\r
161 T diff = other.LowerRightCorner.X - LowerRightCorner.X;
\r
164 LowerRightCorner.X += diff;
\r
165 UpperLeftCorner.X += diff;
\r
168 diff = other.LowerRightCorner.Y - LowerRightCorner.Y;
\r
171 LowerRightCorner.Y += diff;
\r
172 UpperLeftCorner.Y += diff;
\r
175 diff = UpperLeftCorner.X - other.UpperLeftCorner.X;
\r
178 UpperLeftCorner.X -= diff;
\r
179 LowerRightCorner.X -= diff;
\r
182 diff = UpperLeftCorner.Y - other.UpperLeftCorner.Y;
\r
185 UpperLeftCorner.Y -= diff;
\r
186 LowerRightCorner.Y -= diff;
\r
192 //! Get width of rectangle.
\r
195 return LowerRightCorner.X - UpperLeftCorner.X;
\r
198 //! Get height of rectangle.
\r
199 T getHeight() const
\r
201 return LowerRightCorner.Y - UpperLeftCorner.Y;
\r
204 //! If the lower right corner of the rect is smaller then the upper left, the points are swapped.
\r
207 if (LowerRightCorner.X < UpperLeftCorner.X)
\r
209 T t = LowerRightCorner.X;
\r
210 LowerRightCorner.X = UpperLeftCorner.X;
\r
211 UpperLeftCorner.X = t;
\r
214 if (LowerRightCorner.Y < UpperLeftCorner.Y)
\r
216 T t = LowerRightCorner.Y;
\r
217 LowerRightCorner.Y = UpperLeftCorner.Y;
\r
218 UpperLeftCorner.Y = t;
\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
227 return ((LowerRightCorner.X >= UpperLeftCorner.X) &&
\r
228 (LowerRightCorner.Y >= UpperLeftCorner.Y));
\r
231 //! Get the center of the rectangle
\r
232 position2d<T> getCenter() const
\r
234 return position2d<T>(
\r
235 (UpperLeftCorner.X + LowerRightCorner.X) / 2,
\r
236 (UpperLeftCorner.Y + LowerRightCorner.Y) / 2);
\r
239 //! Get the dimensions of the rectangle
\r
240 dimension2d<T> getSize() const
\r
242 return dimension2d<T>(getWidth(), getHeight());
\r
246 //! Adds a point to the rectangle
\r
247 /** Causes the rectangle to grow bigger if point is outside of
\r
249 \param p Point to add to the box. */
\r
250 void addInternalPoint(const position2d<T>& p)
\r
252 addInternalPoint(p.X, p.Y);
\r
255 //! Adds a point to the bounding rectangle
\r
256 /** Causes the rectangle to grow bigger if point is outside of
\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
262 if (x>LowerRightCorner.X)
\r
263 LowerRightCorner.X = x;
\r
264 if (y>LowerRightCorner.Y)
\r
265 LowerRightCorner.Y = y;
\r
267 if (x<UpperLeftCorner.X)
\r
268 UpperLeftCorner.X = x;
\r
269 if (y<UpperLeftCorner.Y)
\r
270 UpperLeftCorner.Y = y;
\r
273 //! Upper left corner
\r
274 position2d<T> UpperLeftCorner;
\r
275 //! Lower right corner
\r
276 position2d<T> LowerRightCorner;
\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
284 } // end namespace core
\r
285 } // end namespace irr
\r