123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- // Copyright (C) 2002-2012 Nikolaus Gebhardt
- // This file is part of the "Irrlicht Engine".
- // For conditions of distribution and use, see copyright notice in irrlicht.h
- #pragma once
- #include "irrTypes.h"
- #include "dimension2d.h"
- #include "position2d.h"
- namespace irr
- {
- namespace core
- {
- //! Rectangle template.
- /** Mostly used by 2D GUI elements and for 2D drawing methods.
- It has 2 positions instead of position and dimension and a fast
- method for collision detection with other rectangles and points.
- Coordinates are (0,0) for top-left corner, and increasing to the right
- and to the bottom.
- */
- template <class T>
- class rect
- {
- public:
- //! Default constructor creating empty rectangle at (0,0)
- constexpr rect() :
- UpperLeftCorner(0, 0), LowerRightCorner(0, 0) {}
- //! Constructor with two corners
- constexpr rect(T x, T y, T x2, T y2) :
- UpperLeftCorner(x, y), LowerRightCorner(x2, y2) {}
- //! Constructor with two corners
- constexpr rect(const position2d<T> &upperLeft, const position2d<T> &lowerRight) :
- UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {}
- //! Constructor with upper left corner and dimension
- template <class U>
- constexpr rect(const position2d<T> &pos, const dimension2d<U> &size) :
- UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height)
- {
- }
- //! Constructor with upper left at 0,0 and lower right using dimension
- template <class U>
- explicit constexpr rect(const dimension2d<U> &size) :
- UpperLeftCorner(0, 0), LowerRightCorner(size.Width, size.Height)
- {
- }
- //! move right by given numbers
- rect<T> operator+(const position2d<T> &pos) const
- {
- rect<T> ret(*this);
- return ret += pos;
- }
- //! move right by given numbers
- rect<T> &operator+=(const position2d<T> &pos)
- {
- UpperLeftCorner += pos;
- LowerRightCorner += pos;
- return *this;
- }
- //! move left by given numbers
- rect<T> operator-(const position2d<T> &pos) const
- {
- rect<T> ret(*this);
- return ret -= pos;
- }
- //! move left by given numbers
- rect<T> &operator-=(const position2d<T> &pos)
- {
- UpperLeftCorner -= pos;
- LowerRightCorner -= pos;
- return *this;
- }
- //! equality operator
- constexpr bool operator==(const rect<T> &other) const
- {
- return (UpperLeftCorner == other.UpperLeftCorner &&
- LowerRightCorner == other.LowerRightCorner);
- }
- //! inequality operator
- constexpr bool operator!=(const rect<T> &other) const
- {
- return (UpperLeftCorner != other.UpperLeftCorner ||
- LowerRightCorner != other.LowerRightCorner);
- }
- //! compares size of rectangles
- bool operator<(const rect<T> &other) const
- {
- return getArea() < other.getArea();
- }
- //! Returns size of rectangle
- T getArea() const
- {
- return getWidth() * getHeight();
- }
- //! Returns if a 2d point is within this rectangle.
- /** \param pos Position to test if it lies within this rectangle.
- \return True if the position is within the rectangle, false if not. */
- bool isPointInside(const position2d<T> &pos) const
- {
- return (UpperLeftCorner.X <= pos.X &&
- UpperLeftCorner.Y <= pos.Y &&
- LowerRightCorner.X >= pos.X &&
- LowerRightCorner.Y >= pos.Y);
- }
- //! Check if the rectangle collides with another rectangle.
- /** \param other Rectangle to test collision with
- \return True if the rectangles collide. */
- bool isRectCollided(const rect<T> &other) const
- {
- return (LowerRightCorner.Y > other.UpperLeftCorner.Y &&
- UpperLeftCorner.Y < other.LowerRightCorner.Y &&
- LowerRightCorner.X > other.UpperLeftCorner.X &&
- UpperLeftCorner.X < other.LowerRightCorner.X);
- }
- //! Clips this rectangle with another one.
- /** \param other Rectangle to clip with */
- void clipAgainst(const rect<T> &other)
- {
- if (other.LowerRightCorner.X < LowerRightCorner.X)
- LowerRightCorner.X = other.LowerRightCorner.X;
- if (other.LowerRightCorner.Y < LowerRightCorner.Y)
- LowerRightCorner.Y = other.LowerRightCorner.Y;
- if (other.UpperLeftCorner.X > LowerRightCorner.X)
- LowerRightCorner.X = other.UpperLeftCorner.X;
- if (other.UpperLeftCorner.Y > LowerRightCorner.Y)
- LowerRightCorner.Y = other.UpperLeftCorner.Y;
- if (other.LowerRightCorner.X < UpperLeftCorner.X)
- UpperLeftCorner.X = other.LowerRightCorner.X;
- if (other.LowerRightCorner.Y < UpperLeftCorner.Y)
- UpperLeftCorner.Y = other.LowerRightCorner.Y;
- if (other.UpperLeftCorner.X > UpperLeftCorner.X)
- UpperLeftCorner.X = other.UpperLeftCorner.X;
- if (other.UpperLeftCorner.Y > UpperLeftCorner.Y)
- UpperLeftCorner.Y = other.UpperLeftCorner.Y;
- }
- //! Moves this rectangle to fit inside another one.
- /** \return True on success, false if not possible */
- bool constrainTo(const rect<T> &other)
- {
- if (other.getWidth() < getWidth() || other.getHeight() < getHeight())
- return false;
- T diff = other.LowerRightCorner.X - LowerRightCorner.X;
- if (diff < 0) {
- LowerRightCorner.X += diff;
- UpperLeftCorner.X += diff;
- }
- diff = other.LowerRightCorner.Y - LowerRightCorner.Y;
- if (diff < 0) {
- LowerRightCorner.Y += diff;
- UpperLeftCorner.Y += diff;
- }
- diff = UpperLeftCorner.X - other.UpperLeftCorner.X;
- if (diff < 0) {
- UpperLeftCorner.X -= diff;
- LowerRightCorner.X -= diff;
- }
- diff = UpperLeftCorner.Y - other.UpperLeftCorner.Y;
- if (diff < 0) {
- UpperLeftCorner.Y -= diff;
- LowerRightCorner.Y -= diff;
- }
- return true;
- }
- //! Get width of rectangle.
- T getWidth() const
- {
- return LowerRightCorner.X - UpperLeftCorner.X;
- }
- //! Get height of rectangle.
- T getHeight() const
- {
- return LowerRightCorner.Y - UpperLeftCorner.Y;
- }
- //! If the lower right corner of the rect is smaller then the upper left, the points are swapped.
- void repair()
- {
- if (LowerRightCorner.X < UpperLeftCorner.X) {
- T t = LowerRightCorner.X;
- LowerRightCorner.X = UpperLeftCorner.X;
- UpperLeftCorner.X = t;
- }
- if (LowerRightCorner.Y < UpperLeftCorner.Y) {
- T t = LowerRightCorner.Y;
- LowerRightCorner.Y = UpperLeftCorner.Y;
- UpperLeftCorner.Y = t;
- }
- }
- //! Returns if the rect is valid to draw.
- /** It would be invalid if the UpperLeftCorner is lower or more
- right than the LowerRightCorner. */
- bool isValid() const
- {
- return ((LowerRightCorner.X >= UpperLeftCorner.X) &&
- (LowerRightCorner.Y >= UpperLeftCorner.Y));
- }
- //! Get the center of the rectangle
- position2d<T> getCenter() const
- {
- return position2d<T>(
- (UpperLeftCorner.X + LowerRightCorner.X) / 2,
- (UpperLeftCorner.Y + LowerRightCorner.Y) / 2);
- }
- //! Get the dimensions of the rectangle
- dimension2d<T> getSize() const
- {
- return dimension2d<T>(getWidth(), getHeight());
- }
- //! Adds a point to the rectangle
- /** Causes the rectangle to grow bigger if point is outside of
- the box
- \param p Point to add to the box. */
- void addInternalPoint(const position2d<T> &p)
- {
- addInternalPoint(p.X, p.Y);
- }
- //! Adds a point to the bounding rectangle
- /** Causes the rectangle to grow bigger if point is outside of
- the box
- \param x X-Coordinate of the point to add to this box.
- \param y Y-Coordinate of the point to add to this box. */
- void addInternalPoint(T x, T y)
- {
- if (x > LowerRightCorner.X)
- LowerRightCorner.X = x;
- if (y > LowerRightCorner.Y)
- LowerRightCorner.Y = y;
- if (x < UpperLeftCorner.X)
- UpperLeftCorner.X = x;
- if (y < UpperLeftCorner.Y)
- UpperLeftCorner.Y = y;
- }
- //! Upper left corner
- position2d<T> UpperLeftCorner;
- //! Lower right corner
- position2d<T> LowerRightCorner;
- };
- //! Rectangle with float values
- typedef rect<f32> rectf;
- //! Rectangle with int values
- typedef rect<s32> recti;
- } // end namespace core
- } // end namespace irr
|