#pragma once
/**
 * @file rect.h
 * @brief 定义表示二维空间中矩形的模板类
 *
 * 本文件定义了rect_t模板类，提供了丰富的矩形操作功能，包括创建、变换、
 * 查询、测试、集合运算和布局等功能。适用于UI系统的几何计算。
 */

#include <Eigen/Eigen>
#include <limits>
#include <sstream>
#include <vector>
#include <array>

#include "margin.h"
#include "misc/mirage_type.h"

/**
 * @brief 表示二维空间中的矩形
 *
 * 矩形由左上角位置(position_)和大小(size_)表示。
 * 支持各种几何操作如平移、缩放、合并等。
 *
 * @tparam T 坐标和尺寸的数据类型，默认为float
 */
template<typename T = float>
class rect_t {
public:
    //-------------- 构造函数和工厂方法 --------------

    /** @brief 默认构造函数 */
    rect_t() = default;

    /**
     * @brief 使用位置和大小构造矩形
     * @param in_position 左上角位置
     * @param in_size 矩形大小
     */
    rect_t(const Eigen::Vector2<T>& in_position, const Eigen::Vector2<T>& in_size) :
        position_(in_position), size_(in_size) {
    }

    /**
     * @brief 从两个点构造矩形
     * @param in_point1 第一个点
     * @param in_point2 第二个点
     * @return 新构造的矩形
     */
    static auto from_two_points(const Eigen::Vector2<T>& in_point1, const Eigen::Vector2<T>& in_point2) {
        auto min = in_point1.cwiseMin(in_point2);
        auto max = in_point1.cwiseMax(in_point2);
        return rect_t(min, max - min);
    }

    /**
     * @brief 从中心点和大小构造矩形
     * @param in_center 中心点
     * @param in_size 矩形大小
     * @return 新构造的矩形
     */
    static auto from_center_and_size(const Eigen::Vector2<T>& in_center, const Eigen::Vector2<T>& in_size) {
        return rect_t(in_center - in_size / 2, in_size);
    }

    /**
     * @brief 创建空矩形
     * @return 位置和大小均为零的矩形
     */
    static auto empty() {
        return rect_t(Eigen::Vector2<T>(0, 0), Eigen::Vector2<T>(0, 0));
    }

    /**
     * @brief 从大小创建矩形
     * @param in_size 矩形大小
     * @return 位置为原点，指定大小的矩形
     */
    static auto from_size(const Eigen::Vector2<T>& in_size) {
        return rect_t(Eigen::Vector2<T>(0, 0), in_size);
    }

    /**
     * @brief 创建单位矩形
     * @return 位置为原点，大小为1的矩形
     */
    static auto unit() {
        return rect_t(Eigen::Vector2<T>(0, 0), Eigen::Vector2<T>(1, 1));
    }

    /**
     * @brief 创建具有指定宽高比和面积的矩形
     * @param in_aspect_ratio 宽高比(宽/高)
     * @param in_area 面积，默认为1
     * @return 具有指定宽高比和面积的矩形
     */
    static auto with_aspect_ratio(float in_aspect_ratio, float in_area = 1.f) {
        if (in_aspect_ratio <= 0) {
            return empty();
        }
        auto width = std::sqrt(in_area * in_aspect_ratio);
        auto height = width / in_aspect_ratio;

        return rect_t(Eigen::Vector2<T>(0, 0), Eigen::Vector2<T>(width, height));
    }

    /**
     * @brief 从物理像素矩形转换
     * @param in_physical_rect 物理像素矩形
     * @param in_dpi_scale DPI比例
     * @return 转换后的矩形
     */
    static auto from_physical_pixels(const rect_t& in_physical_rect, float in_dpi_scale) {
        if (in_dpi_scale == 1.0f) {
            return in_physical_rect;
        }
        return rect_t(in_physical_rect.position_ / in_dpi_scale, in_physical_rect.size() / in_dpi_scale);
    }

