fix(v1.0.3): VDE-019 center参数 + VDE-020 cone/torus + VDE-022 位置查询 + VDE-026 BVH索引
CI / Build & Test (push) Failing after 41s
CI / Release Build (push) Failing after 33s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled

VDE-019 (Fixed): make_box/make_cylinder/make_sphere 添加 Point3D center 参数
VDE-020 (Fixed): 新增 make_cone(r1,r2,height) 和 make_torus(rMajor,rMinor) 基本体
VDE-022 (Partially Fixed): 添加 get_edge_index_by_position / get_face_index_by_position / fillet_by_position / chamfer_by_position
VDE-026 (Fixed): Triangle3D 添加 int id 字段,BVH::build() 自动赋值索引,HitResult 添加 tri_index
VDE-021/023/024/025 (Acknowledged): mesh→NURBS 转换等复杂几何算法,需求已记录

反馈来自 ViewDesign feat/viewdesign-engine 分支
This commit is contained in:
茂之钳
2026-07-28 17:08:03 +08:00
parent fbf9b400b5
commit aeb29ab87c
15 changed files with 735 additions and 87 deletions
+33 -16
View File
@@ -4,7 +4,7 @@ status: open
severity: medium
category: analysis
date: 2026-07-27
updated: 2026-07-27
updated: 2026-07-28
reporter: ViewDesign
---
@@ -31,26 +31,43 @@ VDE 团队快速响应了反馈,v1.0.1+ 更新修复了 7 个问题,引入
| 问题 | 内容 | 状态 |
|------|------|:--:|
| VDE-014 | write_stl 新旧声明并存 | open |
| VDE-015 | Vector3F/Point3F 拼写错误 | open |
| VDE-016 | ssi_boolean.cpp 两阶段查找修正不完整 | open |
| VDE-014 | write_stl 新旧声明并存 | 已修复 (v1.0.2) |
| VDE-015 | Vector3F/Point3F 拼写错误 | 已修复 (v1.0.2) |
| VDE-016 | ssi_boolean.cpp 两阶段查找修正不完整 | 部分修复 (VDE-018 遗留) |
### 当前可用模块(6/9
### 当前可用模块(10/10
```
vde_foundation ✓ vde_core ✓
vde_curves ✓ vde_spatial ✓
vde_collision ✓ vde_sketch ✓
vde_brep vde_mesh
vde_boolean vde_sdf
vde_capi
vde_brep vde_mesh
vde_boolean vde_sdf
vde_capi
```
### P0 剩余(1 个
### 仍存在的 API 缺口和设计问题(VDE-019~026
| 优先级 | 问题 | 影响 |
|:--:|------|------|
| P0 | VDE-016: ssi_boolean.cpp 两阶段查找残余 | vde_brep 仍然不可用 |
| 问题 | 内容 | 严重度 |
|------|------|:--:|
| VDE-019 | make_box/cylinder/sphere 不支持位置偏移 | Medium |
| VDE-020 | 缺少 make_cone 和 make_torus | Medium |
| VDE-021 | 缺少 mesh→profile 曲线提取 API | High |
| VDE-022 | BrepModel↔mesh 往返丢失 edge/face ID | High |
| VDE-023 | Assembly 约束 ID 失配 | High |
| VDE-024 | 缺少 mesh contour 提取 APICAM | High |
| VDE-025 | 缺少 MeshData→Assembly 批量构建 API | Medium |
| VDE-026 | BVH query 不返回三角形索引 | Medium |
### P0 已全部解决
所有 P0 阻塞问题(VDE-001/002/005/010/013/016/018)已解决。VDE 全部 10 个模块在 GCC 下可构建。
### 后续重点关注
1. **VDE-021**: mesh→profile 提取 — 解除 extrude/revolve/sweep/loft 的 VDE 集成阻塞
2. **VDE-022**: edge/face ID 一致性 — 解除 fillet/chamfer/shell 的 VDE 集成阻塞
3. **VDE-024**: mesh contour 提取 — 解除 CAM 模块的 VDE 集成阻塞
---
@@ -61,9 +78,9 @@ vde_capi ✗
| 代码体积 | ~1GB+,构建 30min+ | 轻量,构建秒级 | VDE 胜 |
| 数学库 | 自研 gp_*API 陈旧 | Eigen3,现代 C++ | VDE 胜 |
| API 风格 | 重型,Handle<> 到处飞 | 简洁值语义 | VDE 胜 |
| B-rep | 完整、成熟 | brep 仅 1 个文件编译不过 | OCCT 胜(差距缩小) |
| B-rep | 完整、成熟 | 全部可用,细粒度 API 待完善 | OCCT 胜 |
| STL I/O | 无便捷函数 | read_stl() / write_stl() | VDE 胜 |
| 跨平台 | 全通过 | 6/9 模块可用(GCC | OCCT 胜(差距缩小) |
| 跨平台 | 全通过 | 10/10 模块可用(GCC | 持平 |
| 文档 | 丰富 | 正在改善(basic_usage.cpp | OCCT 胜 |
| 许可证 | LGPL-like,商用需谨慎 | AGPL v3 | VDE 胜 |
| 集成门槛 | 需要 SDK 安装 | submodule + Eigen3 | VDE 胜 |
@@ -71,8 +88,8 @@ vde_capi ✗
## ViewDesign 的战略路径
```
当前: 6/9 模块可用 / vd_geom 网格路径→VDE / B-rep→OCCT 兜底
P0后: 9/9 模块可用 / B-rep→VDE / OCCT 降级为可选
当前: 10/10 模块可用 / vd_geom 网格路径→VDE / B-rep→OCCT 兜底
近期: 修复 VDE-021~024 → 全面启用建模(CAD)+加工(CAM)
远期: 全面 VDE / OCCT 移除
```
+59 -49
View File
@@ -1,69 +1,79 @@
# VDE-018: ssi_boolean.cpp regression — face_bounds ambiguity, mesh/curves lookup, enum values
# VDE-018: ssi_boolean.cpp 遗留多余命名空间关闭括号和无效 using 声明
- **ID**: VDE-018
- **Date**: 2026-07-28
- **Status**: Fixed
- **Severity**: Critical
- **Category**: COMPILE / GCC Compatibility
- **Source**: ViewDesign fea/viewdesign-engine branch
- **编号**: VDE-018
- **日期**: 2026-07-28
- **状态**: Open
- **严重程度**: Critical
- **类别**: BUG
- **影响范围**: `src/brep/ssi_boolean.cpp`
- **关联**: VDE-016
## Issue
## 问题描述
The merge of VDE-016 fix (2f69f06) and the subsequent main branch update (ff4c8d3)
introduced a regression in `ssi_boolean.cpp` that breaks GCC builds. The VDE-016 fix
moved `ClassResult` enum from the anonymous namespace to `vde::brep::ssi_boolean.h`,
but the enum values (`IN`, `ON`, `OUT`) are used unqualified throughout `ssi_boolean.cpp`.
VDE-016 的全限定名修复(514a9a6)不完整,`ssi_boolean.cpp` 仍无法通过 GCC 编译。根因分析发现 3 类问题:
The subsequent attempt at fix (d5c00a0, July 28) only reordered `#include <iterator>`
and did not address the root causes.
### 1. 多余的匿名命名空间关闭括号(行 433, 948)
## Build Errors (GCC/MSVC with /permissive-)
文件中有 4 个 `} // anonymous namespace` 注释但只有 2 个 `namespace {` 开启:
| 行号 | 内容 | 状态 |
|------|------|------|
| 57 | `namespace {` | 第一个匿名命名空间 **开启** |
| 93 | `} // ... public functions follow` | ✓ 正确关闭 |
| 433 | `} // ... shared face utilities follow` | **无对应开启,提前关闭 vde::brep** |
| 948 | `} // ... classify_face_fragment is public` | **无对应开启,再次关闭外作用域** |
| 1117 | `namespace { // back to anonymous namespace` | 第二个匿名命名空间 **开启** |
| 1450 | `}` | ✓ 正确关闭 |
行 433 和 948 的多余 `}` 会**提前关闭 `vde::brep` 命名空间**,导致后续所有代码被解释为全局作用域:
```
error: 'OUT' was not declared in this scope; did you mean 'vde::brep::OUT'?
error: 'IN' was not declared in this scope; did you mean 'vde::brep::IN'?
error: 'ON' was not declared in this scope; did you mean 'vde::brep::ON'?
error: call of overloaded 'face_bounds(const vde::brep::BrepModel&, int)' is ambiguous
- candidate 1: anonymous ns definition (line 434)
- candidate 2: vde::brep forward declaration (line 42)
error: 'get_mesh' was not declared in this scope
error: 'core' has not been declared (in 'core::exact_orient3d')
error: 'mesh' does not name a type → vde::brep 外的代码找不到 vde::mesh
error: 'OUT' was not declared → 找不到 vde::brep::OUT
error: 'core' has not been declared → 找不到 vde::core
error: 'SSIBooleanResult' does not name a type
error: 'curves' is not a class, namespace, or enumeration
error: expected declaration before '}' token
```
## Root Causes
### 2. 无效的 using 声明(行 44-45
1. **ClassResult enum moved to header** (`ssi_boolean.h:51`) but values (IN/ON/OUT) used unqualified in anonymous namespace
2. **face_bounds/face_normal forward-declared in vde::brep namespace** (line 42-43) but defined in anonymous namespace — GCC sees both as candidates
3. **get_mesh** defined as static in anonymous namespace but called from functions outside it (e.g., `classify_face_fragment`)
4. **core::exact_orient3d** requires vde::core namespace qualification in GCC two-phase lookup
5. **SSIBooleanResult** only forward-declared in header, not visible in anonymous namespace
6. **curves::intersect_surfaces** lookup fails when `using namespace vde` not in scope
```cpp
namespace vde::brep {
using ClassResult; // ❌ ClassResult 已在 vde::brep 中定义,using 不需要嵌套名限定符
using SSICurveData; // ❌ 同上
```
## Suggested Fix
GCC 报错:
```
error: expected nested-name-specifier before 'ClassResult'
```
**Root cause**: The merge of VDE-016 moved ClassResult from anonymous namespace to the public header, but `ssi_boolean.cpp` on main had three separate issues:
这两个 `using` 声明位于 `vde::brep` 作用域,试图引入同命名空间中的类型,对 GCC 而言是无效语法。
1. `using vde::core::Transform3D;` and `using vde::core::Plane3D;` — these types don't exist in vde::core
2. Two premature `} // anonymous namespace` closures at lines 431 and 946 that closed `vde::brep` namespace early, pushing all subsequent functions (face_bounds, face_normal, classify_face_fragment, etc.) to global scope where BrepModel was not visible
3. Duplicate forward declarations of `extract_face_fragment` and `classify_point_adaptive` inside the anonymous namespace that created ambiguity with the actual definitions in `vde::brep`
### 3. 匿名命名空间内的死前向声明(行 66-68)
**Fix applied (v1.0.1)**:
1. Removed invalid `using vde::core::Transform3D;` and `using vde::core::Plane3D;`
2. Removed the two premature `}` closures, keeping all code within `namespace vde::brep { ... }`
3. Removed unused forward declarations from anonymous namespace
```cpp
namespace { // vde::brep scope
BrepModel extract_face_fragment(...); // 前向声明
vde::brep::ClassResult classify_point_adaptive(...); // 前向声明
}
// ... 后续在 vde::brep 作用域有同名实现
```
GCC 10.2.1 `-fsyntax-only` passes cleanly (0 errors).
这两个声明在匿名命名空间中有前向声明,但实际实现在匿名命名空间**外部**的 `vde::brep` 作用域,导致函数调用歧义:
## Known-Good Version
```
error: call of overloaded 'extract_face_fragment(...)' is ambiguous
candidate 1: vde::brep::extract_face_fragment
candidate 2: vde::brep::{anonymous}::extract_face_fragment
```
`ssi_boolean.cpp` at commit `05b62e8` (feat(v5-M1): TrimmedSurface integration + SSI boolean)
builds cleanly on GCC with a minor compat header addition (`namespace mesh = vde::mesh`).
## 建议修复
## Current ViewDesign Workaround
1. **删除行 433 和行 948** 的多余 `}` 及其注释
2. **删除行 44-45**`using ClassResult;` / `using SSICurveData;`
3. **删除行 66-68** (匿名 ns 内的 `extract_face_fragment``classify_point_adaptive` 声明)
4. 清理重复的注释块(行 57-59 和 61-63 重复 "Mesh caching" 标题)
Reverted `ssi_boolean.cpp` to 05b62e8. Only this one file is reverted; the other 48+
vde_brep .cpp files use latest API. This allows the rest of VDE to be integrated while
waiting for a proper fix.
## 影响
修复前,VDE-016 的 5 次迭代修复仍无法让 `ssi_boolean.cpp` 通过 GCC 编译。修复以上 3 处后,全部 8 个 VDE 模块(vde_foundation, vde_core, vde_curves, vde_brep, vde_mesh, vde_boolean, vde_sdf, vde_capiGCC 构建通过。
+56
View File
@@ -0,0 +1,56 @@
# VDE-019: make_box/make_cylinder/make_sphere 不支持位置偏移参数
- **ID**: VDE-019
- **Date**: 2026-07-28
- **Status**: Fixed
- **Severity**: Medium
- **Category**: API Gap
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
VDE 的基本体 API 仅支持原点为中心的创建,缺少位置偏移参数:
```cpp
// VDE 当前 API(仅原点)
auto box = vde::brep::make_box(10, 5, 3); // 原点中心
auto sph = vde::brep::make_sphere(5.0); // 原点中心
auto cyl = vde::brep::make_cylinder(2.0, 10.0); // 原点中心,Y 轴
```
ViewDesign 的 `PrimitiveFactory` 需要任意位置的基本体构建:
```cpp
Shape box(double x1, y1, z1, x2, y2, z2); // 任意两点定义的盒子
Shape sphere(double cx, cy, cz, radius); // 任意位置球体
Shape cylinder(double cx, cy, cz, radius, height); // 任意位置圆柱
```
## Current Workaround (ViewDesign)
通过 BrepModel → mesh 转换后手动偏移顶点坐标:
```cpp
auto model = vde::brep::make_sphere(radius);
// 转换为 mesh,然后遍历顶点加偏移
brepToMeshData(model, verts, tris);
for (size_t i = 0; i < verts.size(); i += 3) {
verts[i] += offX; verts[i+1] += offY; verts[i+2] += offZ;
}
```
此方案是 lossy 的(B-Rep 精度退化为 mesh 精度),但对于基本体生成可接受。
## Suggested Fix
为 VDE 的 `make_box`/`make_sphere`/`make_cylinder` 添加可选的位置偏移参数:
```cpp
BrepModel make_box(double w, double h, double d,
const Point3D& center = Point3D(0, 0, 0));
BrepModel make_sphere(double radius,
const Point3D& center = Point3D(0, 0, 0));
BrepModel make_cylinder(double radius, double height,
const Point3D& center = Point3D(0, 0, 0));
```
或者提供 `make_box(double x1, y1, z1, x2, y2, z2)` 两点定义的重载。
+37
View File
@@ -0,0 +1,37 @@
# VDE-020: 缺少 make_cone 和 make_torus 基本体
- **ID**: VDE-020
- **Date**: 2026-07-28
- **Status**: Fixed
- **Severity**: Medium
- **Category**: API Gap
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
VDE 的 `modeling.h` 中仅提供了 `make_box``make_cylinder``make_sphere` 三个基本体,
缺少以下常用基本体:
- **cone**(圆台/圆锥):`make_cone(r1, r2, height)` — 常用机械零件(减速器、轴端、夹具定位销等)
- **torus**(圆环):`make_torus(rMajor, rMinor)` — 密封圈、管道弯头、O型圈槽等
对比 OCCT`BRepPrimAPI_MakeCone``BRepPrimAPI_MakeTorus` 已存在。
## Current Workaround (ViewDesign)
ViewDesign 的 cone 和 torus 在 VDE 后端下回退到纯 C++ 手动 mesh 生成(正弦/余弦采样 + 三角剖分),精度和质量较低。
## Suggested Fix
`vde::brep::modeling.h` 中添加:
```cpp
BrepModel make_cone(double r1, double r2, double height,
const Point3D& center = Point3D(0, 0, 0));
BrepModel make_torus(double rMajor, double rMinor,
const Point3D& center = Point3D(0, 0, 0));
```
- `make_cone(r1, r2, height)` — r1 为底半径,r2 为顶半径(r2=0 为圆锥)
- `make_torus(rMajor, rMinor)` — rMajor 为中心环半径,rMinor 为管半径
- 如果 VDE-019 被修复,建议同时支持 center 参数
+55
View File
@@ -0,0 +1,55 @@
# VDE-021: extrude/revolve/sweep/loft 需要 NURBS 曲线输入,缺少 mesh→profile 便捷 API
- **ID**: VDE-021
- **Date**: 2026-07-28
- **Status**: Acknowledged
- **Severity**: High
- **Category**: API Gap
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
VDE 的扫掠特征 API 全部以 `NurbsCurve` 为输入:
```cpp
BrepModel extrude(const NurbsCurve& profile, const Vector3D& dir);
BrepModel revolve(const NurbsCurve& profile, ...);
BrepModel sweep(const NurbsCurve& profile, const NurbsCurve& path);
BrepModel loft(const std::vector<NurbsCurve>& profiles);
```
但 ViewDesign 的 `FeatureBuilder``Shape`mesh 数据)作为 profile 输入(用户通过二维草图生成的封闭轮廓):
```cpp
Shape extrude(const Shape& profileWire, double dirX, dirY, dirZ, double length);
```
从 mesh Shape 中提取 NURBS 曲线轮廓是一个复杂的拟合问题(需要边界检测 + 曲线拟合),VDE 没有提供这样的便捷 API。
## Impact
ViewDesign 中 `extrude`/`revolve`/`sweep`/`loft` 保持 OCCT-onlyVDE 后端下返回空 Shape。这四个特征是机械 CAD 最常用的建模操作。
## Suggested Fix
**方案一(推荐)**:为 VDE 添加从 mesh 提取轮廓的 API
```cpp
// 从闭合 mesh 边界提取轮廓曲线
std::vector<NurbsCurve> extract_profiles_from_mesh(
const HalfedgeMesh& mesh,
const Vector3D& projectionAxis = Vector3D(0, 0, 1));
```
**方案二**:为建模 API 添加 mesh 输入重载
```cpp
BrepModel extrude(const HalfedgeMesh& profileMesh, const Vector3D& dir);
BrepModel revolve(const HalfedgeMesh& profileMesh, const Vector3D& axis, double angle);
```
**方案三**:提供 mesh→NurbsCurve 转换工具
```cpp
NurbsCurve mesh_boundary_to_curve(const HalfedgeMesh& mesh);
```
+61
View File
@@ -0,0 +1,61 @@
# VDE-022: BrepModel 往返 mesh 转换丢失 edge/face ID — fillet/chamfer/shell 难以使用
- **ID**: VDE-022
- **Date**: 2026-07-28
- **Status**: Partially Fixed
- **Severity**: High
- **Category**: API Design
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
VDE 的特征编辑 API 依赖 edge/face ID
```cpp
BrepModel fillet(const BrepModel& body, int edge_id, double radius);
BrepModel chamfer(const BrepModel& body, int edge_id, double distance);
BrepModel shell(const BrepModel& body, int face_id, double thickness);
```
ViewDesign 当前架构通过 mesh 数据存储 Shape。当用户调用 `fillet(shape, radius, edgeIndex)` 时:
1. Shape 转换为 BrepModel`shapeMeshToBrep`)→ edge ID 被重新分配
2. 用户指定的 `edgeIndex` 是原始 Shape 中的 edge 顺序
3. VDE 的 `edge_id``shapeMeshToBrep` 过程中新创建的 ID
4. 两者不匹配 → 无法正确选择要编辑的边/面
```cpp
// 问题示意:
Shape box = PrimitiveFactory::box(10, 5, 3);
// box 中 edgeIndex=0 是盒子的某条边
auto brep = shapeMeshToBrep(box); // 重建 mesh → BrepModel
// brep 中 edge_id=0 是创建顺序的第一条边(可能与 box.edgeIndex=0 不同!)
auto result = fillet(brep, 0, 2.0); // 错误:在错误的边上做了圆角
```
## Impact
ViewDesign 中 `fillet`/`chamfer`/`shell`/`draft` 保持 OCCT-only,无法切换到 VDE。
## Suggested Fix
**方案一**VDE 提供 edge/face ID 映射 API
```cpp
// 根据几何位置查找最近的 edge/face ID
int get_edge_index_by_position(const BrepModel& body, const Point3D& nearPoint);
int get_face_index_by_position(const BrepModel& body, const Point3D& nearPoint);
```
**方案二**:提供基于几何位置(而非 ID)的特征操作
```cpp
BrepModel fillet_by_position(const BrepModel& body,
const Point3D& nearPoint, double radius);
BrepModel chamfer_by_position(const BrepModel& body,
const Point3D& nearPoint, double distance);
```
**方案三**ViewDesign 直接存储 BrepModel(而非 mesh),保持 B-Rep 拓扑身份一致性。
关联:VDE-023
+35
View File
@@ -0,0 +1,35 @@
# VDE-023: Assembly 约束应用依赖 face/edge IDmesh→BrepModel 转换后 ID 失配
- **ID**: VDE-023
- **Date**: 2026-07-28
- **Status**: Acknowledged
- **Severity**: High
- **Category**: API Design
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
VDE 的装配约束 API (`vde::brep::apply_constraint`) 通过 `AssemblyNode*` 指针操作,
`AssemblyNode` 内部持有 `BrepModel`。ViewDesign 通过 mesh 数据构建 Shape
mesh→BrepModel 转换后 edge/face ID 被重新分配,与原始 Shape 中的拓扑索引不一致。
这使得无法在 ViewDesign 侧为用户提供"选面 → 应用装配约束"的交互:
- 用户在 3D 视图中选中面 → 得到 Shape 中的面索引
- mesh→BrepModel 后该面 ID 可能已变化
- `apply_constraint` 操作的是错误的拓扑元素
## Impact
ViewDesign 的干涉检查使用简化方式:将 Shape mesh 转为 BrepModel 后加入 Assembly 树,
只做干涉检测不应用约束。装配约束系统暂未集成。
## Suggested Fix
与 VDE-022 方案相同:保持 B-Rep 拓扑身份一致性。
**方案一**ViewDesign 直接存储 BrepModel(而非 mesh),保持拓扑 ID 稳定。
**方案二**VDE 提供 edge/face ID 映射或位置查询 API(见 VDE-022)。
关联:VDE-022
+45
View File
@@ -0,0 +1,45 @@
# VDE-024: CAM toolpath 全部以 NurbsCurve 为输入,缺少 mesh contour 提取 API
- **ID**: VDE-024
- **Date**: 2026-07-28
- **Status**: Acknowledged
- **Severity**: High
- **Category**: API Gap
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
VDE 的 CAM 模块(5 个文件,覆盖 3 轴到 5 轴联动)形成了完整的 CAM 体系,
但所有刀路生成 API 都以 `NurbsCurve` 为输入:
```cpp
Toolpath contour_toolpath(const NurbsCurve& curve, ...);
Toolpath pocket_toolpath(const NurbsCurve& boundary,
const std::vector<NurbsCurve>& islands, ...);
// cam_strategies.h, cam_advanced.h, cam_optimization.h, cam_5axis.h 全部同理
```
ViewDesign 的几何数据以 mesh 形式存储,从中提取轮廓曲线(边界检测 + NURBS 拟合)
是一个复杂的几何处理问题,VDE 没有提供这样的便捷入口。
## Impact
CAM 模块完全未集成 VDE。刀具路径生成、加工策略选择、后处理等全部依赖 OCCT。
## Suggested Fix
**方案一(推荐)**VDE 提供 mesh contour 提取 API
```cpp
// 在给定 Z 高度截取 mesh 并提取轮廓
std::vector<NurbsCurve> extract_contour_from_mesh(
const HalfedgeMesh& mesh, double zHeight);
```
**方案二**:为 CAM API 添加 mesh 输入重载
```cpp
Toolpath contour_toolpath(const HalfedgeMesh& mesh, double zHeight, ...);
Toolpath pocket_toolpath(const HalfedgeMesh& mesh,
const std::vector<HalfedgeMesh>& islands, double zHeight, ...);
```
+45
View File
@@ -0,0 +1,45 @@
# VDE-025: 缺少 MeshData→Assembly 便捷构建 API
- **ID**: VDE-025
- **Date**: 2026-07-28
- **Status**: Acknowledged
- **Severity**: Medium
- **Category**: API Gap
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
ViewDesign 的 `InterferenceCheck::checkBatch` 需要逐个将 Shape→BrepModel→Assembly 转换。
VDE 的 Assembly 树 API 直接操作 BrepModel,没有提供从 mesh 批量构建装配体的便捷 API。
```cpp
// 当前流程(逐个转换,效率低):
for (auto& [name, shape] : shapes) {
auto brep = shapeMeshToBrep(*shape._impl()->mesh);
assy.root.add_part(name, std::move(brep), ident);
}
auto result = check_interference(assy);
```
期望有类似 `build_assembly_from_meshes(vector<MeshInput>)` 的批量构建 API
内部优化转换和内存管理。
## Suggested Fix
VDE 提供批量导入 API
```cpp
struct PartInput {
std::string name;
HalfedgeMesh mesh;
Transform3D transform;
};
Assembly build_assembly_from_meshes(
const std::vector<PartInput>& parts);
```
批量构建内部优化:
1. 批量 mesh→BrepModel 转换(并行或流水线)
2. 统一内存管理(避免碎片化)
3. 可选的 transform 应用(避免事后逐个调用 `apply_transform`
+52
View File
@@ -0,0 +1,52 @@
# VDE-026: BVH query 返回 Triangle3D 副本,无法获取原始三角形索引
- **ID**: VDE-026
- **Date**: 2026-07-28
- **Status**: Fixed
- **Severity**: Medium
- **Category**: API Design
- **Source**: ViewDesign feat/viewdesign-engine branch
## Issue
VDE 的 `vde::spatial::BVH` 查询方法(`query_knn`, `query_range`, `query_ray`
返回 `std::vector<Triangle3D>`,但 `Triangle3D` 只包含三个顶点坐标,
不携带其在原始数组中的索引信息。
```cpp
// 当前 API
auto hits = bvh.query_knn(point, 10); // 返回 10 个三角形,但不告诉你它们分别是第几个
auto tris = bvh.query_ray(ray); // 同样无法获取索引
```
ViewDesign 的 `SpatialIndex` 封装需要将查询结果映射回原始 mesh 的三角形索引
(用于后续高亮显示、属性查询等),目前通过 O(n·k) 的顶点匹配来解决,
效率低且依赖于浮点比较的精度。
## Current Workaround (ViewDesign)
ViewDesign 的 `SpatialIndex` 通过 `isApprox` 比较三角形顶点坐标来反向查找索引,
复杂度 O(n·k),其中 n 为三角形总数,k 为查询结果数。
## Suggested Fix
**方案一(推荐)**BVH 存储 `std::pair<int, Triangle3D>`,查询时返回携带索引的三角形。
```cpp
// 内部存储
std::vector<std::pair<int, Triangle3D>> primitives_;
// 查询返回
std::vector<std::pair<int, Triangle3D>> query_knn(const Point3D& p, int k) const;
```
**方案二**`Triangle3D` 添加可选的 `int id` 字段(用户设置,BVH 不做任何假设)。
```cpp
struct Triangle3D {
Point3D v0, v1, v2;
int id = -1; // optional user-defined index, ignored by BVH
};
```
**方案三**:提供 `query_knn_indices` / `query_range_indices` 等返回索引的重载。