| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- //
- // Copyright (c) 2008-2020 the Urho3D project.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- #pragma once
- #include "../Math/Vector4.h"
- namespace Urho3D
- {
- /// Two-dimensional bounding rectangle.
- /// @allfloats
- class URHO3D_API Rect
- {
- public:
- /// Construct an undefined rect.
- Rect() noexcept :
- min_(M_INFINITY, M_INFINITY),
- max_(-M_INFINITY, -M_INFINITY)
- {
- }
- /// Construct from minimum and maximum vectors.
- Rect(const Vector2& min, const Vector2& max) noexcept :
- min_(min),
- max_(max)
- {
- }
- /// Construct from coordinates.
- Rect(float left, float top, float right, float bottom) noexcept :
- min_(left, top),
- max_(right, bottom)
- {
- }
- /// Construct from a Vector4.
- explicit Rect(const Vector4& vector) noexcept :
- min_(vector.x_, vector.y_),
- max_(vector.z_, vector.w_)
- {
- }
- /// Construct from a float array.
- explicit Rect(const float* data) noexcept :
- min_(data[0], data[1]),
- max_(data[2], data[3])
- {
- }
- /// Copy-construct from another rect.
- Rect(const Rect& rect) noexcept = default;
- /// Assign from another rect.
- Rect& operator =(const Rect& rhs) noexcept = default;
- /// Test for equality with another rect.
- bool operator ==(const Rect& rhs) const { return min_ == rhs.min_ && max_ == rhs.max_; }
- /// Test for inequality with another rect.
- bool operator !=(const Rect& rhs) const { return min_ != rhs.min_ || max_ != rhs.max_; }
- /// Add another rect to this one inplace.
- Rect& operator +=(const Rect& rhs)
- {
- min_ += rhs.min_;
- max_ += rhs.max_;
- return *this;
- }
- /// Subtract another rect from this one inplace.
- Rect& operator -=(const Rect& rhs)
- {
- min_ -= rhs.min_;
- max_ -= rhs.max_;
- return *this;
- }
- /// Divide by scalar inplace.
- Rect& operator /=(float value)
- {
- min_ /= value;
- max_ /= value;
- return *this;
- }
- /// Multiply by scalar inplace.
- Rect& operator *=(float value)
- {
- min_ *= value;
- max_ *= value;
- return *this;
- }
- /// Divide by scalar.
- Rect operator /(float value) const
- {
- return Rect(min_ / value, max_ / value);
- }
- /// Multiply by scalar.
- Rect operator *(float value) const
- {
- return Rect(min_ * value, max_ * value);
- }
- /// Add another rect.
- Rect operator +(const Rect& rhs) const
- {
- return Rect(min_ + rhs.min_, max_ + rhs.max_);
- }
- /// Subtract another rect.
- Rect operator -(const Rect& rhs) const
- {
- return Rect(min_ - rhs.min_, max_ - rhs.max_);
- }
- /// Define from another rect.
- void Define(const Rect& rect)
- {
- min_ = rect.min_;
- max_ = rect.max_;
- }
- /// Define from minimum and maximum vectors.
- void Define(const Vector2& min, const Vector2& max)
- {
- min_ = min;
- max_ = max;
- }
- /// Define from a point.
- void Define(const Vector2& point)
- {
- min_ = max_ = point;
- }
- /// Merge a point.
- void Merge(const Vector2& point)
- {
- if (point.x_ < min_.x_)
- min_.x_ = point.x_;
- if (point.x_ > max_.x_)
- max_.x_ = point.x_;
- if (point.y_ < min_.y_)
- min_.y_ = point.y_;
- if (point.y_ > max_.y_)
- max_.y_ = point.y_;
- }
- /// Merge a rect.
- void Merge(const Rect& rect)
- {
- if (rect.min_.x_ < min_.x_)
- min_.x_ = rect.min_.x_;
- if (rect.min_.y_ < min_.y_)
- min_.y_ = rect.min_.y_;
- if (rect.max_.x_ > max_.x_)
- max_.x_ = rect.max_.x_;
- if (rect.max_.y_ > max_.y_)
- max_.y_ = rect.max_.y_;
- }
- /// Clear to undefined state.
- void Clear()
- {
- min_ = Vector2(M_INFINITY, M_INFINITY);
- max_ = Vector2(-M_INFINITY, -M_INFINITY);
- }
- /// Clip with another rect.
- void Clip(const Rect& rect);
- /// Return true if this rect is defined via a previous call to Define() or Merge().
- bool Defined() const
- {
- return min_.x_ != M_INFINITY;
- }
- /// Return center.
- /// @property
- Vector2 Center() const { return (max_ + min_) * 0.5f; }
- /// Return size.
- /// @property
- Vector2 Size() const { return max_ - min_; }
- /// Return half-size.
- /// @property
- Vector2 HalfSize() const { return (max_ - min_) * 0.5f; }
- /// Test for equality with another rect with epsilon.
- bool Equals(const Rect& rhs) const { return min_.Equals(rhs.min_) && max_.Equals(rhs.max_); }
- /// Test whether a point is inside.
- Intersection IsInside(const Vector2& point) const
- {
- if (point.x_ < min_.x_ || point.y_ < min_.y_ || point.x_ > max_.x_ || point.y_ > max_.y_)
- return OUTSIDE;
- else
- return INSIDE;
- }
- /// Test if another rect is inside, outside or intersects.
- Intersection IsInside(const Rect& rect) const
- {
- if (rect.max_.x_ < min_.x_ || rect.min_.x_ > max_.x_ || rect.max_.y_ < min_.y_ || rect.min_.y_ > max_.y_)
- return OUTSIDE;
- else if (rect.min_.x_ < min_.x_ || rect.max_.x_ > max_.x_ || rect.min_.y_ < min_.y_ || rect.max_.y_ > max_.y_)
- return INTERSECTS;
- else
- return INSIDE;
- }
- /// Return float data.
- const float* Data() const { return &min_.x_; }
- /// Return as a vector.
- Vector4 ToVector4() const { return Vector4(min_.x_, min_.y_, max_.x_, max_.y_); }
- /// Return as string.
- String ToString() const;
- /// Return left-top corner position.
- Vector2 Min() const { return min_; }
- /// Return right-bottom corner position.
- Vector2 Max() const { return max_; }
- /// Return left coordinate.
- /// @property
- float Left() const { return min_.x_; }
- /// Return top coordinate.
- /// @property
- float Top() const { return min_.y_; }
- /// Return right coordinate.
- /// @property
- float Right() const { return max_.x_; }
- /// Return bottom coordinate.
- /// @property
- float Bottom() const { return max_.y_; }
- /// Minimum vector.
- Vector2 min_;
- /// Maximum vector.
- Vector2 max_;
- /// Rect in the range (-1, -1) - (1, 1).
- static const Rect FULL;
- /// Rect in the range (0, 0) - (1, 1).
- static const Rect POSITIVE;
- /// Zero-sized rect.
- static const Rect ZERO;
- };
- /// Two-dimensional bounding rectangle with integer values.
- class URHO3D_API IntRect
- {
- public:
- /// Construct a zero rect.
- IntRect() noexcept :
- left_(0),
- top_(0),
- right_(0),
- bottom_(0)
- {
- }
- /// Construct from minimum and maximum vectors.
- IntRect(const IntVector2& min, const IntVector2& max) noexcept :
- left_(min.x_),
- top_(min.y_),
- right_(max.x_),
- bottom_(max.y_)
- {
- }
- /// Construct from coordinates.
- IntRect(int left, int top, int right, int bottom) noexcept :
- left_(left),
- top_(top),
- right_(right),
- bottom_(bottom)
- {
- }
- /// Construct from an int array.
- explicit IntRect(const int* data) noexcept :
- left_(data[0]),
- top_(data[1]),
- right_(data[2]),
- bottom_(data[3])
- {
- }
- /// Test for equality with another rect.
- bool operator ==(const IntRect& rhs) const
- {
- return left_ == rhs.left_ && top_ == rhs.top_ && right_ == rhs.right_ && bottom_ == rhs.bottom_;
- }
- /// Test for inequality with another rect.
- bool operator !=(const IntRect& rhs) const
- {
- return left_ != rhs.left_ || top_ != rhs.top_ || right_ != rhs.right_ || bottom_ != rhs.bottom_;
- }
- /// Add another rect to this one inplace.
- IntRect& operator +=(const IntRect& rhs)
- {
- left_ += rhs.left_;
- top_ += rhs.top_;
- right_ += rhs.right_;
- bottom_ += rhs.bottom_;
- return *this;
- }
- /// Subtract another rect from this one inplace.
- IntRect& operator -=(const IntRect& rhs)
- {
- left_ -= rhs.left_;
- top_ -= rhs.top_;
- right_ -= rhs.right_;
- bottom_ -= rhs.bottom_;
- return *this;
- }
- /// Divide by scalar inplace.
- IntRect& operator /=(float value)
- {
- left_ = static_cast<int>(left_ / value);
- top_ = static_cast<int>(top_ / value);
- right_ = static_cast<int>(right_ / value);
- bottom_ = static_cast<int>(bottom_ / value);
- return *this;
- }
- /// Multiply by scalar inplace.
- IntRect& operator *=(float value)
- {
- left_ = static_cast<int>(left_ * value);
- top_ = static_cast<int>(top_ * value);
- right_ = static_cast<int>(right_ * value);
- bottom_ = static_cast<int>(bottom_ * value);
- return *this;
- }
- /// Divide by scalar.
- IntRect operator /(float value) const
- {
- return {
- static_cast<int>(left_ / value), static_cast<int>(top_ / value),
- static_cast<int>(right_ / value), static_cast<int>(bottom_ / value)
- };
- }
- /// Multiply by scalar.
- IntRect operator *(float value) const
- {
- return {
- static_cast<int>(left_ * value), static_cast<int>(top_ * value),
- static_cast<int>(right_ * value), static_cast<int>(bottom_ * value)
- };
- }
- /// Add another rect.
- IntRect operator +(const IntRect& rhs) const
- {
- return {
- left_ + rhs.left_, top_ + rhs.top_,
- right_ + rhs.right_, bottom_ + rhs.bottom_
- };
- }
- /// Subtract another rect.
- IntRect operator -(const IntRect& rhs) const
- {
- return {
- left_ - rhs.left_, top_ - rhs.top_,
- right_ - rhs.right_, bottom_ - rhs.bottom_
- };
- }
- /// Return size.
- /// @property
- IntVector2 Size() const { return IntVector2(Width(), Height()); }
- /// Return width.
- /// @property
- int Width() const { return right_ - left_; }
- /// Return height.
- /// @property
- int Height() const { return bottom_ - top_; }
- /// Test whether a point is inside.
- Intersection IsInside(const IntVector2& point) const
- {
- if (point.x_ < left_ || point.y_ < top_ || point.x_ >= right_ || point.y_ >= bottom_)
- return OUTSIDE;
- else
- return INSIDE;
- }
- /// Test if another rect is inside, outside or intersects.
- Intersection IsInside(const IntRect& rect) const
- {
- if (rect.right_ < left_ || rect.left_ >= right_ || rect.bottom_ < top_ || rect.top_ >= bottom_)
- return OUTSIDE;
- else if (rect.left_ < left_ || rect.right_ > right_ || rect.top_ < top_ || rect.bottom_ > bottom_)
- return INTERSECTS;
- else
- return INSIDE;
- }
- /// Clip with another rect. Since IntRect does not have an undefined state
- /// like Rect, return (0, 0, 0, 0) if the result is empty.
- void Clip(const IntRect& rect);
- /// Merge a rect. If this rect was empty, become the other rect. If the
- /// other rect is empty, do nothing.
- void Merge(const IntRect& rect);
- /// Return integer data.
- const int* Data() const { return &left_; }
- /// Return as string.
- String ToString() const;
- /// Return left-top corner position.
- IntVector2 Min() const { return {left_, top_}; }
- /// Return right-bottom corner position.
- IntVector2 Max() const { return {right_, bottom_}; }
- /// Return left coordinate.
- int Left() const { return left_; }
- /// Return top coordinate.
- int Top() const { return top_; }
- /// Return right coordinate.
- int Right() const { return right_; }
- /// Return bottom coordinate.
- int Bottom() const { return bottom_; }
- /// Left coordinate.
- int left_;
- /// Top coordinate.
- int top_;
- /// Right coordinate.
- int right_;
- /// Bottom coordinate.
- int bottom_;
- /// Zero-sized rect.
- static const IntRect ZERO;
- };
- }
|