    /**
     * @brief 计算一组点的包围盒
     * @param in_points 点的集合
     * @tparam U 点的数据类型
     * @return 包含所有点的最小矩形
     */
    template<typename U>
    static auto bounding_box(const std::vector<Eigen::Vector2<U>>& in_points) {
        if (in_points.empty()) {
            return empty();
        }
        auto min = in_points[0];
        auto max = in_points[0];
        for (const auto& point : in_points) {
            min = min.cwiseMin(point);
            max = max.cwiseMax(point);
        }
        return rect_t(Eigen::Vector2<T>(min), Eigen::Vector2<T>(max - min));
    }

    //-------------- 类型转换 --------------

    /**
     * @brief 转换矩形的数据类型
     * @tparam U 目标数据类型
     * @return 转换后的矩形
     */
    template<typename U>
    auto cast() const {
        return rect_t<U>(position_.template cast<U>(), size_.template cast<U>());
    }

    //-------------- 基本属性访问 --------------

    /**
     * @brief 获取位置
     * @return 矩形位置
     */
    const auto& position() const { return position_; }

    /**
     * @brief 获取大小
     * @return 矩形大小
     */
    const auto& size() const { return size_; }

    /**
     * @brief 获取位置
     * @return 矩形位置
     */
    auto& position() { return position_; }

    /**
     * @brief 获取大小
     * @return 矩形大小
     */
    auto& size() { return size_; }

    /**
     * @brief 获取左边界
     * @return 左边界位置
     */
    auto left() const { return position_.x(); }

    /**
     * @brief 获取右边界
     * @return 右边界位置
     */
    auto right() const { return position_.x() + size_.x(); }

    /**
     * @brief 获取上边界
     * @return 上边界位置
     */
    auto top() const { return position_.y(); }

    /**
     * @brief 获取下边界
     * @return 下边界位置
     */
    auto bottom() const { return position_.y() + size_.y(); }

    /**
     * @brief 获取宽度
     * @return 矩形宽度
     */
    auto width() const { return size_.x(); }

    /**
     * @brief 获取高度
     * @return 矩形高度
     */
    auto height() const { return size_.y(); }

    /**
     * @brief 获取左上角点
     * @return 左上角点
     */
    auto top_left() const { return position_; }

    /**
     * @brief 获取右上角点
     * @return 右上角点
     */
    auto top_right() const { return position_ + Eigen::Vector2<T>(size_.x(), 0); }

    /**
     * @brief 获取左下角点
     * @return 左下角点
     */
    auto bottom_left() const { return position_ + Eigen::Vector2<T>(0, size_.y()); }

    /**
     * @brief 获取右下角点
     * @return 右下角点
     */
    auto bottom_right() const { return position_ + size_; }

    /**
     * @brief 获取中心点
     * @return 中心点
     */
    auto center() const { return position_ + size_ / 2; }

    //-------------- 属性计算 --------------

    /**
     * @brief 计算矩形面积
     * @return 矩形面积
     */
    auto area() const { return size_.x() * size_.y(); }

    /**
     * @brief 计算矩形周长
     * @return 矩形周长
     */
    auto perimeter() const { return 2 * (size_.x() + size_.y()); }

    /**
     * @brief 计算矩形宽高比
     * @return 宽度/高度比值
     */
    auto aspect_ratio() const { return size_.x() / size_.y(); }

    /**
     * @brief 检查矩形是否有效(宽高均为正)
     * @return 若矩形有效则为true，否则为false
     */
    auto is_valid() const { return size_.x() > 0 && size_.y() > 0; }

    /**
     * @brief 检查矩形是否为空(宽或高不为正)
     * @return 若矩形为空则为true，否则为false
     */
    auto is_empty() const { return size_.x() <= 0 || size_.y() <= 0; }

    //-------------- 设置属性 --------------

    /**
     * @brief 设置左边界
     * @param in_left 左边界位置
     */
    void set_left(T in_left) { position_.x() = in_left; }

    /**
     * @brief 设置右边界
     * @param in_right 右边界位置
     */
    void set_right(T in_right) { position_.x() = in_right - size_.x(); }

