#pragma once #include #include #include #include namespace vde::foundation { /** * @brief 分层容差管理类 * * 提供四级容差(绝对、相对、角度、吸附),支持全局实例和局部作用域覆盖。 * 用于数值比较、几何判定和点合并时的精度控制。 * * 四级容差含义: * - **绝对容差 (absolute)**: 对接近零的值使用,直接比较差值的绝对值 * - **相对容差 (relative)**: 对大值使用,比较差值 / max(|a|, |b|) * - **角度容差 (angular)**: 角度/方向比较时的阈值(弧度) * - **吸附容差 (snapping)**: 点合并/对齐时的容差,通常比判定容差宽松 * * 预设精度等级: * - Modeling(): 1e-6 — 通用建模精度 * - Fitting(): 1e-3 — 近似拟合 * - Intersection(): 1e-8 — 精确求交 * - Snapping(): 1e-4 — 点吸附 * * @ingroup foundation */ class Tolerance { public: /** * @brief 构造容差对象 * * @param absolute 绝对容差,默认 1e-6 * @param relative 相对容差,默认 1e-8 * @param angular 角度容差(弧度),默认 1e-8 * @param snapping 吸附容差,默认 1e-4 */ Tolerance(double absolute = 1e-6, double relative = 1e-8, double angular = 1e-8, double snapping = 1e-4) : absolute_(absolute), relative_(relative), angular_(angular), snapping_(snapping) {} // ── 判定 ── /** * @brief 判断两点是否相等(基于绝对容差) * * 使用欧氏距离与绝对容差比较。 * * @param a 第一个点(Eigen 矩阵) * @param b 第二个点(Eigen 矩阵) * @return true 若两点的欧氏距离 < absolute_ */ bool points_equal(const Eigen::MatrixXd& a, const Eigen::MatrixXd& b) const { return (a - b).norm() < absolute_; } /** * @brief 判断值是否接近零 * * @param value 测试值 * @return true 若 |value| < absolute_ */ template bool is_zero(T value) const { return std::abs(value) < absolute_; } /** * @brief 混合容差相等判断 * * 综合使用绝对和相对容差: * |a - b| < absolute + relative * max(|a|, |b|) * * @tparam T 数值类型 * @param a 第一个值 * @param b 第二个值 * @return true 若两值在容差范围内相等 * * @code{.cpp} * Tolerance tol(1e-6, 1e-8); * tol.equals(1.0000001, 1.0); // true * tol.equals(1000.0001, 1000.0); // true (相对项起作用) * @endcode */ template bool equals(T a, T b) const { return std::abs(a - b) < absolute_ + relative_ * std::max(std::abs(a), std::abs(b)); } /// 获取绝对容差 double absolute() const { return absolute_; } /// 获取相对容差 double relative() const { return relative_; } /// 获取角度容差 double angular() const { return angular_; } /// 获取吸附容差 double snapping() const { return snapping_; } // ── 分层容差:继承并收紧 ── /** * @brief 收紧容差 * * 所有容差乘以 factor(< 1),用于在子操作中提高精度要求。 * * @param factor 收紧因子(默认 0.1) * @return 收紧后的新容差对象 * * @code{.cpp} * auto rough = Tolerance(Tolerance::Fitting()); * auto precise = rough.tighten(0.01); // 拟合 → 建模级 * @endcode */ Tolerance tighten(double factor = 0.1) const { return Tolerance(absolute_ * factor, relative_ * factor, angular_ * factor, snapping_ * factor); } /** * @brief 放宽容差 * * 所有容差乘以 factor(> 1),用于在上层操作中降低精度要求。 * * @param factor 放宽因子(默认 10.0) * @return 放宽后的新容差对象 */ Tolerance relax(double factor = 10.0) const { return Tolerance(absolute_ * factor, relative_ * factor, angular_ * factor, snapping_ * factor); } /** * @brief 合并两个容差,取更严格的(更小的) * * @param a 第一个容差 * @param b 第二个容差 * @return 每项取 min 的新容差 */ static Tolerance min(const Tolerance& a, const Tolerance& b) { return Tolerance(std::min(a.absolute_, b.absolute_), std::min(a.relative_, b.relative_), std::min(a.angular_, b.angular_), std::min(a.snapping_, b.snapping_)); } // ── 全局实例 ── /** * @brief 获取全局容差实例 * * 线程局部存储,默认值为建模精度 (1e-6)。 * * @return 全局容差的引用 */ static Tolerance& global() { return global_; } /** * @brief 设置全局容差 * * @param tol 新的全局容差 * * @note 推荐使用 ToleranceScope 进行临时修改,确保自动恢复 */ static void set_global(const Tolerance& tol) { global_ = tol; } // ── 默认建模容差等级 ── /// 建模级精度 (1e-6):通用几何建模 static constexpr double Modeling() { return 1e-6; } /// 拟合级精度 (1e-3):曲面拟合、近似计算 static constexpr double Fitting() { return 1e-3; } /// 求交级精度 (1e-8):精确求交、布尔运算 static constexpr double Intersection() { return 1e-8; } /// 吸附级精度 (1e-4):点合并、顶点焊接 static constexpr double Snapping() { return 1e-4; } private: double absolute_; double relative_; double angular_; double snapping_; static Tolerance global_; }; /** * @brief 局部容差作用域(RAII) * * 构造时设置新的全局容差,析构时自动恢复为之前的值。 * 用于在特定代码块内临时修改容差。 * * @code{.cpp} * void precise_operation() { * ToleranceScope scope(Tolerance::Intersection()); * // 在此作用域内使用求交级精度 * // ... 布尔运算 ... * } // scope 析构,自动恢复 * @endcode * * @ingroup foundation */ class ToleranceScope { public: /** * @brief 进入新的容差作用域 * * 保存当前全局容差并设置新值。 * * @param tol 此作用域内使用的容差 */ explicit ToleranceScope(const Tolerance& tol) : previous_(Tolerance::global()) { Tolerance::set_global(tol); } /** * @brief 退出容差作用域,恢复之前的全局容差 */ ~ToleranceScope() { Tolerance::set_global(previous_); } private: Tolerance previous_; }; } // namespace vde::foundation