From 72197916856aac2d6f3d7f9d198fcf1f64233e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=82=E4=B9=8B=E9=92=B3?= Date: Fri, 24 Jul 2026 11:58:54 +0000 Subject: [PATCH] docs: Markdown API reference (6942 lines, 76 headers) --- docs/API-REFERENCE.md | 6942 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6942 insertions(+) create mode 100644 docs/API-REFERENCE.md diff --git a/docs/API-REFERENCE.md b/docs/API-REFERENCE.md new file mode 100644 index 0000000..4386c67 --- /dev/null +++ b/docs/API-REFERENCE.md @@ -0,0 +1,6942 @@ +# ViewDesignEngine API 参考手册 + +> 版本 3.2.0 | 76 个头文件 + + +## 基础模块 (`vde::foundation`) + + +### `error_codes.h` + +**全局错误码枚举** +`enum class ErrorCode : int32_t {` + + + +### `exact_predicates.h` + +**二维定向测试结果** +`enum class Orientation { Clockwise, CounterClockwise, Collinear }` + + +**圆测试结果** +`enum class CircleTest { Inside, On, Outside }` + + +**自适应精度二维定向测试(Shewchuk 算法)** +`Orientation orient_2d(const Point2D& a, const Point2D& b, const Point2D& c)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个点 | +| `b` | 第二个点 | +| `c` | 第三个点 | + +**返回**: Orientation::Collinear 若三点共线 +> Delaunay 三角剖分、凸包计算等几何算法的核心原语 + +**参见**: `orient_3d, in_circle` + + +**自适应精度三维定向测试** +`Orientation orient_3d(const Point3D& a, const Point3D& b,` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个点 | +| `b` | 第二个点 | +| `c` | 第三个点 | +| `d` | 第四个点(测试点) | + +**返回**: Orientation::Collinear 若四点共面 +> 三维 Delaunay 剖分和凸包计算的核心原语 + +**参见**: `orient_2d, in_circle` + + +**自适应精度圆内测试(In-Circle Test)** +`CircleTest in_circle(const Point2D& a, const Point2D& b,` + +| 参数 | 说明 | +|------|------| +| `a` | 三角形第一个顶点 | +| `b` | 三角形第二个顶点 | +| `c` | 三角形第三个顶点 | +| `d` | 待测试点 | + +**返回**: CircleTest::Outside 若 d 在三角形外接圆外部 +> Delaunay 三角剖分的空圆性质检查核心原语 + +**参见**: `orient_2d, orient_3d` + + +**自适应双精度谓词后端(默认)** + + +**二维定向测试** +`static exact::Orientation orient_2d(const Point2D& a, const Point2D& b, const Point2D& c) {` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三个二维点 | + +**返回**: 定向结果 + +**参见**: `exact::orient_2d` + + +**三维定向测试** +`static exact::Orientation orient_3d(const Point3D& a, const Point3D& b,` + +| 参数 | 说明 | +|------|------| +| `a,b,c,d` | 四个三维点 | + +**返回**: 定向结果 + +**参见**: `exact::orient_3d` + + +**圆内测试** +`static exact::CircleTest in_circle(const Point2D& a, const Point2D& b,` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三角形三顶点 | +| `d` | 待测试点 | + +**返回**: 圆测试结果 + +**参见**: `exact::in_circle` + + + +### `exact_predicates_gmp.h` + +**GMP 精确算术谓词后端** +`struct GmpExact {` +> 仅在定义了 VDE_USE_GMP 宏且链接了 GMP 库时可用 + + +**精确有理数二维定向测试** +`static Orientation orient_2d(const Point2D& a, const Point2D& b, const Point2D& c) {` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个点 | +| `b` | 第二个点 | +| `c` | 第三个点 | + +**返回**: 定向结果(保证正确,无舍入误差) + +**参见**: `GmpExact::orient_3d, GmpExact::in_circle` + + +**精确有理数三维定向测试** +`static Orientation orient_3d(const Point3D& a, const Point3D& b,` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 定义平面的三点 | +| `d` | 待测试点 | + +**返回**: 定向结果(零误差) + +**参见**: `GmpExact::orient_2d` + + +**精确有理数圆内测试** +`static CircleTest in_circle(const Point2D& a, const Point2D& b,` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三角形三顶点 | +| `d` | 待测试点 | + +**返回**: 圆测试结果(零误差) + +**参见**: `GmpExact::orient_2d` + + + +### `format_utils.h` + +**以 CAD 级别精度格式化双精度浮点数** +`inline std::string fmt_double(double v, int precision = 12) {` + +| 参数 | 说明 | +|------|------| +| `v` | 要格式化的双精度数 | +| `precision` | 有效数字位数(默认 12) | + +**返回**: 格式化后的字符串,如 "1.234567890123e+02" +> 总是确保指数部分带符号(如 "e+00" 而非 "e00"),便于解析器统一处理 + +**参见**: `fmt_iges_real, fmt_point` + + +**IGES 格式实数输出** +`inline std::string fmt_iges_real(double v, int /*precision*/ = 12) {` + +| 参数 | 说明 | +|------|------| +| `v` | 要格式化的双精度数 | + +**返回**: IGES 格式字符串,如 "3.141592653590D+00" + +**参见**: `fmt_double` + + +**格式化三维点为逗号分隔字符串** +`inline std::string fmt_point(const core::Point3D& p, bool use_d = false) {` + +| 参数 | 说明 | +|------|------| +| `p` | 三维点 | +| `use_d` | 若为 true,使用 IGES 风格 D 指数标记 | + +**返回**: 逗号分隔的坐标字符串 + +**参见**: `fmt_double, fmt_iges_real` + + +**将字符串填充到恰好 72 个字符** +`inline std::string pad72(const std::string& s) {` + +| 参数 | 说明 | +|------|------| +| `s` | 输入字符串 | + +**返回**: 恰好 72 字符的字符串(不足右侧补空格,超出截断) + +**参见**: `format_iges_line` + + +**格式化 IGES 段落行** +`inline std::string format_iges_line(const std::string& data, char section_char, int seq) {` + +| 参数 | 说明 | +|------|------| +| `data` | 数据内容(最多 72 字符,超出截断) | +| `section_char` | 段落标识符(如 'P' 参数段, 'D' 目录段) | +| `seq` | 行序号(1-based) | + +**返回**: 完整 IGES 行(含换行符),共 81 字符 + +**参见**: `pad72` + + + +### `interval.h` + +**双精度区间算术类** + + +**从单值构造精确区间(退化为点)** +`Interval(double v) : lo(v), hi(v) {}` + +| 参数 | 说明 | +|------|------| +| `v` | 区间值,[v, v] | + + +**从上下界构造区间** +`Interval(double l, double h) : lo(std::min(l,h)), hi(std::max(l,h)) {}` + +| 参数 | 说明 | +|------|------| +| `l` | 下界 | +| `h` | 上界 | + + +**区间中点** +`[[nodiscard]] double mid() const { return (lo + hi) * 0.5; }` + +**返回**: (lo + hi) / 2 + + +**区间宽度** +`[[nodiscard]] double width() const { return hi - lo; }` + +**返回**: hi - lo + + +**判断区间是否包含给定值** +`[[nodiscard]] bool contains(double v) const { return lo <= v && v <= hi; }` + +| 参数 | 说明 | +|------|------| +| `v` | 测试值 | + +**返回**: true 若 lo ≤ v ≤ hi + + +**判断区间是否足够窄(收敛)** +`[[nodiscard]] bool is_exact(double eps = 1e-12) const { return width() < eps; }` + +| 参数 | 说明 | +|------|------| +| `eps` | 宽度阈值(默认 1e-12) | + +**返回**: true 若区间宽度 < eps + + +**判断两个区间是否有重叠** +`[[nodiscard]] bool overlaps(const Interval& o) const {` + +| 参数 | 说明 | +|------|------| +| `o` | 另一个区间 | + +**返回**: true 若存在公共点 + + +**确定性区间比较** +`[[nodiscard]] int cmp(const Interval& o) const {` + +| 参数 | 说明 | +|------|------| +| `o` | 另一个区间 | + +**返回**: 0 若区间重叠,无法确定 + + +**区间加法** +`Interval operator+(const Interval& o) const {` + +**返回**: [this.lo + o.lo, this.hi + o.hi] + + +**区间减法** +`Interval operator-(const Interval& o) const {` + +**返回**: [this.lo - o.hi, this.hi - o.lo](保守估计) + + +**区间乘法** +`Interval operator*(const Interval& o) const {` + +**返回**: [min(a*c,a*d,b*c,b*d), max(a*c,a*d,b*c,b*d)] + + +**区间除法** +`Interval operator/(const Interval& o) const {` + +**返回**: 结果区间或 [-∞, +∞](除数为零区间) + + +**区间平方根** +`[[nodiscard]] Interval sqrt() const {` + +**返回**: [sqrt(max(0, lo)), sqrt(max(0, hi))] + + +**从双精度值创建区间(含舍入误差带)** +`static Interval from_double(double v, double error = 0) {` + +| 参数 | 说明 | +|------|------| +| `v` | 中心值 | +| `error` | 误差半径(默认 0) | + +**返回**: [v - error, v + error] + + +**从坐标值创建区间(含 ULP 误差带)** +`static Interval from_coord(double v) {` + +| 参数 | 说明 | +|------|------| +| `v` | 坐标值 | + +**返回**: 包含浮点舍入误差的区间 + + +**二维定向行列式的区间验证** +`inline Interval orient_2d_interval(double ax, double ay, double bx, double by, double cx, double cy) {` + +| 参数 | 说明 | +|------|------| +| `ax,ay` | 点 a 的坐标 | +| `bx,by` | 点 b 的坐标 | +| `cx,cy` | 点 c 的坐标 | + +**返回**: 行列式的区间值 + +**参见**: `orient_2d_verified` + + +**使用区间算术验证 orient_2d 结果** +`inline int orient_2d_verified(double ax, double ay, double bx, double by, double cx, double cy) {` + +| 参数 | 说明 | +|------|------| +| `ax,ay` | 点 a 的坐标 | +| `bx,by` | 点 b 的坐标 | +| `cx,cy` | 点 c 的坐标 | + +**返回**: 1 确认 CounterClockwise + +**参见**: `orient_2d_interval, Interval::cmp` + + + +### `io_gltf.h` + +**glTF 2.0 导出选项** +`struct GltfOptions {` + + +**导出网格为 glTF 2.0 / GLB 格式** +`bool write_gltf(const std::string& filepath, const mesh::HalfedgeMesh& mesh,` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径(.glb 或 .gltf) | +| `mesh` | 要导出的半边网格 | +| `options` | 导出选项(格式、法线、颜色等) | + +**返回**: false 导出失败(文件无法创建等) +> 生成的 glTF 符合 2.0 规范,兼容 Blender、three.js、Unreal Engine 等工具 + +**参见**: `write_brep_gltf, GltfOptions` + + +**导出 B-Rep 模型为 GLB 格式(通过面片化)** +`bool write_brep_gltf(const std::string& filepath, const brep::BrepModel& model,` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径(建议 .glb) | +| `model` | 要导出的 B-Rep 模型 | +| `tessellation_res` | 每条边的离散段数(默认 32),越大越精确 | + +**返回**: false 导出失败 + +**参见**: `write_gltf` + + + +### `io_obj.h` + +**OBJ 文件解析结果数据结构** +`struct ObjMeshData {` + + +**每个面的顶点索引列表(0-based)** +`std::vector> faces` + + +**每个面的纹理坐标索引列表(0-based)** +`std::vector> face_texcoords` + + +**每个面的法线索引列表(0-based)** +`std::vector> face_normals` + + +**每个面对应的材质名称** +`std::vector face_materials` + + +**读取 Wavefront OBJ 文件** +`ObjMeshData read_obj(const std::string& filepath)` + +| 参数 | 说明 | +|------|------| +| `filepath` | OBJ 文件路径 | + +**返回**: 解析后的 ObjMeshData +> 不解析 MTL 材质文件,仅记录 usemtl 指令中的材质名称 +> 面索引在内部转换为 0-based;若文件中使用相对索引(负值),自动转换为正向 + +**参见**: `write_obj, ObjMeshData` + + +**写入 Wavefront OBJ 文件** +`void write_obj(const std::string& filepath, const ObjMeshData& data)` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径 | +| `data` | 要写出的网格数据 | +> 输出的面索引为 1-based(OBJ 标准) + +**参见**: `read_obj` + + + +### `io_ply.h` + +**读取 PLY 文件(Stanford Polygon Format)** +`mesh::HalfedgeMesh read_ply(const std::string& filepath)` + +| 参数 | 说明 | +|------|------| +| `filepath` | PLY 文件路径 | + +**返回**: 解析后的半边网格 +> 自动检测文件头部 magic number 判断 ASCII / 二进制格式 +> 二进制格式仅支持小端序(little-endian) +> 返回类型为 HalfedgeMesh,内部自动建立半边拓扑 + +**参见**: `write_ply` + + +**写入 PLY 文件(ASCII 格式)** +`void write_ply(const std::string& filepath, const mesh::HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径 | +| `mesh` | 要导出的半边网格 | +> 输出的 PLY 为 ASCII 编码,易于人工阅读和编辑 +> 若需要二进制输出以提高性能,请使用 BinarySerializer + +**参见**: `read_ply, BinarySerializer` + + + +### `io_stl.h` + +**STL 三角形面片** +`struct StlTriangle {` + + +**读取 STL 文件(自动检测格式)** +`std::vector read_stl(const std::string& filepath)` + +| 参数 | 说明 | +|------|------| +| `filepath` | STL 文件路径 | + +**返回**: 三角形面片列表 +> 自动格式检测:二进制 STL 的 80 字节头后跟 4 字节三角形数量 +> ASCII STL 以 "solid name" 开头 + +**参见**: `write_stl, write_stl_ascii` + + +**写入二进制 STL 文件** +`void write_stl(const std::string& filepath, const std::vector& tris)` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径 | +| `tris` | 三角形面片列表 | +> 二进制 STL 格式:80 字节头 + 4 字节三角形数 + 每三角形 50 字节 +> 法向量在写入时自动归一化 + +**参见**: `read_stl, write_stl_ascii` + + +**写入 ASCII STL 文件** +`void write_stl_ascii(const std::string& filepath, const std::vector& tris)` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径 | +| `tris` | 三角形面片列表 | + +**参见**: `read_stl, write_stl` + + + +### `math_types.h` + +**通用 N 维点类型(使用 Eigen 列向量)** +`template ` + + +**通用 N 维向量类型(与 Point 相同的列向量表示)** +`template ` + + +**基础模块提供 VDE 引擎的核心基础设施:** +`/** @} */ // end of foundation group` + + + +### `memory_pool.h` + +**固定块大小的内存池** +`template ` +> 内存池不调用对象的构造函数/析构函数,仅管理原始内存 +> 适合 POD 类型或通过 placement new 手动管理生命周期的类型 + + +**构造内存池** +`explicit MemoryPool(size_t chunk_size = 1024) : chunk_size_(chunk_size) {}` + +| 参数 | 说明 | +|------|------| +| `chunk_size` | 每个内存块可容纳的对象数(默认 1024) | + + +**析构内存池,释放所有已分配的内存块** +`~MemoryPool() { for (auto* p : chunks_) ::operator delete(p); }` + + +**从池中分配 n 个 T 对象的内存** +`T* allocate(size_t n = 1) {` + +| 参数 | 说明 | +|------|------| +| `n` | 对象数量(当前未使用,保留用于 API 兼容) | + +**返回**: 指向未初始化内存的指针 + + +**将内存归还到池中** +`void deallocate(T* p, size_t = 1) {` + +| 参数 | 说明 | +|------|------| +| `p` | 之前从 allocate() 获取的指针 | + + +**分配一个新的内存块并初始化空闲链表** +`void allocate_chunk() {` + + + +### `predicates.h` + +**统一谓词接口 — 编译时选择 GMP 或自适应双精度后端** +`struct Predicates {` + + +**二维定向测试** +`static exact::Orientation orient_2d(const Point2D& a, const Point2D& b, const Point2D& c) {` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三点 | + +**返回**: 定向结果 + + +**三维定向测试** +`static exact::Orientation orient_3d(const Point3D& a, const Point3D& b,` + +| 参数 | 说明 | +|------|------| +| `a,b,c,d` | 四点 | + +**返回**: 定向结果 + + +**圆内测试** +`static exact::CircleTest in_circle(const Point2D& a, const Point2D& b,` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三角形三顶点 | +| `d` | 测试点 | + +**返回**: 圆测试结果 + + +**二维定向测试便捷封装** +`inline exact::Orientation orient(const Point2D& a, const Point2D& b, const Point2D& c) {` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三个二维点 | + +**返回**: Orientation::Clockwise / CounterClockwise / Collinear + + +**三维定向测试便捷封装** +`inline exact::Orientation orient(const Point3D& a, const Point3D& b, const Point3D& c, const Point3D& d) {` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 定义平面的三点 | +| `d` | 测试点 | + +**返回**: Orientation::Clockwise / CounterClockwise / Collinear + + +**圆内测试便捷封装** +`inline exact::CircleTest in_circle(const Point2D& a, const Point2D& b, const Point2D& c, const Point2D& d) {` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三角形三顶点 | +| `d` | 测试点 | + +**返回**: CircleTest::Inside / On / Outside + + + +### `serializer.h` + +**二进制序列化格式的网格数据结构** +`struct SerializedMesh {` + + +**二进制序列化器** +> 该格式专为 VDE 内部快速读写设计,不适用于跨平台数据交换 +> 使用 glTF/OBJ/STL 进行外部交换,此格式用于本地缓存 + + +**序列化网格到二进制缓冲区** +`static std::vector serialize(const mesh::HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 要序列化的半边网格 | + +**返回**: 压缩后的二进制数据(含文件头) + + +**从二进制缓冲区反序列化网格** +`static mesh::HalfedgeMesh deserialize(const std::vector& data)` + +| 参数 | 说明 | +|------|------| +| `data` | 之前由 serialize() 生成的二进制数据 | + +**返回**: 恢复的半边网格 + + +**序列化并写入文件** +`static bool write_file(const std::string& path, const mesh::HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `path` | 输出文件路径 | +| `mesh` | 要保存的半边网格 | + +**返回**: false 文件创建失败 + +**参见**: `read_file` + + +**从文件读取并反序列化** +`static mesh::HalfedgeMesh read_file(const std::string& path)` + +| 参数 | 说明 | +|------|------| +| `path` | VDE 二进制格式文件路径 | + +**返回**: 恢复的半边网格 + +**参见**: `write_file` + + +**VDE 二进制文件魔数:"VDEGEOM\0"** + + +**VDE 二进制格式当前版本号** + + + +### `tolerance.h` + +**分层容差管理类** + + +**构造容差对象** +`Tolerance(double absolute = 1e-6, double relative = 1e-8,` + +| 参数 | 说明 | +|------|------| +| `absolute` | 绝对容差,默认 1e-6 | +| `relative` | 相对容差,默认 1e-8 | +| `angular` | 角度容差(弧度),默认 1e-8 | +| `snapping` | 吸附容差,默认 1e-4 | + + +**判断两点是否相等(基于绝对容差)** +`bool points_equal(const Eigen::MatrixXd& a, const Eigen::MatrixXd& b) const {` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个点(Eigen 矩阵) | +| `b` | 第二个点(Eigen 矩阵) | + +**返回**: true 若两点的欧氏距离 < absolute_ + + +**判断值是否接近零** +`template ` + +| 参数 | 说明 | +|------|------| +| `value` | 测试值 | + +**返回**: true 若 |value| < absolute_ + + +**混合容差相等判断** +`template ` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个值 | +| `b` | 第二个值 | + +**返回**: true 若两值在容差范围内相等 + + +**收紧容差** +`Tolerance tighten(double factor = 0.1) const {` + +| 参数 | 说明 | +|------|------| +| `factor` | 收紧因子(默认 0.1) | + +**返回**: 收紧后的新容差对象 + + +**放宽容差** +`Tolerance relax(double factor = 10.0) const {` + +| 参数 | 说明 | +|------|------| +| `factor` | 放宽因子(默认 10.0) | + +**返回**: 放宽后的新容差对象 + + +**合并两个容差,取更严格的(更小的)** +`static Tolerance min(const Tolerance& a, const Tolerance& b) {` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个容差 | +| `b` | 第二个容差 | + +**返回**: 每项取 min 的新容差 + + +**获取全局容差实例** +`static Tolerance& global() { return global_; }` + +**返回**: 全局容差的引用 + + +**设置全局容差** +`static void set_global(const Tolerance& tol) { global_ = tol; }` + +| 参数 | 说明 | +|------|------| +| `tol` | 新的全局容差 | +> 推荐使用 ToleranceScope 进行临时修改,确保自动恢复 + + +**局部容差作用域(RAII)** + + +**进入新的容差作用域** +`explicit ToleranceScope(const Tolerance& tol) : previous_(Tolerance::global()) {` + +| 参数 | 说明 | +|------|------| +| `tol` | 此作用域内使用的容差 | + + +**退出容差作用域,恢复之前的全局容差** +`~ToleranceScope() { Tolerance::set_global(previous_); }` + + + +## 核心几何 (`vde::core`) + + +### `aabb.h` + +**轴对齐包围盒(AABB)** +`template ` +> 初始状态为空(min = +∞, max = -∞),需要通过 expand() 初始化 + + +**构造空包围盒** +`AABB() : min_(Point3D::Constant(std::numeric_limits::max())),` + + +**从两个角点构造包围盒** +`AABB(const Point3D& min, const Point3D& max) : min_(min), max_(max) {}` + +| 参数 | 说明 | +|------|------| +| `min` | 最小角点 | +| `max` | 最大角点 | + + +**扩展包围盒以包含给定点** +`void expand(const Point3D& p) {` + +| 参数 | 说明 | +|------|------| +| `p` | 要包含的点 | + + +**扩展包围盒以包含另一个 AABB** +`void expand(const AABB& other) {` + +| 参数 | 说明 | +|------|------| +| `other` | 另一个包围盒 | + + +**包围盒中心点** +`[[nodiscard]] Point3D center() const { return (min_ + max_) * 0.5; }` + +**返回**: (min + max) / 2 + + +**包围盒对角线向量(从 min 到 max)** +`[[nodiscard]] Vector3D extent() const { return max_ - min_; }` + +**返回**: max - min + + +**包围盒表面积** +`[[nodiscard]] T surface_area() const {` + +**返回**: 2 * (dx*dy + dy*dz + dz*dx) + + +**包围盒体积** +`[[nodiscard]] T volume() const {` + +**返回**: dx * dy * dz + + +**测试点是否在包围盒内部(含边界)** +`[[nodiscard]] bool contains(const Point3D& p) const {` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | + +**返回**: true 若 min ≤ p ≤ max(各分量) + + +**测试两个包围盒是否相交(含边界接触)** +`[[nodiscard]] bool intersects(const AABB& other) const {` + +| 参数 | 说明 | +|------|------| +| `other` | 另一个包围盒 | + +**返回**: true 若存在交集 + + + +### `convex_hull.h` + +**二维凸包计算(Graham Scan 算法)** +`std::vector convex_hull_2d(const std::vector& points)` + +| 参数 | 说明 | +|------|------| +| `points` | 输入点集(至少 3 个不共线点) | + +**返回**: 凸包顶点序列(逆时针排列),不含共线的中间点 +> 自动过滤共线点,返回严格的凸包顶点 +> 若所有点共线,返回两个端点 + +**参见**: `convex_hull_3d, Polygon2D::convex_hull_2d` + + +**三维凸包计算(QuickHull 算法)** +`std::vector> convex_hull_3d(const std::vector& points)` + +| 参数 | 说明 | +|------|------| +| `points` | 输入点集(至少 4 个不共面点) | + +**返回**: 凸包三角形列表,每个三角形三顶点按逆时针排列(从外部观察) +> 返回的三角形法线方向朝外 +> 共面/退化点被自动丢弃 + +**参见**: `convex_hull_2d` + + + +### `distance.h` + +**两点之间的欧氏距离** +`double distance(const Point3D& a, const Point3D& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个点 | +| `b` | 第二个点 | + +**返回**: ||b - a|| + + +**点到直线的距离** +`double distance(const Point3D& p, const Line3D& line)` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | +| `line` | 直线 | + +**返回**: 垂直距离 + + +**点到线段的距离** +`double distance(const Point3D& p, const Segment3D& seg)` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | +| `seg` | 线段 | + +**返回**: 最短距离 + + +**点到平面的距离** +`double distance(const Point3D& p, const Plane& plane)` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | +| `plane` | 平面 | + +**返回**: 绝对垂直距离 + +**参见**: `Plane::signed_distance` + + +**点到三角形的距离** +`double distance(const Point3D& p, const Triangle& tri)` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | +| `tri` | 三角形 | + +**返回**: 最短距离 + + +**点到包围盒的距离** +`double distance(const Point3D& p, const AABB& box)` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | +| `box` | 包围盒 | + +**返回**: 最短距离(内部点返回 0) + + +**两条线段之间的最短距离** +`double distance(const Segment3D& a, const Segment3D& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一条线段 | +| `b` | 第二条线段 | + +**返回**: 最短距离(若相交则为 0) + + +**两条直线之间的最短距离** +`double distance(const Line3D& a, const Line3D& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一条直线 | +| `b` | 第二条直线 | + +**返回**: 最短距离 + + +**两个包围盒之间的最短距离** +`double distance(const AABB& a, const AABB& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个包围盒 | +| `b` | 第二个包围盒 | + +**返回**: 最短距离 + + +**两个三角形之间的最短距离** +`double distance(const Triangle& a, const Triangle& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个三角形 | +| `b` | 第二个三角形 | + +**返回**: 最短距离(若相交则为 0) + + +**三角形上距给定点最近的点** +`Point3D closest_point(const Point3D& p, const Triangle& tri)` + +| 参数 | 说明 | +|------|------| +| `p` | 查询点 | +| `tri` | 三角形 | + +**返回**: 三角形上距离 p 最近的点 + + +**线段上距给定点最近的点** +`Point3D closest_point(const Point3D& p, const Segment3D& seg)` + +| 参数 | 说明 | +|------|------| +| `p` | 查询点 | +| `seg` | 线段 | + +**返回**: 线段上距离 p 最近的点(可能为端点) + + +**包围盒上距给定点最近的点** +`Point3D closest_point(const Point3D& p, const AABB& box)` + +| 参数 | 说明 | +|------|------| +| `p` | 查询点 | +| `box` | 包围盒 | + +**返回**: 包围盒边界上(或内部)距离 p 最近的点 + + +**平面上距给定点最近的点(正交投影)** +`Point3D closest_point(const Point3D& p, const Plane& plane)` + +| 参数 | 说明 | +|------|------| +| `p` | 查询点 | +| `plane` | 平面 | + +**返回**: 点 p 在平面上的正交投影 + +**参见**: `Plane::project` + + + +### `icp.h` + +**ICP(迭代最近点)配准结果** +`struct ICPResult {` + + +**配准后的均方根误差** +`double rms_error` + + +**迭代最近点(ICP)刚体点云配准** +`[[nodiscard]] ICPResult icp_register(const std::vector& source,` + +| 参数 | 说明 | +|------|------| +| `source` | 源点云(将被移动) | +| `target` | 目标点云(固定参考) | +| `max_iter` | 最大迭代次数(默认 50) | +| `tolerance` | 收敛容差:相邻两次 RMS 变化的阈值(默认 1e-6) | + +**返回**: 配准结果,包含最终变换和误差 +> source 和 target 点数可以不同 +> 初始对齐越好,收敛越快;若初始偏差太大,可能收敛到局部最优 + + + +### `line.h` + +**三维无限直线** +`template ` + + +**从原点和方向构造直线** +`Line3D(const Point3D& origin, const Vector3D& direction)` + +| 参数 | 说明 | +|------|------| +| `origin` | 直线上一点 | +| `direction` | 方向向量(自动归一化) | + + +**参数方程求点** +`[[nodiscard]] Point3D point_at(T t) const { return origin_ + direction_ * t; }` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值 | + +**返回**: origin + direction * t + + +**三维线段** +`template ` + + +**从两个端点构造线段** +`Segment3D(const Point3D& p0, const Point3D& p1) : p0_(p0), p1_(p1) {}` + +| 参数 | 说明 | +|------|------| +| `p0` | 起点 | +| `p1` | 终点 | + + +**方向向量(未归一化)** +`[[nodiscard]] Vector3D direction() const { return p1_ - p0_; }` + +**返回**: p1 - p0 + + +**线段长度** +`[[nodiscard]] T length() const { return direction().norm(); }` + +**返回**: ||p1 - p0|| + + +**三维射线** +`template ` + + +**从原点和方向构造射线** +`Ray3D(const Point3D& origin, const Vector3D& direction)` + +| 参数 | 说明 | +|------|------| +| `origin` | 射线起点 | +| `direction` | 方向向量(自动归一化) | + + +**参数方程求点(t ≥ 0)** +`[[nodiscard]] Point3D point_at(T t) const { return origin_ + direction_ * t; }` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值(应为非负) | + +**返回**: origin + direction * t + + + +### `plane.h` + +**三维平面** +`template ` + + +**从点和法线构造平面** +`Plane(const Point3D& point, const Vector3D& normal)` + +| 参数 | 说明 | +|------|------| +| `point` | 平面上一点 | +| `normal` | 法向量(自动归一化) | + + +**从三点构造平面** +`Plane(const Point3D& a, const Point3D& b, const Point3D& c)` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 平面上不共线的三点(右手定则决定法线方向) | + + +**获取平面方程常数 d** +`[[nodiscard]] T d() const { return d_; }` + +**返回**: d 值 + + +**有向点到平面距离** +`[[nodiscard]] T signed_distance(const Point3D& p) const { return normal_.dot(p) + d_; }` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | + +**返回**: normal · p + d + + +**绝对点到平面距离** +`[[nodiscard]] T distance(const Point3D& p) const { return std::abs(signed_distance(p)); }` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | + +**返回**: |signed_distance(p)| + + +**点在平面上的正交投影** +`[[nodiscard]] Point3D project(const Point3D& p) const {` + +| 参数 | 说明 | +|------|------| +| `p` | 原点 | + +**返回**: 投影点(满足在平面上且连线垂直于平面) + + + +### `point.h` + +**核心模块提供 VDE 引擎的几何操作 API:** + + +**通用 N 维点类型(重新导出,便于 core 模块使用)** +`template ` + + +**通用 N 维向量类型(重新导出)** +`template ` + + + +### `polygon.h` + +**二维平面多边形** +> 内部假设简单多边形(无自交),非简单多边形的行为未定义 +> 所有几何计算基于(假设的)XY 平面 + + +**从顶点列表构造多边形** +`explicit Polygon2D(std::vector vertices) : vertices_(std::move(vertices)) {}` + +| 参数 | 说明 | +|------|------| +| `vertices` | 顶点序列(逆时针或顺时针均可) | + + +**有向面积(Shoelace 公式)** +`[[nodiscard]] double signed_area() const` + +**返回**: 有向面积 + + +**绝对面积** +`[[nodiscard]] double area() const { return std::abs(signed_area()); }` + +**返回**: |signed_area()| + + +**周长(各边长之和)** +`[[nodiscard]] double perimeter() const` + +**返回**: 总边长 + + +**面积加权质心** +`[[nodiscard]] Point2D centroid() const` + +**返回**: 质心坐标 + + +**二维轴对齐包围盒** +`[[nodiscard]] AABB bounding_box() const` + +**返回**: 包围盒 + + +**点包含测试(射线法)** +`[[nodiscard]] bool contains(const Point2D& p) const` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点 | + +**返回**: true 若点在多边形内部或边界上 +> 边界上的点也返回 true + + +**多边形是否为逆时针方向** +`[[nodiscard]] bool is_ccw() const { return signed_area() > 0; }` + +**返回**: signed_area() > 0 + + +**Douglas-Peucker 简化** +`[[nodiscard]] Polygon2D simplify(double tolerance) const` + +| 参数 | 说明 | +|------|------| +| `tolerance` | 允许的最大偏差 | + +**返回**: 简化后的新多边形 + +**参见**: `triangulate` + + +**耳切法三角剖分(Ear Clipping)** +`[[nodiscard]] std::vector> triangulate() const` + +**返回**: 三角形列表,每个元素为 {i, j, k} 表示顶点索引 +> 时间复杂度 O(n²),适用于顶点数 < 1000 的多边形 + +**参见**: `simplify` + + +**Andrew's Monotone Chain 二维凸包** +`static Polygon2D convex_hull_2d(const std::vector& points)` + +| 参数 | 说明 | +|------|------| +| `points` | 输入点集 | + +**返回**: 凸包多边形(CCW,不含共线中间点) + +**参见**: `convex_hull_2d` + + + +### `transform.h` + +**三维仿射变换类型** +`using Transform3D = Eigen::Transform` + + +**创建平移变换** +`inline Transform3D translate(const Vector3D& v) {` + +| 参数 | 说明 | +|------|------| +| `v` | 平移向量 | + +**返回**: 平移变换矩阵 + + +**创建平移变换(分量形式)** +`inline Transform3D translate(double x, double y, double z) {` + +| 参数 | 说明 | +|------|------| +| `x` | X 方向位移 | +| `y` | Y 方向位移 | +| `z` | Z 方向位移 | + +**返回**: 平移变换矩阵 + + +**创建旋转变换(轴-角表示)** +`inline Transform3D rotate(const Vector3D& axis, double angle_rad) {` + +| 参数 | 说明 | +|------|------| +| `axis` | 旋转轴(自动归一化) | +| `angle_rad` | 旋转角度(弧度) | + +**返回**: 旋转变换矩阵 + + +**绕 X 轴旋转** +`inline Transform3D rotate_x(double rad) { return rotate(Vector3D::UnitX(), rad); }` + +| 参数 | 说明 | +|------|------| +| `rad` | 旋转角度(弧度) | + +**返回**: 旋转变换矩阵 + + +**绕 Y 轴旋转** +`inline Transform3D rotate_y(double rad) { return rotate(Vector3D::UnitY(), rad); }` + +| 参数 | 说明 | +|------|------| +| `rad` | 旋转角度(弧度) | + +**返回**: 旋转变换矩阵 + + +**绕 Z 轴旋转** +`inline Transform3D rotate_z(double rad) { return rotate(Vector3D::UnitZ(), rad); }` + +| 参数 | 说明 | +|------|------| +| `rad` | 旋转角度(弧度) | + +**返回**: 旋转变换矩阵 + + +**创建非均匀缩放变换** +`inline Transform3D scale(double sx, double sy, double sz) {` + +| 参数 | 说明 | +|------|------| +| `sx` | X 方向缩放因子 | +| `sy` | Y 方向缩放因子 | +| `sz` | Z 方向缩放因子 | + +**返回**: 缩放变换矩阵 +> 非均匀缩放可能导致法线方向不准确;使用场景中应考虑法线变换 = (M^{-1})^T + + +**创建均匀缩放变换** +`inline Transform3D scale(double s) { return scale(s, s, s); }` + +| 参数 | 说明 | +|------|------| +| `s` | 各方向统一的缩放因子 | + +**返回**: 缩放变换矩阵 + + + +### `triangle.h` + +**三维三角形** +`template ` + + +**从三个顶点构造三角形** +`Triangle(const Point3D& v0, const Point3D& v1, const Point3D& v2)` + +| 参数 | 说明 | +|------|------| +| `v0` | 第一个顶点 | +| `v1` | 第二个顶点 | +| `v2` | 第三个顶点 | + + +**获取第 i 个顶点** +`[[nodiscard]] const Point3D& v(int i) const { return v_[i]; }` + +| 参数 | 说明 | +|------|------| +| `i` | 顶点索引(0, 1, 2) | + +**返回**: 顶点引用 + + +**三角形单位法向量** +`[[nodiscard]] Vector3D normal() const {` + +**返回**: 单位法向量 +> 若三角形退化(面积为零),返回零向量 + + +**三角形面积** +`[[nodiscard]] T area() const {` + +**返回**: 0.5 * ||(v1 - v0) × (v2 - v0)|| + + +**三角形质心(几何中心)** +`[[nodiscard]] Point3D centroid() const {` + +**返回**: (v0 + v1 + v2) / 3 + + +**重心坐标包含测试** +`[[nodiscard]] bool contains(const Point3D& p) const {` + +| 参数 | 说明 | +|------|------| +| `p` | 测试点(三维空间中的任意点) | + +**返回**: true 若投影点在三角形内部或边界上 +> 该测试等效于三维点在三角形上的包含测试(先投影再测试) + + + +### `voronoi.h` + +**Voronoi 单元格** +`struct VoronoiCell {` + + +**单元格边界顶点(按逆时针顺序排列)** +`std::vector vertices` + + +**单元格边界边** +`std::vector> edges` + + +**二维 Voronoi 图生成(通过 Delaunay 对偶图)** +`std::vector voronoi_2d(const std::vector& points)` + +| 参数 | 说明 | +|------|------| +| `points` | 输入点集(站点) | + +**返回**: 每个站点对应的 VoronoiCell 列表(顺序与输入一致) +> 对于凸包边界上的站点,对应的 Voronoi 单元格无界,顶点不完全闭合 +> 内部使用 Delaunay 三角剖分作为中间步骤 + + + +## 曲线曲面 (`vde::curves`) + + +### `bezier_curve.h` + +**任意阶 Bézier 曲线** + + +**构造 Bézier 曲线** +`explicit BezierCurve(std::vector control_points)` + +| 参数 | 说明 | +|------|------| +| `control_points` | 控制点序列,点数 = degree + 1,最少 2 个 | +> 控制点数量决定了曲线阶次;点数越多,曲线越灵活但计算越昂贵 + + +**在参数 t 处求值曲线点** +`[[nodiscard]] Point3D evaluate(double t) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值,范围 [0, 1] | + +**返回**: 曲线上对应 t 的点坐标 +> 使用 de Casteljau 递推算法,O(n²) 复杂度 + + +**在参数 t 处求导数** +`[[nodiscard]] Vector3D derivative(double t, int order = 1) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值,范围 [0, 1] | +| `order` | 导数阶数,1 = 一阶(切向量),2 = 二阶(曲率相关) | + +**返回**: 导数向量 +> 高阶导数通过降阶 Bézier 曲线计算: + + +**曲线阶次** +`[[nodiscard]] int degree() const { return static_cast(cp_.size()) - 1; }` + +**返回**: 阶次 = 控制点数 - 1 + + +**参数定义域** +`[[nodiscard]] std::pair domain() const { return {0.0, 1.0}; }` + +**返回**: 固定为 [0, 1] + + +**控制点访问** +`[[nodiscard]] const std::vector& control_points() const { return cp_; }` + +**返回**: 控制点向量的只读引用 + + +**在 t 处将曲线一分为二** +`[[nodiscard]] std::pair split(double t) const` + +| 参数 | 说明 | +|------|------| +| `t` | 分割参数,范围 [0, 1] | + +**返回**: 左段 + 右段两条 Bézier 曲线 +> 使用 de Casteljau 分割算法,分割点为三角阵的对角线 + + +**升阶操作** +`[[nodiscard]] BezierCurve degree_elevate(int times = 1) const` + +| 参数 | 说明 | +|------|------| +| `times` | 升阶次数,≥ 1 | + +**返回**: 升阶后的 Bézier 曲线(控制点数增加 times,形状不变) +> 通过反复应用公式 P_i' = i/(n+1) P_{i-1} + (1 - i/(n+1)) P_i + +**参见**: `split` + + + +### `bezier_surface.h` + +**Bézier 张量积曲面** + + +**构造 Bézier 曲面** +`BezierSurface(std::vector> control_grid)` + +| 参数 | 说明 | +|------|------| +| `control_grid` | 控制点网格,grid[i][j] 对应 u 方向第 i 个、v 方向第 j 个控制点 | +> grid 必须矩整(所有行等长);grid.size() = degree_u+1, grid[0].size() = degree_v+1 + + +**求曲面点 S(u,v)** +`[[nodiscard]] Point3D evaluate(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数,范围 [0, 1] | +| `v` | v 参数,范围 [0, 1] | + +**返回**: 曲面上对应 (u,v) 的 3D 坐标 +> 张量积求值:先按 v 方向对每行做 de Casteljau,再沿 u 方向对结果做一次 + + +**u 方向偏导数 ∂S/∂u** +`[[nodiscard]] Vector3D derivative_u(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: u 方向切向量 +> 通过降阶 Bézier 曲线计算:对 v 求值后沿 u 求导 + + +**v 方向偏导数 ∂S/∂v** +`[[nodiscard]] Vector3D derivative_v(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: v 方向切向量 + + +**单位法向量 N(u,v) = (∂S/∂u × ∂S/∂v) / |…|** +`[[nodiscard]] Vector3D normal(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: 归一化法向量(指向曲面的特选侧) +> 当两个偏导数平行时返回零向量(奇异点) + + +**u 向阶次** +`[[nodiscard]] int degree_u() const { return static_cast(cp_.size()) - 1; }` + +**返回**: u 方向阶次(控制点行数 - 1) + + +**v 向阶次** +`[[nodiscard]] int degree_v() const { return static_cast(cp_[0].size()) - 1; }` + +**返回**: v 方向阶次(控制点列数 - 1) + + +**一维 de Casteljau 求值(内部辅助)** +`[[nodiscard]] Point3D de_casteljau(double t, const std::vector& pts) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数 | +| `pts` | 一维控制点序列 | + +**返回**: 求值结果 + + + +### `bspline_curve.h` + +**B 样条曲线(非有理、均匀/非均匀节点)** + + +**构造 B 样条曲线** +`BSplineCurve(std::vector control_points,` + +| 参数 | 说明 | +|------|------| +| `control_points` | n+1 个控制点 | +| `knots` | 节点向量,必须为非递减序列 | +| `degree` | 阶次 p | +> 节点数量 = 控制点数 + 阶次 + 1;clamped 端点多重度为 p+1 + + +**在参数 t 处求值曲线点** +`[[nodiscard]] Point3D evaluate(double t) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值,必须在 domain() 范围内 | + +**返回**: 曲线上对应 t 的点坐标 +> 使用 de Boor(Cox-de Boor)递推算法 + + +**在参数 t 处求导数** +`[[nodiscard]] Vector3D derivative(double t, int order = 1) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值 | +| `order` | 导数阶数,1 = 一切向量 | + +**返回**: 导数向量 +> B 样条导数公式: + + +**曲线阶次** +`[[nodiscard]] int degree() const { return degree_; }` + +**返回**: 阶次 p + + +**参数定义域** +`[[nodiscard]] std::pair domain() const` + +**返回**: 有效参数范围 [knots[p], knots[n+1]] + + +**控制点访问** +`[[nodiscard]] const std::vector& control_points() const { return cp_; }` + +**返回**: 控制点数组只读引用 + + +**节点向量访问** +`[[nodiscard]] const std::vector& knots() const { return knots_; }` + +**返回**: 节点向量只读引用 + + +**查找 t 所在的节点区间** +`[[nodiscard]] int find_span(double t) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值 | + +**返回**: 节点区间索引 i 满足 knots[i] ≤ t < knots[i+1] +> 使用二分查找,O(log n);求值和基函数的前置步骤 + + +**在 t 处求非零基函数值** +`[[nodiscard]] std::vector basis_functions(double t, int span = -1) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值 | +| `span` | 节点区间索引,-1 表示自动查找 | + +**返回**: N_{span-p}(t), ..., N_{span}(t) 共 p+1 个值 +> 仅返回 p+1 个非零基函数;用于端点求值及插值 + +**参见**: `find_span` + + +**在 t 处求非零基函数的一阶导数** +`[[nodiscard]] std::vector basis_derivatives(double t, int span = -1) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值 | +| `span` | 节点区间索引,-1 表示自动查找 | + +**返回**: dN_{span-p}/du, ..., dN_{span}/du 共 p+1 个值 +> B 样条基函数导数递推: + +**参见**: `basis_functions` + + + +### `bspline_surface.h` + +**B 样条张量积曲面(非有理)** + + +**构造 B 样条曲面** +`BSplineSurface(std::vector> control_grid,` + +| 参数 | 说明 | +|------|------| +| `control_grid` | (nu+1)×(nv+1) 控制点网格 | +| `knots_u` | u 向节点向量,长度 = nu + pu + 1 | +| `knots_v` | v 向节点向量,长度 = nv + pv + 1 | +| `degree_u` | u 向阶次 pu | +| `degree_v` | v 向阶次 pv | + + +**求曲面点 S(u,v)** +`[[nodiscard]] Point3D evaluate(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: 曲面上的 3D 点 +> 张量积分解:先行后列(或先列后行)做两次 B 样条求值 + + +**u 向偏导数 ∂S/∂u** +`[[nodiscard]] Vector3D derivative_u(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: u 向切向量 + + +**v 向偏导数 ∂S/∂v** +`[[nodiscard]] Vector3D derivative_v(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: v 向切向量 + + +**单位法向量** +`[[nodiscard]] Vector3D normal(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: N(u,v) = (∂S/∂u × ∂S/∂v) / |…| + + +**u 向阶次** +`[[nodiscard]] int degree_u() const { return degree_u_; }` + +**返回**: pu + + +**v 向阶次** +`[[nodiscard]] int degree_v() const { return degree_v_; }` + +**返回**: pv + + +**u 向节点向量** +`[[nodiscard]] const std::vector& knots_u() const { return knots_u_; }` + +**返回**: 只读引用 + + +**v 向节点向量** +`[[nodiscard]] const std::vector& knots_v() const { return knots_v_; }` + +**返回**: 只读引用 + + + +### `nurbs_curve.h` + +**NURBS 曲线(Non-Uniform Rational B-Spline)** + + +**构造 NURBS 曲线** +`NurbsCurve(std::vector control_points, std::vector knots,` + +| 参数 | 说明 | +|------|------| +| `control_points` | 控制点序列 | +| `knots` | 节点向量 | +| `weights` | 权重序列,必须与 control_points 等长,各分量 > 0 | +| `degree` | 阶次 p | +> 所有权重必须 > 0 以保证分母不为零(非退化) + + +**在参数 t 处求值** +`[[nodiscard]] Point3D evaluate(double t) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值 | + +**返回**: 曲线上对应 t 的点坐标 +> 内部将 (w·P, w) 提升为齐次坐标的 B 样条,求值后投影回 3D + + +**在参数 t 处求导数** +`[[nodiscard]] Vector3D derivative(double t, int order = 1) const` + +| 参数 | 说明 | +|------|------| +| `t` | 参数值 | +| `order` | 导数阶数 | + +**返回**: 导数向量 +> 有理导数公式: + + +**曲线阶次** +`[[nodiscard]] int degree() const { return degree_; }` + +**返回**: p + + +**参数定义域** +`[[nodiscard]] std::pair domain() const` + +**返回**: [knots[degree], knots[n+1]] + + +**控制点访问** +`[[nodiscard]] const std::vector& control_points() const { return cp_; }` + +**返回**: 只读引用 + + +**权重访问** +`[[nodiscard]] const std::vector& weights() const { return weights_; }` + +**返回**: 只读引用 + + +**节点向量访问** +`[[nodiscard]] const std::vector& knots() const { return knots_; }` + +**返回**: 只读引用 + + + +### `nurbs_operations.h` + +**NURBS 曲面等距偏移** +`[[nodiscard]] NurbsSurface offset_surface(const NurbsSurface& surf, double distance)` + +| 参数 | 说明 | +|------|------| +| `surf` | 输入 NURBS 曲面 | +| `distance` | 偏移距离(正值 = 沿法向外,负值 = 向内) | + +**返回**: 偏移后的 NURBS 曲面(近似,阶次与原曲面相同) +> 这是几何近似,非精确偏移。对于大变曲率曲面,增大控制点数量 +> 偏移可能导致自交(distance 超过曲面局部曲率半径时) + +**参见**: `trim_surface blend_surfaces` + + +**NURBS 曲面参数域裁剪** +`[[nodiscard]] NurbsSurface trim_surface(const NurbsSurface& surf,` + +| 参数 | 说明 | +|------|------| +| `surf` | 输入曲面 | +| `u_min,u_max` | 裁剪后的 u 参数范围(必须在原 domain 内) | +| `v_min,v_max` | 裁剪后的 v 参数范围(必须在原 domain 内) | + +**返回**: 裁剪后的 NURBS 曲面 +> 裁剪是"软裁剪"——几何不变,仅改变参数化。如需"硬裁剪" + + +**两 NURBS 曲面沿边界边的过渡面** +`[[nodiscard]] NurbsSurface blend_surfaces(const NurbsSurface& surf_a,` + +| 参数 | 说明 | +|------|------| +| `surf_a` | 第一个曲面 | +| `surf_b` | 第二个曲面 | +| `edge_a` | surf_a 的边界边索引(0=u_min, 1=u_max, 2=v_min, 3=v_max) | +| `edge_b` | surf_b 的边界边索引(0=u_min, 1=u_max, 2=v_min, 3=v_max) | +| `blend_radius` | 过渡半径 | + +**返回**: 过渡 NURBS 曲面(在偏移边界曲线间的直纹面) +> 过渡面与原始曲面在边界处为 C⁰ 连续(非切线连续) + +**参见**: `ruled_surface` + + +**两 NURBS 曲线间的直纹面** +`[[nodiscard]] NurbsSurface ruled_surface(const NurbsCurve& curve_a,` + +| 参数 | 说明 | +|------|------| +| `curve_a` | 第一条曲线(v=0 边界) | +| `curve_b` | 第二条曲线(v=1 边界) | + +**返回**: 直纹 NURBS 曲面 +> 两条曲线需有兼容的阶次和节点结构(内部执行升阶和节点精化) + +**参见**: `coons_patch blend_surfaces` + + +**由四条边界曲线创建 Coons 曲面** +`[[nodiscard]] NurbsSurface coons_patch(const NurbsCurve& curve_u0,` + +| 参数 | 说明 | +|------|------| +| `curve_u0` | v=0 处边界(沿 u 方向) | +| `curve_u1` | v=1 处边界(沿 u 方向) | +| `curve_v0` | u=0 处边界(沿 v 方向) | +| `curve_v1` | u=1 处边界(沿 v 方向) | + +**返回**: Coons 曲面 +> 仅保证边界插值,不保证内部形状与设计意图一致 + +**参见**: `ruled_surface` + + +**沿方向向量拉伸 NURBS 曲线为曲面** +`[[nodiscard]] NurbsSurface extrude_curve(const NurbsCurve& curve,` + +| 参数 | 说明 | +|------|------| +| `curve` | 截面曲线 | +| `direction` | 拉伸方向(内部归一化) | +| `length` | 拉伸长度 | + +**返回**: 拉伸 NURBS 曲面 + + +**提取 NURBS 曲面的等参边界曲线** +`[[nodiscard]] NurbsCurve extract_boundary_curve(const NurbsSurface& surf, int edge)` + +| 参数 | 说明 | +|------|------| +| `surf` | 输入曲面 | +| `edge` | 边界索引:0=u_min, 1=u_max, 2=v_min, 3=v_max | + +**返回**: 指定边界上的 NURBS 曲线 +> 边界曲线继承原曲面该方向的阶次和节点向量 + + + +### `nurbs_surface.h` + +**NURBS 张量积曲面** + + +**构造 NURBS 曲面** +`NurbsSurface(std::vector> control_grid,` + +| 参数 | 说明 | +|------|------| +| `control_grid` | 控制点网格 | +| `knots_u` | u 向节点向量 | +| `knots_v` | v 向节点向量 | +| `weights` | 权重网格,维度与 control_grid 一致,所有值 > 0 | +| `degree_u` | u 向阶次 | +| `degree_v` | v 向阶次 | + + +**求曲面点 S(u,v)** +`[[nodiscard]] Point3D evaluate(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: 曲面上对应 (u,v) 的 3D 点 + + +**u 向偏导数** +`[[nodiscard]] Vector3D derivative_u(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: ∂S/∂u + + +**v 向偏导数** +`[[nodiscard]] Vector3D derivative_v(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: ∂S/∂v + + +**单位法向量** +`[[nodiscard]] Vector3D normal(double u, double v) const` + +| 参数 | 说明 | +|------|------| +| `u` | u 参数 | +| `v` | v 参数 | + +**返回**: N(u,v) = normalize(∂S/∂u × ∂S/∂v) + + +**u 向阶次** +`[[nodiscard]] int degree_u() const { return degree_u_; }` + +**返回**: pu + + +**v 向阶次** +`[[nodiscard]] int degree_v() const { return degree_v_; }` + +**返回**: pv + + +**控制点数量** +`[[nodiscard]] std::array num_control_points() const {` + +**返回**: {nu+1, nv+1},即网格的行数和列数 + + +**u 向节点向量** +`[[nodiscard]] const std::vector& knots_u() const { return knots_u_; }` + +**返回**: 只读引用 + + +**v 向节点向量** +`[[nodiscard]] const std::vector& knots_v() const { return knots_v_; }` + +**返回**: 只读引用 + + +**控制点网格访问** +`[[nodiscard]] const std::vector>& control_points() const { return cp_; }` + +**返回**: 只读引用 + + +**权重网格访问** +`[[nodiscard]] const std::vector>& weights() const { return weights_; }` + +**返回**: 只读引用 + + +**由两条 NURBS 曲线创建直纹面** +`static NurbsSurface ruled(const NurbsCurve& c1, const NurbsCurve& c2)` + +| 参数 | 说明 | +|------|------| +| `c1` | 起始曲线(v=0 边界) | +| `c2` | 终止曲线(v=1 边界) | + +**返回**: 直纹 NURBS 曲面 +> 两条曲线需具有兼容的阶次和节点结构(内部做升阶和节点精化对齐) + +**参见**: `blend_surfaces ruled_surface` + + +**由截面曲线旋转生成旋转曲面** +`static NurbsSurface revolve(const NurbsCurve& profile, const Point3D& axis_origin,` + +| 参数 | 说明 | +|------|------| +| `profile` | 截面 NURBS 曲线 | +| `axis_origin` | 旋转轴上一点 | +| `axis_dir` | 旋转轴方向 | +| `angle_rad` | 旋转角度(弧度),≤ 2π | + +**返回**: 旋转 NURBS 曲面 +> 使用 NURBS 表示圆弧的权重方案;完整旋转生成闭曲面 + + +**将 NURBS 曲面三角化** +`[[nodiscard]] std::pair, std::vector>>` + +| 参数 | 说明 | +|------|------| +| `res_u` | u 方向采样分辨率 | +| `res_v` | v 方向采样分辨率 | + +**返回**: {顶点数组, 三角形索引数组},每个三角形为 {i0,i1,i2} +> 生成 res_u×res_v 均匀网格,每个单元格拆为两个三角形 + +**参见**: `tessellate` + + + +### `tessellation.h` + +**均匀参数化曲面三角化** +`std::pair, std::vector>>` + +| 参数 | 说明 | +|------|------| +| `eval` | 曲面求值函数 eval(u,v) -> Point3D,参数 (u,v) ∈ [0,1]×[0,1] | +| `res_u` | u 方向子分段数(≥ 1) | +| `res_v` | v 方向子分段数(≥ 1) | + +**返回**: {顶点数组, 三角形索引数组},三角形为 {i0,i1,i2} +> 总顶点数 = (res_u+1)×(res_v+1),三角形数 = 2×res_u×res_v + +**参见**: `adaptive_tessellate` + + +**自适应曲面三角化** +`std::pair, std::vector>>` + +| 参数 | 说明 | +|------|------| +| `eval` | 曲面求值函数 eval(u,v) -> Point3D | +| `normal_fn` | 单位法向函数 normal_fn(u,v) -> Vector3D | +| `min_res` | 初始每向子分段数(≥ 1),默认 2 | +| `max_depth` | 最大递归深度,限制总面数,默认 6 | +| `angle_threshold_deg` | 法向角度偏差阈值(度),默认 5.0 | + +**返回**: {顶点数组, 三角形索引数组} +> 最终面数上限约为 2·min_res²·4^max_depth(实际远小于此上限) + +**参见**: `tessellate` + + + +## 网格处理 (`vde::mesh`) + + +### `alpha_shapes.h` + +**Alpha Shapes 点云表面重建** +`TetrahedronMesh alpha_shapes(const std::vector& points, double alpha)` + +| 参数 | 说明 | +|------|------| +| `points` | 输入 3D 点云 | +| `alpha` | α 半径阈值,通常取平均点间距的 1~3 倍 | + +**返回**: TetrahedronMesh 保留的四面体网格 + +**参见**: `alpha_shapes_surface delaunay_3d` + + +**将 Alpha Shapes 四面体网格的表面提取为三角形网格** +`std::pair, std::vector>>` + +| 参数 | 说明 | +|------|------| +| `tet_mesh` | Alpha Shapes 输出的四面体网格 | + +**返回**: {顶点数组, 三角形索引数组} +> 表面三角形法向指向四面体外部(右手定则) + +**参见**: `alpha_shapes` + + + +### `cdt_2d.h` + +**约束 Delaunay 三角化(CDT)** +`DelaunayResult constrained_delaunay_2d(` + +| 参数 | 说明 | +|------|------| +| `points` | 输入 2D 点集 | +| `constraints` | 约束边列表,每项为 {起点索引, 终点索引} | + +**返回**: DelaunayResult 含约束边的三角化结果 +> 约束边不能相交(否则行为未定义);自相交约束需先分割交点 + +**参见**: `delaunay_2d` + + + +### `delaunay_2d.h` + +**2D Delaunay 三角化结果** +`struct DelaunayResult {` + + +**2D Delaunay 三角化(Bowyer-Watson 增量算法)** +`DelaunayResult delaunay_2d(const std::vector& points)` + +| 参数 | 说明 | +|------|------| +| `points` | 输入 2D 点集(至少 3 个不共线点) | + +**返回**: DelaunayResult 三角化结果 +> 时间复杂度:平均 O(n log n),最坏 O(n²) + +**参见**: `constrained_delaunay_2d` + + + +### `delaunay_3d.h` + +**四面体网格结构** +`struct TetrahedronMesh {` + + +**3D Delaunay 四面体化(Bowyer-Watson 增量算法)** +`TetrahedronMesh delaunay_3d(const std::vector& points)` + +| 参数 | 说明 | +|------|------| +| `points` | 输入 3D 点集(至少 4 个不共面点) | + +**返回**: TetrahedronMesh 四面体网格 +> 时间复杂度与 2D 类似:平均 O(n log n),最坏 O(n²) +> 输出包括内部和边界四面体;通过 alpha_shapes 可提取表面 + +**参见**: `alpha_shapes` + + + +### `geodesic.h` + +**热方法(Heat Method)计算测地距离** +`std::vector geodesic_distance(const HalfedgeMesh& mesh,` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格 | +| `sources` | 源顶点索引列表(距离为 0 的顶点) | +| `t` | 时间步长,< 0 时自动设为平均边长平方 | + +**返回**: 每顶点到最近源点的测地距离 +> 要求网格为连通流形;时间步长 t 越小精度越高但数值越不稳定 + + + +### `halfedge_mesh.h` + +**半边数据结构元素** +`struct Halfedge {` + + +**面元素** +`struct Face {` + + +**半边数据结构三角网格** + + +**清空所有数据** +`void clear()` + + +**添加顶点** +`int add_vertex(const Point3D& p)` + +| 参数 | 说明 | +|------|------| +| `p` | 3D 坐标 | + +**返回**: 新顶点的索引(0-based) + + +**添加面** +`int add_face(const std::vector& vertex_indices)` + +| 参数 | 说明 | +|------|------| +| `vertex_indices` | 按逆时针顺序排列的顶点索引(至少 3 个) | + +**返回**: 新面的索引,失败返回 -1 +> 自动创建/查找半边并设置对侧关系;面法向遵循右手定则 + + +**从三角形列表批量构建半边形网格** +`void build_from_triangles(const std::vector& verts,` + +| 参数 | 说明 | +|------|------| +| `verts` | 顶点位置数组 | +| `tris` | 三角形索引数组,每个 {i0,i1,i2} | +> 等价于反复调用 add_vertex + add_face,但内部做批处理优化 + + +**顶点数量** +`[[nodiscard]] size_t num_vertices() const { return vertices_.size(); }` + +**返回**: vertices_ 大小 + + +**面数量** +`[[nodiscard]] size_t num_faces() const { return faces_.size(); }` + +**返回**: faces_ 大小 + + +**边数量** +`[[nodiscard]] size_t num_edges() const { return halfedges_.size() / 2; }` + +**返回**: halfedges_.size() / 2 + + +**访问顶点** +`[[nodiscard]] const Point3D& vertex(size_t idx) const { return vertices_[idx]; }` + +| 参数 | 说明 | +|------|------| +| `idx` | 顶点索引,0 ≤ idx < num_vertices() | + +**返回**: 顶点坐标只读引用 + + +**访问面** +`[[nodiscard]] const Face& face(size_t idx) const { return faces_[idx]; }` + +| 参数 | 说明 | +|------|------| +| `idx` | 面索引 | + +**返回**: Face 只读引用 + + +**访问半边** +`[[nodiscard]] const Halfedge& halfedge(size_t idx) const { return halfedges_[idx]; }` + +| 参数 | 说明 | +|------|------| +| `idx` | 半边索引 | + +**返回**: Halfedge 只读引用 + + +**更新顶点位置** +`void set_vertex(size_t idx, const Point3D& p) { vertices_[idx] = p; normals_dirty_ = true; }` + +| 参数 | 说明 | +|------|------| +| `idx` | 顶点索引 | +| `p` | 新坐标 | +> 标记法向缓存为脏,下次查询时重新计算 + + +**获取面的所有顶点索引(按环绕顺序)** +`[[nodiscard]] std::vector face_vertices(int fi) const` + +| 参数 | 说明 | +|------|------| +| `fi` | 面索引 | + +**返回**: 顶点索引序列 + + +**获取顶点的邻面索引环** +`[[nodiscard]] std::vector vertex_faces(int vi) const` + +| 参数 | 说明 | +|------|------| +| `vi` | 顶点索引 | + +**返回**: 所有以 vi 为顶点的面索引 + + +**是否为边界半边** +`[[nodiscard]] bool is_boundary_edge(int hei) const { return halfedges_[hei].face_index < 0; }` + +| 参数 | 说明 | +|------|------| +| `hei` | 半边索引 | + +**返回**: 没有所属面时为 true + + +**是否为边界顶点** +`[[nodiscard]] bool is_boundary_vertex(int vi) const` + +| 参数 | 说明 | +|------|------| +| `vi` | 顶点索引 | + +**返回**: 邻接任何边界半边时为 true + + +**面法向(几何法向,非归一化?由实现决定)** +`[[nodiscard]] Vector3D face_normal(int fi) const` + +| 参数 | 说明 | +|------|------| +| `fi` | 面索引 | + +**返回**: (v1-v0)×(v2-v0) 归一化结果 + + +**顶点法向(邻面法向的面积加权平均)** +`[[nodiscard]] Vector3D vertex_normal(int vi) const` + +| 参数 | 说明 | +|------|------| +| `vi` | 顶点索引 | + +**返回**: 归一化顶点法向 + + +**重新计算所有面法向和顶点法向** +`void update_normals()` +> 修改顶点位置后自动标记脏位,调用此方法触发重新计算 + + +**网格包围盒** +`[[nodiscard]] AABB3D bounds() const` + +**返回**: AABB3D 轴对齐包围盒 + + +**面迭代器范围(支持 for-range)** + + +**顶点单邻环迭代器** + + +**获取所有面范围(range-based for 支持)** +`[[nodiscard]] FaceRange faces_range() const` + +**返回**: FaceRange 对象 + + +**获取顶点的 1-ring 邻域迭代器** +`[[nodiscard]] VertexOneRing vertex_one_ring(int vi) const` + +| 参数 | 说明 | +|------|------| +| `vi` | 顶点索引 | + +**返回**: VertexOneRing 对象 + + +**查找或创建半边 (v0→v1)** +`int find_or_create_edge(int v0, int v1)` + +| 参数 | 说明 | +|------|------| +| `v0` | 起点顶点索引 | +| `v1` | 终点顶点索引 | + +**返回**: 半边索引 + + + +### `marching_cubes.h` + +**Marching Cubes 输出网格** +`struct MCMesh {` + + +**Marching Cubes 等值面提取** +`MCMesh marching_cubes(const std::function& f,` + +| 参数 | 说明 | +|------|------| +| `f` | 标量场函数 f(x,y,z) → double | +| `iso_level` | 等值面值(默认 0) | +| `bmin` | 包围盒最小角 | +| `bmax` | 包围盒最大角 | +| `resolution` | 每轴采样分辨率(≥ 1),总网格 = resolution³ 个立方体 | + +**返回**: MCMesh 三角形网格 +> 使用经典的 256 查表法(Lorensen & Cline 1987) + +**参见**: `sdf_sphere sdf_box` + + +**SDF 球体函数** +`inline double sdf_sphere(double x, double y, double z, double cx, double cy, double cz, double r) {` + +| 参数 | 说明 | +|------|------| +| `x,y,z` | 采样点坐标 | +| `cx,cy,cz` | 球心坐标 | +| `r` | 半径 | + +**返回**: 有符号距离:内部 < 0,表面 = 0,外部 > 0 + + +**SDF 立方体函数(轴对齐,中心在原点)** +`inline double sdf_box(double x, double y, double z, double hx, double hy, double hz) {` + +| 参数 | 说明 | +|------|------| +| `x,y,z` | 采样点坐标 | +| `hx,hy,hz` | 半边长 | + +**返回**: 有符号距离 + + +**SDF 平滑并集(Smooth Union)** + +| 参数 | 说明 | +|------|------| +| `d1,d2` | 两个 SDF 值 | +| `k` | 平滑宽度(> 0),值越大过渡越平滑 | + +**返回**: 混合后的 SDF 值 + + +**SDF 平滑差集(Smooth Subtraction)** +`inline double sdf_smooth_subtraction(double d1, double d2, double k) {` + +| 参数 | 说明 | +|------|------| +| `d1,d2` | 两个 SDF 值 | +| `k` | 平滑宽度(> 0) | + +**返回**: 混合后的 SDF 值 + + + +### `mesh_boolean.h` + +**布尔运算类型(CSG 组合)** +`enum class BooleanOp {` + + +**三角网格布尔运算** +`HalfedgeMesh mesh_boolean(const HalfedgeMesh& a, const HalfedgeMesh& b, BooleanOp op)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个三角网格(必须为封闭流形) | +| `b` | 第二个三角网格(必须为封闭流形) | +| `op` | 布尔运算类型 | + +**返回**: 结果三角网格 +> 要求输入网格为封闭流形(watertight),否则分类不可靠 + + + +### `mesh_curvature.h` + +**离散曲率计算结果** +`struct CurvatureResult {` + + +**离散曲率计算(Cotan 公式,Meyer et al. 2003)** +`CurvatureResult compute_curvature(const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格 | + +**返回**: CurvatureResult 每顶点曲率 +> 要求网格为流形;边界顶点曲率使用近似公式 + + + +### `mesh_parameterize.h` + +**Tutte 参数化(调和参数化)** +`[[nodiscard]] std::vector tutte_parameterization(const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格(需含边界) | + +**返回**: 每顶点 UV 坐标(Point2D),顺序与 mesh 顶点一致 +> 网格必须有边界(开网格);闭曲面需先切割为拓扑圆盘 + +**参见**: `lscm_parameterization` + + +**LSCM(Least Squares Conformal Maps)参数化** +`[[nodiscard]] std::vector lscm_parameterization(const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格 | + +**返回**: 每顶点 UV 坐标(Point2D) +> 简化实现,不包含完整 Lévy 论文中所有的退化处理 + +**参见**: `tutte_parameterization` + + + +### `mesh_quality.h` + +**三角网格质量指标** +`struct MeshQuality {` + + +**评估三角网格质量** +`MeshQuality evaluate_mesh_quality(const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格 | + +**返回**: MeshQuality 质量指标汇总 + + +**四面体网格质量指标** +`struct TetQuality {` + + +**评估三角网格作为四面体边界的质量** +`TetQuality evaluate_tet_quality(const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 封闭三角网格(volume boundary) | + +**返回**: TetQuality 四面体质量指标 +> 这不是真正的四面体网格质量评估——仅用于表面网格的代理指标 + + +**单元类型枚举** +`enum class ElementType {` + + +**通用单元质量指标** +`struct ElemQuality {` + + +**按单元类型分派的网格质量评估** +`ElemQuality evaluate_element_quality(const HalfedgeMesh& mesh, ElementType type)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入网格 | +| `type` | 单元类型 | + +**返回**: ElemQuality 质量指标 +> 目前仅 Tri 和 Tet 完整实现;Quad / Hex 返回 stub(全零) + + +**详细质量报告** +`struct QualityReport {` + + +**生成三角网格的完整质量报告** +`QualityReport mesh_quality_report(const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格 | + +**返回**: QualityReport 完整质量报告 + + +**生成四面体网格的完整质量报告** +`QualityReport mesh_quality_report_tet(const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 封闭三角网格 | + +**返回**: QualityReport 完整质量报告 + + +**三角形归一化 Jacobian** +`double tri_scaled_jacobian(const Point3D& a, const Point3D& b, const Point3D& c)` + +| 参数 | 说明 | +|------|------| +| `a,b,c` | 三角形三个顶点 | + +**返回**: 归一化 Jacobian [-1, 1] + + +**四面体归一化 Jacobian** +`double tet_scaled_jacobian(const Point3D& a, const Point3D& b,` + +| 参数 | 说明 | +|------|------| +| `a,b,c,d` | 四面体四个顶点 | + +**返回**: 归一化 Jacobian [0, 1] + + + +### `mesh_repair.h` + +**网格修复选项** +`struct RepairOptions {` + + +**自动网格修复** +`HalfedgeMesh repair_mesh(const HalfedgeMesh& mesh, const RepairOptions& opts = {})` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入网格(可能有缺陷) | +| `opts` | 修复选项(默认全部启用) | + +**返回**: 修复后的网格 +> 修复为启发式算法,不保证 100% 成功;孔洞过大或非流形边可能仍有残留问题 + + + +### `mesh_simplify.h` + +**网格简化选项** +`struct SimplifyOptions {` + + +**QEM(Quadric Error Metrics)网格简化** +`HalfedgeMesh simplify_mesh(const HalfedgeMesh& mesh, const SimplifyOptions& opts = {})` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格 | +| `opts` | 简化选项 | + +**返回**: 简化后的网格 +> preserve_boundary 模式下,边界边通过惩罚项(大代价)被保护 + + + +### `mesh_smooth.h` + +**网格光顺方法** +`enum class SmoothMethod {` + + +**网格光顺参数** +`struct SmoothOptions {` + + +**网格光顺(通用分发器)** +`HalfedgeMesh smooth_mesh(const HalfedgeMesh& mesh, const SmoothOptions& opts = {})` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入三角网格 | +| `opts` | 光顺选项 | + +**返回**: 光顺后的网格(顶点位置更新,拓扑不变) + + +**标准拉普拉斯光顺** +`HalfedgeMesh smooth_laplacian(const HalfedgeMesh& mesh, int iterations, double lambda)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入网格 | +| `iterations` | 迭代次数 | +| `lambda` | 步长系数 (0, 1] | + +**返回**: 光顺后的网格 +> 迭代过多会导致网格坍塌;对于体积关键的应用优先选 Taubin 或 HC + +**参见**: `smooth_taubin smooth_hc_laplacian` + + +**Taubin λ|μ 光顺(体积保持)** +`HalfedgeMesh smooth_taubin(const HalfedgeMesh& mesh, int iterations, double lambda, double mu)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入网格 | +| `iterations` | 完整 λ/μ 循环次数 | +| `lambda` | 正步系数 (0, 1] | +| `mu` | 负步系数,需满足 mu < 0 且 |mu| > lambda | + +**返回**: 光顺后的网格 +> 典型值:λ = 0.5, μ = -0.53;|mu| 过大可能导致不稳定振荡 + + +**HC 拉普拉斯光顺(Humphrey's Classes)** +`HalfedgeMesh smooth_hc_laplacian(const HalfedgeMesh& mesh, const SmoothOptions& opts = {})` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入网格 | +| `opts` | 光顺选项(使用 hc_alpha 和 hc_beta 字段) | + +**返回**: 光顺后的网格 + + +**双边网格滤波** +`HalfedgeMesh smooth_bilateral(const HalfedgeMesh& mesh, const SmoothOptions& opts = {})` + +| 参数 | 说明 | +|------|------| +| `mesh` | 输入网格 | +| `opts` | 光顺选项(使用 bilateral_ 前缀字段) | + +**返回**: 光顺后的网格 + + + +## 空间索引 (`vde::spatial`) + + +### `bvh.h` + +**包围盒层次结构 (Bounding Volume Hierarchy)** + + +**BVH 构建分裂策略** +`enum class BVHSplitStrategy {` + + +**< 按最长轴中点分裂** +`Equal, /**< 按数量均等分裂 */` + + +**< 按数量均等分裂** +`SAH /**< Surface Area Heuristic — 最小化射线击中概率期望 */` + + +**< Surface Area Heuristic — 最小化射线击中概率期望** +`}` + + +**BVH 构建选项** +`struct BVHBuildOptions {` + + +**< 分裂策略** +`int leaf_size = 4; /**< 叶节点最大图元数 */` + + +**< 叶节点最大图元数** +`int max_depth = 64; /**< 树的最大深度 */` + + +**< 树的最大深度** +`}` + + +**包围盒层次结构 — 三角形网格加速结构** + +**参见**: `SpatialIndex, Octree, KDTree, RTree` + + +**构造 BVH 并指定构建选项** +`explicit BVH(const BVHBuildOptions& opts = {}) : opts_(opts) {}` + +| 参数 | 说明 | +|------|------| +| `opts` | 构建选项(分裂策略、叶节点大小、最大深度) | + + +**清除已有数据并重建 BVH** +`void build(const std::vector& tris) override` + +| 参数 | 说明 | +|------|------| +| `tris` | 三角形数组 | + + +**插入单个三角形** +`void insert(const Triangle3D& tri) override` + +| 参数 | 说明 | +|------|------| +| `tri` | 要插入的三角形 | + + +**删除三角形** +`bool remove(const Triangle3D& tri) override` + +| 参数 | 说明 | +|------|------| +| `tri` | 要删除的三角形 | + +**返回**: 删除成功返回 true + + +**AABB 范围查询** +`std::vector query_range(const AABB3D& range) const override` + +| 参数 | 说明 | +|------|------| +| `range` | 查询包围盒 | + +**返回**: 与 range 相交的三角形列表 + + +**K 近邻查询** +`std::vector query_knn(const Point3D& point, size_t k) const override` + +| 参数 | 说明 | +|------|------| +| `point` | 查询点 | +| `k` | 返回数量 | + +**返回**: 最近的 k 个三角形 + + +**射线查询:返回所有命中的三角形** +`std::vector query_ray(const Ray3Dd& ray) const override` + +| 参数 | 说明 | +|------|------| +| `ray` | 查询射线 | + +**返回**: 按命中顺序排列的三角形列表 + + +**清空 BVH 树和所有三角形** +`void clear() override` + + +**三角形数量** +`size_t size() const override { return primitives_.size(); }` + +**返回**: 当前索引的三角形总数 + + +**射线最近命中查询结果** +`struct HitResult {` + + +**< 沿射线的参数 t** +`Triangle3D tri; /**< 命中的三角形 */` + + +**< 命中的三角形** +`Point3D point; /**< 命中点的世界坐标 = origin + t * dir */` + + +**< 命中点的世界坐标 = origin + t * dir** +`}` + + +**射线最近命中查询** +`std::optional query_ray_nearest(const Ray3Dd& ray) const` + +| 参数 | 说明 | +|------|------| +| `ray` | 查询射线 | + +**返回**: 最近命中结果(若无命中则返回空) +> 比 query_ray() 更高效,仅返回最近命中 + + +**BVH 节点** +`struct Node {` + + +**< 节点的包围盒(所有子节点/图元的并集)** +`int left = -1; /**< 左子节点索引,叶节点为 -1 */` + + +**< 左子节点索引,叶节点为 -1** +`int right = -1; /**< 右子节点索引,叶节点为 -1 */` + + +**< 右子节点索引,叶节点为 -1** +`int first_prim = 0; /**< 叶节点第一个图元的索引 */` + + +**< 叶节点第一个图元的索引** +`int prim_count = 0; /**< 叶节点图元数量 */` + + +**< 叶节点图元数量** +`/** @brief 判断是否为叶节点 */` + + +**判断是否为叶节点** +`bool leaf() const { return left < 0; }` + + +**< 节点数组(根节点为 nodes_[0])** +`std::vector primitives_; /**< 图元数组 */` + + +**< 图元数组** +`BVHBuildOptions opts_; /**< 构建选项 */` + + +**< 构建选项** +`/**` + + +**递归构建 BVH 子树** +`void build_recursive(int node, int first, int count, int depth)` + +| 参数 | 说明 | +|------|------| +| `node` | 当前节点索引 | +| `first` | 图元范围的起始索引 | +| `count` | 图元数量 | +| `depth` | 当前递归深度 | + + +**计算 SAH 分裂代价** +`double sah_cost(int n_left, int n_right, const AABB3D& left, const AABB3D& right) const` + +| 参数 | 说明 | +|------|------| +| `n_left` | 左子树图元数 | +| `n_right` | 右子树图元数 | +| `left` | 左子树包围盒 | +| `right` | 右子树包围盒 | + +**返回**: SAH 代价估值 + + + +### `kd_tree.h` + +**k-d 树 (K-Dimensional Tree) 空间划分结构** + + +**k-d 树空间索引** +`template ` +> k-d 树在维度约 2~6 时效率最佳。三维场景中, + +**参见**: `SpatialIndex, BVH, Octree` + + +**批量构建 k-d 树** +`void build(const std::vector& items) override` + +| 参数 | 说明 | +|------|------| +| `items` | 待索引的对象数组 | + + +**插入单个对象** +`void insert(const T& item) override` + +| 参数 | 说明 | +|------|------| +| `item` | 待插入的空间对象 | + + +**删除对象** +`bool remove(const T& item) override` + +| 参数 | 说明 | +|------|------| +| `item` | 待删除的空间对象 | + +**返回**: 删除成功返回 true + + +**范围查询** +`std::vector query_range(const AABB3D& range) const override` + +| 参数 | 说明 | +|------|------| +| `range` | 查询包围盒 | + +**返回**: 与 range 相交的对象列表 + + +**K 近邻查询** +`std::vector query_knn(const Point3D& point, size_t k) const override` + +| 参数 | 说明 | +|------|------| +| `point` | 查询点 | +| `k` | 返回数量 | + +**返回**: 最近的 k 个对象 + + +**射线查询** +`std::vector query_ray(const Ray3Dd& ray) const override` + +| 参数 | 说明 | +|------|------| +| `ray` | 查询射线 | + +**返回**: 与射线相交的对象列表 + + +**清空 k-d 树** +`void clear() override` + + +**对象数量** +`size_t size() const override { return items_.size(); }` + +**返回**: 当前索引的对象总数 + + +**k-d 树节点** +`struct Node {` + + +**< 节点包围盒** +`int item_idx = -1; /**< 叶节点对应的对象索引(-1 表示内部节点) */` + + +**< 叶节点对应的对象索引(-1 表示内部节点)** +`int split_axis = 0; /**< 分裂轴:0=x, 1=y, 2=z */` + + +**< 分裂轴:0=x, 1=y, 2=z** +`int left = -1; /**< 左子节点索引 */` + + +**< 左子节点索引** +`int right = -1; /**< 右子节点索引 */` + + +**< 右子节点索引** +`}` + + +**< 对象数组** +`std::vector nodes_; /**< 节点数组 */` + + +**< 节点数组** +`int root_ = -1; /**< 根节点索引 */` + + +**< 根节点索引** +`/**` + + +**获取对象代表位置(用于空间排序)** +`static Point3D get_position(const T& item)` + +| 参数 | 说明 | +|------|------| +| `item` | 空间对象 | + +**返回**: 对象的三维代表点 + + +**获取对象的轴对齐包围盒** +`static AABB3D get_aabb(const T& item)` + +| 参数 | 说明 | +|------|------| +| `item` | 空间对象 | + +**返回**: 包围盒 + + +**判断对象是否与射线相交** +`static bool ray_hits_item(const T& item, const Ray3Dd& ray)` + +| 参数 | 说明 | +|------|------| +| `item` | 空间对象 | +| `ray` | 查询射线 | + +**返回**: 相交返回 true + + +**递归构建 k-d 树** +`int build_recursive(int start, int end)` + +| 参数 | 说明 | +|------|------| +| `start` | items_ 中当前范围起始索引 | +| `end` | items_ 中当前范围结束索引 | + +**返回**: 新节点的索引 + + +**递归范围查询** +`void query_range_recursive(int node_idx, const AABB3D& range,` + +| 参数 | 说明 | +|------|------| +| `node_idx` | 当前节点索引 | +| `range` | 查询包围盒 | +| `result` | 累积结果 | + + +**递归射线查询** +`void query_ray_recursive(int node_idx, const Ray3Dd& ray,` + +| 参数 | 说明 | +|------|------| +| `node_idx` | 当前节点索引 | +| `ray` | 查询射线 | +| `result` | 累积结果 | + + + +### `octree.h` + +**八叉树 (Octree) 空间划分结构** + + +**八叉树空间索引** +`template ` +> 适用于体积数据、粒子系统、空间哈希等场景。 + +**参见**: `SpatialIndex, BVH, KDTree` + + +**构造八叉树** +`explicit Octree(int max_depth = 8, int max_items = 16)` + +| 参数 | 说明 | +|------|------| +| `max_depth` | 最大递归深度(默认 8,对应 256³ 分辨率) | +| `max_items` | 节点剖分前可容纳的最大对象数(默认 16) | + + +**批量构建八叉树** +`void build(const std::vector& items) override` + +| 参数 | 说明 | +|------|------| +| `items` | 待索引的对象数组 | + + +**增量插入对象** +`void insert(const T& item) override` + +| 参数 | 说明 | +|------|------| +| `item` | 待插入的空间对象 | + + +**删除对象** +`bool remove(const T& item) override` + +| 参数 | 说明 | +|------|------| +| `item` | 待删除的空间对象 | + +**返回**: 删除成功返回 true;对象不存在返回 false + + +**范围查询** +`std::vector query_range(const AABB3D& range) const override` + +| 参数 | 说明 | +|------|------| +| `range` | 查询包围盒 | + +**返回**: 与 range 相交的对象列表 + + +**K 近邻查询** +`std::vector query_knn(const Point3D& point, size_t k) const override` + +| 参数 | 说明 | +|------|------| +| `point` | 查询点 | +| `k` | 返回数量 | + +**返回**: 最近的 k 个对象 + + +**射线查询** +`std::vector query_ray(const Ray3Dd& ray) const override` + +| 参数 | 说明 | +|------|------| +| `ray` | 查询射线 | + +**返回**: 按命中顺序排列的相交对象列表 + + +**清空八叉树** +`void clear() override` + + +**当前索引中的对象数量** +`size_t size() const override` + +**返回**: 对象总数 + + +**递归插入对象到指定节点** +`void insert_recursive(int node_idx, const T& item, int depth)` + +| 参数 | 说明 | +|------|------| +| `node_idx` | 目标节点索引 | +| `item` | 待插入的对象 | +| `depth` | 当前递归深度 | + + +**递归剖分节点** +`void subdivide_recursive(int node_idx, int depth)` + +| 参数 | 说明 | +|------|------| +| `node_idx` | 当前节点索引 | +| `depth` | 当前深度 | + + +**递归范围查询** +`void query_range_recursive(int node_idx, const AABB3D& range,` + +| 参数 | 说明 | +|------|------| +| `node_idx` | 当前节点索引 | +| `range` | 查询包围盒 | +| `result` | 累积结果 | + + +**递归射线查询** +`void query_ray_recursive(int node_idx, const Ray3Dd& ray,` + +| 参数 | 说明 | +|------|------| +| `node_idx` | 当前节点索引 | +| `ray` | 查询射线 | +| `result` | 累积结果 | + + +**获取对象空间位置(用于剖分分配)** +`static Point3D get_position(const T& item)` + +| 参数 | 说明 | +|------|------| +| `item` | 空间对象 | + +**返回**: 对象的代表点 + + +**< 八叉树内部数据** +`int max_depth_; /**< 最大递归深度 */` + + +**< 最大递归深度** +`int max_items_; /**< 节点剖分阈值 */` + + +**< 节点剖分阈值** +`}` + + + +### `r_tree.h` + +**R 树 (R-Tree) 动态空间索引** + + +**R 树节点** +`template ` + + +**< 节点包围盒(子节点/对象 MBR 的并集)** +`bool is_leaf = true; /**< 是否为叶节点 */` + + +**< 是否为叶节点** +`std::vector children; /**< 内部节点:子节点索引列表 */` + + +**< 内部节点:子节点索引列表** +`std::vector item_indices; /**< 叶节点:对象索引列表 */` + + +**< 叶节点:对象索引列表** +`size_t parent = static_cast(-1); /**< 父节点索引 */` + + +**< 父节点索引** +`}` + + +**R 树动态空间索引** +`template ` +> R 树在动态场景(如编辑中的几何体)中比 BVH 更合适。 + +**参见**: `SpatialIndex, BVH, RStarTree` + + +**批量构建 R 树** +`void build(const std::vector& items) override` + +| 参数 | 说明 | +|------|------| +| `items` | 待索引的对象数组 | + + +**增量插入对象** +`void insert(const T& item) override` + +| 参数 | 说明 | +|------|------| +| `item` | 待插入的空间对象 | + + +**删除对象** +`bool remove(const T& item) override` + +| 参数 | 说明 | +|------|------| +| `item` | 待删除的空间对象 | + +**返回**: 删除成功返回 true + + +**范围查询** +`std::vector query_range(const AABB3D& range) const override` + +| 参数 | 说明 | +|------|------| +| `range` | 查询包围盒 | + +**返回**: 与 range 相交的对象列表 + + +**K 近邻查询** +`std::vector query_knn(const Point3D& point, size_t k) const override` + +| 参数 | 说明 | +|------|------| +| `point` | 查询点 | +| `k` | 返回数量 | + +**返回**: 最近的 k 个对象 + + +**射线查询** +`std::vector query_ray(const Ray3Dd& ray) const override` + +| 参数 | 说明 | +|------|------| +| `ray` | 查询射线 | + +**返回**: 与射线相交的对象列表 + + +**清空 R 树** +`void clear() override` + + +**对象数量** +`size_t size() const override { return count_; }` + +**返回**: 当前索引的对象总数 + + +**R 树节点总数** +`size_t node_count() const { return nodes_.size(); }` + +**返回**: 内部节点 + 叶节点数量 + + +**递归范围查询** +`void query_range_recursive(size_t node_idx, const AABB3D& range,` + +| 参数 | 说明 | +|------|------| +| `node_idx` | 当前节点索引 | +| `range` | 查询包围盒 | +| `result` | 累积结果 | + + +**< 对象数组** +`std::vector item_bounds_; /**< 对象包围盒数组 */` + + +**< 对象包围盒数组** +`std::vector> nodes_; /**< R 树节点数组 */` + + +**< R 树节点数组** +`size_t root_idx_ = 0; /**< 根节点索引 */` + + +**< 根节点索引** +`size_t count_ = 0; /**< 对象计数 */` + + +**< 对象计数** +`}` + + + +### `spatial_index.h` + +**空间索引抽象基类** + + +**空间索引抽象基类** +`template ` +> 本类为纯虚接口,不可直接实例化 + + +**批量构建索引** +`virtual void build(const std::vector& items) = 0` + +| 参数 | 说明 | +|------|------| +| `items` | 待索引的对象数组 | + + +**插入单个对象** +`virtual void insert(const T& item) = 0` + +| 参数 | 说明 | +|------|------| +| `item` | 待插入的空间对象 | + + +**删除单个对象** +`virtual bool remove(const T& item) = 0` + +| 参数 | 说明 | +|------|------| +| `item` | 待删除的空间对象 | + +**返回**: true 删除成功;false 对象不存在 + + +**范围查询:返回与 AABB 相交的所有对象** +`virtual std::vector query_range(const AABB3D& range) const = 0` + +| 参数 | 说明 | +|------|------| +| `range` | 查询的轴对齐包围盒 | + +**返回**: 与 range 相交的对象列表 + + +**K 近邻查询:返回距 point 最近的 k 个对象** +`virtual std::vector query_knn(const Point3D& point, size_t k) const = 0` + +| 参数 | 说明 | +|------|------| +| `point` | 查询点 | +| `k` | 需要返回的对象数量 | + +**返回**: 按距离升序排列的 k 个最近对象 + + +**射线查询:返回与射线相交的所有对象** +`virtual std::vector query_ray(const Ray3Dd& ray) const = 0` + +| 参数 | 说明 | +|------|------| +| `ray` | 查询射线 | + +**返回**: 按命中距离升序排列的相交对象列表 + + +**清空索引中所有数据** +`virtual void clear() = 0` + + +**当前索引中的对象数量** +`virtual size_t size() const = 0` + +**返回**: 对象计数 + + + +## 布尔运算 (`vde::boolean`) + + +### `boolean_2d.h` + +**二维多边形布尔运算** + + +**布尔运算类型** +`enum class BooleanOp {` + + +**< 并集 A ∪ B** +`Intersection, /**< 交集 A ∩ B */` + + +**< 交集 A ∩ B** +`Difference, /**< 差集 A − B */` + + +**< 差集 A − B** +`SymDiff /**< 对称差 (A − B) ∪ (B − A) */` + + +**< 对称差 (A − B) ∪ (B − A)** +`}` + + +**二维多边形布尔运算** +`std::vector boolean_2d(const Polygon2D& a, const Polygon2D& b, BooleanOp op)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个多边形 | +| `b` | 第二个多边形 | +| `op` | 布尔操作类型 | + +**返回**: 结果多边形列表(可能有多个分离的组件) +> 当前版本优化了凸多边形路径。对于带孔洞或自交的 + +**参见**: `BooleanOp, mesh_boolean, polygon_offset` + + + +### `boolean_mesh.h` + +**三维网格布尔运算** + + +**网格并集 A ∪ B** +`HalfedgeMesh mesh_union(const HalfedgeMesh& a, const HalfedgeMesh& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 网格 A | +| `b` | 网格 B | + +**返回**: A ∪ B 的合并网格 + +**参见**: `mesh_intersection, mesh_difference, is_point_inside_mesh` + + +**网格交集 A ∩ B** +`HalfedgeMesh mesh_intersection(const HalfedgeMesh& a, const HalfedgeMesh& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 网格 A | +| `b` | 网格 B | + +**返回**: A ∩ B 的交集网格 +> 结果体积为两网格公共区域 + +**参见**: `mesh_union, mesh_difference` + + +**网格差集 A − B** +`HalfedgeMesh mesh_difference(const HalfedgeMesh& a, const HalfedgeMesh& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 网格 A | +| `b` | 网格 B | + +**返回**: A − B 的差集网格 +> 结果中来自 B 的面片会被翻转法线以保持内-外一致性 + +**参见**: `mesh_union, mesh_intersection, mesh_sym_diff` + + +**网格对称差 (A − B) ∪ (B − A)** +`HalfedgeMesh mesh_sym_diff(const HalfedgeMesh& a, const HalfedgeMesh& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 网格 A | +| `b` | 网格 B | + +**返回**: 对称差网格 + +**参见**: `mesh_difference, mesh_union` + + +**用网格 B 裁剪网格 A** +`HalfedgeMesh clip_mesh(const HalfedgeMesh& a, const HalfedgeMesh& b,` + +| 参数 | 说明 | +|------|------| +| `a` | 待裁剪网格 | +| `b` | 裁剪体网格 | +| `invert_b` | 若为 true,将 B 的内外判定取反(裁剪外部) | + +**返回**: 裁剪后的网格(仅包含 A 的面片) + +**参见**: `mesh_difference, is_point_inside_mesh` + + +**翻转网格所有面片的法线方向** +`HalfedgeMesh invert_mesh(const HalfedgeMesh& m)` + +| 参数 | 说明 | +|------|------| +| `m` | 原始网格 | + +**返回**: 法线翻转后的网格 + +**参见**: `mesh_difference` + + +**合并两个网格** +`HalfedgeMesh merge_meshes(const HalfedgeMesh& a, const HalfedgeMesh& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 网格 A | +| `b` | 网格 B | + +**返回**: 包含 A 和 B 全部顶点和面片的合并网格 +> 不处理重叠区域;仅做纯几何拼接 + +**参见**: `mesh_union(做布尔合并)` + + +**网格布尔运算统一接口** +`HalfedgeMesh mesh_boolean(const HalfedgeMesh& a, const HalfedgeMesh& b, BooleanOp op)` + +| 参数 | 说明 | +|------|------| +| `a` | 网格 A | +| `b` | 网格 B | +| `op` | 布尔操作类型 | + +**返回**: 结果网格 + +**参见**: `BooleanOp, mesh_union, mesh_intersection, mesh_difference, mesh_sym_diff` + + +**判断三维点是否在封闭网格内部** +`bool is_point_inside_mesh(const core::Point3D& p, const HalfedgeMesh& mesh)` + +| 参数 | 说明 | +|------|------| +| `p` | 待判定点 | +| `mesh` | 封闭网格 | + +**返回**: 点在网格内部返回 true +> 网格必须是封闭(水密)的,否则结果不可靠。 + +**参见**: `clip_mesh, mesh_difference` + + + +### `polygon_offset.h` + +**多边形等距偏移 (Polygon Offset / Inset)** + + +**多边形等距偏移** +`std::vector polygon_offset(const Polygon2D& poly, double distance)` + +| 参数 | 说明 | +|------|------| +| `poly` | 原始多边形 | +| `distance` | 偏移距离(正=外扩,负=内缩) | + +**返回**: 偏移后的多边形列表(内缩或自交可能产生多个碎片) +> 使用直骨架近似而非精确圆弧偏移,转角处为斜角连接。 + +**参见**: `boolean_2d` + + + +## 碰撞检测 (`vde::collision`) + + +### `gjk.h` + +**GJK (Gilbert–Johnson–Keerthi) 碰撞检测算法** + + +**支撑函数类型** +`using SupportFunc = std::function` + + +**GJK 完整检测结果** +`struct GJKResult {` + + +**< 两凸体是否相交** +`double distance; /**< 最近距离(不相交时 >0,相交时为 0) */` + + +**< 最近距离(不相交时 >0,相交时为 0)** +`Point3D point_a; /**< 形状 A 上的最近点 */` + + +**< 形状 A 上的最近点** +`Point3D point_b; /**< 形状 B 上的最近点 */` + + +**< 形状 B 上的最近点** +`}` + + +**GJK 相交检测(仅判断是否碰撞)** +`bool gjk_intersect(const SupportFunc& shape_a, const SupportFunc& shape_b)` + +| 参数 | 说明 | +|------|------| +| `shape_a` | 形状 A 的支撑函数 | +| `shape_b` | 形状 B 的支撑函数 | + +**返回**: 相交返回 true + +**参见**: `gjk_distance, gjk_full, SupportFunc` + + +**GJK 最近距离查询** +`double gjk_distance(const SupportFunc& shape_a, const SupportFunc& shape_b)` + +| 参数 | 说明 | +|------|------| +| `shape_a` | 形状 A 的支撑函数 | +| `shape_b` | 形状 B 的支撑函数 | + +**返回**: 最近距离(相交时返回 0),始终 ≥ 0 + +**参见**: `gjk_intersect, gjk_full` + + +**GJK 完整检测:碰撞状态、距离、最近点对** +`GJKResult gjk_full(const SupportFunc& shape_a, const SupportFunc& shape_b)` + +| 参数 | 说明 | +|------|------| +| `shape_a` | 形状 A 的支撑函数 | +| `shape_b` | 形状 B 的支撑函数 | + +**返回**: GJKResult 包含碰撞状态、距离、最近点对 +> 对于连续碰撞检测 (CCD) 或需要分离向量的场景, + +**参见**: `gjk_intersect, gjk_distance` + + + +### `ray_intersect.h` + +**射线求交工具集** + + +**射线-三角形求交结果** +`struct RayTriResult {` + + +**< 沿射线的参数:hit_point = origin + t * dir** +`double u, v; /**< 三角形重心坐标:hit_point = (1−u−v)*v0 + u*v1 + v*v2 */` + + +**< 三角形重心坐标:hit_point = (1−u−v)*v0 + u*v1 + v*v2** +`Point3D point; /**< 命中点的世界坐标 */` + + +**< 命中点的世界坐标** +`}` + + +**射线-三角形求交(Möller-Trumbore 算法)** +`std::optional ray_triangle_intersect(` + +| 参数 | 说明 | +|------|------| +| `origin` | 射线起点 | +| `dir` | 射线方向(需归一化以获得正确 t 值) | +| `tri` | 三角形 | + +**返回**: 命中返回 RayTriResult;未命中返回空 + +**参见**: `ray_mesh_intersect` + + +**射线-三角形求交(Ray3Dd 重载)** +`inline std::optional ray_triangle_intersect(` + +| 参数 | 说明 | +|------|------| +| `ray` | 射线 | +| `tri` | 三角形 | + +**返回**: 命中返回 RayTriResult;未命中返回空 + +**参见**: `ray_triangle_intersect(origin, dir, tri)` + + +**射线-AABB 求交(slab 方法)** +`bool ray_aabb_intersect(const Ray3Dd& ray, const AABB3D& box,` + +| 参数 | 说明 | +|------|------| +| `ray` | 射线 | +| `box` | 轴对齐包围盒 | +| `tmin_out` | [输出] 进入包围盒的参数 t | +| `tmax_out` | [输出] 离开包围盒的参数 t | + +**返回**: 命中返回 true +> 常用于 BVH 遍历节点的快速 rejection test + +**参见**: `ray_triangle_intersect` + + +**射线-球体求交结果** +`struct RaySphereResult {` + + +**< 命中参数(通常取较小的 t)** +`Point3D point; /**< 命中点世界坐标 */` + + +**< 命中点世界坐标** +`}` + + +**射线-球体求交(解析法)** +`std::optional ray_sphere_intersect(` + +| 参数 | 说明 | +|------|------| +| `origin` | 射线起点 | +| `dir` | 射线方向 | +| `center` | 球心 | +| `radius` | 球半径 | + +**返回**: 命中返回 RaySphereResult(最近交点);未命中返回空 + +**参见**: `ray_sphere_intersect(ray, center, radius)` + + +**射线-球体求交(Ray3Dd 重载)** +`inline std::optional ray_sphere_intersect(` + +| 参数 | 说明 | +|------|------| +| `ray` | 射线 | +| `center` | 球心 | +| `radius` | 球半径 | + +**返回**: 命中返回 RaySphereResult;未命中返回空 + + +**射线-平面求交** +`std::optional ray_plane_intersect(` + +| 参数 | 说明 | +|------|------| +| `origin` | 射线起点 | +| `dir` | 射线方向 | +| `plane_point` | 平面上一点 | +| `plane_normal` | 平面法线(需归一化以获得正确 t) | + +**返回**: 命中返回参数 t;未命中(平行或反向)返回空 + + +**射线-平面求交(Ray3Dd 重载)** +`inline std::optional ray_plane_intersect(` + +| 参数 | 说明 | +|------|------| +| `ray` | 射线 | +| `plane_point` | 平面上一点 | +| `plane_normal` | 平面法线 | + +**返回**: 命中返回参数 t;未命中返回空 + + +**射线-网格求交(暴力遍历)** +`std::optional ray_mesh_intersect(` + +| 参数 | 说明 | +|------|------| +| `origin` | 射线起点 | +| `dir` | 射线方向 | +| `triangles` | 三角形列表 | + +**返回**: 最近命中结果;无命中返回空 +> 对于大型网格建议配合 BVH 使用: + +**参见**: `ray_tri_intersect.h, query_ray_nearest (BVH)` + + +**射线-网格求交(Ray3Dd 重载)** +`inline std::optional ray_mesh_intersect(` + +| 参数 | 说明 | +|------|------| +| `ray` | 射线 | +| `triangles` | 三角形列表 | + +**返回**: 最近命中结果;无命中返回空 + + + +### `sat.h` + +**SAT (Separating Axis Theorem) 碰撞检测** + + +**SAT 凸多面体相交检测** +`bool sat_intersect(const std::vector& verts_a,` + +| 参数 | 说明 | +|------|------| +| `verts_a` | 多面体 A 的顶点数组 | +| `faces_a` | 多面体 A 的面索引数组(每个面为 {v0, v1, v2}) | +| `verts_b` | 多面体 B 的顶点数组 | +| `faces_b` | 多面体 B 的面索引数组 | + +**返回**: 相交返回 true +> 适用于任意凸多面体。对于胶囊/球等光滑形状,GJK 更合适。 + +**参见**: `gjk_intersect, tri_tri_intersect` + + + +### `tri_intersect.h` + +**三角形-三角形 / 三角形-AABB 相交检测** + + +**三角形-三角形相交检测(布尔测试)** +`bool tri_tri_intersect(const Triangle3D& t1, const Triangle3D& t2)` + +| 参数 | 说明 | +|------|------| +| `t1` | 三角形 1 | +| `t2` | 三角形 2 | + +**返回**: 相交返回 true + +**参见**: `tri_tri_intersect_detailed, sat_intersect` + + +**三角形-三角形相交线段** +`struct TriTriIntersection {` + + +**< 是否相交** +`Point3D p0; /**< 交点段起点 */` + + +**< 交点段起点** +`Point3D p1; /**< 交点段终点 */` + + +**< 交点段终点** +`}` + + +**三角形-三角形详细相交检测** +`TriTriIntersection tri_tri_intersect_detailed(const Triangle3D& t1,` + +| 参数 | 说明 | +|------|------| +| `t1` | 三角形 1 | +| `t2` | 三角形 2 | + +**返回**: TriTriIntersection:相交标志 + 交点段端点 +> 共面情况交集段可能退化为单点(p0 == p1) + +**参见**: `tri_tri_intersect` + + +**三角形-AABB 快速相交测试** +`bool tri_aabb_overlap(const Triangle3D& tri, const AABB3D& box)` + +| 参数 | 说明 | +|------|------| +| `tri` | 三角形 | +| `box` | 轴对齐包围盒 | + +**返回**: 相交返回 true +> AABB 碰撞比三角剖分后的三角-三角检测更高效, + +**参见**: `tri_tri_intersect, ray_aabb_intersect` + + + +## B-Rep建模 (`vde::brep`) + + +### `assembly.h` + +**装配体节点** +`struct AssemblyNode {` + + +**装配体** +`struct Assembly {` + + + +### `brep.h` + +**边界表示(B-Rep)核心数据结构** + + +**边曲线类型枚举** +`enum class CurveType { Line, Circle, Bezier, BSpline, Nurbs }` + + +**拓扑顶点** +`struct TopoVertex {` + + +**拓扑边** +`struct TopoEdge {` + + +**拓扑环(Loop)** +`struct TopoLoop {` + + +**拓扑面** +`struct TopoFace {` + + +**拓扑壳** +`struct TopoShell {` + + +**拓扑体** +`struct TopoBody {` + + +**B-Rep 模型** + +**参见**: `brep_validate.h 验证`, `modeling.h 高层建模 API`, `brep_boolean.h 布尔运算` + + +**添加顶点** +`int add_vertex(const Point3D& p)` + +| 参数 | 说明 | +|------|------| +| `p` | 顶点坐标 | + +**返回**: 新顶点的 ID + + +**添加直线边** +`int add_edge(int v0, int v1)` + +| 参数 | 说明 | +|------|------| +| `v0` | 起点顶点 ID | +| `v1` | 终点顶点 ID | + +**返回**: 新边的 ID + + +**添加曲线边** +`int add_edge(int v0, int v1, const curves::NurbsCurve& curve)` + +| 参数 | 说明 | +|------|------| +| `v0` | 起点顶点 ID | +| `v1` | 终点顶点 ID | +| `curve` | 边的几何曲线 | + +**返回**: 新边的 ID + + +**添加环** +`int add_loop(const std::vector& edges, bool outer = true)` + +| 参数 | 说明 | +|------|------| +| `edges` | 环中边的 ID 序列(顺序连接) | +| `outer` | true = 外环, false = 内环 | + +**返回**: 新环的 ID + + +**添加面** +`int add_face(int surface_id, const std::vector& loops)` + +| 参数 | 说明 | +|------|------| +| `surface_id` | 关联曲面 ID | +| `loops` | 环 ID 列表 | + +**返回**: 新面的 ID + + +**添加壳** +`int add_shell(const std::vector& faces, bool closed = true)` + +| 参数 | 说明 | +|------|------| +| `faces` | 面 ID 列表 | +| `closed` | 是否为封闭壳 | + +**返回**: 新壳的 ID + + +**添加体** +`int add_body(const std::vector& shells, const std::string& name = "")` + +| 参数 | 说明 | +|------|------| +| `shells` | 壳 ID 列表 | +| `name` | 体名称 | + +**返回**: 新体的 ID + + +**添加 NURBS 曲面** +`int add_surface(const curves::NurbsSurface& surf)` + +| 参数 | 说明 | +|------|------| +| `surf` | NURBS 曲面定义 | + +**返回**: 新曲面的 ID + + +**顶点数量** +`[[nodiscard]] size_t num_vertices() const { return vertices_.size(); }` + + +**边数量** +`[[nodiscard]] size_t num_edges() const { return edges_.size(); }` + + +**面数量** +`[[nodiscard]] size_t num_faces() const { return faces_.size(); }` + + +**体数量** +`[[nodiscard]] size_t num_bodies() const { return bodies_.size(); }` + + +**曲面数量** +`[[nodiscard]] size_t num_surfaces() const { return surfaces_.size(); }` + + +**按数组索引访问顶点** +`[[nodiscard]] const TopoVertex& vertex(int id) const { return vertices_[id]; }` + + +**按唯一 ID 访问顶点(适用于边数据中的 ID 引用)** +`[[nodiscard]] const TopoVertex& vertex_by_id(int id) const` + + +**按数组索引访问边** +`[[nodiscard]] const TopoEdge& edge(int id) const { return edges_[id]; }` + + +**按数组索引访问面** +`[[nodiscard]] const TopoFace& face(int id) const { return faces_[id]; }` + + +**按数组索引访问曲面** +`[[nodiscard]] const curves::NurbsSurface& surface(int id) const { return surfaces_[id]; }` + + +**按唯一 ID 访问环** +`[[nodiscard]] const TopoLoop& loop_by_id(int id) const` + + +**获取所有环的只读引用** +`[[nodiscard]] const std::vector& all_loops() const { return loops_; }` + + +**计算模型的轴对齐包围盒** +`[[nodiscard]] core::AABB3D bounds() const` + +**返回**: 包围盒(AABB) + + +**检查模型有效性(快速版本)** +`[[nodiscard]] bool is_valid() const` + +**返回**: true 如果模型通过基本检查 + +**参见**: `validate() 完整验证(水密性、方向一致性等)` + + +**将 B-Rep 模型 tessellate 为三角网格** +`[[nodiscard]] mesh::HalfedgeMesh to_mesh(double deflection = 0.01) const` + +| 参数 | 说明 | +|------|------| +| `deflection` | 弦高误差(控制 tessellation 精度,默认 0.01) | + +**返回**: HalfedgeMesh 三角网格 +> deflection 越小网格越精细,但三角形数量显著增加。 + + +**获取面的所有边** +`[[nodiscard]] std::vector face_edges(int face_id) const` + +| 参数 | 说明 | +|------|------| +| `face_id` | 面 ID | + +**返回**: 边 ID 列表(去重) + + +**获取边的所有相邻面** +`[[nodiscard]] std::vector edge_faces(int edge_id) const` + +| 参数 | 说明 | +|------|------| +| `edge_id` | 边 ID | + +**返回**: 相邻面 ID 列表 + + +**获取顶点的所有相邻边** +`[[nodiscard]] std::vector vertex_edges(int vertex_id) const` + +| 参数 | 说明 | +|------|------| +| `vertex_id` | 顶点 ID | + +**返回**: 相邻边 ID 列表 + + + +### `brep_boolean.h` + +**B-Rep 级别的布尔运算** + + +**B-Rep 布尔并集: A ∪ B** +`[[nodiscard]] BrepModel brep_union(const BrepModel& a, const BrepModel& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个 B-Rep 实体 | +| `b` | 第二个 B-Rep 实体 | + +**返回**: 新的 B-Rep 实体(a ∪ b) + +**参见**: `brep_intersection 交集`, `brep_difference 差集` + + +**B-Rep 布尔交集: A ∩ B** +`[[nodiscard]] BrepModel brep_intersection(const BrepModel& a, const BrepModel& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 第一个 B-Rep 实体 | +| `b` | 第二个 B-Rep 实体 | + +**返回**: 新的 B-Rep 实体(a ∩ b) + +**参见**: `brep_union 并集`, `brep_difference 差集` + + +**B-Rep 布尔差集: A \ B** +`[[nodiscard]] BrepModel brep_difference(const BrepModel& a, const BrepModel& b)` + +| 参数 | 说明 | +|------|------| +| `a` | 被减实体 A | +| `b` | 减去实体 B | + +**返回**: 新的 B-Rep 实体(a \ b) + +**参见**: `brep_union 并集`, `brep_intersection 交集` + + + +### `brep_validate.h` + +**B-Rep 模型综合验证** + + +**B-Rep 模型的综合验证结果** +`struct ValidationResult {` + + +**是否通过所有必要检查** +`bool valid = true` + + +**错误信息列表(导致 valid = false)** +`std::vector errors` + + +**警告信息列表(不影响 valid)** +`std::vector warnings` + + +**水密性比率:恰好有 2 个相邻面的边的比例(1.0 = 完美水密)** +`double watertightness = 1.0` + + +**无自交比率:不与其他面内部相交的面对比例(1.0 = 无自交)** +`double self_intersection_free = 1.0` + + +**最短边的长度(用于检测退化边)** +`double min_edge_length = std::numeric_limits::max()` + + +**最长边的长度(用于检测超长边)** +`double max_edge_length = 0.0` + + +**非流形边数(相邻面 ≠ 2 的边)** +`size_t non_manifold_edges = 0` + + +**悬挂边数(无相邻面的边)** +`size_t dangling_edges = 0` + + +**方向不一致的面数** +`size_t inconsistent_orientations = 0` + + +**总边数** +`size_t total_edges = 0` + + +**总面数** +`size_t total_faces = 0` + + +**对 BrepModel 执行综合验证** +`[[nodiscard]] ValidationResult validate(const BrepModel& body)` + +| 参数 | 说明 | +|------|------| +| `body` | 待验证的 B-Rep 模型 | + +**返回**: ValidationResult 包含所有检查结果的详细报告 +> 自交检测是最昂贵的检查项(O(n²) 面对数), + +**参见**: `BrepModel::is_valid() 快速有效性检查(无详细报告)` + + + +### `iges_export.h` + +**IGES 文件导出(版本 5.3)** + + +**将 B-Rep 体导出为 IGES 格式字符串(版本 5.3)** +`[[nodiscard]] std::string export_iges(const std::vector& bodies)` + +| 参数 | 说明 | +|------|------| +| `bodies` | B-Rep 体列表 | + +**返回**: IGES 5.3 格式字符串 + +**参见**: `export_iges_file 直接写入文件`, `export_step STEP 格式导出` + + +**将 B-Rep 体导出为 IGES 文件** +`void export_iges_file(const std::string& filepath, const std::vector& bodies)` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径(建议扩展名 .igs 或 .iges) | +| `bodies` | B-Rep 体列表 | + +**参见**: `export_iges 获取字符串输出` + + + +### `iges_import.h` + +**IGES 文件导入(ANSI Y14.26M)** + + +**IGES 导入错误码** +`enum class IgesError {` + + +**从文件导入 IGES** +`[[nodiscard]] std::vector import_iges(const std::string& filepath)` + +| 参数 | 说明 | +|------|------| +| `filepath` | .igs 或 .iges 文件路径 | + +**返回**: B-Rep 体列表 +> IGES 格式较为宽松,不同 CAD 系统的实现差异很大。 + +**参见**: `import_iges_from_string 从字符串导入`, `iges_last_error 获取错误码` + + +**从字符串导入 IGES(用于测试)** +`[[nodiscard]] std::vector import_iges_from_string(const std::string& data)` + +| 参数 | 说明 | +|------|------| +| `data` | IGES 文件完整内容(字符串形式) | + +**返回**: B-Rep 体列表 + +**参见**: `import_iges 从文件导入` + + +**获取最近一次 IGES 导入的错误码** +`[[nodiscard]] IgesError iges_last_error()` + +**返回**: IgesError 枚举值 + +**参见**: `iges_last_error_message 获取可读描述` + + +**获取最近一次 IGES 导入的可读错误描述** +`[[nodiscard]] const std::string& iges_last_error_message()` + +**返回**: 错误描述字符串 + +**参见**: `iges_last_error 获取枚举错误码` + + + +### `modeling.h` + +**高层 B-Rep 建模 API** + + +**沿方向挤出平面轮廓** +`[[nodiscard]] BrepModel extrude(const curves::NurbsCurve& profile, const Vector3D& dir)` + +| 参数 | 说明 | +|------|------| +| `profile` | 轮廓曲线(必须位于一个平面内) | +| `dir` | 挤出方向向量(其长度决定挤出距离) | + +**返回**: 挤出后的 B-Rep 实体 + +**参见**: `revolve 旋转扫掠`, `sweep 沿任意路径扫掠` + + +**绕轴旋转平面轮廓** +`[[nodiscard]] BrepModel revolve(const curves::NurbsCurve& profile,` + +| 参数 | 说明 | +|------|------| +| `profile` | 轮廓曲线(通常位于轴的半平面中) | +| `axis_origin` | 旋转轴上的一个点 | +| `axis_dir` | 旋转轴方向(单位向量) | +| `angle_rad` | 旋转角度(弧度,默认 2π = 完整的旋转体) | + +**返回**: 旋转后的 B-Rep 实体 + +**参见**: `extrude 线性挤出`, `make_sphere 直接创建球体` + + +**沿任意路径扫掠轮廓** +`[[nodiscard]] BrepModel sweep(const curves::NurbsCurve& profile,` + +| 参数 | 说明 | +|------|------| +| `profile` | 截面轮廓(需位于路径起点的垂直平面内) | +| `path` | 扫掠路径曲线 | + +**返回**: 扫掠后的 B-Rep 实体 +> 路径曲率过大处可能出现自交,需要控制路径的光滑性。 + +**参见**: `extrude 直线挤出`, `revolve 旋转扫掠` + + +**在两个或多个轮廓曲线之间放样** +`[[nodiscard]] BrepModel loft(const std::vector& profiles)` + +| 参数 | 说明 | +|------|------| +| `profiles` | 轮廓曲线列表(至少 2 条) | + +**返回**: 放样后的 B-Rep 实体 + +**参见**: `extrude 单轮廓挤出` + + +**创建立方体** +`[[nodiscard]] BrepModel make_box(double w, double h, double d)` + +| 参数 | 说明 | +|------|------| +| `w` | 宽度(X 方向),必须 > 0 | +| `h` | 高度(Y 方向),必须 > 0 | +| `d` | 深度(Z 方向),必须 > 0 | + +**返回**: 实心立方体 B-Rep + +**参见**: `make_cylinder 圆柱体`, `make_sphere 球体` + + +**创建圆柱体** +`[[nodiscard]] BrepModel make_cylinder(double radius, double height, int segments = 32)` + +| 参数 | 说明 | +|------|------| +| `radius` | 截面半径,必须 > 0 | +| `height` | 总高度,沿 Y 轴从 -h/2 到 +h/2 | +| `segments` | 截面分段数(边数,默认 32) | + +**返回**: 实心圆柱体 B-Rep +> segments 越大圆柱越光滑,但面和边数增加。 + +**参见**: `make_box 立方体`, `make_sphere 球体` + + +**创建球体** +`[[nodiscard]] BrepModel make_sphere(double radius, int segments_u = 32, int segments_v = 16)` + +| 参数 | 说明 | +|------|------| +| `radius` | 球半径,必须 > 0 | +| `segments_u` | 经度方向分段数(默认 32) | +| `segments_v` | 纬度方向分段数(默认 16) | + +**返回**: 实心球体 B-Rep + +**参见**: `make_cylinder 圆柱体` + + +**对边做圆角处理** +`[[nodiscard]] BrepModel fillet(const BrepModel& body, int edge_id, double radius)` + +| 参数 | 说明 | +|------|------| +| `body` | 输入实体 | +| `edge_id` | 要倒圆的边 ID | +| `radius` | 圆角半径,必须 > 0 | + +**返回**: 圆角后的新实体 +> 圆角半径不能超过相邻面的最小宽度,否则会产生自交。 +> 只支持恒定半径圆角。变半径圆角尚未实现。 + +**参见**: `chamfer 倒角`, `shell 抽壳` + + +**对边做倒角** +`[[nodiscard]] BrepModel chamfer(const BrepModel& body, int edge_id, double distance)` + +| 参数 | 说明 | +|------|------| +| `body` | 输入实体 | +| `edge_id` | 要倒角的边 ID | +| `distance` | 倒角距离(从原边沿两个面各偏移的距离) | + +**返回**: 倒角后的新实体 + +**参见**: `fillet 圆角` + + +**抽壳(挖空实体)** +`[[nodiscard]] BrepModel shell(const BrepModel& body, int face_id, double thickness)` + +| 参数 | 说明 | +|------|------| +| `body` | 输入实心实体 | +| `face_id` | 要移除的面 ID(形成开口),-1 表示封闭壳(不开口) | +| `thickness` | 壁厚(正值 = 向外偏移,负值 = 向内偏移) | + +**返回**: 抽壳后的新实体 +> 壁厚不应超过实体最小尺寸的一半。 +> 当 face_id = -1 时,结果是一个封闭的壳(中空但没有开口)。 + +**参见**: `fillet 圆角` + + + +### `step_export.h` + +**STEP 文件导出(ISO 10303-214)** + + +**将 B-Rep 体导出为 STEP AP214 字符串** +`[[nodiscard]] std::string export_step(const std::vector& bodies)` + +| 参数 | 说明 | +|------|------| +| `bodies` | B-Rep 体列表(每个体对应一个 PRODUCT) | + +**返回**: STEP AP214 格式字符串 +> 输出包含所有必要的 ISO 10303-21 头部信息。 + +**参见**: `export_step_file 直接写入文件`, `export_iges IGES 格式导出` + + +**将 B-Rep 体导出为 STEP 文件** +`void export_step_file(const std::string& filepath, const std::vector& bodies)` + +| 参数 | 说明 | +|------|------| +| `filepath` | 输出文件路径(建议扩展名 .step 或 .stp) | +| `bodies` | B-Rep 体列表 | + +**参见**: `export_step 获取字符串输出` + + + +### `step_import.h` + +**STEP 文件导入(ISO 10303)** + + +**STEP 导入错误码** +`enum class StepError {` + + +**从文件导入 STEP(AP203/AP214)** +`[[nodiscard]] std::vector import_step(const std::string& filepath)` + +| 参数 | 说明 | +|------|------| +| `filepath` | .step 或 .stp 文件路径 | + +**返回**: B-Rep 体列表(每个文件中的 PRODUCT 一个) +> 大型 STEP 文件(> 100 MB)可能需要数秒到数十秒进行解析。 + +**参见**: `import_step_from_string 从内存字符串导入(测试用)`, `step_last_error 获取错误码` + + +**从字符串导入 STEP(用于测试和嵌入式场景)** +`[[nodiscard]] std::vector import_step_from_string(const std::string& step_data)` + +| 参数 | 说明 | +|------|------| +| `step_data` | 完整的 STEP 文件内容(字符串形式) | + +**返回**: B-Rep 体列表 + +**参见**: `import_step 从文件导入` + + +**获取最近一次 STEP 导入的错误码** +`[[nodiscard]] StepError step_last_error()` + +**返回**: StepError 枚举值 + +**参见**: `step_last_error_message 获取可读的错误描述` + + +**获取最近一次 STEP 导入的可读错误描述** +`[[nodiscard]] const std::string& step_last_error_message()` + +**返回**: 错误描述字符串(如 "Missing entity reference #42") + +**参见**: `step_last_error 获取枚举错误码` + + + +## SDF隐式建模 (`vde::sdf`) + + +### `sdf_gradient.h` + +**SDF 梯度计算(数值微分、解析梯度、链式法则)** + + +**SDF 的空间梯度(中心差分近似)** +`[[nodiscard]] inline Vector3D gradient(` + +| 参数 | 说明 | +|------|------| +| `f` | SDF 函数(接受 Point3D 参数) | +| `p` | 求值点 | +| `h` | 差分步长(默认 1e-6) | + +**返回**: 梯度向量 ∇f(p) +> 步长太小会导致舍入误差主导,太大导致截断误差主导。 +> 对于含不连续性的 SDF(如 sharp CSG),有限差分可能在边界产生错误梯度。 + +**参见**: `evaluate_with_gradient 一次性获取值和梯度` + + +**前向模梯度结果: SDF 值 + 梯度** +`struct GradResult {` + + +**同时计算 SDF 值和梯度的便捷函数** +`[[nodiscard]] inline GradResult evaluate_with_gradient(` + +| 参数 | 说明 | +|------|------| +| `f` | SDF 函数 | +| `p` | 求值点 | +| `h` | 差分步长 | + +**返回**: value + grad 结构 + +**参见**: `gradient 仅计算梯度` + + +**球体 SDF 对半径的参数梯度 ∂f/∂r** +`[[nodiscard]] inline double sphere_radius_gradient(const Point3D& p, double radius, double h = 1e-6)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 球体半径 | +| `h` | 差分步长(默认 1e-6) | + +**返回**: ∂f/∂radius +> 对于球体,解析梯度为 -1(球面上),但此函数提供与实现无关的数值验证。 + +**参见**: `sphere_param_grad 封装版本` + + +**长方体 SDF 对各轴半尺寸的参数梯度 ∂f/∂extent[i]** +`[[nodiscard]] inline double box_extent_gradient(const Point3D& p, const Point3D& extents,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `extents` | 半边长 | +| `axis` | 轴索引: 0=x, 1=y, 2=z | +| `h` | 差分步长 | + +**返回**: ∂f/∂extent[axis] + +**参见**: `box_param_grad 封装版本` + + +**圆环 SDF 对主半径的参数梯度 ∂f/∂major_r** +`[[nodiscard]] inline double torus_major_gradient(const Point3D& p, double major_r, double minor_r,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `major_r` | 主半径 | +| `minor_r` | 副半径 | +| `h` | 差分步长 | + +**返回**: 参数梯度 + + +**圆环 SDF 对副半径的参数梯度 ∂f/∂minor_r** +`[[nodiscard]] inline double torus_minor_gradient(const Point3D& p, double major_r, double minor_r,` + +**返回**: 参数梯度 + + +**圆柱 SDF 对高度的参数梯度 ∂f/∂height** +`[[nodiscard]] inline double cylinder_height_gradient(const Point3D& p, double radius, double height,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 圆柱半径 | +| `height` | 圆柱高度 | +| `h` | 差分步长 | + +**返回**: 参数梯度 + + +**圆柱 SDF 对半径的参数梯度 ∂f/∂radius** +`[[nodiscard]] inline double cylinder_radius_gradient(const Point3D& p, double radius, double height,` + +**返回**: 参数梯度 + + +**球体 SDF 的解析梯度** +`[[nodiscard]] inline Vector3D sphere_gradient_analytic(const Point3D& p, double /*radius*/)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 球半径(当前未使用,保留以保持接口一致) | + +**返回**: 解析梯度(单位向量) +> 在表面上 (|p| = radius),梯度即为外法向量。 + + +**长方体 SDF 的解析梯度** +`[[nodiscard]] inline Vector3D box_gradient_analytic(const Point3D& p, const Point3D& half_extents)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `half_extents` | 半边长 | + +**返回**: 解析梯度 + + +**圆环 SDF 的解析梯度** +`[[nodiscard]] inline Vector3D torus_gradient_analytic(const Point3D& p, double major_r, double minor_r)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `major_r` | 主半径 | +| `minor_r` | 副半径 | + +**返回**: 解析梯度 + + +**无限圆柱(沿 Y 轴)的解析梯度** +`[[nodiscard]] inline Vector3D cylinder_gradient_analytic(const Point3D& p, double /*radius*/)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 圆柱半径(未使用,保留接口一致) | + +**返回**: 解析梯度 + + +**平面的解析梯度** +`[[nodiscard]] inline Vector3D plane_gradient_analytic(const Vector3D& normal)` + +| 参数 | 说明 | +|------|------| +| `normal` | 单位法向量 | + +**返回**: 梯度(等于 normal) +> 这是最简单的解析梯度,因为平面 SDF 是线性的。 + + +**胶囊体 SDF 的解析梯度** +`[[nodiscard]] inline Vector3D capsule_gradient_analytic(const Point3D& p,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `a` | 线段起点 | +| `b` | 线段终点 | +| `radius` | 扫掠球半径 | + +**返回**: 解析梯度 + + +**并集操作后的梯度传递** +`[[nodiscard]] inline Vector3D chain_union(const Vector3D& grad_a, const Vector3D& grad_b,` + +| 参数 | 说明 | +|------|------| +| `grad_a` | 子对象 A 的梯度 | +| `grad_b` | 子对象 B 的梯度 | +| `d1` | A 的 SDF 值 | +| `d2` | B 的 SDF 值 | + +**返回**: 合并后的梯度 + +**参见**: `chain_smooth_union 避免不连续的平滑版本` + + +**交集操作后的梯度传递** +`[[nodiscard]] inline Vector3D chain_intersection(const Vector3D& grad_a, const Vector3D& grad_b,` + +**返回**: 合并后的梯度 + + +**差集操作后的梯度传递** +`[[nodiscard]] inline Vector3D chain_difference(const Vector3D& grad_a, const Vector3D& grad_b,` + +| 参数 | 说明 | +|------|------| +| `grad_a` | 子对象 A 的梯度 | +| `grad_b` | 子对象 B 的梯度 | +| `d1` | f_A | +| `d2` | f_B | + +**返回**: 合并后的梯度 + + +**平滑并集操作的梯度传递(含完整链式法则)** +`[[nodiscard]] inline Vector3D chain_smooth_union(const Vector3D& grad_a, const Vector3D& grad_b,` + +| 参数 | 说明 | +|------|------| +| `grad_a` | 子对象 A 的梯度 | +| `grad_b` | 子对象 B 的梯度 | +| `d1` | f_A | +| `d2` | f_B | +| `k` | 混合参数 | + +**返回**: 平滑合并后的梯度 + +**参见**: `op_smooth_union 对应的平滑并集 SDF 操作`, `chain_union 硬切换版本` + + +**平移变换后的梯度传递(梯度不变)** +`[[nodiscard]] inline GradResult chain_translate(const GradResult& child_result, const Point3D& /*offset*/)` + +| 参数 | 说明 | +|------|------| +| `child_result` | 变换空间中的子对象求值结果 | +| `offset` | 平移量(仅接口保留) | + +**返回**: 相同梯度 + + +**绕 Y 轴旋转后的梯度传递** +`[[nodiscard]] inline GradResult chain_rotate(const GradResult& child_result, double angle_rad)` + +| 参数 | 说明 | +|------|------| +| `child_result` | 旋转后坐标系中的子对象求值 | +| `angle_rad` | 旋转角度 | + +**返回**: 世界坐标系的梯度 + +**参见**: `op_rotate 对应的域变形操作` + + +**非均匀缩放后的梯度传递** +`[[nodiscard]] inline GradResult chain_scale(const GradResult& child_result, const Point3D& factors)` + +| 参数 | 说明 | +|------|------| +| `child_result` | 缩放后坐标系中的子对象求值 | +| `factors` | 缩放因子 | + +**返回**: 世界坐标系的梯度 +> 缩放后梯度不再是单位长度,除非是均匀缩放。 + + +**扭曲变换后的梯度传递(含完整雅可比)** +`[[nodiscard]] inline GradResult chain_twist(const GradResult& child_result,` + +| 参数 | 说明 | +|------|------| +| `child_result` | 扭曲空间中的子对象求值 | +| `amount` | 单位高度的旋转量 | +| `p` | 原始采样点 | + +**返回**: 世界坐标系的梯度 + +**参见**: `op_twist 对应的域变形操作`, `chain_rotate 不含 Y 依赖的简化旋转梯度传递` + + +**周期重复后的梯度传递(梯度不变)** +`[[nodiscard]] inline GradResult chain_repeat(const GradResult& child_result,` + +| 参数 | 说明 | +|------|------| +| `child_result` | 中心晶格内的子对象求值 | +| `cell` | 晶格尺寸(仅接口保留) | +| `p` | 原始采样点(仅接口保留) | + +**返回**: 相同梯度 + + +**参数梯度结构体** +`struct ParamGrad {` + +**参见**: `sphere_param_grad, box_param_grad, cylinder_param_grad` + + +**球体所有参数的梯度(当前仅 radius 有意义)** +`[[nodiscard]] inline ParamGrad sphere_param_grad(const Point3D& p, double radius, double h = 1e-6)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 球体半径 | +| `h` | 差分步长 | + +**返回**: 参数梯度(仅 d_radius 非零) + +**参见**: `sphere_radius_gradient 底层数值差分` + + +**长方体所有参数的梯度** +`[[nodiscard]] inline ParamGrad box_param_grad(const Point3D& p, const Point3D& half_extents,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `half_extents` | 半边长 | +| `h` | 差分步长 | + +**返回**: 参数梯度(d_extents 分量填充) + +**参见**: `box_extent_gradient 底层数值差分` + + +**圆柱所有参数的梯度** +`[[nodiscard]] inline ParamGrad cylinder_param_grad(const Point3D& p, double radius, double height,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 圆柱半径 | +| `height` | 圆柱高度 | +| `h` | 差分步长 | + +**返回**: 参数梯度(d_radius, d_height 填充) + + + +### `sdf_operations.h` + +**SDF 布尔运算、修饰算子与域变形** + + +**布尔并集: A ∪ B** +`[[nodiscard]] inline double op_union(double d1, double d2) {` + +| 参数 | 说明 | +|------|------| +| `d1` | 第一个对象的 SDF 值 | +| `d2` | 第二个对象的 SDF 值 | + +**返回**: 并集的 SDF 值 + +**参见**: `op_smooth_union 带平滑过渡的并集`, `op_intersection 交集` + + +**布尔交集: A ∩ B** +`[[nodiscard]] inline double op_intersection(double d1, double d2) {` + +| 参数 | 说明 | +|------|------| +| `d1` | 第一个对象的 SDF 值 | +| `d2` | 第二个对象的 SDF 值 | + +**返回**: 交集的 SDF 值 + +**参见**: `op_smooth_intersection 带平滑过渡的交集` + + +**布尔差集: A \ B** +`[[nodiscard]] inline double op_difference(double d1, double d2) {` + +| 参数 | 说明 | +|------|------| +| `d1` | 被减对象 A 的 SDF 值 | +| `d2` | 减去对象 B 的 SDF 值 | + +**返回**: 差集的 SDF 值 + +**参见**: `op_smooth_difference 带平滑过渡的差集` + + +**平滑并集(带混合过渡)** +`[[nodiscard]] inline double op_smooth_union(double d1, double d2, double k) {` + +| 参数 | 说明 | +|------|------| +| `d1` | 第一个对象的 SDF 值 | +| `d2` | 第二个对象的 SDF 值 | +| `k` | 混合强度参数(> 0 时平滑过渡;≤ 0 时退化为普通并集) | + +**返回**: 平滑混合后的 SDF 值 +> 多项式混合是函数 f(x)=x 在 [0,k] 区间的平滑近似。在 d1=d2 处,f 向下偏移 k/4。 + +**参见**: `op_union 无平滑的标准并集`, `op_smooth_intersection 平滑交集`, `op_smooth_difference 平滑差集` + + +**平滑交集(带混合过渡)** +`[[nodiscard]] inline double op_smooth_intersection(double d1, double d2, double k) {` + +| 参数 | 说明 | +|------|------| +| `d1` | 第一个对象的 SDF 值 | +| `d2` | 第二个对象的 SDF 值 | +| `k` | 混合强度参数 | + +**返回**: 平滑混合后的 SDF 值 + +**参见**: `op_intersection 无平滑的标准交集`, `op_smooth_union 平滑并集` + + +**平滑差集(带混合过渡)** +`[[nodiscard]] inline double op_smooth_difference(double d1, double d2, double k) {` + +| 参数 | 说明 | +|------|------| +| `d1` | 被减对象 A 的 SDF 值 | +| `d2` | 减去对象 B 的 SDF 值 | +| `k` | 混合强度参数 | + +**返回**: 平滑混合后的 SDF 值 + +**参见**: `op_difference 无平滑的标准差集`, `op_smooth_union 平滑并集` + + +**圆角偏移: 将等值面向外扩展 r 单位** +`[[nodiscard]] inline double op_round(double d, double r) {` + +| 参数 | 说明 | +|------|------| +| `d` | SDF 值 | +| `r` | 偏移距离(正值 = 膨胀,负值 = 收缩) | + +**返回**: 偏移后的 SDF 值 + +**参见**: `op_onion 壳层修饰`, `round_box 特例化的圆角立方体` + + +**洋葱皮/壳层修饰: 取绝对值后减去厚度** +`[[nodiscard]] inline double op_onion(double d, double thickness) {` + +| 参数 | 说明 | +|------|------| +| `d` | SDF 值 | +| `thickness` | 壳层半厚度,必须 > 0 | + +**返回**: 壳层的 SDF 值 + +**参见**: `op_round 圆角偏移` + + +**无限重复(周期复制)** +`[[nodiscard]] inline Point3D op_repeat(const Point3D& p, const Point3D& cell) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `cell` | 晶格尺寸 (cx, cy, cz),各分量必须 > 0 才生效 | + +**返回**: 映射到中心晶格内的点 +> 边界处 SDF 可能不连续,需要确保各晶格间映射是连续的。 + + +**镜像对称(X=0 平面),可选偏移** +`[[nodiscard]] inline Point3D op_mirror_x(const Point3D& p, double offset = 0.0) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `offset` | 镜像平面沿 X 轴的偏移量(默认 0 = X=0 平面) | + +**返回**: 映射到镜像半空间的点 + +**参见**: `op_mirror_y YZ 平面镜像`, `op_mirror_z XY 平面镜像` + + +**镜像对称(Y=0 平面)** +`[[nodiscard]] inline Point3D op_mirror_y(const Point3D& p) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | + +**返回**: 映射到上半空间的点 + + +**镜像对称(Z=0 平面)** +`[[nodiscard]] inline Point3D op_mirror_z(const Point3D& p) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | + +**返回**: 映射到前半空间的点 + + +**空间平移(逆变换)** +`[[nodiscard]] inline Point3D op_translate(const Point3D& p, const Point3D& offset) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `offset` | 平移量(对象正向移动的方向) | + +**返回**: 逆平移后的采样点 + +**参见**: `op_rotate 旋转变换`, `op_scale 缩放变换` + + +**绕 Y 轴旋转(逆变换)** +`[[nodiscard]] inline Point3D op_rotate(const Point3D& p, double angle_rad) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `angle_rad` | 旋转角度(弧度),正值 = 逆时针(从上往下看) | + +**返回**: 逆旋转后的采样点 + +**参见**: `op_twist 绕 Y 轴的扭曲变换`, `op_bend 弯曲变换` + + +**非均匀缩放(逆变换)** +`[[nodiscard]] inline Point3D op_scale(const Point3D& p, const Point3D& s) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `s` | 各轴缩放因子 (sx, sy, sz),均必须 ≠ 0 | + +**返回**: 缩放后的采样点 + +**参见**: `op_translate 平移(等距变换)`, `op_rotate 旋转(等距变换)` + + +**绕 Y 轴的扭曲变换** +`[[nodiscard]] inline Point3D op_twist(const Point3D& p, double amount) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `amount` | 单位高度上的旋转量(弧度/单位长度) | + +**返回**: 扭曲后的采样点 + +**参见**: `op_rotate 恒定角度旋转`, `op_bend 弯曲变换` + + +**弯曲变换(绕 Z 轴弯曲 XZ 平面)** +`[[nodiscard]] inline Point3D op_bend(const Point3D& p, double k) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `k` | 弯曲曲率参数(k 越大弯曲越剧烈) | + +**返回**: 弯曲后的采样点 + +**参见**: `op_cheap_bend 简化版弯曲(仅绕 X 轴)`, `op_twist 扭曲变换` + + +**拉伸/压扁域变形(消除拉伸方向上的内部体积)** +`[[nodiscard]] inline Point3D op_elongate(const Point3D& p, const Point3D& h) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `h` | 各轴的拉伸阈值 (hx, hy, hz),均 ≥ 0 | + +**返回**: 变形后的采样点 + +**参见**: `op_repeat 周期重复` + + +**简化弯曲变换(绕 X 轴弯曲 YZ 平面)** +`[[nodiscard]] inline Point3D op_cheap_bend(const Point3D& p, double k) {` + +| 参数 | 说明 | +|------|------| +| `p` | 原始采样点 | +| `k` | 弯曲曲率参数 | + +**返回**: 弯曲后的采样点 +> 使用场景:不需要精确物理弯曲,仅需视觉效果时优先用此函数以节省计算。 + +**参见**: `op_bend 完整弯曲变换` + + +**正弦波位移扰动** +`[[nodiscard]] inline double op_displace(double d, const Point3D& p,` + +| 参数 | 说明 | +|------|------| +| `d` | 原始 SDF 值 | +| `p` | 采样点(用于扰动计算) | +| `amplitude` | 扰动幅值 | +| `frequency` | 空间频率 | + +**返回**: 扰动后的 SDF 值 + + + +### `sdf_optimize.h` + +**基于梯度的 SDF 形状优化** + + +**优化结果** +`struct OptimizeResult {` + + +**损失函数类型** +`using LossFn = std::function&)>` + +**参见**: `fit_to_point_cloud 使用该类型的内置实现` + + +**将参数化形状拟合到目标点云** +`[[nodiscard]] OptimizeResult fit_to_point_cloud(` + +| 参数 | 说明 | +|------|------| +| `initial` | 初始形状(sphere, box, cylinder 等),其参数将被优化 | +| `target_points` | 目标点云(表面采样点) | +| `learning_rate` | 梯度下降步长(默认 0.01) | +| `max_iterations` | 最大迭代次数(默认 100) | + +**返回**: 优化结果(含优化后的形状和收敛信息) +> 损失函数为 L = mean(|sdf(p_i)|),即点到表面的平均绝对距离。 +> initial 的共享子节点不会被复制——返回的 optimize_shape 共享未修改的子树。 + +**参见**: `fit_surface_to_points 类似但仅最小化 |sdf| 而非有符号距离`, `fit_to_sdf 拟合到另一个 SDF` + + +**将形状表面移动到目标采样点** +`[[nodiscard]] OptimizeResult fit_surface_to_points(` + +| 参数 | 说明 | +|------|------| +| `initial` | 初始形状 | +| `surface_points` | 目标表面点 | +| `learning_rate` | 学习率 | +| `max_iterations` | 最大迭代次数 | + +**返回**: 优化结果 + +**参见**: `fit_to_point_cloud 更通用的点云拟合(可包含内部/外部点)` + + +**拟合一个 SDF 形状以匹配另一个目标 SDF** +`[[nodiscard]] OptimizeResult fit_to_sdf(` + +| 参数 | 说明 | +|------|------| +| `source` | 被优化的参数化形状 | +| `target_sdf` | 目标 SDF 函数 | +| `bmin` | 采样网格最小角点 | +| `bmax` | 采样网格最大角点 | +| `grid_resolution` | 采样网格分辨率(默认 16) | +| `learning_rate` | 学习率 | +| `max_iterations` | 最大迭代次数 | + +**返回**: 优化结果 + +**参见**: `fit_to_point_cloud 拟合到点云` + + +**通过平移解决两个形状之间的穿透** +`[[nodiscard]] bool resolve_collision(` + +| 参数 | 说明 | +|------|------| +| `shape_a` | 形状 A(原地修改) | +| `shape_b` | 形状 B(原地修改) | +| `step_size` | 每次迭代的平移步长(默认 0.1) | +| `max_iterations` | 最大迭代次数(默认 50) | + +**返回**: true 如果碰撞被成功解决;false 如果在迭代次数内未能解决 + +**参见**: `penetration_depth 估算穿透深度` + + +**估算两个形状之间的最小穿透距离** +`[[nodiscard]] double penetration_depth(` + +| 参数 | 说明 | +|------|------| +| `shape_a` | 形状 A | +| `shape_b` | 形状 B | +| `bmin` | 公共包围盒最小角点 | +| `bmax` | 公共包围盒最大角点 | +| `samples` | 蒙地卡罗采样数(默认 1000) | + +**返回**: 最大穿透深度(负值表示不重叠时的最小间距) + +**参见**: `resolve_collision 解决穿透` + + +**计算形状表面上点的可及性分数** +`[[nodiscard]] double accessibility(` + +| 参数 | 说明 | +|------|------| +| `shape` | SDF 形状 | +| `p` | 表面点(应满足 |sdf(p)| < ε) | +| `direction` | 接近方向 | +| `hemisphere_samples` | 半球采样光线数量(默认 64) | + +**返回**: 可及性分数 [0, 1] +> 采样数越多越精确,但线性增加计算量。 + +**参见**: `find_accessible_point 找到最大可及性的表面点` + + +**找到给定接近方向下具有最大可及性的表面点** +`[[nodiscard]] Point3D find_accessible_point(` + +| 参数 | 说明 | +|------|------| +| `shape` | SDF 形状 | +| `approach_dir` | 接近方向(如工具接近方向) | +| `bmin` | 搜索包围盒最小角点 | +| `bmax` | 搜索包围盒最大角点 | +| `grid_res` | 搜索网格分辨率(默认 32) | + +**返回**: 最大可及性的表面点 + +**参见**: `accessibility 单点可及性计算` + + +**检测形状在给定方向上的反射对称性** +`[[nodiscard]] double symmetry_score(` + +| 参数 | 说明 | +|------|------| +| `shape` | SDF 形状 | +| `bmin` | 包围盒最小角点 | +| `bmax` | 包围盒最大角点 | +| `plane_normal` | 反射平面的法向量 | +| `plane_offset` | 反射平面的偏移量(沿法向量方向,默认 0) | +| `samples` | 采样点对数(默认 1000) | + +**返回**: 对称性分数 [0, 1](0 = 完全不对称,1 = 完美对称) + +**参见**: `find_symmetry_plane 自动寻找最佳对称平面` + + +**对称检测结果** +`struct SymmetryResult {` + + +**自动找到形状的最佳反射对称平面** +`[[nodiscard]] SymmetryResult find_symmetry_plane(` + +| 参数 | 说明 | +|------|------| +| `shape` | SDF 形状 | +| `bmin` | 包围盒最小角点 | +| `bmax` | 包围盒最大角点 | +| `samples` | 每个候选方向的采样数(默认 1000) | + +**返回**: 最佳对称平面及其分数 + +**参见**: `symmetry_score 给定方向的对称性检测` + + +**通过蒙地卡罗法估算隐式形状的体积** +`[[nodiscard]] double estimate_volume(` + +| 参数 | 说明 | +|------|------| +| `shape` | SDF 形状 | +| `bmin` | 采样包围盒最小角点 | +| `bmax` | 采样包围盒最大角点 | +| `samples` | 蒙地卡罗采样数(默认 10000) | + +**返回**: 近似体积 +> 精度与 √samples 成正比。10000 采样 ≈ 1% 相对误差。 +> 包围盒应尽可能紧致以减小方差。 + +**参见**: `center_of_mass 蒙地卡罗质心估算` + + +**通过蒙地卡罗法估算形状的质心** +`[[nodiscard]] Point3D center_of_mass(` + +| 参数 | 说明 | +|------|------| +| `shape` | SDF 形状 | +| `bmin` | 采样包围盒最小角点 | +| `bmax` | 采样包围盒最大角点 | +| `samples` | 蒙地卡罗采样数(默认 10000) | + +**返回**: 近似质心坐标 + +**参见**: `estimate_volume 体积估算` + + +**SDF 树中可变参数的引用** +`struct ParamRef {` + + +**从叶节点收集所有可变数值参数** +`[[nodiscard]] std::vector collect_params(SdfNodePtr& root)` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 树根节点(可写引用,因为参数将被原地修改) | + +**返回**: 可变参数引用列表 + +**参见**: `numerical_gradient 计算损失对参数的数值梯度` + + +**计算标量损失对收集到的参数的数值梯度** +`[[nodiscard]] std::vector numerical_gradient(` + +| 参数 | 说明 | +|------|------| +| `params` | collect_params() 返回的参数引用列表 | +| `loss_fn` | 损失函数(无参数的可调用对象) | +| `eps` | 差分步长(默认 1e-6) | + +**返回**: 梯度向量 grad_loss,grad_loss[i] = ∂loss / ∂params[i].value + +**参见**: `collect_params 收集参数`, `GradientDescent 梯度下降优化器` + + +**固定学习率的简单梯度下降优化器** + + +**构造优化器** +`explicit GradientDescent(double lr) : lr_(lr) {}` + +| 参数 | 说明 | +|------|------| +| `lr` | 学习率(步长因子) | + + +**执行单步梯度下降** +`double step(std::vector& params,` + +| 参数 | 说明 | +|------|------| +| `params` | 参数向量(原地修改) | +| `grad_fn` | 梯度计算函数,签名为 | + +**返回**: 当前损失值 + + +**设置学习率** +`void set_learning_rate(double lr) { lr_ = lr; }` + + +**获取学习率** +`[[nodiscard]] double learning_rate() const { return lr_; }` + + +**获取当前迭代次数** +`[[nodiscard]] int iteration() const { return iteration_; }` + + + +### `sdf_primitives.h` + +**有符号距离函数(SDF)基础图元** +> 所有图元假设未施加变换——坐标系原点即图元中心/基点。 + + +**球体的 SDF** +`[[nodiscard]] inline double sphere(const Point3D& p, double radius) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点(三维坐标) | +| `radius` | 球半径,必须 > 0 | + +**返回**: 有符号距离 +> 球位于原点。如需其他位置,使用 op_translate 对采样点做反向平移。 + +**参见**: `ellipsoid 各轴半径不同的椭球`, `cylinder 沿 Y 轴的圆柱` + + +**轴对齐立方体的 SDF** +`[[nodiscard]] inline double box(const Point3D& p, const Point3D& half_extents) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `half_extents` | 半边长 (hx, hy, hz),均必须 ≥ 0 | + +**返回**: 有符号距离 + +**参见**: `round_box 带圆角的盒子`, `wedge 对角切割的半盒子` + + +**圆角立方体的 SDF** +`[[nodiscard]] inline double round_box(const Point3D& p, const Point3D& half_extents, double r) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `half_extents` | 半边长 (hx, hy, hz) | +| `r` | 圆角半径,必须 < min(half_extents) 否则整体形态改变 | + +**返回**: 有符号距离 + +**参见**: `box 无圆角的长方体`, `op_round 对任意 SDF 做圆角偏移` + + +**圆环面的 SDF** +`[[nodiscard]] inline double torus(const Point3D& p, double major_radius, double minor_radius) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `major_radius` | 主半径(环的半径),必须 > 0 | +| `minor_radius` | 副半径(管的粗细),必须 > 0 | + +**返回**: 有符号距离 + +**参见**: `link 双环连接体(两个并行圆环的组合)` + + +**胶囊体的 SDF** +`[[nodiscard]] inline double capsule(const Point3D& p, const Point3D& a, const Point3D& b, double radius) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `a` | 线段起点 | +| `b` | 线段终点 | +| `radius` | 扫掠球半径,必须 > 0 | + +**返回**: 有符号距离 + +**参见**: `cylinder 两端平头的圆柱(非球形端盖)` + + +**带平端盖的圆柱体 SDF** +`[[nodiscard]] inline double cylinder(const Point3D& p, double radius, double height) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 圆柱截面半径,必须 > 0 | +| `height` | 圆柱总高度(从 -h/2 到 +h/2),必须 > 0 | + +**返回**: 有符号距离 + +**参见**: `capsule 两端球形端盖的圆柱`, `infinite_cylinder 无限长圆柱`, `cone 圆锥台` + + +**平面的 SDF** +`[[nodiscard]] inline double plane(const Point3D& p, const Vector3D& normal, double offset) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `normal` | 单位法向量(必须已归一化) | +| `offset` | 沿法向量正方向的偏移量 | + +**返回**: 有符号距离 + +**参见**: `wedge 两个平面+盒子的组合(对角切割)` + + +**椭球体的 SDF(有界梯度近似)** +`[[nodiscard]] inline double ellipsoid(const Point3D& p, const Point3D& radii) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radii` | 半轴长 (rx, ry, rz),均必须 > 0 | + +**返回**: 有符号距离(近似) +> 当三个半径相等时退化为球体,此时使用 sphere() 更精确高效。 +> 当点到原点距离远大于最大半径时,近似精度下降。 + +**参见**: `sphere 精确球体(rx=ry=rz 时的特例)` + + +**正六棱柱的 SDF** +`[[nodiscard]] inline double hex_prism(const Point3D& p, double radius, double height) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `radius` | 六边形外接圆半径(中心到顶点),必须 > 0 | +| `height` | 挤出总高度(±h/2 沿 Y 轴),必须 > 0 | + +**返回**: 有符号距离 + +**参见**: `extrusion_bounded 通用 bounded extrusion 算子` + + +**无限长圆柱的 SDF** +`[[nodiscard]] inline double infinite_cylinder(const Point3D& p, const Vector3D& axis, double radius) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `axis` | 圆柱轴线方向(必须归一化,|axis| = 1) | +| `radius` | 截面半径,必须 > 0 | + +**返回**: 有符号距离 + +**参见**: `cylinder 有限长圆柱(带平端盖)` + + +**楔形体的 SDF** +`[[nodiscard]] inline double wedge(const Point3D& p, double w, double h, double d) {` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `w` | 宽度(X 方向) | +| `h` | 高度(Y 方向) | +| `d` | 深度(Z 方向) | + +**返回**: 有符号距离 + +**参见**: `box 完整立方体`, `plane 独立平面 SDF` + + +**二维 SDF 沿 Z 轴的无限挤出** +`[[nodiscard]] inline double extrusion(const Point3D& /*p*/, double sdf_2d) {` + +| 参数 | 说明 | +|------|------| +| `p` | 三维采样点(仅 x,y 分量被隐式使用——通过 sdf_2d 参数间接) | +| `sdf_2d` | 预计算的二维 SDF 值(在 (p.x, p.y) 处求值) | + +**返回**: 三维有符号距离(等于 sdf_2d) +> p 参数仅保持接口一致,实际不影响结果。 +> 对于有限长度的挤出,使用 extrusion_bounded()。 + +**参见**: `extrusion_bounded 有限长度的挤出`, `revolution 二维轮廓绕 Y 轴旋转` + + +**二维 SDF 的有限长度挤出** +`[[nodiscard]] inline double extrusion_bounded(const Point3D& p, double sdf_2d, double half_height) {` + +| 参数 | 说明 | +|------|------| +| `p` | 三维采样点 | +| `sdf_2d` | 预计算的二维 SDF 值(在 (p.x, p.y) 处求值) | +| `half_height` | 挤出半高度(Z 方向),必须 ≥ 0 | + +**返回**: 有符号距离 + +**参见**: `extrusion 无限挤出`, `hex_prism 六棱柱(特例化 bounded extrusion 实现)` + + +**二维轮廓绕 Y 轴的旋转体 SDF** +`[[nodiscard]] inline double revolution(const Point3D& /*p*/, double sdf_2d, double /*offset*/) {` + +| 参数 | 说明 | +|------|------| +| `p` | 三维采样点(接口保留,不直接使用) | +| `sdf_2d` | 预计算的二维 SDF(在 (√(pₓ²+p𝓏²)-offset, p.y) 处求值) | +| `offset` | 径向偏移量(从 Y 轴的起点距离) | + +**返回**: 有符号距离 + +**参见**: `torus 圆环(revolution 的特例:截面为圆)` + + +**圆锥台的 SDF(非内联实现)** +`[[nodiscard]] double cone(const Point3D& p, double angle_rad, double height)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `angle_rad` | 半锥角(弧度),决定底面半径 | +| `height` | 锥体总高度,必须 > 0 | + +**返回**: 有符号距离 + +**参见**: `cylinder 半锥角为 0 时的退化情况`, `infinite_cone 无限圆锥` + + +**三角棱柱的 SDF(非内联实现)** +`[[nodiscard]] double triangular_prism(const Point3D& p, const Point3D& a, const Point3D& b,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `a` | 三角形顶点 A(XY 平面内) | +| `b` | 三角形顶点 B(XY 平面内) | +| `c` | 三角形顶点 C(XY 平面内) | +| `height` | 挤出总高度(沿 Z 轴),必须 > 0 | + +**返回**: 有符号距离 + +**参见**: `wedge 直角三角形楔形体` + + +**双环链接体的 SDF(非内联实现)** +`[[nodiscard]] double link(const Point3D& p, double length, double major_r, double minor_r)` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `length` | 两个环心沿 X 轴的距离 | +| `major_r` | 每个环的主半径(环的半径) | +| `minor_r` | 每个环的管半径(截面的粗细) | + +**返回**: 有符号距离 + +**参见**: `torus 单个圆环` + + +**无限圆锥的 SDF(非内联实现)** +`[[nodiscard]] double infinite_cone(const Point3D& p, const Point3D& apex,` + +| 参数 | 说明 | +|------|------| +| `p` | 采样点 | +| `apex` | 锥顶位置 | +| `axis` | 锥轴方向(必须归一化),锥体沿此方向扩展 | +| `angle_rad` | 半锥角(弧度) | + +**返回**: 有符号距离 + +**参见**: `cone 有限高圆锥台` + + + +### `sdf_to_mesh.h` + +**SDF 到三角网格的转换** + + +**将 SDF 表达式树转换为三角网格** +`[[nodiscard]] mesh::MCMesh sdf_to_mesh(const SdfNodePtr& root,` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 表达式树的根节点 | +| `resolution` | 每轴的网格分辨率(例如 64 表示 64³ 体素网格) | +| `iso_level` | 等值面水平(0.0 = 隐式表面) | + +**返回**: 包含顶点和三角形索引的 MCMesh +> 分辨率推荐为 2 的幂(32, 64, 128, 256)以获得最佳缓存性能。 +> 对于大尺寸但细节少的几何体,使用较低的 resolution 即可获得光滑结果。 + +**参见**: `sdf_to_mesh_lambda Lambda 版本的 SDF 转网格(Python 友好)`, `estimate_bbox 包围盒估算` + + +**将 Lambda SDF 函数转换为三角网格** +`[[nodiscard]] mesh::MCMesh sdf_to_mesh_lambda(` + +| 参数 | 说明 | +|------|------| +| `f` | SDF 函数,签名为 double(double x, double y, double z) → 有符号距离 | +| `bmin` | 采样包围盒最小角点 | +| `bmax` | 采样包围盒最大角点 | +| `resolution` | 每轴分辨率 | +| `iso_level` | 等值面水平(默认 0.0) | + +**返回**: MCMesh 三角网格 + +**参见**: `sdf_to_mesh 基于 SDF 树的网格转换` + + + +### `sdf_torch.h` + +**SDF 批量求值与梯度计算(CPU 后端)** + + +**在批处理模式下求值 SDF** +`void evaluate_batch(const SdfNodePtr& root,` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 表达式树根节点 | +| `points` | 点数组,length = 3·n,x,y,z 交替存储 | +| `n` | 点数 | +| `distances` | 输出数组,length = n,写入有符号距离值 | + +**参见**: `evaluate 单点求值`, `gradient_batch 批量梯度计算` + + +**在批处理模式下求值 SDF 的空间梯度** +`void gradient_batch(const SdfNodePtr& root,` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 表达式树根节点 | +| `points` | 点数组,length = 3·n | +| `n` | 点数 | +| `gradients` | 输出数组,length = 3·n,x,y,z 梯度分量交替存储 | + +**参见**: `evaluate_batch 批量距离求值`, `evaluate_with_gradient_batch 同时获取距离和梯度(减少重复采样)` + + +**一次遍历同时求值 SDF 值和梯度** +`void evaluate_with_gradient_batch(const SdfNodePtr& root,` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 表达式树根节点 | +| `points` | 点数组,length = 3·n | +| `n` | 点数 | +| `distances` | 输出距离数组,length = n | +| `gradients` | 输出梯度数组,length = 3·n | +> 对于大量点的场景(n > 1000),推荐使用本函数以获得 ~2× 速度提升。 + +**参见**: `evaluate_batch 仅求距离`, `gradient_batch 仅求梯度` + + + +### `sdf_tree.h` + +**SDF 表达式树结构** + + +**CSG 树的所有节点类型** +`enum class SdfOp : uint8_t {` + +**参见**: `SdfParams 对应的参数结构` + + +**SDF 节点参数联合体** +`struct SdfParams {` + + +**SDF 表达式树节点** +> 树是不可变的——节点创建后 op 和子节点关系不变,但 params 可被外部修改以支持参数优化。 + + +**创建球体节点** +`static SdfNodePtr sphere(double r)` + + +**创建轴对齐长方体节点** +`static SdfNodePtr box(const Point3D& half_extents)` + + +**创建圆角长方体节点** +`static SdfNodePtr round_box(const Point3D& half_extents, double r)` + + +**创建圆柱体节点** +`static SdfNodePtr cylinder(double r, double h)` + + +**创建圆环体节点** +`static SdfNodePtr torus(double major_r, double minor_r)` + + +**创建胶囊体节点** +`static SdfNodePtr capsule(const Point3D& a, const Point3D& b, double r)` + + +**创建圆锥台节点** +`static SdfNodePtr cone(double angle_rad, double h)` + + +**创建平面节点** +`static SdfNodePtr plane(const Vector3D& normal, double offset)` + + +**创建椭球体节点** +`static SdfNodePtr ellipsoid(const Point3D& radii)` + + +**创建三角棱柱节点** +`static SdfNodePtr triangular_prism(double h)` + + +**创建六棱柱节点** +`static SdfNodePtr hex_prism(double h)` + + +**创建双环链接节点** +`static SdfNodePtr link(double r, double length, double thickness)` + + +**创建楔形体节点** +`static SdfNodePtr wedge(const Point3D& extents)` + + +**创建并集节点: A ∪ B** +`static SdfNodePtr op_union(SdfNodePtr a, SdfNodePtr b)` + + +**创建交集节点: A ∩ B** +`static SdfNodePtr op_intersection(SdfNodePtr a, SdfNodePtr b)` + + +**创建差集节点: A \ B** +`static SdfNodePtr op_difference(SdfNodePtr a, SdfNodePtr b)` + + +**创建平滑并集节点** +`static SdfNodePtr smooth_union(SdfNodePtr a, SdfNodePtr b, double k)` + + +**创建平滑交集节点** +`static SdfNodePtr smooth_intersection(SdfNodePtr a, SdfNodePtr b, double k)` + + +**创建平滑差集节点** +`static SdfNodePtr smooth_difference(SdfNodePtr a, SdfNodePtr b, double k)` + + +**创建圆角偏移节点** +`static SdfNodePtr round(SdfNodePtr child, double r)` + + +**创建壳层修饰节点** +`static SdfNodePtr onion(SdfNodePtr child, double thickness)` + + +**创建周期重复节点** +`static SdfNodePtr repeat(SdfNodePtr child, const Point3D& cell)` + + +**创建 X 镜像节点** +`static SdfNodePtr mirror_x(SdfNodePtr child)` + + +**创建 Y 镜像节点** +`static SdfNodePtr mirror_y(SdfNodePtr child)` + + +**创建 Z 镜像节点** +`static SdfNodePtr mirror_z(SdfNodePtr child)` + + +**创建平移节点** +`static SdfNodePtr translate(SdfNodePtr child, const Point3D& offset)` + + +**创建旋转节点(绕 Y 轴)** +`static SdfNodePtr rotate(SdfNodePtr child, double angle_rad)` + + +**创建缩放节点** +`static SdfNodePtr scale(SdfNodePtr child, const Point3D& factors)` + + +**创建扭曲节点** +`static SdfNodePtr twist(SdfNodePtr child, double amount)` + + +**创建弯曲节点** +`static SdfNodePtr bend(SdfNodePtr child, double amount)` + + +**创建拉伸节点** +`static SdfNodePtr elongate(SdfNodePtr child, const Point3D& h)` + + +**创建简化弯曲节点** +`static SdfNodePtr cheap_bend(SdfNodePtr child, double amount)` + + +**创建位移扰动节点** +`static SdfNodePtr displace(SdfNodePtr child, double amplitude, double frequency)` + + +**前序遍历所有节点** +`template ` + + +**前序遍历(const 版本)** +`template ` + +**参见**: `visit(Fn&&)` + + +**构造 SDF 节点** +`explicit SdfNode(SdfOp o) : op(o) {}` + +| 参数 | 说明 | +|------|------| +| `o` | 操作类型 | + + +**在空间点 p 处求值 SDF 树** +`[[nodiscard]] double evaluate(const SdfNodePtr& root, const Point3D& p)` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 表达式树的根节点 | +| `p` | 世界空间中的采样点 | + +**返回**: 有符号距离(负 = 内部,零 = 表面,正 = 外部) + +**参见**: `estimate_bounds 估计树的包围盒` + + +**估算 SDF 树的包围半尺寸** +`[[nodiscard]] Point3D estimate_bounds(const SdfNodePtr& root, double margin = 1.0)` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 树的根节点 | +| `margin` | 额外安全边距(默认 1.0) | + +**返回**: 包围半边长 (hx, hy, hz) +> 变形节点(旋转/弯曲/扭曲等)会使包围盒放大,以保守估计覆盖变形后区域。 + +**参见**: `estimate_bbox 完整 AABB 结果` + + +**SDF 树的包围盒(AABB)** +`struct SdfBBox {` + + +**估算 SDF 树的完整轴对齐包围盒** +`[[nodiscard]] SdfBBox estimate_bbox(const SdfNodePtr& root, double margin = 1.0)` + +| 参数 | 说明 | +|------|------| +| `root` | SDF 树的根节点 | +| `margin` | 额外安全边距 | + +**返回**: AABB 包围盒 + + + +## 草图约束 (`vde::sketch`) + + +### `constraint_solver.h` + +**草图点元素** +`struct SketchPoint {` + + +**草图线段元素** +`struct SketchLine {` + + +**草图圆元素** +`struct SketchCircle {` + + +**约束类型枚举** +`enum class ConstraintType {` + + +**约束实例** +`struct Constraint {` + + +**求解器返回结果** +`struct SolverResult {` + + +**二维几何约束求解器** + + +**添加自由点** +`int add_point(double x, double y, bool fixed = false)` + +| 参数 | 说明 | +|------|------| +| `x` | X 坐标 | +| `y` | Y 坐标 | +| `fixed` | 是否固定(true 则排除变量) | + +**返回**: 点 ID + + +**添加线段** +`int add_line(int p0, int p1)` + +| 参数 | 说明 | +|------|------| +| `p0` | 起点 ID | +| `p1` | 终点 ID | + +**返回**: 线段 ID + + +**添加圆** +`int add_circle(int center, double radius)` + +| 参数 | 说明 | +|------|------| +| `center` | 圆心点 ID | +| `radius` | 半径 | + +**返回**: 圆 ID + + +**添加约束** +`void add_constraint(ConstraintType type, const std::vector& elements, double val = 0.0)` + +| 参数 | 说明 | +|------|------| +| `type` | 约束类型 | +| `elements` | 约束涉及的元素 ID 列表 | +| `val` | 约束值(距离、角度等),默认 0 | +> 不同类型 elements 的语义: + + +**标记点为固定(硬约束)** +`void fix_point(int pid) {` + +| 参数 | 说明 | +|------|------| +| `pid` | 点 ID | +> 固定点不参与变量优化,从自由度中排除 + + +**执行约束求解** +`[[nodiscard]] SolverResult solve(int max_iter = 100, double tol = 1e-8)` + +| 参数 | 说明 | +|------|------| +| `max_iter` | 最大 Gauss-Newton 迭代次数,默认 100 | +| `tol` | 收敛容差(梯度范数 < tol 时停止),默认 1e-8 | + +**返回**: SolverResult 求解结果 +> 收敛判断:||J^T r|| < tol +> 欠约束时(DOF > 0)解不唯一;过约束时(DOF < 0)为最小二乘解 + + +**计算自由度** +`[[nodiscard]] int degrees_of_freedom() const` + +**返回**: DOF = 2·N_free - Σ(约束方程数) +> DOF < 0 时系统过约束,求解器仍然工作但解非精确满足所有约束 + + +**当前点集访问** +`[[nodiscard]] const std::vector& points() const { return points_; }` + +**返回**: SketchPoint 数组只读引用 + + +**查询点坐标** +`[[nodiscard]] Point2D get_point(int id) const` + +| 参数 | 说明 | +|------|------| +| `id` | 点 ID | + +**返回**: Point2D 当前坐标 + + +**将求解器变量向量同步回 points_(用于 Jacobian 数值计算)** +`void sync_from_vars(const double* vars, int nv)` + +| 参数 | 说明 | +|------|------| +| `vars` | 变量数组(长度为 2·N_free) | +| `nv` | 变量数 | + + +**评估单个约束的残差值** +`double eval_constraint(const Constraint& c) const` + +| 参数 | 说明 | +|------|------| +| `c` | 约束 | + +**返回**: 残差(方程 → 0 表示约束满足) + + +**计算单个约束的方程数** +`int count_equations(const Constraint& c) const` + +| 参数 | 说明 | +|------|------| +| `c` | 约束 | + +**返回**: Coincident/Fixed → 2,其余 → 1 + + +**填充 Jacobian 矩阵中对应约束 ci 的行** +`void fill_jacobian_rows(const Constraint& c, int ci,` + +| 参数 | 说明 | +|------|------| +| `c` | 约束 | +| `ci` | 约束索引 | +| `row_map` | 方程行映射 | +| `J_data` | Jacobian 矩阵数据(行优先) | +| `nv` | 变量数 | +| `stride` | 行跨度 | + + + +## C API (`vde::capi`) + + +### `vde_capi.h` + +**ViewDesignEngine C API — 跨语言边界接口** +`extern "C" {` + +**参见**: `vde.h C++ 等价接口` + + +**引擎上下文句柄 — 管理错误状态和内部资源** +`typedef struct VdeContext* VdeHandle` + + +**三角网格句柄 — 顶点+面集合** +`typedef struct VdeMesh* VdeMeshHandle` + + +**参数曲线句柄 — NURBS 曲线** +`typedef struct VdeCurve* VdeCurveHandle` + + +**约束求解器句柄 — 二维草图约束** +`typedef struct VdeSolver* VdeSolverHandle` + + +**B-Rep 实体句柄 — 边界表示模型** +`typedef struct VdeBody* VdeBodyHandle` + + +**创建 ViewDesignEngine 上下文** +`VdeHandle vde_create(void)` + +**返回**: 新的引擎句柄,不需要时通过 vde_destroy() 释放 + +**参见**: `vde_destroy 释放上下文` + + +**销毁引擎上下文** +`void vde_destroy(VdeHandle ctx)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | + +**参见**: `vde_create` + + +**获取引擎版本字符串** +`const char* vde_version(void)` + +**返回**: 语义版本号字符串(如 "0.5.0"),静态生命周期,无需释放 + + +**获取最后一次操作的错误描述** +`const char* vde_last_error(VdeHandle ctx)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | + +**返回**: 错误描述字符串(上下文的内部缓冲区,静态生命周期) +> 每次新的失败操作会覆盖此描述。成功操作不会清除它。 + + +**从文件加载三角网格** +`VdeMeshHandle vde_load_mesh(VdeHandle ctx, const char* path)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `path` | 文件路径(UTF-8 编码) | + +**返回**: 网格句柄,失败时返回 NULL(通过 vde_last_error() 获取原因) + +**参见**: `vde_mesh_free 释放网格`, `vde_save_mesh 保存网格` + + +**将三角网格保存为文件** +`int vde_save_mesh(VdeHandle ctx, VdeMeshHandle mesh, const char* path, const char* format)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `mesh` | 网格句柄 | +| `path` | 输出文件路径 | +| `format` | 输出格式(当前仅 "obj" 有效) | + +**返回**: 成功返回 1,失败返回 0 + +**参见**: `vde_load_mesh 加载网格` + + +**获取网格的顶点数量** +`size_t vde_mesh_num_vertices(VdeMeshHandle mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 网格句柄(必须有效且非 NULL) | + +**返回**: 顶点数 + +**参见**: `vde_mesh_num_faces 面数` + + +**获取网格的三角面数量** +`size_t vde_mesh_num_faces(VdeMeshHandle mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 网格句柄 | + +**返回**: 面数 + +**参见**: `vde_mesh_num_vertices 顶点数` + + +**获取指定索引的顶点坐标** +`void vde_mesh_get_vertex(VdeMeshHandle mesh, size_t idx,` + +| 参数 | 说明 | +|------|------| +| `mesh` | 网格句柄 | +| `idx` | 顶点索引 [0, num_vertices) | +| `out_x` | [out] 顶点 X 坐标 | +| `out_y` | [out] 顶点 Y 坐标 | +| `out_z` | [out] 顶点 Z 坐标 | + + +**获取网格的轴对齐包围盒** +`void vde_mesh_get_bounds(VdeMeshHandle mesh,` + +| 参数 | 说明 | +|------|------| +| `mesh` | 网格句柄 | +| `out_min_x` | [out] 最小 X 坐标 | +| `out_min_y` | [out] 最小 Y 坐标 | +| `out_min_z` | [out] 最小 Z 坐标 | +| `out_max_x` | [out] 最大 X 坐标 | +| `out_max_y` | [out] 最大 Y 坐标 | +| `out_max_z` | [out] 最大 Z 坐标 | + + +**释放网格句柄及其资源** +`void vde_mesh_free(VdeMeshHandle mesh)` + +| 参数 | 说明 | +|------|------| +| `mesh` | 网格句柄 | + + +**网格简化** +`VdeMeshHandle vde_mesh_simplify(VdeHandle ctx, VdeMeshHandle mesh, double target_ratio)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `mesh` | 输入网格句柄(不修改输入) | +| `target_ratio` | 目标简化比率 [0, 1](0 = 不变,1 = 最大简化) | + +**返回**: 简化后的新网格句柄 + +**参见**: `vde_mesh_smooth 网格平滑` + + +**网格平滑(Laplacian 或 Taubin 平滑)** +`VdeMeshHandle vde_mesh_smooth(VdeHandle ctx, VdeMeshHandle mesh, int iterations)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `mesh` | 输入网格句柄 | +| `iterations` | 平滑迭代次数 | + +**返回**: 平滑后的新网格句柄 + +**参见**: `vde_mesh_simplify 网格简化` + + +**网格布尔运算** +`VdeMeshHandle vde_mesh_boolean(VdeHandle ctx, VdeMeshHandle a, VdeMeshHandle b, int operation)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `a` | 网格 A | +| `b` | 网格 B | +| `operation` | 布尔操作类型: 0 = 并集, 1 = 交集, 2 = 差集 (A \ B) | + +**返回**: 布尔结果的新网格句柄 + + +**创建 Bézier 曲线** +`VdeCurveHandle vde_curve_create_bezier(VdeHandle ctx, const double* control_points,` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `control_points` | 控制点数组,每 3 个 double 表示一个三维点 (x,y,z) | +| `num_points` | 控制点数量(次数 = num_points - 1) | +| `dim` | 维度(固定为 3) | + +**返回**: 曲线句柄 + +**参见**: `vde_curve_evaluate 求值`, `vde_curve_free 释放` + + +**在参数 t 处求值曲线** +`void vde_curve_evaluate(VdeCurveHandle curve, double t,` + +| 参数 | 说明 | +|------|------| +| `curve` | 曲线句柄 | +| `t` | 参数值 [0, 1] | +| `out_x` | [out] 曲线上点的 X 坐标 | +| `out_y` | [out] 曲线上点的 Y 坐标 | +| `out_z` | [out] 曲线上点的 Z 坐标 | + + +**获取曲线的次数** +`int vde_curve_degree(VdeCurveHandle curve)` + +| 参数 | 说明 | +|------|------| +| `curve` | 曲线句柄 | + +**返回**: 曲线次数 + + +**释放曲线句柄** +`void vde_curve_free(VdeCurveHandle curve)` + +| 参数 | 说明 | +|------|------| +| `curve` | 曲线句柄 | + + +**两球体碰撞检测(GJK 算法)** +`int vde_collision_gjk_spheres(VdeHandle ctx,` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `cx1,` | cy1, cz1 第一个球体的球心坐标 | +| `r1` | 第一个球体的半径 | +| `cx2,` | cy2, cz2 第二个球体的球心坐标 | +| `r2` | 第二个球体的半径 | + +**返回**: 碰撞返回 1,不碰撞返回 0 + +**参见**: `vde_collision_ray_mesh 射线-网格相交` + + +**射线与网格的最近交点查询** +`int vde_collision_ray_mesh(VdeHandle ctx, VdeMeshHandle mesh,` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `mesh` | 目标网格句柄 | +| `ox,` | oy, oz 射线起点 | +| `dx,` | dy, dz 射线方向(无需归一化) | +| `out_t` | [out] 交点参数 t(沿射线的距离) | +| `out_x,` | out_y, out_z [out] 交点坐标 | + +**返回**: 命中返回 1,未命中返回 0 + +**参见**: `vde_collision_gjk_spheres GJK 球体碰撞` + + +**创建二维约束求解器** +`VdeSolverHandle vde_solver_create(void)` + +**返回**: 求解器句柄 + +**参见**: `vde_solver_free 释放` + + +**向求解器添加点** +`int vde_solver_add_point(VdeSolverHandle solver, double x, double y, int fixed)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | +| `x` | 初始 X 坐标 | +| `y` | 初始 Y 坐标 | +| `fixed` | 固定点标记(1 = 固定不移动) | + +**返回**: 点的 ID(用于后续约束引用) + +**参见**: `vde_solver_add_line 添加线段` + + +**向求解器添加线段(由两个点定义)** +`int vde_solver_add_line(VdeSolverHandle solver, int p0, int p1)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | +| `p0` | 起点 ID | +| `p1` | 终点 ID | + +**返回**: 线段的 ID + +**参见**: `vde_solver_add_point 添加点`, `vde_solver_add_horizontal 添加水平约束`, `vde_solver_add_vertical 添加垂直约束` + + +**添加距离约束(两点之间)** +`void vde_solver_add_distance_constraint(VdeSolverHandle solver, int p0, int p1, double d)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | +| `p0` | 第一个点的 ID | +| `p1` | 第二个点的 ID | +| `d` | 目标距离(必须 > 0) | + +**参见**: `vde_solver_add_horizontal 水平约束` + + +**添加水平约束(线段水平)** +`void vde_solver_add_horizontal(VdeSolverHandle solver, int line_id)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | +| `line_id` | 线段 ID | + +**参见**: `vde_solver_add_vertical 垂直约束`, `vde_solver_add_line 添加线段` + + +**添加垂直约束(线段垂直)** +`void vde_solver_add_vertical(VdeSolverHandle solver, int line_id)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | +| `line_id` | 线段 ID | + +**参见**: `vde_solver_add_horizontal 水平约束` + + +**求解约束系统** +`int vde_solver_solve(VdeSolverHandle solver, int max_iter, double tol)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | +| `max_iter` | 最大迭代次数 | +| `tol` | 收敛容差 | + +**返回**: 收敛返回 1,未收敛返回 0 + +**参见**: `vde_solver_get_point 获取求解后的点坐标` + + +**获取求解后的点坐标** +`void vde_solver_get_point(VdeSolverHandle solver, int idx, double* out_x, double* out_y)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | +| `idx` | 点 ID | +| `out_x` | [out] 求解后 X 坐标 | +| `out_y` | [out] 求解后 Y 坐标 | + + +**释放求解器句柄** +`void vde_solver_free(VdeSolverHandle solver)` + +| 参数 | 说明 | +|------|------| +| `solver` | 求解器句柄 | + + +**创建实心立方体 B-Rep** +`VdeBodyHandle vde_body_create_box(VdeHandle ctx, double w, double h, double d)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `w` | 宽度(X 方向),> 0 | +| `h` | 高度(Y 方向),> 0 | +| `d` | 深度(Z 方向),> 0 | + +**返回**: B-Rep 实体句柄 + +**参见**: `vde_body_create_cylinder 圆柱体`, `vde_body_create_sphere 球体` + + +**创建实心圆柱体 B-Rep** +`VdeBodyHandle vde_body_create_cylinder(VdeHandle ctx, double r, double h, int segs)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `r` | 截面半径,> 0 | +| `h` | 总高度(从 -h/2 到 +h/2) | +| `segs` | 截面分段数(边数) | + +**返回**: B-Rep 实体句柄 + +**参见**: `vde_body_create_box 立方体` + + +**创建球体 B-Rep** +`VdeBodyHandle vde_body_create_sphere(VdeHandle ctx, double r, int su, int sv)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `r` | 球半径,> 0 | +| `su` | 经度方向分段数 | +| `sv` | 纬度方向分段数 | + +**返回**: B-Rep 实体句柄 + + +**将 B-Rep 实体转换为三角网格** +`VdeMeshHandle vde_body_to_mesh(VdeHandle ctx, VdeBodyHandle body, double deflection)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `body` | B-Rep 实体句柄 | +| `deflection` | 弦高误差(越小 = 越精细,推荐 0.01) | + +**返回**: 三角网格句柄 + +**参见**: `vde_body_free 释放 B-Rep 实体` + + +**释放 B-Rep 实体句柄** +`void vde_body_free(VdeBodyHandle body)` + +| 参数 | 说明 | +|------|------| +| `body` | B-Rep 实体句柄 | + + +**将网格序列化为二进制字节流** +`size_t vde_serialize_mesh(VdeHandle ctx, VdeMeshHandle mesh, uint8_t** out_data)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `mesh` | 网格句柄 | +| `out_data` | [out] 指向序列化字节数组的指针 | + +**返回**: 字节数 +> 输出的缓冲区由库管理,调用方不得直接 free/delete。 + +**参见**: `vde_deserialize_mesh 反序列化`, `vde_free_buffer 释放序列化缓冲区` + + +**从二进制字节流反序列化为网格** +`VdeMeshHandle vde_deserialize_mesh(VdeHandle ctx, const uint8_t* data, size_t len)` + +| 参数 | 说明 | +|------|------| +| `ctx` | 引擎上下文句柄 | +| `data` | 序列化数据缓冲区 | +| `len` | 数据长度(字节数) | + +**返回**: 反序列化后的网格句柄 + +**参见**: `vde_serialize_mesh 序列化` + + +**释放由 vde_serialize_mesh 分配的缓冲区** +`void vde_free_buffer(uint8_t* ptr)` + +| 参数 | 说明 | +|------|------| +| `ptr` | 由 vde_serialize_mesh 返回的缓冲区指针 | +