#pragma once #include #include #include namespace extra2d { // --------------------------------------------------------------------------- // 2D 矩形 // --------------------------------------------------------------------------- struct Rect { Point origin; Size size; constexpr Rect() = default; constexpr Rect(float x, float y, float w, float h) : origin(x, y), size(w, h) {} constexpr Rect(const Point &o, const Size &s) : origin(o), size(s) {} float left() const { return origin.x; } float top() const { return origin.y; } float right() const { return origin.x + size.width; } float bottom() const { return origin.y + size.height; } float width() const { return size.width; } float height() const { return size.height; } Point center() const { return {origin.x + size.width * 0.5f, origin.y + size.height * 0.5f}; } bool empty() const { return size.empty(); } bool containsPoint(const Point &p) const { return p.x >= left() && p.x <= right() && p.y >= top() && p.y <= bottom(); } bool contains(const Rect &r) const { return r.left() >= left() && r.right() <= right() && r.top() >= top() && r.bottom() <= bottom(); } bool intersects(const Rect &r) const { return !(left() > r.right() || right() < r.left() || top() > r.bottom() || bottom() < r.top()); } Rect intersection(const Rect &r) const { float l = std::max(left(), r.left()); float t = std::max(top(), r.top()); float ri = std::min(right(), r.right()); float b = std::min(bottom(), r.bottom()); if (l < ri && t < b) return {l, t, ri - l, b - t}; return {}; } Rect unionWith(const Rect &r) const { if (empty()) return r; if (r.empty()) return *this; float l = std::min(left(), r.left()); float t = std::min(top(), r.top()); float ri = std::max(right(), r.right()); float b = std::max(bottom(), r.bottom()); return {l, t, ri - l, b - t}; } bool operator==(const Rect &r) const { return origin == r.origin && size == r.size; } bool operator!=(const Rect &r) const { return !(*this == r); } static constexpr Rect Zero() { return {0, 0, 0, 0}; } }; } // namespace extra2d