feat(v6.2): Blender addon + .NET/C# bindings + developer docs + plugin system
CI / Build & Test (push) Failing after 33s
CI / Release Build (push) Failing after 35s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled

v6.2.1 — Blender Integration Addon:
- 5 files, 1,732 lines: __init__, operators (9 ops), panels (4 panels)
- preferences, vde_bridge (subprocess CLI bridge)
- Import/Export STEP, primitives, boolean, SDF→Mesh

v6.2.2 — .NET/C# Bindings (VdeSharp):
- 8 files: NativeMethods (50+ P/Invoke), BrepModel, MeshData, SdfEngine, Assembly
- C API extended with 20 new functions (STEP I/O, Boolean, SDF, Assembly)
- vde_capi rebuilt as SHARED library
- Example: import STEP → boolean → export

v6.2.3 — Developer Docs + Plugin System:
- 7 docs: architecture, contributing, API overview, building, testing, plugin-system
- plugin_system.h/.cpp: PluginInterface, PluginManager, dlopen/LoadLibrary
- README.md updated with v6 features
- Syntax-check passed (GCC 10.2.1, -Wall -Wextra -Wpedantic)
This commit is contained in:
茂之钳
2026-07-26 22:24:40 +08:00
parent 66777e0839
commit 5e2812a6f3
27 changed files with 5748 additions and 2 deletions
+106
View File
@@ -0,0 +1,106 @@
# ViewDesignEngine 开发者指南
欢迎来到 ViewDesignEngine (VDE) 开发者文档。本指南面向希望理解 VDE 内部架构、贡献代码或基于 VDE 构建应用的开发者。
## 文档导航
| 文档 | 说明 |
|------|------|
| [架构概览](architecture.md) | 模块依赖关系图、数据流、分层架构设计 |
| [API 总览](api-overview.md) | 公开 API 接口一览、命名空间规范、核心类型 |
| [构建指南](building.md) | 从源码构建、Docker 环境、CMake 选项、依赖管理 |
| [测试指南](testing.md) | 测试框架、编写测试、运行测试、覆盖率 |
| [贡献指南](contributing.md) | 代码规范、提交流程、Code Review、分支策略 |
| [插件系统设计](plugin-system.md) | 插件架构、生命周期、动态加载、清单文件 |
## 快速开始
```bash
# 克隆仓库
git clone ssh://git@localhost:22/hm/ViewDesignEngine.git
cd ViewDesignEngine
# Docker 构建(推荐)
docker run --rm -v $PWD:/ws vde-builder:latest bash -c \
"cd /ws && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j\$(nproc)"
# 本地构建
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
# 运行测试
cd build && ctest --output-on-failure
```
## 项目结构
```
ViewDesignEngine/
├── CMakeLists.txt # 顶层 CMake
├── cmake/ # CMake 模块 (CompilerSettings 等)
├── include/vde/ # 公开头文件
│ ├── foundation/ # 基础数学、I/O、公差
│ ├── core/ # 几何核心、CAM
│ ├── curves/ # 曲线曲面
│ ├── mesh/ # 网格处理
│ ├── spatial/ # 空间索引
│ ├── boolean/ # 布尔运算
│ ├── collision/ # 碰撞检测
│ ├── brep/ # B-Rep 建模
│ ├── sdf/ # SDF 隐式建模
│ ├── sketch/ # 草图约束
│ └── plugin/ # 插件系统 (v6.0+)
├── src/ # 实现文件(按模块分目录)
├── tests/ # 单元测试
├── bench/ # 性能基准
├── examples/ # 示例程序
├── python/ # Python 绑定
└── docs/ # 文档
```
## 关键概念
### 命名空间
所有 VDE 代码位于 `vde::` 命名空间下,按模块分子命名空间:
```cpp
namespace vde::foundation { /* 基础设施 */ }
namespace vde::core { /* 几何核心 */ }
namespace vde::curves { /* 曲线曲面 */ }
namespace vde::mesh { /* 网格处理 */ }
namespace vde::spatial { /* 空间索引 */ }
namespace vde::boolean { /* 布尔运算 */ }
namespace vde::collision { /* 碰撞检测 */ }
namespace vde::brep { /* B-Rep 建模 */ }
namespace vde::sdf { /* SDF 隐式建模 */ }
namespace vde::sketch { /* 草图约束 */ }
namespace vde::plugin { /* 插件系统 */ }
```
### 依赖关系
- **L0 foundation**: 零上游依赖(仅 Eigen
- **L1 core**: 依赖 foundation
- **L2 curves**: 依赖 core
- **L3 mesh**: 依赖 core + brep
- **L4 spatial**: 依赖 core
- **L5 boolean/collision**: 依赖 L1-L4
- **brep**: 依赖 curves + mesh + collision
- **sdf**: 依赖 core + mesh
- **plugin**: 依赖 foundation(独立于其他模块)
### 设计原则
1. **零开销抽象** — 模板与编译期多态,避免不必要的虚函数
2. **数据驱动** — SoA 布局优化缓存命中率
3. **不可变优先** — 几何实体默认不可变,变换返回新实体
4. **RAII 资源管理** — 智能指针管理所有资源
5. **单一依赖** — 仅依赖 Eigen,不引入 Boost
## 相关文档
- [项目开发计划](../00-开发计划.md)
- [系统架构设计](../02-概要设计/01-系统架构设计.md)
- [CHANGELOG](../../CHANGELOG.md)
- [API 参考手册](../API-REFERENCE.md)
+222
View File
@@ -0,0 +1,222 @@
# API 总览
ViewDesignEngine 提供 C++17 头文件 API,所有公开接口位于 `include/vde/` 目录下。
## 模块 API 概览
### foundation — 基础设施 (`vde::foundation`)
```cpp
// 数学类型
#include <vde/foundation/point.h> // Point2D, Point3D, Vector2D, Vector3D
#include <vde/foundation/matrix.h> // Matrix3x3, Matrix4x4, Transform3D
#include <vde/foundation/aabb.h> // AABB2D, AABB3D
// 公差与精确谓词
#include <vde/foundation/tolerance.h> // Tolerance, is_zero(), is_equal()
#include <vde/foundation/exact_predicates.h> // orient2d, orient3d, incircle
// 格式 I/O
#include <vde/foundation/io_obj.h> // load_obj(), export_obj()
#include <vde/foundation/io_stl.h> // load_stl(), export_stl()
#include <vde/foundation/io_ply.h> // load_ply(), export_ply()
#include <vde/foundation/io_gltf.h> // export_gltf(), export_glb()
#include <vde/foundation/io_3mf.h> // load_3mf(), export_3mf()
#include <vde/foundation/industrial_formats.h> // STEP/IGES 导入导出
```
### core — 几何核心 (`vde::core`)
```cpp
#include <vde/core/polygon.h> // Polygon2D, triangulate(), simplify()
#include <vde/core/voronoi.h> // VoronoiDiagram2D
#include <vde/core/convex_hull.h> // convex_hull_2d(), convex_hull_3d()
#include <vde/core/distance.h> // point_to_line(), point_to_triangle()
#include <vde/core/icp.h> // icp_align()
#include <vde/core/cam_toolpath.h> // ToolPath, GCode, CLData
#include <vde/core/cam_strategies.h> // contour_toolpath, pocket_toolpath
#include <vde/core/cam_5axis.h> // 5轴联动: swarf, multi_axis_roughing
#include <vde/core/object_pool.h> // ObjectPool<T> 内存池
```
### curves — 曲线曲面 (`vde::curves`)
```cpp
#include <vde/curves/bezier_curve.h> // BezierCurve
#include <vde/curves/bspline_curve.h> // BSplineCurve
#include <vde/curves/nurbs_curve.h> // NurbsCurve
#include <vde/curves/bezier_surface.h> // BezierSurface
#include <vde/curves/bspline_surface.h> // BSplineSurface
#include <vde/curves/nurbs_surface.h> // NurbsSurface
#include <vde/curves/nurbs_operations.h> // offset, trim, blend, ruled, coons, extrude
#include <vde/curves/tessellation.h> // adaptive_tessellate()
#include <vde/curves/surface_intersection.h> // surface_intersect()
#include <vde/curves/surface_analysis.h> // curvature_analysis()
#include <vde/curves/surface_continuity.h>// G0/G1/G2 continuity check
#include <vde/curves/surface_fairing.h> // surface_fairing()
#include <vde/curves/exact_offset.h> // exact_offset_curve()
#include <vde/curves/surface_extension.h> // extend_surface()
#include <vde/curves/parallel_intersection.h> // parallel_intersect()
```
### mesh — 网格处理 (`vde::mesh`)
```cpp
#include <vde/mesh/halfedge_mesh.h> // HalfedgeMesh
#include <vde/mesh/delaunay_2d.h> // delaunay_2d(), cdt_2d()
#include <vde/mesh/delaunay_3d.h> // delaunay_3d()
#include <vde/mesh/mesh_simplify.h> // qem_simplify()
#include <vde/mesh/mesh_smooth.h> // laplacian_smooth(), hc_smooth(), bilateral_smooth()
#include <vde/mesh/mesh_boolean.h> // mesh_union(), mesh_intersection(), mesh_difference()
#include <vde/mesh/mesh_quality.h> // mesh_quality_report()
#include <vde/mesh/mesh_repair.h> // repair_non_manifold()
#include <vde/mesh/alpha_shapes.h> // alpha_shape()
#include <vde/mesh/mesh_parameterize.h> // parameterize()
#include <vde/mesh/geodesic.h> // geodesic_distance()
#include <vde/mesh/mesh_curvature.h> // curvature()
#include <vde/mesh/marching_cubes.h> // marching_cubes()
#include <vde/mesh/parallel_mc.h> // parallel_marching_cubes()
#include <vde/mesh/mesh_lod.h> // generate_lod()
#include <vde/mesh/reverse_engineering.h> // reverse_engineering pipeline
#include <vde/mesh/point_cloud.h> // PointCloud processing
#include <vde/mesh/fea_mesh.h> // FEA mesh generation
```
### spatial — 空间索引 (`vde::spatial`)
```cpp
#include <vde/spatial/bvh.h> // BVH<Triangle>
#include <vde/spatial/octree.h> // Octree<Point3D>
#include <vde/spatial/kd_tree.h> // KDTree<Point3D>
#include <vde/spatial/r_tree.h> // RTree<AABB3D>
#include <vde/spatial/incremental_bvh.h> // IncrementalBVH
```
### boolean — 布尔运算 (`vde::boolean`)
```cpp
#include <vde/boolean/boolean_2d.h> // clip_polygon(), boolean_2d()
#include <vde/boolean/boolean_mesh.h> // mesh_union(), mesh_difference(), mesh_intersection()
#include <vde/boolean/polygon_offset.h> // offset_polygon()
```
### collision — 碰撞检测 (`vde::collision`)
```cpp
#include <vde/collision/gjk.h> // gjk_distance(), gjk_intersect()
#include <vde/collision/sat.h> // sat_intersect()
#include <vde/collision/ray_intersect.h> // ray_triangle(), ray_aabb(), ray_mesh()
#include <vde/collision/tri_intersect.h> // tri_tri_intersection()
```
### brep — B-Rep 建模 (`vde::brep`)
```cpp
#include <vde/brep/brep.h> // BrepModel, TopoVertex, TopoEdge, TopoFace
#include <vde/brep/modeling.h> // make_box, make_sphere, fillet, chamfer, shell
#include <vde/brep/brep_boolean.h> // brep_union, brep_intersection, brep_difference
#include <vde/brep/brep_validate.h> // validate()
#include <vde/brep/brep_heal.h> // heal()
#include <vde/brep/tolerance.h> // Tolerance settings
#include <vde/brep/trimmed_surface.h> // TrimmedSurface
#include <vde/brep/ssi_boolean.h> // Surface-surface intersection boolean
#include <vde/brep/format_io.h> // STEP/IGES import/export
#include <vde/brep/measure.h> // distance, surface_area, volume, centroid
#include <vde/brep/brep_drawing.h> // Drawing generation
#include <vde/brep/auto_dimensioning.h> // Automatic dimensioning
#include <vde/brep/pmi_mbd.h> // PMI/MBD annotations
#include <vde/brep/gdt.h> // GD&T annotations
#include <vde/brep/euler_op.h> // Euler operators
#include <vde/brep/draft_analysis.h> // Draft angle analysis
#include <vde/brep/feature_recognition.h> // Feature recognition
#include <vde/brep/defeature.h> // Defeaturing
#include <vde/brep/advanced_blend.h> // Advanced blending
#include <vde/brep/ffd_deformation.h> // Free-form deformation
#include <vde/brep/constraint_solver.h> // Assembly constraint solving
#include <vde/brep/direct_modeling.h> // Direct modeling
#include <vde/brep/kinematic_chain.h> // Kinematic chains
#include <vde/brep/motion_simulation.h> // Motion simulation
#include <vde/brep/assembly_lod.h> // Assembly LOD
#include <vde/brep/fastener_library.h> // Fastener library
```
### sdf — 隐式建模 (`vde::sdf`)
```cpp
#include <vde/sdf/sdf_primitives.h> // sphere, box, cylinder, torus, cone, etc.
#include <vde/sdf/sdf_operations.h> // union, intersection, difference, smooth_union
#include <vde/sdf/sdf_tree.h> // SdfNode, evaluate()
#include <vde/sdf/sdf_to_mesh.h> // sdf_to_mesh()
#include <vde/sdf/sdf_gradient.h> // gradient()
#include <vde/sdf/sdf_optimize.h> // fit_to_point_cloud(), optimize()
```
### sketch — 草图约束 (`vde::sketch`)
```cpp
#include <vde/sketch/constraint_solver.h> // ConstraintSolver
```
### plugin — 插件系统 (`vde::plugin`, v6.0+)
```cpp
#include <vde/plugin/plugin_system.h> // PluginInterface, PluginManager, PluginManifest
```
详见 [插件系统设计](plugin-system.md)。
## 核心类型速查
| 类型 | 命名空间 | 说明 |
|------|---------|------|
| `Point2D` / `Point3D` | `vde::core` | 2D/3D 点 |
| `Vector2D` / `Vector3D` | `vde::core` | 2D/3D 向量 |
| `AABB2D` / `AABB3D` | `vde::core` | 轴对齐包围盒 |
| `Matrix3x3` / `Matrix4x4` | `vde::core` | 3x3 / 4x4 变换矩阵 |
| `Triangle` | `vde::core` | 三角形 |
| `HalfedgeMesh` | `vde::mesh` | 半边网格数据结构 |
| `BrepModel` | `vde::brep` | B-Rep 实体模型 |
| `SdfNode` | `vde::sdf` | SDF 场景图节点 |
| `BezierCurve` | `vde::curves` | Bézier 曲线 |
| `NurbsSurface` | `vde::curves` | NURBS 曲面 |
## 使用约定
### 头文件包含
```cpp
// 推荐:只包含需要的头文件
#include <vde/mesh/halfedge_mesh.h>
#include <vde/core/point.h>
// 不推荐:包含聚合头(编译慢)
// #include <vde/vde.h> // 不存在此文件
```
### 命名空间使用
```cpp
// .cpp 文件中可以使用 using
using namespace vde::core;
using namespace vde::mesh;
// .h 文件中禁止 using namespace
// 使用完整限定名或在作用域内声明
namespace vde::my_module {
using vde::core::Point3D;
}
```
### 错误处理
VDE 采用以下错误处理策略:
- **返回值**: 大部分函数返回 `std::optional<T>` 或错误码
- **断言**: 内部不变量使用 `assert()`
- **异常**: 仅在构造函数/资源分配失败时使用(RAII 保证)
- **日志**: 通过 `VDE_LOG_WARNING` / `VDE_LOG_ERROR`
### 线程安全
- 所有 `const` 方法可并发调用
-`const` 方法需要外部同步
- PluginManager 提供内部读写锁
+240
View File
@@ -0,0 +1,240 @@
# 架构概览
## 1. 整体架构
ViewDesignEngine 采用分层架构,从底层数学基础设施到高层领域建模,层层递进。v6.0 引入了插件系统,支持第三方扩展。
```
┌─────────────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
│ │ C++ API │ │ Python绑定│ │ C API │ │ 插件系统 (v6) │ │
│ │ (头文件) │ │(pybind11) │ │ (vde_capi)│ │ PluginManager │ │
│ └─────┬─────┘ └─────┬────┘ └─────┬────┘ └───────┬────────┘ │
│ │ │ │ │ │
├────────┴──────────────┴─────────────┴───────────────┴────────────┤
│ 领域建模层 (Domain) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ B-Rep │ │ SDF │ │ Sketch │ │ CAM │ │
│ │ 实体建模 │ │ 隐式建模 │ │ 草图约束 │ │ 加工策略 │ │
│ └─────┬─────┘ └─────┬────┘ └─────┬────┘ └────────┬─────────┘ │
│ │ │ │ │ │
├────────┴──────────────┴─────────────┴───────────────┴────────────┤
│ 几何处理层 (Geometry) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Curves │ │ Mesh │ │ Boolean │ │ Collision │ │
│ │ 曲线曲面 │ │ 网格处理 │ │ 布尔运算 │ │ 碰撞检测 │ │
│ └─────┬─────┘ └─────┬────┘ └─────┬────┘ └────────┬─────────┘ │
│ │ │ │ │ │
│ └──────────────┴──────┬──────┴───────────────┘ │
│ │ │
├──────────────────────────────┴────────────────────────────────────┤
│ 空间索引层 (Spatial) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ BVH │ │ Octree │ │ KD-Tree │ │ R-Tree │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
├───────────────────────────────────────────────────────────────────┤
│ 基础设施层 (Foundation) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Eigen封装│ │ 公差系统 │ │ I/O │ │ 精确谓词 │ │
│ │ 数学库 │ │Tolerance │ │格式读写 │ │ exact_predicates│ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
```
## 2. 模块依赖图
```
┌─────────────────────┐
│ vde (聚合) │
└──────────┬──────────┘
┌───────────────────┼───────────────────┐
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ vde_capi │ │ vde_brep │ │ vde_plugin │
│ (C 接口) │ │ (B-Rep) │ │ (插件系统) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌──────┼──────────┬──────┼──────────┐ │
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ │
┌──────┐┌──────┐┌──────┐┌──────┐┌─────────┐ │
│vde_ ││vde_ ││vde_ ││vde_ ││vde_ │ │
│sdf ││sketch││mesh ││curves││collision│ │
└──┬───┘└──┬───┘└──┬───┘└──┬───┘└────┬────┘ │
│ │ │ │ │ │
└───────┴───────┼───────┴─────────┘ │
│ │
┌────┴────┐ ┌─────┴──────┐
│vde_core │ │vde_spatial │
└────┬────┘ └─────┬──────┘
│ │
┌────┴──────────────────────────┘
┌────┴──────────┐
│vde_foundation │
└───────┬───────┘
┌─────┴─────┐
│Eigen3 (外部)│
└───────────┘
vde_boolean 依赖: vde_mesh + vde_spatial + vde_core
vde_collision 依赖: vde_core + vde_spatial
vde_gpu (可选): vde_mesh + CUDA::cudart
vde_plugin 依赖: vde_foundation (独立于其他模块)
```
## 3. 数据流
### 3.1 典型几何处理管线
```
输入 (STEP/IGES/OBJ/STL)
┌──────────────┐
│ Format I/O │ foundation::import_step / import_iges / load_obj / load_stl
│ 格式解析 │
└──────┬───────┘
┌──────────────┐
│ 几何核心 │ core::Point3D, core::AABB3D, core::transform
│ 类型系统 │
└──────┬───────┘
├─────────────────────────────────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ 曲线曲面建模 │ │ 网格处理 │
│ curves │ │ mesh │
│ Bezier/NURBS │ │ Delaunay/MC │
└──────┬───────┘ └──────┬───────┘
│ │
├──────────────┬──────────────────────┘
▼ ▼
┌──────────────┐┌──────────────┐
│ 空间索引 ││ 布尔运算 │
│ spatial ││ boolean │
│ BVH/Octree ││ CSG │
└──────┬───────┘└──────┬───────┘
│ │
▼ ▼
┌──────────────┐┌──────────────┐
│ 碰撞检测 ││ B-Rep 建模 │
│ collision ││ brep │
│ GJK/SAT ││ 抽壳/倒圆 │
└──────┬───────┘└──────┬───────┘
│ │
└───────┬───────┘
┌──────────────┐
│ Format I/O │ foundation::export_step / export_gltf / export_stl
│ 格式导出 │
└──────┬───────┘
输出 (STEP/glTF/STL/OBJ)
```
### 3.2 插件系统数据流 (v6.0)
```
┌─────────────────────────────────────────────────────┐
│ PluginManager │
│ │
│ load_plugin_dir("/usr/lib/vde/plugins") │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ 扫描 .so/.dylib/.dll 文件 │ │
│ │ dlopen → dlsym(create_plugin) │ │
│ │ → PluginInterface* │ │
│ └──────────────┬──────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ PluginRegistry (name → Plugin*) │ │
│ │ io_exporters / io_importers │ │
│ │ geometry_filters │ │
│ │ custom_tools │ │
│ └─────────────────────────────────────┘ │
│ │
│ 调用: manager.get_plugin("io.export.gltf") │
│ → PluginInterface::execute(...) │
└─────────────────────────────────────────────────────┘
```
### 3.3 可微分几何管线 (SDF)
```
参数化形状 (SdfNode)
┌──────────────────┐
│ SDF 求值 │ sdf::evaluate(node, point)
│ (CSG 树遍历) │
└────────┬─────────┘
┌──────────────────┐
│ 自动微分 │ sdf::gradient(node, point)
│ (正向/反向模式) │
└────────┬─────────┘
┌──────────────────┐
│ 梯度优化 │ sdf::optimize::fit_to_point_cloud
│ (Adam/SGD) │
└────────┬─────────┘
┌──────────────────┐
│ SDF → Mesh │ sdf::marching_cubes → HalfedgeMesh
│ (Marching Cubes) │
└────────┬─────────┘
┌──────────────────┐
│ 导出 GLB │ foundation::export_gltf_binary
└──────────────────┘
```
## 4. 线程模型
- **单线程默认**: 所有 API 默认线程安全,内部无全局可变状态
- **OpenMP 并行**: 在 B-Rep 布尔、网格处理等热点路径启用 (`VDE_USE_OPENMP=ON`)
- **CUDA 加速**: 独立 GPU 库 `vde_gpu`,不阻塞 CPU 路径
- **插件线程安全**: 插件需自行保证线程安全,PluginManager 提供读写锁
## 5. 内存模型
```
┌─────────────────────────────────────────┐
│ 内存分配策略 │
│ │
│ ┌──────────────┐ ┌─────────────────┐ │
│ │ ObjectPool │ │ std::unique_ptr │ │
│ │ (mesh顶点/面) │ │ (B-Rep 实体) │ │
│ │ 连续内存块 │ │ RAII 所有权 │ │
│ └──────────────┘ └─────────────────┘ │
│ │
│ ┌──────────────┐ ┌─────────────────┐ │
│ │ SoA 布局 │ │ 小对象栈分配 │ │
│ │ (AoS→SoA) │ │ (Point3D/AABB) │ │
│ │ 缓存友好 │ │ 零堆开销 │ │
│ └──────────────┘ └─────────────────┘ │
└─────────────────────────────────────────┘
```
## 6. 版本演进
| 版本 | 关键里程碑 | 日期 |
|------|-----------|------|
| v0.1 - v0.9 | 核心模块建立 | 2026-07-23 |
| v1.0 | 首个稳定版本 | 2026-07-24 |
| v2.0 | B-Rep 完善 + STEP | 2026-07-24 |
| v3.0 - v3.5 | SDF/IGES/装配/CAM | 2026-07-24 |
| v4.x | 工业强化 (GDT/PMI/特征识别) | 计划中 |
| v5.x | 性能优化 + 反向工程 | 计划中 |
| v6.0 | 插件系统 + 开发者生态 | 计划中 |
+292
View File
@@ -0,0 +1,292 @@
# 构建指南
本文档说明如何从源码构建 ViewDesignEngine。
## 目录
1. [环境要求](#1-环境要求)
2. [快速构建](#2-快速构建)
3. [Docker 构建](#3-docker-构建)
4. [CMake 选项](#4-cmake-选项)
5. [依赖管理](#5-依赖管理)
6. [跨平台构建](#6-跨平台构建)
7. [常见问题](#7-常见问题)
---
## 1. 环境要求
| 组件 | 最低版本 | 推荐版本 |
|------|---------|---------|
| C++ 编译器 | GCC 11 / Clang 16 | GCC 13 / Clang 18 |
| CMake | 3.16 | 3.28+ |
| Eigen 3 | 3.3 | 3.4.0 (自动下载) |
| Python (可选) | 3.8 | 3.11+ |
| pybind11 (可选) | 2.10 | 2.12+ |
| CUDA (可选) | 10.0 | 12.0+ |
### 安装编译工具
**Ubuntu/Debian**:
```bash
sudo apt update
sudo apt install build-essential cmake g++-11
```
**CentOS/RHEL 8**:
```bash
sudo yum install gcc-toolset-11 cmake3
scl enable gcc-toolset-11 bash
```
**macOS**:
```bash
brew install cmake gcc@13
```
**Windows (MSYS2)**:
```bash
pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc
```
## 2. 快速构建
```bash
# 克隆仓库
git clone ssh://git@localhost:22/hm/ViewDesignEngine.git
cd ViewDesignEngine
# 创建构建目录
cmake -B build -DCMAKE_BUILD_TYPE=Release
# 构建(使用所有 CPU 核心)
cmake --build build -j$(nproc)
# 运行测试
cd build && ctest --output-on-failure
```
### 构建类型
| 类型 | 说明 |
|------|------|
| `Release` | 优化构建,生产环境使用 |
| `Debug` | 调试符号,无优化 |
| `RelWithDebInfo` | 优化 + 调试符号 |
| `MinSizeRel` | 最小体积 |
```bash
# Debug 构建(包含 Address Sanitizer
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZERS=ON
cmake --build build -j$(nproc)
```
## 3. Docker 构建
推荐使用 Docker 确保构建环境一致。
### 3.1 预构建镜像
```bash
# 拉取或构建镜像
docker build -t vde-builder -f docker/Dockerfile.dev .
# Release 构建
docker run --rm --cpus=4 --memory=8g \
-v $(pwd):/ws vde-builder bash -c \
"cd /ws && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j4"
# 运行测试
docker run --rm --cpus=4 --memory=8g \
-v $(pwd):/ws vde-builder bash -c \
"cd /ws/build && ctest --output-on-failure"
```
### 3.2 资源限制
```bash
# 模拟低配环境(2 核 / 4GB
docker run --rm --cpus=2 --memory=4g --memory-swap=4g \
-v $(pwd):/ws vde-builder bash -c \
"cd /ws && cmake -B build_ci -DCMAKE_BUILD_TYPE=Release && cmake --build build_ci -j2"
```
## 4. CMake 选项
| 选项 | 默认值 | 说明 |
|------|--------|------|
| `BUILD_TESTS` | ON | 构建测试 |
| `BUILD_BENCHMARKS` | OFF | 构建性能基准 |
| `BUILD_EXAMPLES` | ON | 构建示例程序 |
| `ENABLE_SANITIZERS` | OFF | 启用 Address Sanitizer |
| `VDE_USE_GMP` | OFF | GMP 精确运算 |
| `VDE_USE_OPENMP` | ON | OpenMP 并行 |
| `VDE_USE_CUDA` | OFF | CUDA GPU 加速 |
| `VDE_BUILD_PYTHON` | OFF | Python 绑定 |
### 常用组合
```bash
# 开发调试(ASan + Debug
cmake -B build_asan \
-DCMAKE_BUILD_TYPE=Debug \
-DENABLE_SANITIZERS=ON \
-DVDE_USE_OPENMP=OFF
# 生产构建(Release + OpenMP
cmake -B build_release \
-DCMAKE_BUILD_TYPE=Release \
-DVDE_USE_OPENMP=ON
# GPU 加速
cmake -B build_gpu \
-DCMAKE_BUILD_TYPE=Release \
-DVDE_USE_CUDA=ON
# Python 绑定
cmake -B build_py \
-DCMAKE_BUILD_TYPE=Release \
-DVDE_BUILD_PYTHON=ON
# 基准测试
cmake -B build_bench \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_BENCHMARKS=ON
```
## 5. 依赖管理
VDE 使用 CMake FetchContent 自动下载依赖,无需手动安装。
### 自动下载的依赖
| 依赖 | 版本 | 用途 |
|------|------|------|
| Eigen 3 | 3.4.0 | 线性代数 |
| Google Test | 1.14.0 | 单元测试 |
| Google Benchmark | (可选) | 性能基准 |
| pybind11 | (可选) | Python 绑定 |
### 系统依赖
| 依赖 | 检测方式 | 回退 |
|------|---------|------|
| Eigen 3 | `find_package(Eigen3)` | FetchContent 自动下载 |
| GMP | `find_package(GMP)` | `VDE_USE_GMP=OFF` 时跳过 |
| OpenMP | `find_package(OpenMP)` | `VDE_USE_OPENMP=OFF` 时跳过 |
| CUDA | `find_package(CUDAToolkit)` | `VDE_USE_CUDA=OFF` 时跳过 |
```bash
# 使用系统 Eigen(加速首次构建)
sudo apt install libeigen3-dev # Ubuntu
sudo yum install eigen3-devel # CentOS
# 使用系统 GTest
sudo apt install libgtest-dev # Ubuntu
```
## 6. 跨平台构建
### Linux
```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
```
### macOS
```bash
# 使用 Homebrew GCC
export CC=/usr/local/bin/gcc-13
export CXX=/usr/local/bin/g++-13
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(sysctl -n hw.ncpu)
```
### Windows (MSYS2 MinGW64)
```bash
cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
```
### Windows (Visual Studio)
```bash
cmake -B build -G "Visual Studio 17 2022"
cmake --build build --config Release
```
## 7. 常见问题
### Q: CMake 找不到编译器
```bash
export CC=/usr/bin/gcc-11
export CXX=/usr/bin/g++-11
cmake -B build ...
```
### Q: FetchContent 下载失败(网络问题)
手动下载并放到 `build/_deps/`
```bash
mkdir -p build/_deps
# 下载 eigen-3.4.0.tar.gz 到 build/_deps/
# 下载 googletest-1.14.0.tar.gz 到 build/_deps/
```
### Q: 编译内存不足
```bash
# 限制并行数
cmake --build build -j2
# 或在 Docker 中限制内存
docker run --memory=4g ...
```
### Q: ASan 报告内存泄漏
```bash
# Debug + ASan 构建
cmake -B build_asan -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZERS=ON
cmake --build build_asan -j$(nproc)
# 运行测试并检查泄漏
cd build_asan
ASAN_OPTIONS=detect_leaks=1 ctest --output-on-failure
```
### Q: 如何加速增量构建
```bash
# 安装 ccache
sudo apt install ccache
export CMAKE_C_COMPILER_LAUNCHER=ccache
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake -B build ...
```
### Q: 构建产物位置
```
build/
├── src/ # 静态库 (.a)
│ ├── libvde_foundation.a
│ ├── libvde_core.a
│ ├── libvde_curves.a
│ ├── libvde_mesh.a
│ ├── libvde_spatial.a
│ ├── libvde_boolean.a
│ ├── libvde_collision.a
│ ├── libvde_brep.a
│ ├── libvde_sdf.a
│ ├── libvde_sketch.a
│ └── libvde_capi.a
├── tests/ # 测试可执行文件
├── bench/ # 基准测试 (BUILD_BENCHMARKS=ON)
├── examples/ # 示例程序
└── python/ # Python 绑定 (VDE_BUILD_PYTHON=ON)
```
+249
View File
@@ -0,0 +1,249 @@
# 贡献指南
感谢你对 ViewDesignEngine 的关注!本文档说明如何参与 VDE 开发。
## 目录
1. [行为准则](#1-行为准则)
2. [如何贡献](#2-如何贡献)
3. [开发环境搭建](#3-开发环境搭建)
4. [代码规范](#4-代码规范)
5. [提交规范](#5-提交规范)
6. [Code Review 流程](#6-code-review-流程)
7. [测试要求](#7-测试要求)
8. [文档要求](#8-文档要求)
---
## 1. 行为准则
- 尊重所有贡献者,建设性沟通
- 关注代码质量而非个人
- 接受建设性批评,乐于改进
- 帮助新人融入项目
## 2. 如何贡献
| 贡献方式 | 说明 |
|---------|------|
| Bug 报告 | 通过 Issue 提交,附重现步骤 |
| 功能请求 | 先开 Issue 讨论,获得认同后再实现 |
| 代码贡献 | Fork → Branch → PR → Review → Merge |
| 文档改进 | 直接提 PR 修正文档错误 |
| 测试补充 | 新增测试用例,提高覆盖率 |
| 插件开发 | 按 [插件系统设计](plugin-system.md) 开发第三方插件 |
### 贡献流程
```bash
# 1. 创建分支
git checkout -b feat/my-feature
# 2. 开发(遵循代码规范)
# ... 编写代码 + 测试 ...
# 3. 本地验证
cmake -B build -DBUILD_TESTS=ON
cmake --build build -j$(nproc)
cd build && ctest --output-on-failure
# 4. 提交
git add -A
git commit -m "feat(module): description"
# 5. 推送并创建 PR
git push origin feat/my-feature
```
## 3. 开发环境搭建
### 前提条件
- **编译器**: GCC 11+ / Clang 16+
- **CMake**: ≥ 3.16
- **Eigen 3**: 自动下载(FetchContent
- **Google Test**: 自动下载(FetchContent
### Docker 环境(推荐)
```bash
# 构建 Docker 镜像
docker build -t vde-builder -f docker/Dockerfile.dev .
# 运行开发容器
docker run -it --rm -v $PWD:/ws vde-builder bash
cd /ws
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j$(nproc)
```
### 本地环境
```bash
# Ubuntu/Debian
sudo apt install build-essential cmake g++-11
# CentOS/RHEL
sudo yum install gcc-toolset-11 cmake3
# 构建
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j$(nproc)
```
## 4. 代码规范
### 命名规范
| 元素 | 规范 | 示例 |
|------|------|------|
| 命名空间 | 小写,`vde::` 前缀 | `vde::brep`, `vde::mesh` |
| 类/结构体 | PascalCase | `HalfedgeMesh`, `BrepModel` |
| 函数/方法 | snake_case | `add_vertex()`, `to_mesh()` |
| 成员变量 | snake_case,尾部 `_` | `vertices_`, `tolerance_` |
| 常量 | kPascalCase 或 UPPER_SNAKE | `kDefaultTolerance`, `VDE_PI` |
| 头文件 | snake_case.h | `halfedge_mesh.h` |
| 源文件 | snake_case.cpp | `halfedge_mesh.cpp` |
| 模板参数 | PascalCase | `typename T`, `typename Scalar` |
### 文件组织
```cpp
// 头文件示例
#pragma once
#include <vde/foundation/point.h> // 公开依赖
#include <vector> // 标准库
namespace vde::mesh {
/// 简要描述
class HalfedgeMesh {
public:
// 构造/析构
HalfedgeMesh();
~HalfedgeMesh();
// 禁止拷贝,允许移动
HalfedgeMesh(const HalfedgeMesh&) = delete;
HalfedgeMesh& operator=(const HalfedgeMesh&) = delete;
HalfedgeMesh(HalfedgeMesh&&) noexcept = default;
HalfedgeMesh& operator=(HalfedgeMesh&&) noexcept = default;
// 公开接口
int add_vertex(const Point3D& p);
int add_face(const std::vector<int>& vertex_ids);
private:
// 成员变量
std::vector<Point3D> vertices_;
};
} // namespace vde::mesh
```
### 编码风格
- 缩进: 4 空格,不用 Tab
- 行宽: 100 字符
- 大括号: K&R 风格(开括号不换行)
- 注释: Doxygen `///` 风格
- `#include` 顺序: 本模块头 → 项目头 → 标准库
- 避免 `using namespace` 在头文件中
- 优先使用 `std::unique_ptr` 而非裸指针
### 禁止事项
- ❌ 全局可变状态
- ❌ 裸 `new`/`delete`(用智能指针)
- ❌ C 风格类型转换(用 `static_cast` 等)
- ❌ 可变参数 `...`
- ❌ 异常规范声明(`throw()`
- ❌ 头文件 `using namespace`
## 5. 提交规范
### 提交消息格式
```
<type>(<scope>): <subject>
<body>
<footer>
```
| type | 说明 |
|------|------|
| `feat` | 新功能 |
| `fix` | Bug 修复 |
| `docs` | 文档变更 |
| `style` | 格式调整(不影响逻辑) |
| `refactor` | 重构 |
| `test` | 测试相关 |
| `perf` | 性能优化 |
| `chore` | 构建/工具 |
示例:
```
feat(brep): add variable radius fillet support
Implement rolling-ball variable radius fillet along edges.
Supports linear and cubic radius variation.
Closes #42
```
### 分支策略
- `main` — 稳定分支,只接受 PR
- `feat/xxx` — 功能分支
- `fix/xxx` — 修复分支
- `docs/xxx` — 文档分支
- `release/vX.Y` — 发布分支
## 6. Code Review 流程
1. **提交者**: 创建 PR,填写描述,关联 Issue
2. **CI 检查**: 自动编译 + 测试必须通过
3. **Reviewer**: 检查代码逻辑、风格、测试覆盖
4. **迭代**: 根据反馈修改,`git commit --amend` + force push
5. **合并**: Reviewer 批准后 squash merge
### Review 检查项
- [ ] 代码逻辑正确,无边界 bug
- [ ] 命名清晰,符合规范
- [ ] 公开 API 有 Doxygen 文档
- [ ] 有对应的单元测试
- [ ] 无编译警告(`-Wall -Wextra`
- [ ] 无内存泄漏(ASan 通过)
- [ ] 性能不退化(benchmark 对比)
## 7. 测试要求
| 要求 | 说明 |
|------|------|
| 新功能 | 必须包含测试 |
| Bug 修复 | 必须包含回归测试 |
| 测试框架 | Google Test |
| 覆盖率目标 | ≥ 80% 行覆盖 |
| Sanitizer | 关键路径需通过 ASan/UBSan |
测试文件位置: `tests/<module>/test_<feature>.cpp`
详见 [测试指南](testing.md)。
## 8. 文档要求
| 变更类型 | 文档要求 |
|---------|---------|
| 新模块 | architecture.md 更新 + API 文档 + 教程 |
| 新公开 API | Doxygen 注释 + API-REFERENCE 更新 |
| 行为变更 | CHANGELOG 更新 |
| 构建变更 | building.md 更新 |
## 联系方式
- Issue Tracker: Gitea Issues
- 代码仓库: `ssh://git@localhost:22/hm/ViewDesignEngine.git`
+501
View File
@@ -0,0 +1,501 @@
# 插件系统设计
v6.0 引入插件系统,允许第三方开发者扩展 ViewDesignEngine 的功能,无需修改核心代码。
## 目录
1. [设计目标](#1-设计目标)
2. [架构概览](#2-架构概览)
3. [核心组件](#3-核心组件)
4. [插件开发](#4-插件开发)
5. [插件加载流程](#5-插件加载流程)
6. [生命周期管理](#6-生命周期管理)
7. [清单文件](#7-清单文件)
8. [安全考虑](#8-安全考虑)
9. [最佳实践](#9-最佳实践)
---
## 1. 设计目标
| 目标 | 说明 |
|------|------|
| **零侵入** | 插件不修改核心代码,独立编译 |
| **动态加载** | 运行时 dlopen 加载,无需重新编译 VDE |
| **版本兼容** | Manifest 声明版本约束,自动检查兼容性 |
| **隔离性** | 插件崩溃不影响主程序 |
| **易开发** | 继承 `PluginInterface` 即可,最少样板代码 |
## 2. 架构概览
```
┌─────────────────────────────────────────────────────────────┐
│ Application │
│ │ │
│ PluginManager │
│ ┌──────┴──────┐ │
│ │ Registry │ │
│ │ name→Plugin* │ │
│ └──────┬──────┘ │
│ ┌───────────────┼───────────────┐ │
│ │ │ │ │
│ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │
│ │Plugin A │ │Plugin B │ │Plugin C │ │
│ │(.so) │ │(.so) │ │(.so) │ │
│ │IO Format│ │Geometry │ │ Custom │ │
│ │Exporter │ │Filter │ │ Tool │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ Plugin Directory: /usr/lib/vde/plugins/ │
│ ./vde_plugins/ │
│ $VDE_PLUGIN_PATH │
└─────────────────────────────────────────────────────────────┘
```
## 3. 核心组件
### 3.1 PluginInterface(抽象基类)
所有插件必须实现的接口:
```cpp
namespace vde::plugin {
class PluginInterface {
public:
virtual ~PluginInterface() = default;
/// 插件初始化(加载后调用一次)
virtual bool initialize() = 0;
/// 插件清理(卸载前调用一次)
virtual void shutdown() = 0;
/// 返回插件清单
virtual const PluginManifest& manifest() const = 0;
/// 插件唯一名称(如 "io.export.usdz"
virtual const char* name() const = 0;
/// 插件版本(语义化版本)
virtual const char* version() const = 0;
/// 执行插件功能
virtual bool execute(const std::string& action,
const std::map<std::string, std::string>& params,
void* input, void* output) = 0;
};
} // namespace vde::plugin
```
### 3.2 PluginManifest(插件元数据)
```cpp
namespace vde::plugin {
struct PluginManifest {
std::string name; ///< 唯一标识符,如 "io.export.usdz"
std::string version; ///< 语义化版本 "1.0.0"
std::string author; ///< 作者信息
std::string description; ///< 功能描述
std::string license; ///< 许可证 "MIT" / "Apache-2.0"
std::string vde_version_min;///< 最低 VDE 版本 "6.0.0"
std::string vde_version_max;///< 最高兼容 VDE 版本 (空=无上限)
/// 插件类型
enum class Type {
IO_IMPORT, ///< 格式导入器
IO_EXPORT, ///< 格式导出器
GEOMETRY_FILTER,///< 几何过滤器
CUSTOM_TOOL, ///< 自定义工具
OTHER
};
Type type = Type::OTHER;
/// 依赖的其他插件名称(可选)
std::vector<std::string> dependencies;
/// 从 JSON 文件加载
static std::optional<PluginManifest> from_file(const std::string& path);
};
} // namespace vde::plugin
```
### 3.3 PluginManager(插件管理器)
```cpp
namespace vde::plugin {
class PluginManager {
public:
PluginManager();
~PluginManager();
// 禁止拷贝
PluginManager(const PluginManager&) = delete;
PluginManager& operator=(const PluginManager&) = delete;
/// 从目录加载所有插件
int load_plugin_dir(const std::string& dir_path);
/// 加载单个插件(路径到 .so/.dylib/.dll
bool load_plugin(const std::string& plugin_path);
/// 卸载指定插件
bool unload_plugin(const std::string& name);
/// 卸载所有插件
void unload_all();
/// 获取已加载的插件
PluginInterface* get_plugin(const std::string& name);
/// 列出所有已加载插件
std::vector<std::string> list_plugins() const;
/// 检查插件是否已加载
bool is_loaded(const std::string& name) const;
/// 获取加载错误信息
std::string last_error() const;
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace vde::plugin
```
### 3.4 注册/加载函数
每个插件动态库必须导出以下 C 链接符号:
```cpp
// 创建插件实例(必须导出)
extern "C" VDE_PLUGIN_EXPORT vde::plugin::PluginInterface* create_plugin();
// 销毁插件实例(必须导出)
extern "C" VDE_PLUGIN_EXPORT void destroy_plugin(vde::plugin::PluginInterface* plugin);
// 获取插件清单(可选,优化加载速度)
extern "C" VDE_PLUGIN_EXPORT const vde::plugin::PluginManifest* get_manifest();
```
## 4. 插件开发
### 4.1 最小插件示例
```cpp
// my_exporter.cpp
#include <vde/plugin/plugin_system.h>
#include <iostream>
using namespace vde::plugin;
class MyExporter : public PluginInterface {
public:
bool initialize() override {
manifest_.name = "io.export.myformat";
manifest_.version = "1.0.0";
manifest_.author = "Your Name";
manifest_.description = "Export to MyFormat";
manifest_.type = PluginManifest::Type::IO_EXPORT;
manifest_.vde_version_min = "6.0.0";
return true;
}
void shutdown() override {
// 清理资源
}
const PluginManifest& manifest() const override {
return manifest_;
}
const char* name() const override {
return manifest_.name.c_str();
}
const char* version() const override {
return manifest_.version.c_str();
}
bool execute(const std::string& action,
const std::map<std::string, std::string>& params,
void* input, void* output) override {
if (action == "export") {
// 执行导出逻辑
return true;
}
return false;
}
private:
PluginManifest manifest_;
};
// 必需的导出符号
extern "C" VDE_PLUGIN_EXPORT PluginInterface* create_plugin() {
return new MyExporter();
}
extern "C" VDE_PLUGIN_EXPORT void destroy_plugin(PluginInterface* plugin) {
delete plugin;
}
```
### 4.2 CMake 构建
```cmake
# CMakeLists.txt for plugin
cmake_minimum_required(VERSION 3.16)
project(my_exporter VERSION 1.0.0)
find_package(ViewDesignEngine REQUIRED)
add_library(my_exporter SHARED my_exporter.cpp)
target_link_libraries(my_exporter PRIVATE vde::engine)
target_include_directories(my_exporter PRIVATE ${VDE_INCLUDE_DIRS})
# 设置输出到插件目录
set_target_properties(my_exporter PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
)
```
### 4.3 插件类型
| 类型 | 枚举值 | 说明 | 示例 |
|------|--------|------|------|
| 格式导入器 | `IO_IMPORT` | 新增文件格式导入 | USDZ, 3DS, AMF |
| 格式导出器 | `IO_EXPORT` | 新增文件格式导出 | USDZ, FBX, X3D |
| 几何过滤器 | `GEOMETRY_FILTER` | 几何后处理 | 平滑、简化、重网格 |
| 自定义工具 | `CUSTOM_TOOL` | 领域特定工具 | 应力分析、拓扑优化 |
## 5. 插件加载流程
```
Application::init()
PluginManager::load_plugin_dir("/usr/lib/vde/plugins")
├── 扫描目录: for each *.so / *.dylib / *.dll
├── dlopen(plugin_path, RTLD_NOW)
│ │
│ ├── 成功 → 继续
│ └── 失败 → 记录错误,跳过
├── dlsym(handle, "get_manifest")
│ │
│ ├── 找到 → 读取 manifest,检查版本兼容性
│ └── 未找到 → 继续加载(稍后从 initialize 获取)
├── dlsym(handle, "create_plugin")
│ │
│ ├── 找到 → PluginInterface* plugin = create_plugin()
│ └── 未找到 → dlclose,跳过
├── plugin->initialize()
│ │
│ ├── 返回 true → 注册到 Registry
│ └── 返回 false → destroy_plugin + dlclose
└── 返回加载成功数量
```
### 版本兼容性检查
```cpp
// 伪代码
bool is_compatible(const PluginManifest& m, const std::string& vde_version) {
// 检查最小版本
if (compare_versions(vde_version, m.vde_version_min) < 0)
return false;
// 检查最大版本(如果指定)
if (!m.vde_version_max.empty() &&
compare_versions(vde_version, m.vde_version_max) > 0)
return false;
return true;
}
```
## 6. 生命周期管理
```
┌──────────────────────────────────────────────────────────────┐
│ 插件生命周期 │
│ │
│ [编译] → [发现] → [加载] → [初始化] → [运行] → [卸载] │
│ │
│ 编译: 开发者编写代码,构建为 .so/.dylib/.dll │
│ 发现: PluginManager 扫描插件目录 │
│ 加载: dlopen 加载动态库 │
│ 初始化: initialize() 注册功能 │
│ 运行: execute() 被调用 │
│ 卸载: shutdown() + dlclose │
│ │
│ 状态机: │
│ UNLOADED → LOADING → INITIALIZED → RUNNING │
│ ↑ ↓ ↓ │
│ └── ERROR SHUTTING_DOWN → UNLOADED│
└──────────────────────────────────────────────────────────────┘
```
### 状态说明
| 状态 | 说明 |
|------|------|
| `UNLOADED` | 插件未加载或已卸载 |
| `LOADING` | dlopen 成功,正在初始化 |
| `INITIALIZED` | initialize() 完成,等待 execute |
| `RUNNING` | execute() 正在执行中 |
| `SHUTTING_DOWN` | shutdown() 执行中 |
| `ERROR` | 加载或初始化失败 |
## 7. 清单文件
插件可以在同目录放置 `plugin.json` 描述文件,加快发现速度:
```json
{
"name": "io.export.usdz",
"version": "1.0.0",
"author": "Your Name <email@example.com>",
"description": "Export geometry to USDZ format for Apple AR",
"license": "MIT",
"type": "IO_EXPORT",
"vde_version_min": "6.0.0",
"vde_version_max": "",
"dependencies": [],
"library": "libvde_usdz_export.so",
"entry_points": {
"create": "create_plugin",
"destroy": "destroy_plugin"
}
}
```
### PluginManager 加载优先级
1. 如果存在 `plugin.json` → 先读取 JSON 验证兼容性
2. 兼容 → `dlopen` + `dlsym(create_plugin)`
3. 不兼容 → 跳过,记录日志
4.`plugin.json` → 直接 `dlopen` + 尝试 `get_manifest` 符号
## 8. 安全考虑
### 8.1 隔离性
| 措施 | 说明 |
|------|------|
| 独立 .so | 每个插件独立动态库 |
| 崩溃隔离 | 插件 SIGSEGV 不传播到主程序(信号处理器) |
| 符号可见性 | 插件使用 `-fvisibility=hidden` 隐藏内部符号 |
| 内存隔离 | 插件通过 PluginInterface 与主程序交互,不直接访问内部数据 |
### 8.2 信任模型
```
┌───────────────────────────────────────┐
│ 插件信任级别 │
│ │
│ L0 内置: VDE 官方维护,完全信任 │
│ L1 签名: 第三方已签名,受信任 │
│ L2 社区: 社区插件,有限沙箱 │
│ L3 未知: 未签名/未知来源,严格沙箱 │
│ │
│ L3 限制: │
│ - 不能访问文件系统(除了输出目录) │
│ - 不能调用网络 │
│ - 不能 fork │
│ - CPU/内存限制 │
└───────────────────────────────────────┘
```
### 8.3 最佳安全实践
1. **始终验证 manifest 版本兼容性**后再 initialize
2. **dlopen 使用 `RTLD_NOW | RTLD_LOCAL`** 而非 `RTLD_LAZY | RTLD_GLOBAL`
3. **设置超时**execute() 调用应有超时机制
4. **资源限制**:通过 cgroups/Docker 限制插件资源
5. **日志审计**:记录所有插件加载/卸载/执行事件
## 9. 最佳实践
### 9.1 插件开发建议
- ✅ 插件尽量无状态,每次 execute 独立
- ✅ 用 manifest 声明清晰的功能范围
- ✅ 支持版本协商(`vde_version_min` / `vde_version_max`
- ✅ 提供详细的错误信息(通过返回值 + 日志)
- ✅ 清理所有资源在 shutdown() 中
- ❌ 不要在 initialize() 中做耗时操作
- ❌ 不要依赖全局可变状态
- ❌ 不要修改 VDE 核心数据结构
### 9.2 插件命名规范
```
格式: <category>.<subcategory>.<name>
示例:
- io.import.fbx # FBX 格式导入
- io.export.usdz # USDZ 格式导出
- geometry.smooth.laplacian # Laplacian 平滑
- tool.analysis.stress # 应力分析工具
```
### 9.3 使用示例
```cpp
#include <vde/plugin/plugin_system.h>
int main() {
vde::plugin::PluginManager mgr;
// 加载所有插件
int count = mgr.load_plugin_dir("/usr/lib/vde/plugins");
std::cout << "Loaded " << count << " plugins\n";
// 列出已加载插件
for (auto& name : mgr.list_plugins()) {
std::cout << " - " << name << "\n";
}
// 使用特定插件
auto* exporter = mgr.get_plugin("io.export.gltf");
if (exporter) {
std::map<std::string, std::string> params;
params["path"] = "output.glb";
params["binary"] = "true";
void* mesh_data = /* ... */;
bool ok = exporter->execute("export", params, mesh_data, nullptr);
}
// 卸载
mgr.unload_all();
return 0;
}
```
---
## 附录: 平台差异
| 操作 | Linux | macOS | Windows |
|------|-------|-------|---------|
| 动态库后缀 | `.so` | `.dylib` | `.dll` |
| 加载函数 | `dlopen` | `dlopen` | `LoadLibraryA` |
| 符号解析 | `dlsym` | `dlsym` | `GetProcAddress` |
| 卸载函数 | `dlclose` | `dlclose` | `FreeLibrary` |
| 错误信息 | `dlerror()` | `dlerror()` | `GetLastError()` |
| 链接库 | `-ldl` | (内置) | `kernel32.lib` |
| 可见性宏 | `__attribute__((visibility("default")))` | 同 Linux | `__declspec(dllexport)` |
+361
View File
@@ -0,0 +1,361 @@
# 测试指南
ViewDesignEngine 使用 Google Test 框架,通过 CTest 运行测试。
## 目录
1. [测试架构](#1-测试架构)
2. [运行测试](#2-运行测试)
3. [编写测试](#3-编写测试)
4. [测试规范](#4-测试规范)
5. [Sanitizer 测试](#5-sanitizer-测试)
6. [性能基准](#6-性能基准)
7. [模糊测试](#7-模糊测试)
8. [CI 集成](#8-ci-集成)
---
## 1. 测试架构
```
tests/
├── CMakeLists.txt # 顶层测试 CMake
├── foundation/ # 基础设施测试
│ ├── CMakeLists.txt
│ └── test_io_obj.cpp
├── core/ # 核心模块测试
│ ├── CMakeLists.txt
│ ├── test_polygon.cpp
│ ├── test_distance.cpp
│ └── test_cam_5axis.cpp
├── curves/ # 曲线曲面测试
├── mesh/ # 网格处理测试
│ ├── CMakeLists.txt
│ ├── test_fea_mesh.cpp
│ ├── test_reverse_engineering.cpp
│ └── test_xxx.cpp
├── spatial/ # 空间索引测试
├── boolean/ # 布尔运算测试
├── collision/ # 碰撞检测测试
├── brep/ # B-Rep 测试
├── sdf/ # SDF 测试
├── sketch/ # 草图约束测试
├── gpu/ # GPU 测试
└── fuzz/ # 模糊测试
```
### 测试数量
| 模块 | 测试数 | 状态 |
|------|--------|------|
| foundation | ~30 | ✅ |
| core | ~40 | ✅ |
| curves | ~50 | ✅ |
| mesh | ~60 | ✅ |
| spatial | ~30 | ✅ |
| boolean | ~40 | ✅ |
| collision | ~30 | ✅ |
| brep | ~70 | ✅ |
| sdf | 189 | ✅ |
| sketch | ~10 | ✅ |
| gpu | ~5 | ✅ |
| **合计** | **~500+** | ✅ |
## 2. 运行测试
### 基础命令
```bash
# 构建并运行所有测试
cmake -B build -DBUILD_TESTS=ON
cmake --build build -j$(nproc)
cd build && ctest --output-on-failure
# 并行运行
ctest -j$(nproc) --output-on-failure
# 详细输出
ctest -V
# 运行特定测试
ctest -R test_brep # 名称匹配
ctest -R "test_brep|test_sdf" # 多个模式
# 排除特定测试
ctest -E test_fuzz
```
### 直接运行可执行文件
```bash
# 运行单个测试文件
./build/tests/brep/test_brep
# 运行特定测试用例
./build/tests/brep/test_brep --gtest_filter="*Box*"
# 列出所有测试用例
./build/tests/brep/test_brep --gtest_list_tests
# 重复运行(检测不稳定性)
./build/tests/mesh/test_fea_mesh --gtest_repeat=100
```
### Docker 中运行
```bash
docker run --rm --cpus=4 --memory=8g \
-v $(pwd):/ws vde-builder bash -c \
"cd /ws/build && ctest -j4 --output-on-failure"
```
## 3. 编写测试
### 3.1 基本模板
```cpp
// tests/mesh/test_my_feature.cpp
#include <gtest/gtest.h>
#include <vde/mesh/halfedge_mesh.h>
#include <vde/core/point.h>
using namespace vde::core;
using namespace vde::mesh;
// 基本断言
TEST(MyFeatureTest, CreateEmptyMesh) {
HalfedgeMesh mesh;
EXPECT_EQ(mesh.vertex_count(), 0);
EXPECT_EQ(mesh.face_count(), 0);
}
// 带 fixture 的测试
class MyFeatureFixture : public ::testing::Test {
protected:
void SetUp() override {
mesh.add_vertex(Point3D(0, 0, 0));
mesh.add_vertex(Point3D(1, 0, 0));
mesh.add_vertex(Point3D(0, 1, 0));
mesh.add_face({0, 1, 2});
}
HalfedgeMesh mesh;
};
TEST_F(MyFeatureFixture, FaceCount) {
EXPECT_EQ(mesh.face_count(), 1);
}
TEST_F(MyFeatureFixture, VertexPositions) {
EXPECT_NEAR(mesh.vertex(0).x, 0.0, 1e-6);
EXPECT_NEAR(mesh.vertex(1).x, 1.0, 1e-6);
}
```
### 3.2 参数化测试
```cpp
// 使用不同参数重复测试
class BooleanOpTest : public ::testing::TestWithParam<
std::tuple<std::string, int, int>> {};
TEST_P(BooleanOpTest, ConsistentResult) {
auto [op_name, n1, n2] = GetParam();
// ... test logic using parameters ...
}
INSTANTIATE_TEST_SUITE_P(
MeshBoolean,
BooleanOpTest,
::testing::Values(
std::make_tuple("union", 100, 50),
std::make_tuple("intersection", 200, 100),
std::make_tuple("difference", 300, 150)
));
```
### 3.3 注册到 CMake
```cmake
# tests/mesh/CMakeLists.txt
add_executable(test_my_feature test_my_feature.cpp)
target_link_libraries(test_my_feature
PRIVATE vde_mesh vde_core
PRIVATE GTest::gtest GTest::gtest_main
)
add_test(NAME test_my_feature COMMAND test_my_feature)
```
## 4. 测试规范
### 命名规范
```
测试文件名: test_<feature>.cpp
测试套件名: <Feature>Test 或 <Module>Test
测试用例名: <Action><Condition> 或 <MethodName><Scenario>
示例:
- TEST(BrepValidateTest, ClosedShellPassesValidation)
- TEST(MeshSimplifyTest, SimplifyingCubeReducesFaceCount)
```
### 断言选择
| 场景 | 推荐断言 |
|------|---------|
| 相等比较 | `EXPECT_EQ(a, b)` |
| 浮点比较 | `EXPECT_NEAR(a, b, tolerance)` |
| 布尔检查 | `EXPECT_TRUE(condition)` |
| 非致命错误 | `EXPECT_*` 继续执行 |
| 致命错误 | `ASSERT_*` 立即终止 |
| 异常检查 | `EXPECT_THROW(expr, exception_type)` |
### 测试清单
每个功能模块的测试应覆盖:
- [ ] **正常路径** (Happy Path)
- [ ] **边界条件** (空输入、极值、零值)
- [ ] **错误处理** (无效输入、超范围)
- [ ] **退化情况** (共线/共面点、零面积面)
- [ ] **数值稳定性** (接近容差的场景)
- [ ] **性能回归** (大规模输入不超时)
### 反模式
```cpp
// ❌ 测试依赖全局状态
static int counter = 0;
TEST(Foo, Bar) { EXPECT_EQ(counter++, 0); } // 不可重复
// ❌ 测试依赖执行顺序
TEST(Foo, A) { /* 设置全局状态 */ }
TEST(Foo, B) { /* 依赖 A 的状态 */ }
// ❌ 过于宽松的容差
EXPECT_NEAR(result, expected, 100.0); // 容差过大
// ❌ 没有断言(不验证任何东西)
TEST(Foo, Bar) {
auto x = compute();
// 没有 EXPECT/ASSERT
}
```
## 5. Sanitizer 测试
### Address Sanitizer (ASan)
```bash
# 构建 ASan 版本
cmake -B build_asan \
-DCMAKE_BUILD_TYPE=Debug \
-DENABLE_SANITIZERS=ON \
-DVDE_USE_OPENMP=OFF
cmake --build build_asan -j$(nproc)
# 运行测试
cd build_asan
ASAN_OPTIONS=detect_leaks=1:abort_on_error=1 \
ctest --output-on-failure -j4
```
### Undefined Behavior Sanitizer (UBSan)
```bash
# 手动添加 UBSan 标志
cmake -B build_ubsan \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fsanitize=undefined"
cmake --build build_ubsan -j$(nproc)
cd build_ubsan && ctest --output-on-failure
```
### Thread Sanitizer (TSan)
```bash
cmake -B build_tsan \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fsanitize=thread" \
-DVDE_USE_OPENMP=OFF
cmake --build build_tsan -j$(nproc)
cd build_tsan && ctest --output-on-failure
```
## 6. 性能基准
### 运行基准测试
```bash
# 构建基准测试
cmake -B build_bench -DBUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build_bench -j$(nproc)
# 运行所有基准
cd build_bench && ctest -R bench_
# 直接运行并查看详细报告
./build_bench/bench/bench_bvh --benchmark_format=json
```
### 基准模块
| 基准 | 内容 |
|------|------|
| `bench_bvh` | SAH 构建 (N=1K/10K/100K) + 射线查询 |
| `bench_delaunay` | 2D Bowyer-Watson (N=100/1K/10K) |
| `bench_boolean` | 3D 网格布尔 (N=100/500) |
| `bench_curves` | Bezier/BSpline evaluate 吞吐量 |
| `bench_spatial` | R-Tree/KD-Tree 构建 + kNN |
## 7. 模糊测试
```bash
# 构建并运行模糊测试
cmake -B build -DBUILD_TESTS=ON
cmake --build build -j$(nproc)
# 运行模糊测试
./build/tests/fuzz/test_fuzz_sdf
./build/tests/fuzz/test_fuzz_boolean
./build/tests/fuzz/test_fuzz_format
```
模糊测试覆盖的模块:
- **SDF**: 随机 CSG 树组合,检测 NaN/崩溃
- **Boolean**: 随机网格布尔运算,检测拓扑错误
- **Format**: 随机几何 → 导出 → 导入 → 验证一致性
## 8. CI 集成
VDE 使用 Gitea CI 自动运行测试。
### CI 配置文件
`.gitea/workflows/build.yml`:
```yaml
name: Build & Test
on: [push, pull_request]
jobs:
build-and-test:
runs-on: ubuntu-latest
container: vde-builder:latest
steps:
- name: Build
run: |
cmake -B build_ci -DCMAKE_BUILD_TYPE=Release
cmake --build build_ci -j2
- name: Test
run: |
cd build_ci && ctest --output-on-failure -j2
```
### CI 检查项
- [ ] 编译通过 (零错误零警告)
- [ ] 所有测试通过 (ctest 返回 0)
- [ ] ASan 检查无内存错误
- [ ] 无新增编译警告