6943 lines
163 KiB
Markdown
6943 lines
163 KiB
Markdown
# 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<std::vector<int>> faces`
|
||
|
||
|
||
**每个面的纹理坐标索引列表(0-based)**
|
||
`std::vector<std::vector<int>> face_texcoords`
|
||
|
||
|
||
**每个面的法线索引列表(0-based)**
|
||
`std::vector<std::vector<int>> face_normals`
|
||
|
||
|
||
**每个面对应的材质名称**
|
||
`std::vector<std::string> 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<StlTriangle> 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<StlTriangle>& 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<StlTriangle>& tris)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `filepath` | 输出文件路径 |
|
||
| `tris` | 三角形面片列表 |
|
||
|
||
**参见**: `read_stl, write_stl`
|
||
|
||
|
||
|
||
### `math_types.h`
|
||
|
||
**通用 N 维点类型(使用 Eigen 列向量)**
|
||
`template <typename T, size_t Dim>`
|
||
|
||
|
||
**通用 N 维向量类型(与 Point 相同的列向量表示)**
|
||
`template <typename T, size_t Dim>`
|
||
|
||
|
||
**基础模块提供 VDE 引擎的核心基础设施:**
|
||
`/** @} */ // end of foundation group`
|
||
|
||
|
||
|
||
### `memory_pool.h`
|
||
|
||
**固定块大小的内存池**
|
||
`template <typename T>`
|
||
> 内存池不调用对象的构造函数/析构函数,仅管理原始内存
|
||
> 适合 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<uint8_t> serialize(const mesh::HalfedgeMesh& mesh)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `mesh` | 要序列化的半边网格 |
|
||
|
||
**返回**: 压缩后的二进制数据(含文件头)
|
||
|
||
|
||
**从二进制缓冲区反序列化网格**
|
||
`static mesh::HalfedgeMesh deserialize(const std::vector<uint8_t>& 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 <typename T>`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `value` | 测试值 |
|
||
|
||
**返回**: true 若 |value| < absolute_
|
||
|
||
|
||
**混合容差相等判断**
|
||
`template <typename T>`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `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 <typename T>`
|
||
> 初始状态为空(min = +∞, max = -∞),需要通过 expand() 初始化
|
||
|
||
|
||
**构造空包围盒**
|
||
`AABB() : min_(Point3D::Constant(std::numeric_limits<T>::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<Point2D> convex_hull_2d(const std::vector<Point2D>& points)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `points` | 输入点集(至少 3 个不共线点) |
|
||
|
||
**返回**: 凸包顶点序列(逆时针排列),不含共线的中间点
|
||
> 自动过滤共线点,返回严格的凸包顶点
|
||
> 若所有点共线,返回两个端点
|
||
|
||
**参见**: `convex_hull_3d, Polygon2D::convex_hull_2d`
|
||
|
||
|
||
**三维凸包计算(QuickHull 算法)**
|
||
`std::vector<std::array<Point3D, 3>> convex_hull_3d(const std::vector<Point3D>& 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<double>& line)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 测试点 |
|
||
| `line` | 直线 |
|
||
|
||
**返回**: 垂直距离
|
||
|
||
|
||
**点到线段的距离**
|
||
`double distance(const Point3D& p, const Segment3D<double>& seg)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 测试点 |
|
||
| `seg` | 线段 |
|
||
|
||
**返回**: 最短距离
|
||
|
||
|
||
**点到平面的距离**
|
||
`double distance(const Point3D& p, const Plane<double>& plane)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 测试点 |
|
||
| `plane` | 平面 |
|
||
|
||
**返回**: 绝对垂直距离
|
||
|
||
**参见**: `Plane::signed_distance`
|
||
|
||
|
||
**点到三角形的距离**
|
||
`double distance(const Point3D& p, const Triangle<double>& tri)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 测试点 |
|
||
| `tri` | 三角形 |
|
||
|
||
**返回**: 最短距离
|
||
|
||
|
||
**点到包围盒的距离**
|
||
`double distance(const Point3D& p, const AABB<double>& box)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 测试点 |
|
||
| `box` | 包围盒 |
|
||
|
||
**返回**: 最短距离(内部点返回 0)
|
||
|
||
|
||
**两条线段之间的最短距离**
|
||
`double distance(const Segment3D<double>& a, const Segment3D<double>& b)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `a` | 第一条线段 |
|
||
| `b` | 第二条线段 |
|
||
|
||
**返回**: 最短距离(若相交则为 0)
|
||
|
||
|
||
**两条直线之间的最短距离**
|
||
`double distance(const Line3D<double>& a, const Line3D<double>& b)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `a` | 第一条直线 |
|
||
| `b` | 第二条直线 |
|
||
|
||
**返回**: 最短距离
|
||
|
||
|
||
**两个包围盒之间的最短距离**
|
||
`double distance(const AABB<double>& a, const AABB<double>& b)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `a` | 第一个包围盒 |
|
||
| `b` | 第二个包围盒 |
|
||
|
||
**返回**: 最短距离
|
||
|
||
|
||
**两个三角形之间的最短距离**
|
||
`double distance(const Triangle<double>& a, const Triangle<double>& b)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `a` | 第一个三角形 |
|
||
| `b` | 第二个三角形 |
|
||
|
||
**返回**: 最短距离(若相交则为 0)
|
||
|
||
|
||
**三角形上距给定点最近的点**
|
||
`Point3D closest_point(const Point3D& p, const Triangle<double>& tri)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 查询点 |
|
||
| `tri` | 三角形 |
|
||
|
||
**返回**: 三角形上距离 p 最近的点
|
||
|
||
|
||
**线段上距给定点最近的点**
|
||
`Point3D closest_point(const Point3D& p, const Segment3D<double>& seg)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 查询点 |
|
||
| `seg` | 线段 |
|
||
|
||
**返回**: 线段上距离 p 最近的点(可能为端点)
|
||
|
||
|
||
**包围盒上距给定点最近的点**
|
||
`Point3D closest_point(const Point3D& p, const AABB<double>& box)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 查询点 |
|
||
| `box` | 包围盒 |
|
||
|
||
**返回**: 包围盒边界上(或内部)距离 p 最近的点
|
||
|
||
|
||
**平面上距给定点最近的点(正交投影)**
|
||
`Point3D closest_point(const Point3D& p, const Plane<double>& plane)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p` | 查询点 |
|
||
| `plane` | 平面 |
|
||
|
||
**返回**: 点 p 在平面上的正交投影
|
||
|
||
**参见**: `Plane::project`
|
||
|
||
|
||
|
||
### `icp.h`
|
||
|
||
**ICP(迭代最近点)配准结果**
|
||
`struct ICPResult {`
|
||
|
||
|
||
**配准后的均方根误差**
|
||
`double rms_error`
|
||
|
||
|
||
**迭代最近点(ICP)刚体点云配准**
|
||
`[[nodiscard]] ICPResult icp_register(const std::vector<Point3D>& source,`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `source` | 源点云(将被移动) |
|
||
| `target` | 目标点云(固定参考) |
|
||
| `max_iter` | 最大迭代次数(默认 50) |
|
||
| `tolerance` | 收敛容差:相邻两次 RMS 变化的阈值(默认 1e-6) |
|
||
|
||
**返回**: 配准结果,包含最终变换和误差
|
||
> source 和 target 点数可以不同
|
||
> 初始对齐越好,收敛越快;若初始偏差太大,可能收敛到局部最优
|
||
|
||
|
||
|
||
### `line.h`
|
||
|
||
**三维无限直线**
|
||
`template <typename T>`
|
||
|
||
|
||
**从原点和方向构造直线**
|
||
`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 <typename T>`
|
||
|
||
|
||
**从两个端点构造线段**
|
||
`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 <typename T>`
|
||
|
||
|
||
**从原点和方向构造射线**
|
||
`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 <typename T>`
|
||
|
||
|
||
**从点和法线构造平面**
|
||
`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 <typename T, size_t Dim>`
|
||
|
||
|
||
**通用 N 维向量类型(重新导出)**
|
||
`template <typename T, size_t Dim>`
|
||
|
||
|
||
|
||
### `polygon.h`
|
||
|
||
**二维平面多边形**
|
||
> 内部假设简单多边形(无自交),非简单多边形的行为未定义
|
||
> 所有几何计算基于(假设的)XY 平面
|
||
|
||
|
||
**从顶点列表构造多边形**
|
||
`explicit Polygon2D(std::vector<Point2D> 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<double> 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<std::array<int, 3>> triangulate() const`
|
||
|
||
**返回**: 三角形列表,每个元素为 {i, j, k} 表示顶点索引
|
||
> 时间复杂度 O(n²),适用于顶点数 < 1000 的多边形
|
||
|
||
**参见**: `simplify`
|
||
|
||
|
||
**Andrew's Monotone Chain 二维凸包**
|
||
`static Polygon2D convex_hull_2d(const std::vector<Point2D>& points)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `points` | 输入点集 |
|
||
|
||
**返回**: 凸包多边形(CCW,不含共线中间点)
|
||
|
||
**参见**: `convex_hull_2d`
|
||
|
||
|
||
|
||
### `transform.h`
|
||
|
||
**三维仿射变换类型**
|
||
`using Transform3D = Eigen::Transform<double, 3, Eigen::Affine>`
|
||
|
||
|
||
**创建平移变换**
|
||
`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 <typename T>`
|
||
|
||
|
||
**从三个顶点构造三角形**
|
||
`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<Point2D> vertices`
|
||
|
||
|
||
**单元格边界边**
|
||
`std::vector<std::array<int, 2>> edges`
|
||
|
||
|
||
**二维 Voronoi 图生成(通过 Delaunay 对偶图)**
|
||
`std::vector<VoronoiCell> voronoi_2d(const std::vector<Point2D>& points)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `points` | 输入点集(站点) |
|
||
|
||
**返回**: 每个站点对应的 VoronoiCell 列表(顺序与输入一致)
|
||
> 对于凸包边界上的站点,对应的 Voronoi 单元格无界,顶点不完全闭合
|
||
> 内部使用 Delaunay 三角剖分作为中间步骤
|
||
|
||
|
||
|
||
## 曲线曲面 (`vde::curves`)
|
||
|
||
|
||
### `bezier_curve.h`
|
||
|
||
**任意阶 Bézier 曲线**
|
||
|
||
|
||
**构造 Bézier 曲线**
|
||
`explicit BezierCurve(std::vector<Point3D> 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<int>(cp_.size()) - 1; }`
|
||
|
||
**返回**: 阶次 = 控制点数 - 1
|
||
|
||
|
||
**参数定义域**
|
||
`[[nodiscard]] std::pair<double, double> domain() const { return {0.0, 1.0}; }`
|
||
|
||
**返回**: 固定为 [0, 1]
|
||
|
||
|
||
**控制点访问**
|
||
`[[nodiscard]] const std::vector<Point3D>& control_points() const { return cp_; }`
|
||
|
||
**返回**: 控制点向量的只读引用
|
||
|
||
|
||
**在 t 处将曲线一分为二**
|
||
`[[nodiscard]] std::pair<BezierCurve, BezierCurve> 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<std::vector<Point3D>> 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<int>(cp_.size()) - 1; }`
|
||
|
||
**返回**: u 方向阶次(控制点行数 - 1)
|
||
|
||
|
||
**v 向阶次**
|
||
`[[nodiscard]] int degree_v() const { return static_cast<int>(cp_[0].size()) - 1; }`
|
||
|
||
**返回**: v 方向阶次(控制点列数 - 1)
|
||
|
||
|
||
**一维 de Casteljau 求值(内部辅助)**
|
||
`[[nodiscard]] Point3D de_casteljau(double t, const std::vector<Point3D>& pts) const`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `t` | 参数 |
|
||
| `pts` | 一维控制点序列 |
|
||
|
||
**返回**: 求值结果
|
||
|
||
|
||
|
||
### `bspline_curve.h`
|
||
|
||
**B 样条曲线(非有理、均匀/非均匀节点)**
|
||
|
||
|
||
**构造 B 样条曲线**
|
||
`BSplineCurve(std::vector<Point3D> 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<double, double> domain() const`
|
||
|
||
**返回**: 有效参数范围 [knots[p], knots[n+1]]
|
||
|
||
|
||
**控制点访问**
|
||
`[[nodiscard]] const std::vector<Point3D>& control_points() const { return cp_; }`
|
||
|
||
**返回**: 控制点数组只读引用
|
||
|
||
|
||
**节点向量访问**
|
||
`[[nodiscard]] const std::vector<double>& 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<double> 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<double> 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<std::vector<Point3D>> 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<double>& knots_u() const { return knots_u_; }`
|
||
|
||
**返回**: 只读引用
|
||
|
||
|
||
**v 向节点向量**
|
||
`[[nodiscard]] const std::vector<double>& knots_v() const { return knots_v_; }`
|
||
|
||
**返回**: 只读引用
|
||
|
||
|
||
|
||
### `nurbs_curve.h`
|
||
|
||
**NURBS 曲线(Non-Uniform Rational B-Spline)**
|
||
|
||
|
||
**构造 NURBS 曲线**
|
||
`NurbsCurve(std::vector<Point3D> control_points, std::vector<double> 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<double, double> domain() const`
|
||
|
||
**返回**: [knots[degree], knots[n+1]]
|
||
|
||
|
||
**控制点访问**
|
||
`[[nodiscard]] const std::vector<Point3D>& control_points() const { return cp_; }`
|
||
|
||
**返回**: 只读引用
|
||
|
||
|
||
**权重访问**
|
||
`[[nodiscard]] const std::vector<double>& weights() const { return weights_; }`
|
||
|
||
**返回**: 只读引用
|
||
|
||
|
||
**节点向量访问**
|
||
`[[nodiscard]] const std::vector<double>& 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<std::vector<Point3D>> 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<int, 2> num_control_points() const {`
|
||
|
||
**返回**: {nu+1, nv+1},即网格的行数和列数
|
||
|
||
|
||
**u 向节点向量**
|
||
`[[nodiscard]] const std::vector<double>& knots_u() const { return knots_u_; }`
|
||
|
||
**返回**: 只读引用
|
||
|
||
|
||
**v 向节点向量**
|
||
`[[nodiscard]] const std::vector<double>& knots_v() const { return knots_v_; }`
|
||
|
||
**返回**: 只读引用
|
||
|
||
|
||
**控制点网格访问**
|
||
`[[nodiscard]] const std::vector<std::vector<Point3D>>& control_points() const { return cp_; }`
|
||
|
||
**返回**: 只读引用
|
||
|
||
|
||
**权重网格访问**
|
||
`[[nodiscard]] const std::vector<std::vector<double>>& 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<Point3D>, std::vector<std::array<int,3>>>`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `res_u` | u 方向采样分辨率 |
|
||
| `res_v` | v 方向采样分辨率 |
|
||
|
||
**返回**: {顶点数组, 三角形索引数组},每个三角形为 {i0,i1,i2}
|
||
> 生成 res_u×res_v 均匀网格,每个单元格拆为两个三角形
|
||
|
||
**参见**: `tessellate`
|
||
|
||
|
||
|
||
### `tessellation.h`
|
||
|
||
**均匀参数化曲面三角化**
|
||
`std::pair<std::vector<Point3D>, std::vector<std::array<int, 3>>>`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `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<Point3D>, std::vector<std::array<int, 3>>>`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `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<Point3D>& points, double alpha)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `points` | 输入 3D 点云 |
|
||
| `alpha` | α 半径阈值,通常取平均点间距的 1~3 倍 |
|
||
|
||
**返回**: TetrahedronMesh 保留的四面体网格
|
||
|
||
**参见**: `alpha_shapes_surface delaunay_3d`
|
||
|
||
|
||
**将 Alpha Shapes 四面体网格的表面提取为三角形网格**
|
||
`std::pair<std::vector<Point3D>, std::vector<std::array<int,3>>>`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `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<Point2D>& 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<Point3D>& points)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `points` | 输入 3D 点集(至少 4 个不共面点) |
|
||
|
||
**返回**: TetrahedronMesh 四面体网格
|
||
> 时间复杂度与 2D 类似:平均 O(n log n),最坏 O(n²)
|
||
> 输出包括内部和边界四面体;通过 alpha_shapes 可提取表面
|
||
|
||
**参见**: `alpha_shapes`
|
||
|
||
|
||
|
||
### `geodesic.h`
|
||
|
||
**热方法(Heat Method)计算测地距离**
|
||
`std::vector<double> 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<int>& vertex_indices)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `vertex_indices` | 按逆时针顺序排列的顶点索引(至少 3 个) |
|
||
|
||
**返回**: 新面的索引,失败返回 -1
|
||
> 自动创建/查找半边并设置对侧关系;面法向遵循右手定则
|
||
|
||
|
||
**从三角形列表批量构建半边形网格**
|
||
`void build_from_triangles(const std::vector<Point3D>& 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<int> face_vertices(int fi) const`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `fi` | 面索引 |
|
||
|
||
**返回**: 顶点索引序列
|
||
|
||
|
||
**获取顶点的邻面索引环**
|
||
`[[nodiscard]] std::vector<int> 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<double(double,double,double)>& 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<Point2D> tutte_parameterization(const HalfedgeMesh& mesh)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `mesh` | 输入三角网格(需含边界) |
|
||
|
||
**返回**: 每顶点 UV 坐标(Point2D),顺序与 mesh 顶点一致
|
||
> 网格必须有边界(开网格);闭曲面需先切割为拓扑圆盘
|
||
|
||
**参见**: `lscm_parameterization`
|
||
|
||
|
||
**LSCM(Least Squares Conformal Maps)参数化**
|
||
`[[nodiscard]] std::vector<Point2D> 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<Triangle3D>& tris) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `tris` | 三角形数组 |
|
||
|
||
|
||
**插入单个三角形**
|
||
`void insert(const Triangle3D& tri) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `tri` | 要插入的三角形 |
|
||
|
||
|
||
**删除三角形**
|
||
`bool remove(const Triangle3D& tri) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `tri` | 要删除的三角形 |
|
||
|
||
**返回**: 删除成功返回 true
|
||
|
||
|
||
**AABB 范围查询**
|
||
`std::vector<Triangle3D> query_range(const AABB3D& range) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `range` | 查询包围盒 |
|
||
|
||
**返回**: 与 range 相交的三角形列表
|
||
|
||
|
||
**K 近邻查询**
|
||
`std::vector<Triangle3D> query_knn(const Point3D& point, size_t k) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `point` | 查询点 |
|
||
| `k` | 返回数量 |
|
||
|
||
**返回**: 最近的 k 个三角形
|
||
|
||
|
||
**射线查询:返回所有命中的三角形**
|
||
`std::vector<Triangle3D> 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<HitResult> 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<Triangle3D> 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 <typename T>`
|
||
> k-d 树在维度约 2~6 时效率最佳。三维场景中,
|
||
|
||
**参见**: `SpatialIndex, BVH, Octree`
|
||
|
||
|
||
**批量构建 k-d 树**
|
||
`void build(const std::vector<T>& items) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `items` | 待索引的对象数组 |
|
||
|
||
|
||
**插入单个对象**
|
||
`void insert(const T& item) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `item` | 待插入的空间对象 |
|
||
|
||
|
||
**删除对象**
|
||
`bool remove(const T& item) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `item` | 待删除的空间对象 |
|
||
|
||
**返回**: 删除成功返回 true
|
||
|
||
|
||
**范围查询**
|
||
`std::vector<T> query_range(const AABB3D& range) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `range` | 查询包围盒 |
|
||
|
||
**返回**: 与 range 相交的对象列表
|
||
|
||
|
||
**K 近邻查询**
|
||
`std::vector<T> query_knn(const Point3D& point, size_t k) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `point` | 查询点 |
|
||
| `k` | 返回数量 |
|
||
|
||
**返回**: 最近的 k 个对象
|
||
|
||
|
||
**射线查询**
|
||
`std::vector<T> 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<Node> 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 <typename T>`
|
||
> 适用于体积数据、粒子系统、空间哈希等场景。
|
||
|
||
**参见**: `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<T>& items) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `items` | 待索引的对象数组 |
|
||
|
||
|
||
**增量插入对象**
|
||
`void insert(const T& item) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `item` | 待插入的空间对象 |
|
||
|
||
|
||
**删除对象**
|
||
`bool remove(const T& item) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `item` | 待删除的空间对象 |
|
||
|
||
**返回**: 删除成功返回 true;对象不存在返回 false
|
||
|
||
|
||
**范围查询**
|
||
`std::vector<T> query_range(const AABB3D& range) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `range` | 查询包围盒 |
|
||
|
||
**返回**: 与 range 相交的对象列表
|
||
|
||
|
||
**K 近邻查询**
|
||
`std::vector<T> query_knn(const Point3D& point, size_t k) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `point` | 查询点 |
|
||
| `k` | 返回数量 |
|
||
|
||
**返回**: 最近的 k 个对象
|
||
|
||
|
||
**射线查询**
|
||
`std::vector<T> 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 <typename T>`
|
||
|
||
|
||
**< 节点包围盒(子节点/对象 MBR 的并集)**
|
||
`bool is_leaf = true; /**< 是否为叶节点 */`
|
||
|
||
|
||
**< 是否为叶节点**
|
||
`std::vector<size_t> children; /**< 内部节点:子节点索引列表 */`
|
||
|
||
|
||
**< 内部节点:子节点索引列表**
|
||
`std::vector<size_t> item_indices; /**< 叶节点:对象索引列表 */`
|
||
|
||
|
||
**< 叶节点:对象索引列表**
|
||
`size_t parent = static_cast<size_t>(-1); /**< 父节点索引 */`
|
||
|
||
|
||
**< 父节点索引**
|
||
`}`
|
||
|
||
|
||
**R 树动态空间索引**
|
||
`template <typename T>`
|
||
> R 树在动态场景(如编辑中的几何体)中比 BVH 更合适。
|
||
|
||
**参见**: `SpatialIndex, BVH, RStarTree`
|
||
|
||
|
||
**批量构建 R 树**
|
||
`void build(const std::vector<T>& items) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `items` | 待索引的对象数组 |
|
||
|
||
|
||
**增量插入对象**
|
||
`void insert(const T& item) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `item` | 待插入的空间对象 |
|
||
|
||
|
||
**删除对象**
|
||
`bool remove(const T& item) override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `item` | 待删除的空间对象 |
|
||
|
||
**返回**: 删除成功返回 true
|
||
|
||
|
||
**范围查询**
|
||
`std::vector<T> query_range(const AABB3D& range) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `range` | 查询包围盒 |
|
||
|
||
**返回**: 与 range 相交的对象列表
|
||
|
||
|
||
**K 近邻查询**
|
||
`std::vector<T> query_knn(const Point3D& point, size_t k) const override`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `point` | 查询点 |
|
||
| `k` | 返回数量 |
|
||
|
||
**返回**: 最近的 k 个对象
|
||
|
||
|
||
**射线查询**
|
||
`std::vector<T> 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<AABB3D> item_bounds_; /**< 对象包围盒数组 */`
|
||
|
||
|
||
**< 对象包围盒数组**
|
||
`std::vector<RTreeNode<T>> nodes_; /**< R 树节点数组 */`
|
||
|
||
|
||
**< R 树节点数组**
|
||
`size_t root_idx_ = 0; /**< 根节点索引 */`
|
||
|
||
|
||
**< 根节点索引**
|
||
`size_t count_ = 0; /**< 对象计数 */`
|
||
|
||
|
||
**< 对象计数**
|
||
`}`
|
||
|
||
|
||
|
||
### `spatial_index.h`
|
||
|
||
**空间索引抽象基类**
|
||
|
||
|
||
**空间索引抽象基类**
|
||
`template <typename T>`
|
||
> 本类为纯虚接口,不可直接实例化
|
||
|
||
|
||
**批量构建索引**
|
||
`virtual void build(const std::vector<T>& 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<T> query_range(const AABB3D& range) const = 0`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `range` | 查询的轴对齐包围盒 |
|
||
|
||
**返回**: 与 range 相交的对象列表
|
||
|
||
|
||
**K 近邻查询:返回距 point 最近的 k 个对象**
|
||
`virtual std::vector<T> query_knn(const Point3D& point, size_t k) const = 0`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `point` | 查询点 |
|
||
| `k` | 需要返回的对象数量 |
|
||
|
||
**返回**: 按距离升序排列的 k 个最近对象
|
||
|
||
|
||
**射线查询:返回与射线相交的所有对象**
|
||
`virtual std::vector<T> 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<Polygon2D> 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<Polygon2D> polygon_offset(const Polygon2D& poly, double distance)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `poly` | 原始多边形 |
|
||
| `distance` | 偏移距离(正=外扩,负=内缩) |
|
||
|
||
**返回**: 偏移后的多边形列表(内缩或自交可能产生多个碎片)
|
||
> 使用直骨架近似而非精确圆弧偏移,转角处为斜角连接。
|
||
|
||
**参见**: `boolean_2d`
|
||
|
||
|
||
|
||
## 碰撞检测 (`vde::collision`)
|
||
|
||
|
||
### `gjk.h`
|
||
|
||
**GJK (Gilbert–Johnson–Keerthi) 碰撞检测算法**
|
||
|
||
|
||
**支撑函数类型**
|
||
`using SupportFunc = std::function<Point3D(const Vector3D&)>`
|
||
|
||
|
||
**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<RayTriResult> ray_triangle_intersect(`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `origin` | 射线起点 |
|
||
| `dir` | 射线方向(需归一化以获得正确 t 值) |
|
||
| `tri` | 三角形 |
|
||
|
||
**返回**: 命中返回 RayTriResult;未命中返回空
|
||
|
||
**参见**: `ray_mesh_intersect`
|
||
|
||
|
||
**射线-三角形求交(Ray3Dd 重载)**
|
||
`inline std::optional<RayTriResult> 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<RaySphereResult> ray_sphere_intersect(`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `origin` | 射线起点 |
|
||
| `dir` | 射线方向 |
|
||
| `center` | 球心 |
|
||
| `radius` | 球半径 |
|
||
|
||
**返回**: 命中返回 RaySphereResult(最近交点);未命中返回空
|
||
|
||
**参见**: `ray_sphere_intersect(ray, center, radius)`
|
||
|
||
|
||
**射线-球体求交(Ray3Dd 重载)**
|
||
`inline std::optional<RaySphereResult> ray_sphere_intersect(`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `ray` | 射线 |
|
||
| `center` | 球心 |
|
||
| `radius` | 球半径 |
|
||
|
||
**返回**: 命中返回 RaySphereResult;未命中返回空
|
||
|
||
|
||
**射线-平面求交**
|
||
`std::optional<double> ray_plane_intersect(`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `origin` | 射线起点 |
|
||
| `dir` | 射线方向 |
|
||
| `plane_point` | 平面上一点 |
|
||
| `plane_normal` | 平面法线(需归一化以获得正确 t) |
|
||
|
||
**返回**: 命中返回参数 t;未命中(平行或反向)返回空
|
||
|
||
|
||
**射线-平面求交(Ray3Dd 重载)**
|
||
`inline std::optional<double> ray_plane_intersect(`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `ray` | 射线 |
|
||
| `plane_point` | 平面上一点 |
|
||
| `plane_normal` | 平面法线 |
|
||
|
||
**返回**: 命中返回参数 t;未命中返回空
|
||
|
||
|
||
**射线-网格求交(暴力遍历)**
|
||
`std::optional<RayTriResult> ray_mesh_intersect(`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `origin` | 射线起点 |
|
||
| `dir` | 射线方向 |
|
||
| `triangles` | 三角形列表 |
|
||
|
||
**返回**: 最近命中结果;无命中返回空
|
||
> 对于大型网格建议配合 BVH 使用:
|
||
|
||
**参见**: `ray_tri_intersect.h, query_ray_nearest (BVH)`
|
||
|
||
|
||
**射线-网格求交(Ray3Dd 重载)**
|
||
`inline std::optional<RayTriResult> ray_mesh_intersect(`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `ray` | 射线 |
|
||
| `triangles` | 三角形列表 |
|
||
|
||
**返回**: 最近命中结果;无命中返回空
|
||
|
||
|
||
|
||
### `sat.h`
|
||
|
||
**SAT (Separating Axis Theorem) 碰撞检测**
|
||
|
||
|
||
**SAT 凸多面体相交检测**
|
||
`bool sat_intersect(const std::vector<Point3D>& 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<int>& edges, bool outer = true)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `edges` | 环中边的 ID 序列(顺序连接) |
|
||
| `outer` | true = 外环, false = 内环 |
|
||
|
||
**返回**: 新环的 ID
|
||
|
||
|
||
**添加面**
|
||
`int add_face(int surface_id, const std::vector<int>& loops)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `surface_id` | 关联曲面 ID |
|
||
| `loops` | 环 ID 列表 |
|
||
|
||
**返回**: 新面的 ID
|
||
|
||
|
||
**添加壳**
|
||
`int add_shell(const std::vector<int>& faces, bool closed = true)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `faces` | 面 ID 列表 |
|
||
| `closed` | 是否为封闭壳 |
|
||
|
||
**返回**: 新壳的 ID
|
||
|
||
|
||
**添加体**
|
||
`int add_body(const std::vector<int>& 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<TopoLoop>& 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<int> face_edges(int face_id) const`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `face_id` | 面 ID |
|
||
|
||
**返回**: 边 ID 列表(去重)
|
||
|
||
|
||
**获取边的所有相邻面**
|
||
`[[nodiscard]] std::vector<int> edge_faces(int edge_id) const`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `edge_id` | 边 ID |
|
||
|
||
**返回**: 相邻面 ID 列表
|
||
|
||
|
||
**获取顶点的所有相邻边**
|
||
`[[nodiscard]] std::vector<int> 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<std::string> errors`
|
||
|
||
|
||
**警告信息列表(不影响 valid)**
|
||
`std::vector<std::string> warnings`
|
||
|
||
|
||
**水密性比率:恰好有 2 个相邻面的边的比例(1.0 = 完美水密)**
|
||
`double watertightness = 1.0`
|
||
|
||
|
||
**无自交比率:不与其他面内部相交的面对比例(1.0 = 无自交)**
|
||
`double self_intersection_free = 1.0`
|
||
|
||
|
||
**最短边的长度(用于检测退化边)**
|
||
`double min_edge_length = std::numeric_limits<double>::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<BrepModel>& 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<BrepModel>& bodies)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `filepath` | 输出文件路径(建议扩展名 .igs 或 .iges) |
|
||
| `bodies` | B-Rep 体列表 |
|
||
|
||
**参见**: `export_iges 获取字符串输出`
|
||
|
||
|
||
|
||
### `iges_import.h`
|
||
|
||
**IGES 文件导入(ANSI Y14.26M)**
|
||
|
||
|
||
**IGES 导入错误码**
|
||
`enum class IgesError {`
|
||
|
||
|
||
**从文件导入 IGES**
|
||
`[[nodiscard]] std::vector<BrepModel> import_iges(const std::string& filepath)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `filepath` | .igs 或 .iges 文件路径 |
|
||
|
||
**返回**: B-Rep 体列表
|
||
> IGES 格式较为宽松,不同 CAD 系统的实现差异很大。
|
||
|
||
**参见**: `import_iges_from_string 从字符串导入`, `iges_last_error 获取错误码`
|
||
|
||
|
||
**从字符串导入 IGES(用于测试)**
|
||
`[[nodiscard]] std::vector<BrepModel> 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<curves::NurbsCurve>& 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<BrepModel>& 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<BrepModel>& 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<BrepModel> 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<BrepModel> 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<double(const std::function<double(const Point3D&)>&)>`
|
||
|
||
**参见**: `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<ParamRef> collect_params(SdfNodePtr& root)`
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `root` | SDF 树根节点(可写引用,因为参数将被原地修改) |
|
||
|
||
**返回**: 可变参数引用列表
|
||
|
||
**参见**: `numerical_gradient 计算损失对参数的数值梯度`
|
||
|
||
|
||
**计算标量损失对收集到的参数的数值梯度**
|
||
`[[nodiscard]] std::vector<double> 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<double>& 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 <typename Fn>`
|
||
|
||
|
||
**前序遍历(const 版本)**
|
||
`template <typename Fn>`
|
||
|
||
**参见**: `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<int>& 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<SketchPoint>& 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 返回的缓冲区指针 |
|
||
|