#pragma once #include #include #include namespace renderive { struct Point { int x{}; int y{}; }; struct PointF { double x{}; double y{}; }; struct Size { int width{}; int height{}; [[nodiscard]] bool empty() const { return width <= 0 || height <= 0; } bool operator==(const Size& other) const { return width == other.width && height == other.height; } bool operator!=(const Size& other) const { return !(*this == other); } }; struct Rect { int x{}; int y{}; int width{}; int height{}; [[nodiscard]] bool empty() const { return width <= 0 || height <= 0; } [[nodiscard]] int right() const { return x + width; } [[nodiscard]] int bottom() const { return y + height; } [[nodiscard]] Point top_left() const { return {x, y}; } [[nodiscard]] bool contains(Point point) const { return point.x >= x && point.x <= right() && point.y >= y && point.y <= bottom(); } [[nodiscard]] Rect intersected(const Rect& other) const { int r = std::min(right(), other.right()); int b = std::min(bottom(), other.bottom()); int nx = std::max(x, other.x); int ny = std::max(y, other.y); int w = r - nx; int h = b - ny; if (w <= 0 || h <= 0) return {}; return {nx, ny, w, h}; } }; struct RectF { double x{}; double y{}; double width{}; double height{}; [[nodiscard]] bool empty() const { return width <= 0.0 || height <= 0.0; } [[nodiscard]] double right() const { return x + width; } [[nodiscard]] double bottom() const { return y + height; } [[nodiscard]] PointF top_left() const { return {x, y}; } [[nodiscard]] bool contains(PointF point) const { return point.x >= x && point.x <= right() && point.y >= y && point.y <= bottom(); } [[nodiscard]] RectF normalized() const { double nx = x; double ny = y; double nw = width; double nh = height; if (nw < 0.0) { nx += nw; nw = -nw; } if (nh < 0.0) { ny += nh; nh = -nh; } return {nx, ny, nw, nh}; } [[nodiscard]] RectF intersected(const RectF& other) const { double r = std::min(right(), other.right()); double b = std::min(bottom(), other.bottom()); double nx = std::max(x, other.x); double ny = std::max(y, other.y); double w = r - nx; double h = b - ny; if (w <= 0.0 || h <= 0.0) return {}; return {nx, ny, w, h}; } }; enum class Orientation : std::uint8_t { Horizontal, Vertical }; struct Range { double origin; double target; [[nodiscard]] double size() const { return target > origin ? target - origin : origin - target; } [[nodiscard]] double length() const { return target - origin; } [[nodiscard]] double center() const { return origin + (target - origin) / 2.0; } bool operator==(const Range& other) const { return origin == other.origin && target == other.target; } bool operator!=(const Range& other) const { return !(*this == other); } [[nodiscard]] bool contain(double value) const { if (origin < target) return value > origin - 0.0001 && value < target + 0.0001; return value > target - 0.0001 && value < origin + 0.0001; } }; std::ostream& operator<<(std::ostream& stream, const Range& range); } // namespace renderive