Files

224 lines
6.6 KiB
C++
Raw Permalink Normal View History

#pragma once
#include <Eigen/Core>
#include <cmath>
#include <limits>
#include <vector>
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 <typename T>
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 <typename T>
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