#pragma once /** * @file tolerance.h * @brief 精确容差系统 * * 可配置的几何容差,支持 fuzzy 比较和自适应容差。 * 对齐工业 CAD 内核(Parasolid/ACIS)的容差模型。 * * @ingroup foundation */ #include "vde/core/point.h" #include "vde/brep/brep.h" #include #include #include #include #include namespace vde::brep { // ═══════════════════════════════════════════════════════════ // Tolerance configuration // ═══════════════════════════════════════════════════════════ /** * @brief 容差配置 * * 集中管理所有几何比较的容差值。 * 可全局配置或按操作类型分别设置。 */ struct ToleranceConfig { double vertex_merge = 1e-6; ///< 顶点合并容差 double edge_merge = 1e-6; ///< 边合并容差 double face_plane = 1e-9; ///< 面平面判断容差 double boolean = 1e-6; ///< 布尔运算容差 double intersection = 1e-6; ///< 求交容差 double validation = 1e-6; ///< 验证容差 double point_on_curve = 1e-8; ///< 点在曲线上的容差 double point_on_surface = 1e-8; ///< 点在曲面上的容差 double angular = 1e-10; ///< 角度容差(弧度) /// 全局默认 [[nodiscard]] static const ToleranceConfig& global(); /// 设置全局配置 static void set_global(const ToleranceConfig& cfg); }; // ═══════════════════════════════════════════════════════════ // Fuzzy comparison utilities // ═══════════════════════════════════════════════════════════ /** * @brief Fuzzy 相等(带相对容差) * * 使用绝对 + 相对容差组合: * |a - b| <= max(abs_tol, rel_tol * max(|a|, |b|)) */ [[nodiscard]] inline bool fuzzy_equal( double a, double b, double abs_tol = 1e-9, double rel_tol = 1e-12) { double diff = std::abs(a - b); if (diff <= abs_tol) return true; double scale = std::max(std::abs(a), std::abs(b)); return diff <= rel_tol * scale; } /// Fuzzy 零检查 [[nodiscard]] inline bool fuzzy_zero(double x, double tol = 1e-9) { return std::abs(x) <= tol; } /// Fuzzy 大于 [[nodiscard]] inline bool fuzzy_gt(double a, double b, double tol = 1e-9) { return a > b + tol; } /// Fuzzy 小于 [[nodiscard]] inline bool fuzzy_lt(double a, double b, double tol = 1e-9) { return a < b - tol; } /// Fuzzy 大于等于 [[nodiscard]] inline bool fuzzy_gte(double a, double b, double tol = 1e-9) { return a >= b - tol; } /// Fuzzy 小于等于 [[nodiscard]] inline bool fuzzy_lte(double a, double b, double tol = 1e-9) { return a <= b + tol; } // ═══════════════════════════════════════════════════════════ // Vector fuzzy operations // ═══════════════════════════════════════════════════════════ /// 两向量在容差内相等 [[nodiscard]] inline bool fuzzy_equal_vec( const core::Vector3D& a, const core::Vector3D& b, double tol = 1e-9) { return fuzzy_equal(a.x(), b.x(), tol) && fuzzy_equal(a.y(), b.y(), tol) && fuzzy_equal(a.z(), b.z(), tol); } /// 两点在容差内相等 [[nodiscard]] inline bool fuzzy_equal_point( const core::Point3D& a, const core::Point3D& b, double tol = 1e-9) { return (a - b).norm() <= tol; } /// 两向量平行(共线) [[nodiscard]] inline bool fuzzy_parallel( const core::Vector3D& a, const core::Vector3D& b, double angle_tol = 1e-10) { double dot = std::abs(a.normalized().dot(b.normalized())); return fuzzy_equal(dot, 1.0, 1e-9); } /// 两向量垂直 [[nodiscard]] inline bool fuzzy_perpendicular( const core::Vector3D& a, const core::Vector3D& b, double angle_tol = 1e-10) { double dot = std::abs(a.normalized().dot(b.normalized())); return fuzzy_equal(dot, 0.0, angle_tol); } // ═══════════════════════════════════════════════════════════ // Adaptive tolerance // ═══════════════════════════════════════════════════════════ /** * @brief 根据模型尺寸计算自适应容差 * * 大模型用宽松容差,小模型用精密容差。 * * @param model_size 模型特征尺寸 * @param base_tol 基础容差 * @return 自适应容差 */ [[nodiscard]] inline double adaptive_tolerance( double model_size, double base_tol = 1e-6) { // 1mm 模型 → 0.1μm, 1m 模型 → 100μm return std::max(base_tol, model_size * 1e-7); } /** * @brief 根据 B-Rep 模型计算容差 */ [[nodiscard]] double model_tolerance(const BrepModel& body); // ═══════════════════════════════════════════════════════════ // Tolerance chain — 容差传播追踪 // ═══════════════════════════════════════════════════════════ /** * @brief 容差传播链 * * 追踪操作链中的容差累积。每个操作注入自身的容差贡献, * 末端可查询累积容差上界。 * * 使用场景: * - 布尔运算链:求交 → 分割 → 缝合,累积容差逐级放大 * - 特征链:拉伸 → 倒圆 → 抽壳,容差传播路径 * * @code * ToleranceChain chain; * chain.push("intersect", 1e-6); * chain.push("split", 1e-6); * chain.push("sew", 1e-5); * double worst = chain.cumulative(); // 1.2e-5 (root-sum-square) * @endcode */ class ToleranceChain { public: /** * @brief 记录一个操作及其容差贡献 * @param op_name 操作名称(用于调试/日志) * @param tol 该操作注入的容差 */ void push(const std::string& op_name, double tol); /** * @brief 累积容差 * * 使用均方根 (RSS) 合成:sqrt(Σ tol²) * 比简单求和更保守,但比对数叠加更实用。 * * @return 累积容差 */ [[nodiscard]] double cumulative() const; /** * @brief 最大单步容差 * @return 链中最大的单步容差 */ [[nodiscard]] double max_step() const; /** @brief 链深度 */ [[nodiscard]] size_t depth() const { return steps_.size(); } /** @brief 所有步骤(只读) */ [[nodiscard]] const std::vector>& steps() const { return steps_; } /** @brief 清空链 */ void clear() { steps_.clear(); } private: std::vector> steps_; }; } // namespace vde::brep