# 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 返回的缓冲区指针 |