    /**
     * @brief 设置上边界
     * @param in_top 上边界位置
     */
    void set_top(T in_top) { position_.y() = in_top; }

    /**
     * @brief 设置下边界
     * @param in_bottom 下边界位置
     */
    void set_bottom(T in_bottom) { position_.y() = in_bottom - size_.y(); }

    /**
     * @brief 设置矩形大小
     * @param in_size 新大小
     */
    void set_size(const Eigen::Vector2<T>& in_size) { size_ = in_size; }

    /**
     * @brief 设置矩形位置
     * @param in_position 新位置
     */
    void set_position(const Eigen::Vector2<T>& in_position) { position_ = in_position; }

    /**
     * @brief 设置矩形中心点
     * @param in_center 新中心点
     */
    void set_center(const Eigen::Vector2<T>& in_center) { position_ = in_center - size_ / 2; }

    //-------------- 几何变换 - 创建新实例 --------------

    /**
     * @brief 返回规范化的矩形(保证宽高为正)
     * @return 规范化后的矩形
     */
    auto normalized() const {
        auto min = position_.cwiseMin(position_ + size_);
        auto max = position_.cwiseMax(position_ + size_);
        return rect_t(min, max - min);
    }

    /**
     * @brief 返回平移后的矩形
     * @param in_offset 偏移量
     * @return 平移后的矩形
     */
    auto translated(const Eigen::Vector2<T>& in_offset) const {
        return rect_t(position_ + in_offset, size_);
    }

    /**
     * @brief 返回调整大小后的矩形(保持左上角位置)
     * @param in_size 新大小
     * @return 调整大小后的矩形
     */
    auto resized(const Eigen::Vector2<T>& in_size) const {
        return rect_t(position_, in_size);
    }

    /**
     * @brief 返回从中心调整大小后的矩形
     * @param in_size 新大小
     * @return 调整大小后的矩形
     */
    auto resized_from_center(const Eigen::Vector2<T>& in_size) const {
        return rect_t(position_ + (size_ - in_size) / 2, in_size);
    }

    /**
     * @brief 返回在四个方向上膨胀后的矩形
     * @param in_offset 膨胀量
     * @return 膨胀后的矩形
     */
    auto inflated(T in_offset) const {
        return rect_t(position_ - Eigen::Vector2<T>(in_offset, in_offset),
                      size_ + Eigen::Vector2<T>(in_offset * 2, in_offset * 2));
    }

    /**
     * @brief 返回在水平和垂直方向上膨胀后的矩形
     * @param in_horizontal 水平方向膨胀量
     * @param in_vertical 垂直方向膨胀量
     * @return 膨胀后的矩形
     */
    auto inflated(T in_horizontal, T in_vertical) const {
        return rect_t(position_ - Eigen::Vector2<T>(in_horizontal, in_vertical),
                      size_ + Eigen::Vector2<T>(in_horizontal * 2, in_vertical * 2));
    }

    /**
     * @brief 返回在四个方向上收缩后的矩形
     * @param in_offset 收缩量
     * @return 收缩后的矩形
     */
    auto deflated(T in_offset) const {
        return inflated(-in_offset);
    }

    /**
     * @brief 返回在水平和垂直方向上收缩后的矩形
     * @param in_horizontal 水平方向收缩量
     * @param in_vertical 垂直方向收缩量
     * @return 收缩后的矩形
     */
    auto deflated(T in_horizontal, T in_vertical) const {
        return inflated(-in_horizontal, -in_vertical);
    }

    /**
     * @brief 创建内嵌矩形
     * @param in_left 左边距
     * @param in_top 上边距
     * @param in_right 右边距
     * @param in_bottom 下边距
     * @return 内嵌矩形
     */
    auto inset(T in_left, T in_top, T in_right, T in_bottom) const {
        return rect_t(position_ + Eigen::Vector2<T>(in_left, in_top),
                      size_ - Eigen::Vector2<T>(in_left + in_right, in_top + in_bottom));
    }

