Files
ViewDesignEngine/include/vde/foundation/exact_predicates_gmp.h
T
ViewDesignEngine 8ae4b86e08
CI / Build & Test (push) Failing after 38s
CI / Release Build (push) Failing after 28s
feat: GMP 精确算术后端 + 可插拔谓词接口
新增:
- include/vde/foundation/exact_predicates_gmp.h: GMP 精确谓词
  - orient_2d/3d, in_circle 完全精确(mpq_class 有理数)
  - 零舍入误差,任意精度
- include/vde/foundation/predicates.h: 统一谓词接口
  - Predicates<T> 编译期选择后端
  - VDE_USE_GMP=ON → GMP, OFF → 自适应 double
  - 便捷函数: orient(), in_circle()
- cmake/FindGMP.cmake: GMP 查找模块
- CMake: -DVDE_USE_GMP=ON 启用 GMP 精确模式
- AdaptiveDouble 包装器: 统一后端接口

使用:
  cmake -DVDE_USE_GMP=ON ..  # 完全精确模式
2026-07-23 10:32:51 +00:00

74 lines
2.6 KiB
C++

#pragma once
#include "vde/foundation/exact_predicates.h"
#ifdef VDE_USE_GMP
#include <gmpxx.h>
namespace vde::foundation::exact {
/// GMP-based exact predicates — zero rounding error, arbitrary precision
struct GmpExact {
using Rational = mpq_class;
/// orient_2d with exact rational arithmetic
static Orientation orient_2d(const Point2D& a, const Point2D& b, const Point2D& c) {
Rational ax(a.x()), ay(a.y());
Rational bx(b.x()), by(b.y());
Rational cx(c.x()), cy(c.y());
Rational det = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
int s = mpq_sgn(det.get_mpq_t());
return s > 0 ? Orientation::CounterClockwise :
s < 0 ? Orientation::Clockwise : Orientation::Collinear;
}
/// orient_3d with exact rational arithmetic
static Orientation orient_3d(const Point3D& a, const Point3D& b,
const Point3D& c, const Point3D& d) {
Rational ax(a.x()), ay(a.y()), az(a.z());
Rational bx(b.x()), by(b.y()), bz(b.z());
Rational cx(c.x()), cy(c.y()), cz(c.z());
Rational dx(d.x()), dy(d.y()), dz(d.z());
Rational adx = ax - dx, ady = ay - dy, adz = az - dz;
Rational bdx = bx - dx, bdy = by - dy, bdz = bz - dz;
Rational cdx = cx - dx, cdy = cy - dy, cdz = cz - dz;
Rational det = adx * (bdy * cdz - bdz * cdy)
+ bdx * (cdy * adz - cdz * ady)
+ cdx * (ady * bdz - adz * bdy);
int s = mpq_sgn(det.get_mpq_t());
return s > 0 ? Orientation::CounterClockwise :
s < 0 ? Orientation::Clockwise : Orientation::Collinear;
}
/// in_circle with exact rational arithmetic
static CircleTest in_circle(const Point2D& a, const Point2D& b,
const Point2D& c, const Point2D& d) {
Rational ax(a.x()), ay(a.y());
Rational bx(b.x()), by(b.y());
Rational cx(c.x()), cy(c.y());
Rational dx(d.x()), dy(d.y());
Rational adx = ax - dx, ady = ay - dy;
Rational bdx = bx - dx, bdy = by - dy;
Rational cdx = cx - dx, cdy = cy - dy;
Rational ab = adx * bdy - ady * bdx;
Rational bc = bdx * cdy - bdy * cdx;
Rational ca = cdx * ady - cdy * adx;
Rational al = adx * adx + ady * ady;
Rational bl = bdx * bdx + bdy * bdy;
Rational cl = cdx * cdx + cdy * cdy;
Rational det = al * bc + bl * ca + cl * ab;
int s = mpq_sgn(det.get_mpq_t());
return s > 0 ? CircleTest::Inside :
s < 0 ? CircleTest::Outside : CircleTest::On;
}
};
} // namespace vde::foundation::exact
#endif // VDE_USE_GMP