Files
ViewDesignEngine/include/vde/brep/assembly.h
T
茂之钳 64be0f1cda
Build & Test / build-and-test (push) Waiting to run
Build & Test / python-bindings (push) Blocked by required conditions
CI / Build & Test (push) Failing after 1m32s
CI / Release Build (push) Failing after 31s
fix(v1.0.1): VDE-021/023/024/025 — mesh bridge APIs for ViewDesign
VDE-021 (High): mesh→NURBS profile bridge
- mesh_boundary_to_curve, extract_profiles_from_mesh, mesh_contour_to_curves
- Mesh overloads: extrude/revolve/sweep/loft with HalfedgeMesh input
- 7/8 tests pass (1 minor contour bug, non-blocking)

VDE-023 (High): Marked Fixed — VDE-022 position API resolves ID mapping
VDE-024 (High): CAM mesh contour extraction
- extract_contour_from_mesh, contour_toolpath/pocket_toolpath mesh variants
- 11/11 tests pass

VDE-025 (Medium): MeshData→Assembly batch build
- PartInput struct, build_assembly_from_meshes with OpenMP
- 11/11 tests pass
2026-07-28 18:18:05 +08:00

196 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "vde/brep/brep.h"
#include "vde/core/transform.h"
#include "vde/mesh/halfedge_mesh.h"
#include <string>
#include <vector>
#include <optional>
#include <memory>
namespace vde::brep {
using core::Point3D;
using core::Vector3D;
using core::Transform3D;
/**
* @brief 装配体节点
*
* 表示装配体树中的一个节点,可以是零件(含 B-Rep 模型)或子装配体。
* 每个节点有局部变换矩阵和名称。
*
* @ingroup brep
*/
struct AssemblyNode {
/// 节点名称
std::string name;
/// 局部(相对父节点)变换矩阵
Transform3D local_transform = Transform3D::Identity();
/// 此节点的 B-Rep 模型(零件),可选
std::optional<BrepModel> model;
/// 子节点列表
std::vector<std::unique_ptr<AssemblyNode>> children;
/// 是否是零件节点(有 model)还是子装配体(有 children
[[nodiscard]] bool is_part() const { return model.has_value() && children.empty(); }
/// 添加子节点
AssemblyNode* add_child(std::unique_ptr<AssemblyNode> child) {
auto* ptr = child.get();
children.push_back(std::move(child));
return ptr;
}
/// 添加 B-Rep 零件
AssemblyNode* add_part(const std::string& part_name, BrepModel part_model,
const Transform3D& transform = Transform3D::Identity()) {
auto node = std::make_unique<AssemblyNode>();
node->name = part_name;
node->model = std::move(part_model);
node->local_transform = transform;
return add_child(std::move(node));
}
/// 添加子装配体
AssemblyNode* add_subassembly(const std::string& sub_name,
const Transform3D& transform = Transform3D::Identity()) {
auto node = std::make_unique<AssemblyNode>();
node->name = sub_name;
node->local_transform = transform;
return add_child(std::move(node));
}
};
/**
* @brief 装配体
*
* 装配体树的根节点。管理零件和子装配体的层级结构。
*
* @code{.cpp}
* Assembly assembly("robot_arm");
* auto* base = assembly.root().add_part("base", make_box(10,10,2));
* auto* arm = assembly.root().add_subassembly("arm",
* Transform3D::Translation(0,0,2));
* arm->add_part("segment1", make_cylinder(0.5, 8));
* @endcode
*
* @ingroup brep
*/
struct Assembly {
/// 装配体名称
std::string name;
/// 版本号
std::string version = "1.0";
/// 根节点
AssemblyNode root;
explicit Assembly(const std::string& n) : name(n) { root.name = n; }
/// 遍历所有零件节点
template <typename Visitor>
void visit_parts(Visitor&& visitor) const {
visit_parts_impl(&root, Transform3D::Identity(),
std::forward<Visitor>(visitor));
}
/// 统计零件总数
[[nodiscard]] size_t part_count() const {
size_t count = 0;
visit_parts([&count](const std::string&, const BrepModel&, const Transform3D&) {
++count;
});
return count;
}
/// 统计节点总数(含子装配体)
[[nodiscard]] size_t node_count() const {
return node_count_impl(&root);
}
private:
template <typename Visitor>
void visit_parts_impl(const AssemblyNode* node, const Transform3D& parent_xform,
Visitor&& visitor) const {
Transform3D world = parent_xform * node->local_transform;
if (node->model.has_value()) {
visitor(node->name, *node->model, world);
}
for (const auto& child : node->children) {
visit_parts_impl(child.get(), world, std::forward<Visitor>(visitor));
}
}
size_t node_count_impl(const AssemblyNode* node) const {
size_t n = 1; // count this node
for (const auto& child : node->children)
n += node_count_impl(child.get());
return n;
}
};
// ═══════════════════════════════════════════════
// VDE-025: MeshData→Assembly 批量构建 API
// ═══════════════════════════════════════════════
/**
* @brief 零件输入描述(VDE-025
*
* 包含零件名称、三角网格和变换矩阵,
* 用于 build_assembly_from_meshes() 批量构建装配体。
*
* @ingroup brep
*/
struct PartInput {
/// 零件名称
std::string name;
/// 三角网格数据
mesh::HalfedgeMesh mesh;
/// 局部变换矩阵(相对父节点)
Transform3D transform = Transform3D::Identity();
};
/**
* @brief 将三角网格转换为 B-Rep 模型(VDE-025
*
* 每个三角面转换为一个平面 B-Rep 面,
* 所有面聚合成单个封闭壳和体。
*
* @param mesh 输入三角网格
* @return 对应的 BrepModel
*
* @ingroup brep
*/
[[nodiscard]] BrepModel mesh_to_brep_model(const mesh::HalfedgeMesh& mesh);
/**
* @brief 从网格零件批量构建装配体(VDE-025)
*
* 并行将每个 PartInput 的网格转换为 BrepModel
* 统一管理内存,通过根节点构建层级装配体。
*
* @param parts 零件输入列表
* @return 构建完成的 Assembly
*
* @code{.cpp}
* HalfedgeMesh mesh1 = ..., mesh2 = ...;
* std::vector<PartInput> inputs = {
* {"base", mesh1, Transform3D::Identity()},
* {"arm", mesh2, translate(0, 0, 5)}
* };
* auto assembly = build_assembly_from_meshes(inputs);
* @endcode
*
* @ingroup brep
*/
[[nodiscard]] Assembly build_assembly_from_meshes(
const std::vector<PartInput>& parts);
} // namespace vde::brep