    /**
     * @brief 创建均匀内嵌矩形
     * @param in_amount 内嵌量
     * @return 内嵌矩形
     */
    auto inset(T in_amount) const {
        return inset(in_amount, in_amount, in_amount, in_amount);
    }

    /**
     * @brief 应用边距
     * @param in_margin 边距
     * @return 应用边距后的矩形
     */
    auto apply_margin(const margin_t& in_margin) const {
        return rect_t(position_ + Eigen::Vector2<T>(in_margin.left, in_margin.top),
                     size_ - Eigen::Vector2<T>(in_margin.left + in_margin.right, in_margin.top + in_margin.bottom));
    }

    /**
     * @brief 将矩形坐标对齐到整数像素
     * @return 对齐后的矩形
     */
    auto snap_to_pixels() const {
        return rect_t(position_.template cast<int>().template cast<T>(),
                      size_.template cast<int>().template cast<T>());
    }

    /**
     * @brief 根据DPI缩放矩形
     * @param in_dpi_scale DPI缩放系数
     * @return 缩放后的矩形
     */
    auto scaled_by_dpi(float in_dpi_scale) const {
        return rect_t(position_ * in_dpi_scale, size_ * in_dpi_scale);
    }

    //-------------- 几何变换 - 修改当前实例 --------------

    /**
     * @brief 原地规范化矩形(保证宽高为正)
     */
    void normalize() {
        auto min = position_.cwiseMin(position_ + size_);
        auto max = position_.cwiseMax(position_ + size_);
        position_ = min;
        size_ = max - min;
    }

    /**
     * @brief 原地膨胀矩形
     * @param in_offset 膨胀量
     */
    void inflate(T in_offset) {
        position_ -= Eigen::Vector2<T>(in_offset, in_offset);
        size_ += Eigen::Vector2<T>(in_offset * 2, in_offset * 2);
    }

    /**
     * @brief 原地在水平和垂直方向上膨胀矩形
     * @param in_horizontal 水平方向膨胀量
     * @param in_vertical 垂直方向膨胀量
     */
    void inflate(T in_horizontal, T in_vertical) {
        position_ -= Eigen::Vector2<T>(in_horizontal, in_vertical);
        size_ += Eigen::Vector2<T>(in_horizontal * 2, in_vertical * 2);
    }

    /**
     * @brief 原地收缩矩形
     * @param in_offset 收缩量
     */
    void deflate(T in_offset) { inflate(-in_offset); }

    /**
     * @brief 原地在水平和垂直方向上收缩矩形
     * @param in_horizontal 水平方向收缩量
     * @param in_vertical 垂直方向收缩量
     */
    void deflate(T in_horizontal, T in_vertical) { inflate(-in_horizontal, -in_vertical); }

    //-------------- 测试与查询 --------------

    /**
     * @brief 检查矩形是否包含指定点
     * @tparam U 点的坐标类型
     * @param in_point 检查的点
     * @return 若包含则为true，否则为false
     */
    template<typename U>
    auto contains(const Eigen::Vector2<U>& in_point) const {
        return in_point.x() >= left() && in_point.x() <= right() &&
               in_point.y() >= top() && in_point.y() <= bottom();
    }

    /**
     * @brief 检查矩形是否完全包含另一个矩形
     * @tparam U 另一个矩形的类型
     * @param in_rect 检查的矩形
     * @return 若完全包含则为true，否则为false
     */
    template<typename U>
    auto contains(const rect_t<U>& in_rect) const {
        return in_rect.left() >= left() && in_rect.right() <= right() &&
               in_rect.top() >= top() && in_rect.bottom() <= bottom();
    }

    /**
     * @brief 检查矩形是否与另一个矩形相交
     * @tparam U 另一个矩形的类型
     * @param in_rect 检查的矩形
     * @return 若相交则为true，否则为false
     */
    template<typename U>
    auto intersects(const rect_t<U>& in_rect) const {
        return left() < in_rect.right() && right() > in_rect.left() &&
               top() < in_rect.bottom() && bottom() > in_rect.top();
    }

    //-------------- 集合操作 --------------

