#pragma once #include #include #include namespace vde::foundation { /// 双精度区间算术:存储 [lo, hi] 边界,用于验证计算结果可靠性 class Interval { public: double lo, hi; Interval() : lo(0), hi(0) {} Interval(double v) : lo(v), hi(v) {} Interval(double l, double h) : lo(std::min(l,h)), hi(std::max(l,h)) {} /// 区间中点 [[nodiscard]] double mid() const { return (lo + hi) * 0.5; } /// 区间宽度 [[nodiscard]] double width() const { return hi - lo; } /// 区间是否包含值 [[nodiscard]] bool contains(double v) const { return lo <= v && v <= hi; } /// 是否精确(宽度 < eps) [[nodiscard]] bool is_exact(double eps = 1e-12) const { return width() < eps; } /// 区间是否与另一个区间重叠 [[nodiscard]] bool overlaps(const Interval& o) const { return !(hi < o.lo || o.hi < lo); } /// 确定性比较 [[nodiscard]] int cmp(const Interval& o) const { if (hi < o.lo) return -1; // 确定 this < o if (lo > o.hi) return 1; // 确定 this > o return 0; // 不确定(区间重叠) } // ── 算术运算 ── Interval operator+(const Interval& o) const { return {lo + o.lo, hi + o.hi}; } Interval operator-(const Interval& o) const { return {lo - o.hi, hi - o.lo}; } Interval operator*(const Interval& o) const { double a = lo*o.lo, b = lo*o.hi, c = hi*o.lo, d = hi*o.hi; return {std::min({a,b,c,d}), std::max({a,b,c,d})}; } Interval operator/(const Interval& o) const { if (o.lo <= 0 && o.hi >= 0) return {-std::numeric_limits::max(), std::numeric_limits::max()}; double a = lo/o.lo, b = lo/o.hi, c = hi/o.lo, d = hi/o.hi; return {std::min({a,b,c,d}), std::max({a,b,c,d})}; } Interval operator-() const { return {-hi, -lo}; } // ── 数学函数(保守区间)── [[nodiscard]] Interval sqrt() const { return {std::sqrt(std::max(0.0, lo)), std::sqrt(std::max(0.0, hi))}; } /// 从 double 创建区间(含舍入误差) static Interval from_double(double v, double error = 0) { return {v - error, v + error}; } /// 将 double 表示的坐标转为区间(含 ULP 误差) static Interval from_coord(double v) { double eps = std::abs(v) * 2.22e-16 + 1e-300; return {v - eps, v + eps}; } }; /// 行列式的区间验证 inline Interval orient_2d_interval(double ax, double ay, double bx, double by, double cx, double cy) { Interval acx = Interval::from_coord(ax - cx); Interval acy = Interval::from_coord(ay - cy); Interval bcx = Interval::from_coord(bx - cx); Interval bcy = Interval::from_coord(by - cy); return acx * bcy - acy * bcx; } /// 使用区间算术验证 orient_2d 结果 /// 返回: -1(CW), 0(无法确定), 1(CCW) inline int orient_2d_verified(double ax, double ay, double bx, double by, double cx, double cy) { Interval det = orient_2d_interval(ax, ay, bx, by, cx, cy); return det.cmp(Interval(0.0)); } } // namespace vde::foundation