117 lines
3.6 KiB
C++
117 lines
3.6 KiB
C++
|
|
#pragma once
|
|||
|
|
/**
|
|||
|
|
* @file exact_predicates.h
|
|||
|
|
* @brief 精确几何谓词
|
|||
|
|
*
|
|||
|
|
* 使用 GMP/MPFR 进行精确算术运算,消除浮点误差。
|
|||
|
|
* 关键路径:布尔运算分类、Delaunay 三角剖分、凸包计算。
|
|||
|
|
*
|
|||
|
|
* 支持混合精度:先用 double,检测到不确定时自动升级到 GMP。
|
|||
|
|
*
|
|||
|
|
* @ingroup foundation
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#include "vde/core/point.h"
|
|||
|
|
#include <vector>
|
|||
|
|
|
|||
|
|
namespace vde::core {
|
|||
|
|
|
|||
|
|
// ═══════════════════════════════════════════════════════════
|
|||
|
|
// Exact Predicates (double → GMP fallback)
|
|||
|
|
// ═══════════════════════════════════════════════════════════
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 精确三点定向 (orient2d)
|
|||
|
|
*
|
|||
|
|
* 计算 (ax,ay), (bx,by), (cx,cy) 的有向面积 × 2。
|
|||
|
|
* > 0 → 逆时针, < 0 → 顺时针, = 0 → 共线。
|
|||
|
|
*
|
|||
|
|
* 先使用浮点运算,若结果接近 0 则升级到 GMP。
|
|||
|
|
*
|
|||
|
|
* @return 精确的 orient 值
|
|||
|
|
*/
|
|||
|
|
[[nodiscard]] double exact_orient2d(
|
|||
|
|
double ax, double ay, double bx, double by, double cx, double cy);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 精确四点定向 (orient3d)
|
|||
|
|
*
|
|||
|
|
* 计算四面体 (a,b,c,d) 的有向体积 × 6。
|
|||
|
|
* > 0 → d 在平面 abc 上方, < 0 → 下方, = 0 → 共面。
|
|||
|
|
*/
|
|||
|
|
[[nodiscard]] double exact_orient3d(
|
|||
|
|
double ax, double ay, double az,
|
|||
|
|
double bx, double by, double bz,
|
|||
|
|
double cx, double cy, double cz,
|
|||
|
|
double dx, double dy, double dz);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 精确球内测试 (in_sphere)
|
|||
|
|
*
|
|||
|
|
* 判断点 d 是否在四面体 abc 的外接球内。
|
|||
|
|
* > 0 → 内部, < 0 → 外部, = 0 → 在球面上。
|
|||
|
|
*/
|
|||
|
|
[[nodiscard]] double exact_in_sphere(
|
|||
|
|
double ax, double ay, double az,
|
|||
|
|
double bx, double by, double bz,
|
|||
|
|
double cx, double cy, double cz,
|
|||
|
|
double dx, double dy, double dz,
|
|||
|
|
double ex, double ey, double ez);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 精确点在多边形内测试
|
|||
|
|
*
|
|||
|
|
* 射线投射法 + 精确算术处理边界情况。
|
|||
|
|
*
|
|||
|
|
* @param point 测试点
|
|||
|
|
* @param polygon 多边形顶点(逆时针)
|
|||
|
|
* @return true 如果点在多边形内或边界上
|
|||
|
|
*/
|
|||
|
|
[[nodiscard]] bool exact_point_in_polygon(
|
|||
|
|
const Point3D& point, const std::vector<Point3D>& polygon);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 精确点在多面体内测试
|
|||
|
|
*
|
|||
|
|
* 射线投射法,使用精确算术处理共面/共线退化情况。
|
|||
|
|
*
|
|||
|
|
* @param point 测试点
|
|||
|
|
* @param vertices 多面体顶点
|
|||
|
|
* @param faces 面索引(每面 3+ 个顶点索引)
|
|||
|
|
* @return true 如果点在体内
|
|||
|
|
*/
|
|||
|
|
[[nodiscard]] bool exact_point_in_polyhedron(
|
|||
|
|
const Point3D& point,
|
|||
|
|
const std::vector<Point3D>& vertices,
|
|||
|
|
const std::vector<std::vector<int>>& faces);
|
|||
|
|
|
|||
|
|
// ═══════════════════════════════════════════════════════════
|
|||
|
|
// Adaptive precision wrapper
|
|||
|
|
// ═══════════════════════════════════════════════════════════
|
|||
|
|
|
|||
|
|
/// 精度模式
|
|||
|
|
enum class PrecisionMode {
|
|||
|
|
Fast, ///< 仅使用 double(默认)
|
|||
|
|
Adaptive, ///< 先 double,不确定时升级到 GMP
|
|||
|
|
Exact, ///< 始终使用 GMP
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置全局精度模式
|
|||
|
|
*/
|
|||
|
|
void set_precision_mode(PrecisionMode mode);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取当前精度模式
|
|||
|
|
*/
|
|||
|
|
[[nodiscard]] PrecisionMode precision_mode();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查和报告两浮点数是否在误差范围内"不确定"
|
|||
|
|
*
|
|||
|
|
* 用于自适应精度升级判断。
|
|||
|
|
*/
|
|||
|
|
[[nodiscard]] bool is_uncertain(double value, double threshold = 1e-10);
|
|||
|
|
|
|||
|
|
} // namespace vde::core
|