    /**
     * @brief 计算与另一个矩形的并集
     * @tparam U 另一个矩形的类型
     * @param in_rect 另一个矩形
     * @return 包含两个矩形的最小矩形
     */
    template<typename U>
    auto union_with(const rect_t<U>& in_rect) const {
        auto min = position_.cwiseMin(in_rect.position_);
        auto max = (position_ + size_).cwiseMax(in_rect.position_ + in_rect.size_);
        return rect_t(min, max - min);
    }

    /**
     * @brief 计算与另一个矩形的交集
     * @tparam U 另一个矩形的类型
     * @param in_rect 另一个矩形
     * @return 两个矩形的重叠部分
     */
    template<typename U>
    auto overlap_with(const rect_t<U>& in_rect) const {
        auto min = position_.cwiseMax(in_rect.position_);
        auto max = (position_ + size_).cwiseMin(in_rect.position_ + in_rect.size_);
        return rect_t(min, max - min);
    }

    /**
     * @brief 计算与另一个矩形的交并比(IOU)
     * @tparam U 另一个矩形的类型
     * @param in_rect 另一个矩形
     * @return 交集面积 / 并集面积
     */
    template<typename U>
    auto overlap_ratio(const rect_t<U>& in_rect) const {
        auto overlap = overlap_with(in_rect);
        return overlap.area() / (area() + in_rect.area() - overlap.area());
    }

    /**
     * @brief 将矩形裁剪到指定矩形内
     * @tparam U 裁剪矩形的类型
     * @param in_clip_rect 裁剪矩形
     * @return 裁剪后的矩形
     */
    template<typename U>
    auto clip_to(const rect_t<U>& in_clip_rect) const {
        auto min = position_.cwiseMax(in_clip_rect.position_);
        auto max = (position_ + size_).cwiseMin(in_clip_rect.position_ + in_clip_rect.size_);
        return rect_t(min, max - min);
    }

    //-------------- 布局操作 --------------

    /**
     * @brief 根据对齐方式调整内部矩形的位置
     * @tparam U 内部矩形的类型
     * @param in_inner 内部矩形
     * @param in_h_align 水平对齐方式
     * @param in_v_align 垂直对齐方式
     * @param padding 内边距
     * @return 调整后的内部矩形
     */
    template<typename U>
    auto align_rect(const rect_t<U>& in_inner, horizontal_alignment_t in_h_align, vertical_alignment_t in_v_align, const Eigen::Vector2<U>& padding = {}) const {
        U x{};
        U y{};
        U width = in_inner.width();
        U height = in_inner.height();

        // 水平对齐
        switch (in_h_align) {
            case horizontal_alignment_t::left:
                x = left() + padding.x();
                break;
            case horizontal_alignment_t::center:
                x = left() + (this->width() - width) / 2;
                break;
            case horizontal_alignment_t::right:
                x = right() - width - padding.x();
                break;
            case horizontal_alignment_t::stretch:
                x = left() + padding.x();
                width = std::max(this->width() - padding.x() * 2, U{});
                break;
        }

        // 垂直对齐
        switch (in_v_align) {
            case vertical_alignment_t::top:
                y = top() + padding.y();
                break;
            case vertical_alignment_t::center:
                y = top() + (this->height() - height) / 2;
                break;
            case vertical_alignment_t::bottom:
                y = bottom() - height - padding.y();
                break;
            case vertical_alignment_t::stretch:
                y = top() + padding.y();
                height = std::max(this->height() - padding.y() * 2, U{});
                break;
        }

        return rect_t<U>({ x, y }, { width, height });
    }

    //-------------- 分割操作 --------------

    /**
     * @brief 水平分割矩形
     * @param in_proportions 分割比例数组
     * @param in_spacing 间距
     * @return 分割后的矩形数组
     */
    auto divide_horizontally(const std::vector<float>& in_proportions, float in_spacing = 0.f) const {
        std::vector<rect_t> result;

        if (in_proportions.empty()) {
            return result;
        }

        float total_proportion = 0.f;
        for (auto proportion : in_proportions) {
            total_proportion += proportion;
        }
        if (total_proportion < std::numeric_limits<float>::epsilon()) {
            return result;
        }

        float total_spacing = in_spacing * (in_proportions.size() - 1);
        float available_width = width() - total_spacing;

        result.reserve(in_proportions.size());

        float x = left();
        for (const float prop : in_proportions) {
            if (prop < 0.f) {
                result.emplace_back(rect_t());
                continue;
            }

            float part_width = available_width * (prop / total_proportion);
            result.emplace_back(rect_t({ x, top() }, { part_width, height() }));
            x += part_width + in_spacing;
        }
        return result;
    }

    /**
     * @brief 垂直分割矩形
     * @param in_proportions 分割比例数组
     * @param in_spacing 间距
     * @return 分割后的矩形数组
     */
    auto divide_vertically(const std::vector<float>& in_proportions, T in_spacing = 0.f) const {
        std::vector<rect_t> result;

        if (in_proportions.empty()) {
            return result;
        }

        float total_proportion = 0.f;
        for (auto proportion : in_proportions) {
            total_proportion += proportion;
        }
        if (total_proportion < std::numeric_limits<float>::epsilon()) {
            return result;
        }

        float total_spacing = in_spacing * (in_proportions.size() - 1);
        float available_height = height() - total_spacing;

        result.reserve(in_proportions.size());

        float y = top();
        for (const float prop : in_proportions) {
            if (prop < 0.f) {
                result.emplace_back(rect_t());
                continue;
            }

            float part_height = available_height * (prop / total_proportion);
            result.emplace_back(rect_t({ left(), y }, { width(), part_height }));
            y += part_height + in_spacing;
        }
        return result;
    }

    /**
     * @brief 创建网格
     * @param in_columns 列数
     * @param in_rows 行数
     * @param in_spacing 间距
     * @return 网格矩形数组
     */
    auto create_grid(int32_t in_columns, int32_t in_rows, const Eigen::Vector2<T>& in_spacing) const {
        std::vector<rect_t> grid;
        if (in_columns <= 0 || in_rows <= 0) {
            return grid;
        }

        float total_horizontal_spacing = in_spacing.x() * (in_columns - 1);
        float total_vertical_spacing = in_spacing.y() * (in_rows - 1);

        float cell_width = (width() - total_horizontal_spacing) / in_columns;
        float cell_height = (height() - total_vertical_spacing) / in_rows;

        grid.reserve(in_columns * in_rows);

        for (int row = 0; row < in_rows; ++row) {
            for (int col = 0; col < in_columns; ++col) {
                float cell_x = left() + col * (cell_width + in_spacing.x());
                float cell_y = top() + row * (cell_height + in_spacing.y());

                grid.emplace_back(rect_t({ cell_x, cell_y }, { cell_width, cell_height }));
            }
        }
        return grid;
    }

    /**
     * @brief 获取矩形的四条边
     * @param in_thickness 边的厚度
     * @return 四条边的矩形数组(上、下、左、右)
     */
    auto get_edges(float in_thickness) const {
        return std::array<rect_t, 4>{
            rect_t({ left(), top() }, { width(), in_thickness }),                    // 上边
            rect_t({ left(), bottom() - in_thickness }, { width(), in_thickness }),   // 下边
            rect_t({ left(), top() }, { in_thickness, height() }),                    // 左边
            rect_t({ right() - in_thickness, top() }, { in_thickness, height() })     // 右边
        };
    }

    //-------------- 字符串转换 --------------

    /**
     * @brief 将矩形转换为字符串表示
     * @return 矩形的字符串表示
     */
    auto to_string() const {
        std::stringstream ss;
        ss << "rect_t(" << position_.x() << ", " << position_.y() << ", " << size_.x() << ", " << size_.y() << ")";
        return ss.str();
    }

    /**
     * @brief 将矩形转换为详细的调试字符串
     * @return 矩形的详细调试字符串
     */
    auto to_debug_string() const {
        std::stringstream ss;
        ss << "rect{ position: " << position_.x() << ", " << position_.y() <<
                ", size: " << size_.x() << ", " << size_.y() <<
                ", bounds: [" << left() << ", " << top() << ", " << right() << ", " << bottom() << " ]}";
        return ss.str();
    }

    //-------------- 运算符重载 --------------

    /**
     * @brief 比较两个矩形是否相等
     * @tparam U 另一个矩形的类型
     * @param in_other 另一个矩形
     * @return 相等为true，不相等为false
     */
    template<typename U>
    auto operator==(const rect_t<U>& in_other) const {
        return position_ == in_other.position_ && size_ == in_other.size_;
    }

    /**
     * @brief 比较两个矩形是否不相等
     * @tparam U 另一个矩形的类型
     * @param in_other 另一个矩形
     * @return 不相等为true，相等为false
     */
    template<typename U>
    auto operator!=(const rect_t<U>& in_other) const {
        return !(*this == in_other);
    }

    /**
     * @brief 矩形平移运算符
     * @tparam U 偏移向量的类型
     * @param in_offset 偏移向量
     * @return 平移后的矩形
     */
    template<typename U>
    auto operator+(const Eigen::Vector2<U>& in_offset) const {
        return translated(in_offset);
    }

    /**
     * @brief 矩形反方向平移运算符
     * @tparam U 偏移向量的类型
     * @param in_offset 偏移向量
     * @return 平移后的矩形
     */
    template<typename U>
    auto operator-(const Eigen::Vector2<U>& in_offset) const {
        return translated(-in_offset);
    }

    /**
     * @brief 矩形自增平移运算符
     * @tparam U 偏移向量的类型
     * @param in_offset 偏移向量
     * @return 平移后的矩形引用
     */
    template<typename U>
    auto& operator+=(const Eigen::Vector2<U>& in_offset) {
        position_ += in_offset;
        return *this;
    }

    /**
     * @brief 矩形自减平移运算符
     * @tparam U 偏移向量的类型
     * @param in_offset 偏移向量
     * @return 平移后的矩形引用
     */
    template<typename U>
    auto& operator-=(const Eigen::Vector2<U>& in_offset) {
        position_ -= in_offset;
        return *this;
    }

    /**
     * @brief 矩形缩放运算符
     * @param in_scale 缩放系数
     * @return 缩放后的矩形
     */
    auto operator*(T in_scale) const {
        return rect_t(position_ * in_scale, size_ * in_scale);
    }

    /**
     * @brief 矩形缩小运算符
     * @param in_scale 缩小系数
     * @return 缩小后的矩形
     */
    auto operator/(T in_scale) const {
        if (std::abs(in_scale) < std::numeric_limits<T>::epsilon()) {
            return rect_t();
        }
        return rect_t(position_ / in_scale, size_ / in_scale);
    }

    /**
     * @brief 矩形自乘缩放运算符
     * @param in_scale 缩放系数
     * @return 缩放后的矩形引用
     */
    auto& operator*=(T in_scale) {
        position_ *= in_scale;
        size_ *= in_scale;
        return *this;
    }

    /**
     * @brief 矩形自除缩小运算符
     * @param in_scale 缩小系数
     * @return 缩小后的矩形引用
     */
    auto& operator/=(T in_scale) {
        if (std::abs(in_scale) < std::numeric_limits<T>::epsilon()) {
            position_ = Eigen::Vector2<T>::Zero();
            size_ = Eigen::Vector2<T>::Zero();
        } else {
            position_ /= in_scale;
            size_ /= in_scale;
        }
        return *this;
    }

private:
    /** 矩形左上角位置 */
    Eigen::Vector2<T> position_;

    /** 矩形大小(宽和高) */
    Eigen::Vector2<T> size_;
};

/**
 * @brief 矩形输出流运算符
 * @tparam U 矩形的类型
 * @param in_stream 输出流
 * @param in_rect 矩形
 * @return 输出流引用
 */
template<typename U>
auto& operator<<(std::ostream& in_stream, const rect_t<U>& in_rect) {
    return in_stream << in_rect.to_string();
}
