feat(v7): B-Rep deep attack + Class-A surfacing + CAM deep + performance tuning
Build & Test / build-and-test (push) Waiting to run
Build & Test / python-bindings (push) Blocked by required conditions
CI / Build & Test (push) Failing after 33s
CI / Release Build (push) Failing after 29s

v7.1 — B-Rep 深度攻坚 (对标 Parasolid 95%):
- advanced_healing: auto_heal_pipeline, face_splitting/merging, topology_optimization
- watertight_verification, tolerance_analysis, tolerance diagnostic report
- sheet_metal: unfold_sheet_metal (K-Factor/BFS), bend_deduction_table, create_flange
- direct_modeling enhanced: draft_face_advanced (hinge), scale_body (non-uniform), mirror_body
- 32 tests (17 healing + 15 sheet metal), syntax-check passed

v7.2 — Class-A 曲面攻坚 (对标 CGM 95%):
- class_a_surfacing: g3_blend (4-row CP), curvature_matching (Levenberg-Marquardt)
- highlight_lines, reflection_lines, iso_photes, surface_diagnosis, shape_modification
- advanced_intersection: robust_ssi (3-stage: AABB+subdivision→Newton 1e-12→singularity)
- curve_surface_intersection, self_intersection_detection (BVH)
- 30 tests (18 class-A + 12 intersection), zero compile errors

v7.3 — CAM 深化 + 性能优化:
- cam_advanced: adaptive_clearing, trochoidal_milling, rest_machining, pencil_tracing
- tool_holder_collision_check, toolpath_optimization, feed_rate_optimization
- performance_tuning: parallel_task_graph (DAG+Kahn), work_stealing_scheduler
- memory_pool_integration, cache_optimization_hints, profile_guided_layout
- Fixed BrepModel API compatibility (body.bounds()/to_mesh() instead of .faces())
- 20 tests

12 files, ~5200 lines, 82 tests
This commit is contained in:
茂之钳
2026-07-26 22:54:46 +08:00
parent 5e2812a6f3
commit 921c29cb22
24 changed files with 8204 additions and 0 deletions
+311
View File
@@ -0,0 +1,311 @@
#pragma once
/**
* @file advanced_healing.h
* @brief 高级 B-Rep 修复 — 对标 Parasolid 95%
*
* 提供 Parasolid 级别的全自动修复流水线和诊断工具:
*
* | 操作 | 对标 Parasolid 功能 |
* |----------------------------|-----------------------------------------|
* | auto_heal_pipeline | auto-heal / optimize |
* | face_splitting | face splitting with p-curve |
* | face_merging | coplanar merge / face stitching |
* | topology_optimization | redundant edge/vertex cleanup |
* | tolerance_analysis | tolerance diagnostic report |
* | watertight_verification | strict watertightness certification |
*
* @ingroup brep
*/
#include "vde/brep/brep.h"
#include "vde/brep/brep_validate.h"
#include "vde/brep/tolerance.h"
#include "vde/brep/brep_heal.h"
#include "vde/curves/nurbs_curve.h"
#include "vde/curves/nurbs_surface.h"
#include <string>
#include <vector>
#include <map>
#include <functional>
namespace vde::brep {
// ═══════════════════════════════════════════════════════════
// 修复诊断报告
// ═══════════════════════════════════════════════════════════
/**
* @brief 高级修复诊断报告
*
* 包含自动修复流水线每一步的详细结果,
* 用于日志记录、UI 展示和下游分析。
*/
struct AdvancedHealingReport {
/** @brief 修复是否完全成功 */
bool success = false;
/** @brief 执行步骤链 */
std::vector<std::string> steps_executed;
/** @brief 每步修复的详情 */
struct StepDetail {
std::string step_name; ///< 步骤名称
bool ok = false; ///< 该步骤是否通过
int items_fixed = 0; ///< 修复项数
std::string message; ///< 该步骤的消息
};
std::vector<StepDetail> details;
/** @brief 修复前验证结果 */
ValidationResult before_validation;
/** @brief 修复后验证结果 */
ValidationResult after_validation;
/** @brief 警告汇总 */
std::vector<std::string> warnings;
/** @brief 总修复项数 */
int total_fixes = 0;
};
// ═══════════════════════════════════════════════════════════
// 容差诊断报告
// ═══════════════════════════════════════════════════════════
/**
* @brief 容差分析项
*
* 记录单个拓扑元素的容差诊断信息。
*/
struct ToleranceItem {
int element_id = -1; ///< 拓扑元素 ID
std::string element_type; ///< "vertex", "edge", "face"
double observed_value = 0.0; ///< 观测值(距离/角度/面积)
double tolerance = 0.0; ///< 适用的容差阈值
bool pass = true; ///< 是否通过检查
std::string description; ///< 可读诊断描述
};
/**
* @brief 容差诊断报告
*
* 全面的几何质量诊断报告,对标 Parasolid 的 tolerance analysis。
* 包含顶点间距、边长度、面面积、角度偏差、水密性间隙等诊断项。
*/
struct ToleranceAnalysisReport {
/** @brief 整体通过 */
bool overall_pass = false;
/** @brief 模型信息 */
size_t total_vertices = 0;
size_t total_edges = 0;
size_t total_faces = 0;
double model_size = 0.0; ///< 包围盒对角线长度
/** @brief 容差配置 */
ToleranceConfig config_used;
/** @brief 诊断项列表 */
std::vector<ToleranceItem> items;
/** @brief 通过/失败统计 */
size_t items_passed = 0;
size_t items_failed = 0;
/** @brief 最小间隙(水密性相关) */
double min_gap = std::numeric_limits<double>::max();
/** @brief 最大间隙 */
double max_gap = 0.0;
/** @brief 平均间隙 */
double avg_gap = 0.0;
/** @brief 间隙超过容差的边对数量 */
size_t gap_violations = 0;
/** @brief 退化元素计数 */
size_t degenerate_edges = 0; ///< 长度 < sliver_area 的边
size_t degenerate_faces = 0; ///< 面积 < sliver_area 的面
size_t near_degenerate_elements = 0; ///< 接近退化的元素
/** @brief 建议的操作列表 */
std::vector<std::string> recommendations;
};
// ═══════════════════════════════════════════════════════════
// 水密性验证
// ═══════════════════════════════════════════════════════════
/**
* @brief 水密性严格验证结果
*
* 对标 Parasolid 的 watertight 验证,提供更详细的间隙/穿透分析。
*/
struct WatertightVerificationResult {
/** @brief 是否水密 */
bool is_watertight = false;
/** @brief 水密性分数 (0.0 ~ 1.0) */
double watertight_score = 0.0;
/** @brief 总边数 */
size_t total_edges = 0;
/** @brief 边界边数(恰好被 1 个面引用的边) */
size_t boundary_edges = 0;
/** @brief 非流形边数(被 > 2 个面引用的边) */
size_t non_manifold_edges = 0;
/** @brief 悬挂边(0 个面引用) */
size_t dangling_edges = 0;
/** @brief 间隙位置列表 */
struct GapLocation {
int edge_id = -1; ///< 间隙对应的边 ID
int face_a = -1; ///< 相邻面 A
int face_b = -1; ///< 相邻面 B (可能为 -1)
double gap_size = 0.0; ///< 间隙尺寸
core::Point3D location; ///< 间隙位置
};
std::vector<GapLocation> gaps;
/** @brief 穿透位置 */
struct PenetrationLocation {
int face_a = -1;
int face_b = -1;
double depth = 0.0;
core::Point3D location;
};
std::vector<PenetrationLocation> penetrations;
/** @brief 壳闭合检查 */
struct ShellStatus {
int shell_id = -1;
bool closed = false;
size_t boundary_edge_count = 0;
};
std::vector<ShellStatus> shell_statuses;
/** @brief 错误消息 */
std::vector<std::string> errors;
};
// ═══════════════════════════════════════════════════════════
// Advanced Healing API
// ═══════════════════════════════════════════════════════════
/**
* @brief 全自动修复流水线
*
* 对标 Parasolid auto-heal。按最佳顺序执行:
*
* 1. 容差分析 → 确定自适应容差
* 2. 间隙闭合 (heal_gaps)
* 3. 退化元素移除 (heal_slivers)
* 4. 冗余边顶点清理 (拓扑优化)
* 5. 共面面合并
* 6. 面方向统一 (heal_orientation)
* 7. 水密性验证
*
* @param body 输入 B-Rep 模型(原地修改)
* @return AdvancedHealingReport 含详细诊断报表
*/
[[nodiscard]] AdvancedHealingReport auto_heal_pipeline(BrepModel& body);
/**
* @brief 面分割 — 使用 p-curve 在参数域分割面
*
* 对标 Parasolid face splitting。根据给定的参数曲线(p-curve)
* 在面的参数域 (u,v) 中切割面,生成两个或多个子面。
*
* 算法:
* 1. 将 p-curve 投影到面的 3D 曲面上
* 2. 查找 p-curve 与面边界的交点
* 3. 在交点和端点处分割原始边
* 4. 为每个子区域构建新环和新面
*
* @param body 输入 B-Rep 模型(原地修改面的拓扑)
* @param face_id 要分割的面索引
* @param pcurve_2d 二维参数曲线(在面的 (u,v) 参数域中定义)
* @return 新生成的面 ID 列表(包含原面,因原地修改后原面 ID 变为第一个新面)
*/
[[nodiscard]] std::vector<int> face_splitting(
BrepModel& body, int face_id,
const curves::NurbsCurve& pcurve_2d);
/**
* @brief 共面面合并
*
* 对标 Parasolid coplanar face merge。
* 检测并合并给定面列表中彼此共面且共享边的面。
*
* 算法:
* 1. 对每个面计算平面方程(法向量 + 距原点距离)
* 2. 分组:具有相同平面方程的面归为一组
* 3. 在每组中查找共享边的面对
* 4. 使用 KEF 欧拉操作合并共享边
* 5. 重建合并面的环和曲面
*
* @param body 输入 B-Rep 模型(原地修改)
* @param face_ids 候选面 ID 列表
* @return 实际合并的面对数量
*/
int face_merging(BrepModel& body, const std::vector<int>& face_ids);
/**
* @brief 拓扑优化 — 冗余边/顶点清理
*
* 对标 Parasolid topology optimization。
* 移除对几何形状无贡献的冗余拓扑元素:
*
* 1. **冗余顶点**: 度为 2 且两侧边共线的顶点 → KEV
* 2. **冗余边**: 共面面之间的共享边 → KEF
* 3. **零长边**: 两端点重叠的边 → 合并顶点 + 移除边
* 4. **冗余内环**: 空内环或无面积内环
*
* @param body 输入 B-Rep 模型(原地修改)
* @return 优化项数(移除的顶点数 + 边数 + 面合并数)
*/
int topology_optimization(BrepModel& body);
/**
* @brief 容差诊断报告
*
* 对标 Parasolid tolerance analysis。
* 生成全面的几何质量诊断报告,包括:
* - 顶点间距检查
* - 边长度检查
* - 面面积与平面性检查
* - 面间角度偏差
* - 水密性间隙扫描
*
* @param body 输入 B-Rep 模型
* @param cfg 容差配置(默认使用全局配置)
* @return ToleranceAnalysisReport 含完整诊断报表
*/
[[nodiscard]] ToleranceAnalysisReport tolerance_analysis(
const BrepModel& body,
const ToleranceConfig& cfg = ToleranceConfig::global());
/**
* @brief 水密性严格验证
*
* 对标 Parasolid watertight verification。
* 提供比 validate() 更详细的水密性分析,包括:
* - 每条边的相邻面数统计
* - 间隙位置精确识别
* - 穿透检测(面间非法相交)
* - 逐壳闭合性检查
* - 0.0~1.0 的连续水密性评分
*
* @param body 输入 B-Rep 模型
* @param tolerance 容差(默认 1e-6
* @return WatertightVerificationResult 含详细报表
*/
[[nodiscard]] WatertightVerificationResult watertight_verification(
const BrepModel& body,
double tolerance = 1e-6);
} // namespace vde::brep
+83
View File
@@ -187,4 +187,87 @@ struct DirectModelingResult {
[[nodiscard]] DirectModelingResult offset_face(const BrepModel& body,
int face_id, double offset_distance);
// ═══════════════════════════════════════════════════════════
// Advanced Direct Modeling Operations — v5.4
// ═══════════════════════════════════════════════════════════
/**
* @brief 高级拔模 — 面按拔模方向和角度倾斜
*
* 将指定面相对于拔模方向旋转到目标拔模角。
* 面的与邻面共享的边作为铰链轴(hinge line)。
*
* 对标 Parasolid Draft Face。
*
* @param body 输入 B-Rep 实体
* @param face_id 目标面索引
* @param angle_deg 拔模角度(度),> 0 且 < 90
* @param pull_dir 拔模方向(通常是模具开模方向)
* @return DirectModelingResult 含新模型和诊断
*
* @pre angle_deg 必须在 (0, 90) 度范围内
* @pre pull_dir 不能与面法向量平行
*
* @code{.cpp}
* auto box = make_box(10, 5, 3);
* // 面 0 向 Z+ 方向拔模 5 度
* auto result = draft_face_advanced(box, 0, 5.0, Vector3D::UnitZ());
* @endcode
*/
[[nodiscard]] DirectModelingResult draft_face_advanced(const BrepModel& body,
int face_id, double angle_deg,
const core::Vector3D& pull_dir);
/**
* @brief 非均匀缩放体
*
* 沿 X/Y/Z 轴以独立缩放因子缩放整个 B-Rep 实体。
* 对标 Parasolid Scale Body (non-uniform)。
*
* 均匀缩放时(所有因子相等)使用 Transform3D 加速。
* 非均匀缩放时逐个顶点变换并重建曲面控制点网格。
*
* @param body 输入 B-Rep 实体
* @param factors 各轴缩放因子 (sx, sy, sz),均必须 > 0
* @return DirectModelingResult 含缩放后的新模型
*
* @pre factors.x() > 0, factors.y() > 0, factors.z() > 0
*
* @code{.cpp}
* auto box = make_box(10, 5, 3);
* // X 方向拉伸 2x, Y/Z 不变
* auto stretched = scale_body(box, Vector3D(2.0, 1.0, 1.0));
* @endcode
*/
[[nodiscard]] DirectModelingResult scale_body(const BrepModel& body,
const core::Vector3D& factors);
/**
* @brief 镜像体
*
* 关于指定平面镜像整个 B-Rep 实体。
* 对标 Parasolid Mirror Body。
*
* 算法:
* 1. 所有顶点关于镜像平面对称映射
* 2. 曲面控制点网格镜像(保持参数化方向)
* 3. 环方向反转以保持正确的面朝向
*
* @param body 输入 B-Rep 实体
* @param plane_point 镜像平面上的一点
* @param plane_normal 镜像平面法向量
* @return DirectModelingResult 含镜像体
*
* @pre plane_normal 不能为零向量
*
* @code{.cpp}
* auto box = make_box(10, 5, 3);
* // 关于 YZ 平面 (x=0) 镜像
* auto mirrored = mirror_body(box, Point3D(0,0,0), Vector3D::UnitX());
* @endcode
*/
[[nodiscard]] DirectModelingResult mirror_body(const BrepModel& body,
const core::Point3D& plane_point,
const core::Vector3D& plane_normal);
} // namespace vde::brep
+311
View File
@@ -0,0 +1,311 @@
#pragma once
/**
* @file sheet_metal.h
* @brief 钣金设计模块 — 对标 Parasolid Sheet Metal
*
* 提供钣金件的展开、折弯扣除、法兰创建和 K-factor 计算功能。
* 对标业界标准钣金设计工作流。
*
* ## 功能概览
*
* | 操作 | 对标 Parasolid 功能 |
* |------------------------|---------------------------------------|
* | unfold_sheet_metal | Unbend / Flatten |
* | bend_deduction_table | Bend Allowance / Deduction Table |
* | create_flange | Flange / Edge Flange |
* | compute_k_factor | K-Factor Calculation |
*
* ## 钣金术语
*
* - **K-Factor**: 中性轴位置比例 (0~1),通常取 0.33~0.5
* - K = t_neutral_axis / t (t = 板厚)
* - **Bend Allowance (BA)**: 折弯区展开长度
* - BA = (π × (R + K×T) × A) / 180
* - **Bend Deduction (BD)**: 折弯扣除值
* - BD = 2 × OSSB - BA
* - OSSB = (R + T) × tan(A/2) (外侧退让量)
*
* @ingroup brep
*/
#include "vde/brep/brep.h"
#include "vde/brep/direct_modeling.h"
#include "vde/core/point.h"
#include "vde/core/transform.h"
#include <string>
#include <vector>
#include <map>
#include <cmath>
namespace vde::brep {
// ═══════════════════════════════════════════════════════════
// 材料与折弯表
// ═══════════════════════════════════════════════════════════
/**
* @brief 钣金材料定义
*
* 包含材料的力学特性,用于 K-factor 计算和折弯扣除。
*/
struct SheetMetalMaterial {
std::string name; ///< 材料名称(如 "Steel_A36", "Aluminum_6061"
double yield_strength_mpa = 250.0; ///< 屈服强度 (MPa)
double tensile_strength_mpa = 400.0; ///< 抗拉强度 (MPa)
double elastic_modulus_gpa = 200.0; ///< 弹性模量 (GPa)
double poisson_ratio = 0.3; ///< 泊松比
};
/**
* @brief 折弯扣除表条目
*
* 记录特定材料/厚度/角度/半径组合下的折弯扣除值。
*/
struct BendDeductionEntry {
double thickness = 1.0; ///< 板厚 (mm)
double bend_radius = 1.0; ///< 折弯内半径 (mm)
double bend_angle_deg = 90.0; ///< 折弯角度(度)
double bend_deduction = 0.0; ///< 折弯扣除值 (mm)
double k_factor = 0.33; ///< 使用的 K-factor
};
/**
* @brief 折弯扣除表
*
* 材料/厚度 → 折弯扣除值的查找表。
* 支持精确半径匹配和插值逼近。
*/
class BendDeductionTable {
public:
/// 添加一条记录
void add_entry(const BendDeductionEntry& entry);
/// 通过精确匹配查找
[[nodiscard]] BendDeductionEntry lookup(
double thickness, double bend_radius, double bend_angle_deg) const;
/// 通过插值查找(未找到精确匹配时)
[[nodiscard]] BendDeductionEntry lookup_interpolated(
double thickness, double bend_radius, double bend_angle_deg) const;
/// 获取表大小
[[nodiscard]] size_t size() const { return entries_.size(); }
/// 获取所有条目
[[nodiscard]] const std::vector<BendDeductionEntry>& entries() const {
return entries_;
}
private:
std::vector<BendDeductionEntry> entries_;
};
// ═══════════════════════════════════════════════════════════
// K-Factor 计算
// ═══════════════════════════════════════════════════════════
/**
* @brief 计算 K-Factor
*
* K-Factor = 中性轴到内表面的距离 / 板厚
*
* 使用经验公式,基于材料屈服强度和板厚:
* - 软材料 (低碳钢): K ≈ 0.33
* - 中等材料: K ≈ 0.40
* - 硬材料 (不锈钢): K ≈ 0.45~0.50
*
* 更精确的计算考虑 R/T 比率:
* - R/T < 1.0: K = 0.25 + 0.1 × (R/T)
* - 1.0 ≤ R/T < 3.0: K = 0.33 + 0.05 × (R/T)
* - R/T ≥ 3.0: K = 0.45 + 0.02 × (R/T), 上限 0.5
*
* @param material 材料属性
* @param thickness 板厚 (mm)
* @param bend_radius 折弯内半径 (mm)
* @return K-factor 值 (0.0 ~ 0.5)
*/
[[nodiscard]] double compute_k_factor(
const SheetMetalMaterial& material,
double thickness,
double bend_radius);
/**
* @brief 快速 K-Factor 估算(材料无关)
*
* @param thickness 板厚 (mm)
* @param bend_radius 折弯半径 (mm)
* @return 估算的 K-factor
*/
[[nodiscard]] double compute_k_factor_simple(
double thickness, double bend_radius);
// ═══════════════════════════════════════════════════════════
// 折弯计算
// ═══════════════════════════════════════════════════════════
/**
* @brief 计算折弯余量 (Bend Allowance)
*
* BA = (π/180) × (R + K×T) × A
*
* @param bend_radius 折弯内半径
* @param thickness 板厚
* @param bend_angle_deg 折弯角度(度)
* @param k_factor K-factor
* @return 折弯余量长度 (mm)
*/
[[nodiscard]] double compute_bend_allowance(
double bend_radius, double thickness,
double bend_angle_deg, double k_factor);
/**
* @brief 计算折弯扣除 (Bend Deduction)
*
* BD = 2 × OSSB - BA
* OSSB = (R + T) × tan(A/2)
*
* @param bend_radius 折弯内半径
* @param thickness 板厚
* @param bend_angle_deg 折弯角度(度)
* @param k_factor K-factor
* @return 折弯扣除值 (mm)
*/
[[nodiscard]] double compute_bend_deduction(
double bend_radius, double thickness,
double bend_angle_deg, double k_factor);
// ═══════════════════════════════════════════════════════════
// 折弯扣除表生成
// ═══════════════════════════════════════════════════════════
/**
* @brief 为指定材料和厚度范围生成折弯扣除表
*
* 自动计算 90° 折弯在不同板厚和内半径下的扣除值。
* 使用该材料的 compute_k_factor 确定 K-factor。
*
* @param material 钣金材料
* @param thickness 板厚 (mm)
* @param radii 要计算的内半径列表
* @return 生成的折弯扣除表
*/
[[nodiscard]] BendDeductionTable bend_deduction_table(
const SheetMetalMaterial& material,
double thickness,
const std::vector<double>& radii = {0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0});
/**
* @brief 为指定材料和折弯角生成折弯扣除表(多角度)
*
* @param material 钣金材料
* @param thickness 板厚 (mm)
* @param radius 折弯内半径 (mm)
* @param angles_deg 角度列表
* @return 生成的折弯扣除表
*/
[[nodiscard]] BendDeductionTable bend_deduction_table_angles(
const SheetMetalMaterial& material,
double thickness, double radius,
const std::vector<double>& angles_deg = {30, 45, 60, 90, 120, 135, 150});
// ═══════════════════════════════════════════════════════════
// 钣金展开
// ═══════════════════════════════════════════════════════════
/**
* @brief 钣金展开结果
*/
struct UnfoldResult {
/** @brief 是否成功 */
bool success = false;
/** @brief 展开后的平面 B-Rep */
BrepModel flattened_body;
/** @brief 折弯面列表(展开前) */
std::vector<int> bend_faces;
/** @brief 各折弯的展开信息 */
struct BendUnfoldInfo {
int bend_face_id = -1; ///< 折弯面 ID
double bend_angle_deg = 0.0; ///< 折弯角度
double bend_radius = 0.0; ///< 折弯半径
double unbend_length = 0.0; ///< 展开长度
};
std::vector<BendUnfoldInfo> bend_details;
/** @brief 使用的 K-Factor */
double k_factor_used = 0.33;
/** @brief 错误/警告 */
std::vector<std::string> errors;
std::vector<std::string> warnings;
};
/**
* @brief 钣金展开
*
* 对标 Parasolid Unbend/Flatten。
* 将钣金件的折弯面展开为平面布局。
*
* 算法:
* 1. 识别基准面(face_id 指定的面)
* 2. BFS 遍历相邻面,识别折弯面(柱面或锥面)
* 3. 对每个折弯面计算展开长度(使用 K-factor)
* 4. 将折弯面映射到基准面所在平面
* 5. 重建平坦拓扑
*
* @param body 钣金 B-Rep 模型
* @param face_id 基准面索引(展开时的固定参考面)
* @param material 钣金材料(用于 K-factor 计算)
* @param thickness 板厚 (mm)0 表示自动从模型估算
* @return UnfoldResult 含展开后的平面模型
*/
[[nodiscard]] UnfoldResult unfold_sheet_metal(
const BrepModel& body, int face_id,
const SheetMetalMaterial& material = SheetMetalMaterial{},
double thickness = 0.0);
// ═══════════════════════════════════════════════════════════
// 法兰创建
// ═══════════════════════════════════════════════════════════
/**
* @brief 法兰创建结果
*/
struct FlangeResult {
bool success = false;
BrepModel body; ///< 含新法兰的结果体
std::vector<int> new_face_ids; ///< 新创建的面 ID 列表
std::vector<int> new_edge_ids; ///< 新创建的边 ID 列表
std::vector<std::string> errors;
std::vector<std::string> warnings;
};
/**
* @brief 沿边创建法兰
*
* 对标 Parasolid Flange / Edge Flange。
* 沿钣金件的一条边创建折弯法兰。
*
* 算法:
* 1. 确定边所属的基面
* 2. 计算折弯线(沿边的偏移)
* 3. 生成折弯区的柱面
* 4. 生成法兰面的平面曲面
* 5. 通过布尔或拓扑编辑将法兰附加到模型
*
* @param body 输入钣金 B-Rep 模型
* @param edge_id 附着边索引
* @param angle_deg 法兰折弯角度(度),90=标准法兰
* @param length 法兰长度(从折弯线到法兰自由边的距离)
* @param material 钣金材料
* @param thickness 板厚 (mm)0 表示自动估算
* @return FlangeResult 含新模型
*/
[[nodiscard]] FlangeResult create_flange(
const BrepModel& body, int edge_id,
double angle_deg, double length,
const SheetMetalMaterial& material = SheetMetalMaterial{},
double thickness = 0.0);
} // namespace vde::brep
+237
View File
@@ -0,0 +1,237 @@
#pragma once
/**
* @file cam_advanced.h
* @brief CAM 高级加工策略 — 自适应清除、摆线铣削、残料加工、清根、碰撞检测、刀路优化
*
* 在 cam_strategies.h 的 3 轴基础策略之上提供:
* - adaptive_clearing — 自适应清除(摆线刀路),根据材料负载动态调整步距
* - trochoidal_milling — 摆线铣削,使用圆形/圆弧切入避免全刃切削
* - rest_machining — 残料加工,检测前序刀具未切削区域
* - pencil_tracing — 清根加工,沿角落/交线生成清根刀路
* - tool_holder_collision_check — 刀柄/刀杆碰撞检测
* - toolpath_optimization — 刀路重排序减少空行程
* - feed_rate_optimization — 基于材料去除率的进给优化
*
* @ingroup core
*/
#include "vde/core/point.h"
#include "vde/core/aabb.h"
#include "vde/core/cam_toolpath.h"
#include "vde/core/cam_strategies.h"
#include "vde/mesh/halfedge_mesh.h"
#include <vector>
#include <string>
#include <memory>
#include <optional>
#include <functional>
namespace vde::brep {
class BrepModel;
} // namespace vde::brep
namespace vde::core {
using core::Point3D;
using core::Vector3D;
using core::AABB3D;
// ═══════════════════════════════════════════════════════════════════════════
// 高级 CAM 参数类型
// ═══════════════════════════════════════════════════════════════════════════
/// 自适应清除参数
struct AdaptiveClearingParams {
double step_down = 1.0; ///< 每层切深 (mm)
double min_step_over = 0.5; ///< 最小横向步距 (mm)
double max_step_over = 3.0; ///< 最大横向步距 (mm) — 低负载时扩大
double engagement_angle = 45.0; ///< 最大啮合角 (度)
double feed_rate = 800.0; ///< 进给速度 (mm/min)
double safe_z = 15.0; ///< 安全高度 (mm)
double stock_to_leave = 0.5; ///< 留量 (mm)
};
/// 摆线铣削参数
struct TrochoidalParams {
double step_down = 1.0; ///< 每层切深 (mm)
double trochoid_radius = 2.5; ///< 摆线圈半径 (mm)
double step_forward = 1.0; ///< 每圈前进量 (mm)
double feed_rate = 600.0; ///< 进给速度 (mm/min)
double safe_z = 15.0; ///< 安全高度 (mm)
};
/// 残料加工参数
struct RestMachiningParams {
double step_down = 0.5; ///< 每层切深 (mm)
double step_over = 0.3; ///< 横向步距 (mm)
double feed_rate = 500.0; ///< 进给速度 (mm/min)
double safe_z = 15.0; ///< 安全高度 (mm)
double stock_threshold = 0.1; ///< 残料检测阈值 (mm)
};
/// 清根加工参数
struct PencilTracingParams {
double step_along = 0.2; ///< 沿角落方向的步距 (mm)
double feed_rate = 400.0; ///< 进给速度 (mm/min)
double safe_z = 15.0; ///< 安全高度 (mm)
double corner_angle_min = 5.0; ///< 最小检测角度 (度)
double corner_angle_max = 170.0; ///< 最大检测角度 (度)
};
/// 刀柄/刀杆定义(用于碰撞检测)
struct ToolHolder {
double diameter = 20.0; ///< 刀杆直径 (mm)
double length = 40.0; ///< 刀杆长度 (mm)
double clearance = 3.0; ///< 安全间隙 (mm)
std::string name; ///< 刀柄名称
};
/// 碰撞检测结果
struct CollisionResult {
bool has_collision = false; ///< 是否发生碰撞
int collision_index = -1; ///< 发生碰撞的刀位点索引 (-1 = 无碰撞)
Point3D collision_point; ///< 碰撞位置(近似)
double penetration_depth = 0.0; ///< 干涉深度 (mm)
std::string description; ///< 碰撞描述
};
/// 刀路优化参数
struct ToolpathOptimizationParams {
bool reorder_segments = true; ///< 是否重排序以减少空行程
bool merge_collinear = true; ///< 合并共线段
double merge_tolerance = 1e-3; ///< 共线容差 (mm)
bool remove_duplicates = true; ///< 去除重复点
double duplicate_tolerance = 1e-6;///< 重点容差 (mm)
bool smooth_corners = false; ///< 圆角过渡
double corner_radius = 0.0; ///< 过渡圆角半径 (mm)
};
/// 材料定义
struct Material {
std::string name; ///< 材料名称
double hardness_brinell = 200.0; ///< 布氏硬度
double specific_cutting_force = 2000.0; ///< 比切削力 (N/mm²)
double max_chip_thickness = 0.2; ///< 最大切屑厚度 (mm)
double max_feed_per_tooth = 0.3; ///< 最大每齿进给 (mm/tooth)
};
// ═══════════════════════════════════════════════════════════════════════════
// CAM 高级加工策略函数
// ═══════════════════════════════════════════════════════════════════════════
/// 自适应清除 (Adaptive Clearing)
///
/// 使用摆线/自适应刀路进行粗加工,根据材料负载动态调整步距。
/// 在低负载区域扩大步距(高速切削),在高负载/角落区域缩小步距(避免断刀)。
///
/// @param body B-Rep 实体模型
/// @param tool 使用的刀具
/// @param params 自适应清除参数
/// @return 自适应清除刀路
///
/// @ingroup core
[[nodiscard]] Toolpath adaptive_clearing(
const brep::BrepModel& body,
const Tool& tool,
const AdaptiveClearingParams& params);
/// 摆线铣削 (Trochoidal Milling)
///
/// 刀具沿圆形/摆线路径切入,避免全刃切削。
/// 适用于深槽、窄槽加工,减少刀具负载和振动。
///
/// @param slot 槽/边界曲线(定义槽的走向)
/// @param tool 使用的刀具
/// @param params 摆线铣削参数
/// @return 摆线铣削刀路
///
/// @ingroup core
[[nodiscard]] Toolpath trochoidal_milling(
const std::vector<Point3D>& slot,
const Tool& tool,
const TrochoidalParams& params);
/// 残料加工 (Rest Machining)
///
/// 检测前序大刀具未切削到的角落/窄区域,用小刀具进行残料清除。
/// 通过比较两次不同直径刀具的遍历范围,识别残料区域。
///
/// @param body B-Rep 实体模型
/// @param prev_tool 前序(较大)刀具
/// @param next_tool 后序(较小)刀具
/// @param params 残料加工参数
/// @return 残料加工刀路
///
/// @ingroup core
[[nodiscard]] Toolpath rest_machining(
const brep::BrepModel& body,
const Tool& prev_tool,
const Tool& next_tool,
const RestMachiningParams& params = RestMachiningParams{});
/// 清根加工 (Pencil Tracing)
///
/// 沿模型角落/交线走刀,清除前序加工无法到达的根部材料。
/// 检测曲面之间的凹角交界线(角 < corner_angle_max),
/// 沿交线生成单线刀路。
///
/// @param body B-Rep 实体模型
/// @param tool 使用的刀具(通常为球头刀)
/// @param params 清根加工参数
/// @return 清根刀路
///
/// @ingroup core
[[nodiscard]] Toolpath pencil_tracing(
const brep::BrepModel& body,
const Tool& tool,
const PencilTracingParams& params = PencilTracingParams{});
/// 刀柄碰撞检测 (Tool Holder Collision Check)
///
/// 沿刀路检查刀柄和刀杆是否与工件发生碰撞。
/// 使用快速包围盒预检 + 精确三角形碰撞测试。
///
/// @param toolpath 加工刀路
/// @param holder 刀柄/刀杆定义
/// @param body B-Rep 工件模型
/// @return 碰撞检测结果列表(每个刀位点一个结果)
///
/// @ingroup core
[[nodiscard]] std::vector<CollisionResult> tool_holder_collision_check(
const Toolpath& toolpath,
const ToolHolder& holder,
const brep::BrepModel& body);
/// 刀路优化 (Toolpath Optimization)
///
/// 优化刀路以减少非切削时间:
/// - 重排序段以最小化空行程(最近邻启发式)
/// - 合并共线相邻段
/// - 去除重复/过短段
/// - 可选圆角过渡
///
/// @param toolpath 待优化的原始刀路
/// @param params 优化参数
/// @return 优化后的刀路
///
/// @ingroup core
[[nodiscard]] Toolpath toolpath_optimization(
const Toolpath& toolpath,
const ToolpathOptimizationParams& params = ToolpathOptimizationParams{});
/// 进给优化 (Feed Rate Optimization)
///
/// 基于材料去除率动态调整进给速度:
/// - 估算每个刀位点的材料去除率(切削截面积 × 进给)
/// - 在去除率高的区域降低进给(保护刀具)
/// - 在去除率低的区域提高进给(提高效率)
///
/// @param toolpath 待优化的刀路
/// @param material 工件材料属性
/// @return 进给优化后的刀路(各段 feed_rate 已调整)
///
/// @ingroup core
[[nodiscard]] Toolpath feed_rate_optimization(
const Toolpath& toolpath,
const Material& material);
} // namespace vde::core
+394
View File
@@ -0,0 +1,394 @@
#pragma once
/**
* @file performance_tuning.h
* @brief 性能调优 — 任务图并行调度、工作窃取、内存池、缓存优化、数据布局
*
* 提供计算密集型任务的系统级性能优化工具:
* - parallel_task_graph — 基于任务依赖图的并行调度
* - work_stealing_scheduler — 工作窃取线程池
* - memory_pool_integration — 全局内存池(减少 malloc 开销)
* - cache_optimization_hints — 缓存对齐/预取提示
* - profile_guided_layout — 基于性能分析的数据布局优化
*
* @ingroup core
*/
#include "vde/core/point.h"
#include "vde/core/aabb.h"
#include <vector>
#include <string>
#include <memory>
#include <functional>
#include <future>
#include <atomic>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <type_traits>
#include <cstddef>
namespace vde::core {
// ═══════════════════════════════════════════════════════════════════════════
// 任务图并行调度
// ═══════════════════════════════════════════════════════════════════════════
/// 单个任务节点
struct TaskNode {
int id = 0; ///< 任务 ID
std::string name; ///< 任务名称
std::function<void()> func; ///< 任务执行函数
std::vector<int> dependencies; ///< 依赖任务 ID 列表
int priority = 0; ///< 优先级(越大越优先)
};
/// 并行任务图 — 基于拓扑排序 + 线程池的 DAG 调度器
///
/// 使用示例:
/// @code
/// ParallelTaskGraph graph(4); // 4 线程
/// graph.add_task({0, "read", []{ read_data(); }, {}});
/// graph.add_task({1, "proc1", []{ proc1(); }, {0}}); // 依赖任务 0
/// graph.add_task({2, "proc2", []{ proc2(); }, {0}}); // 依赖任务 0
/// graph.add_task({3, "merge", []{ merge(); }, {1,2}}); // 依赖 1,2
/// graph.execute();
/// @endcode
class ParallelTaskGraph {
public:
/// 构造函数
/// @param num_threads 线程数(0 = 硬件并发数)
explicit ParallelTaskGraph(int num_threads = 0);
~ParallelTaskGraph();
// 禁止拷贝
ParallelTaskGraph(const ParallelTaskGraph&) = delete;
ParallelTaskGraph& operator=(const ParallelTaskGraph&) = delete;
/// 添加任务节点
void add_task(const TaskNode& task);
/// 批量添加任务
void add_tasks(const std::vector<TaskNode>& tasks);
/// 执行所有任务(拓扑排序 + 并行调度)
/// 如果存在循环依赖,抛出 std::runtime_error
void execute();
/// 重置所有任务(可复用)
void reset();
/// 获取任务数
[[nodiscard]] size_t task_count() const { return tasks_.size(); }
/// 获取线程数
[[nodiscard]] int thread_count() const { return num_threads_; }
private:
int num_threads_;
std::vector<TaskNode> tasks_;
struct Impl;
std::unique_ptr<Impl> impl_;
};
/// 便捷函数:直接对任务列表执行并行图调度
///
/// @param tasks 任务图节点列表
/// @param num_threads 线程数(0 = 硬件并发数)
///
/// @ingroup core
void parallel_task_graph(
const std::vector<TaskNode>& tasks,
int num_threads = 0);
// ═══════════════════════════════════════════════════════════════════════════
// 工作窃取调度器
// ═══════════════════════════════════════════════════════════════════════════
/// 工作窃取调度器 — 线程池从任务队列中窃取工作
///
/// 每个线程维护自己的任务队列,空闲线程从其他线程队列窃取任务。
/// 适用于负载不均的批处理场景(如面片处理、CAD 算法随机化)。
class WorkStealingScheduler {
public:
/// 构造函数
/// @param num_threads 线程数(0 = 硬件并发数)
explicit WorkStealingScheduler(int num_threads = 0);
~WorkStealingScheduler();
// 禁止拷贝
WorkStealingScheduler(const WorkStealingScheduler&) = delete;
WorkStealingScheduler& operator=(const WorkStealingScheduler&) = delete;
/// 提交带优先级的任务
/// @param func 任务函数
/// @param priority 优先级(越大越优先,默认 0)
void submit(std::function<void()> func, int priority = 0);
/// 提交任务并返回 future
/// @tparam F 可调用对象类型
/// @tparam Args 参数类型
/// @param f 可调用对象
/// @param args 参数
/// @return 任务的 std::future
template<typename F, typename... Args>
auto submit_with_result(F&& f, Args&&... args)
-> std::future<decltype(f(args...))>;
/// 等待所有任务完成
void wait_all();
/// 获取活跃线程数
[[nodiscard]] int active_threads() const;
/// 获取队列中待处理任务数
[[nodiscard]] size_t pending_tasks() const;
/// 停止调度器
void shutdown();
private:
int num_threads_;
struct Impl;
std::unique_ptr<Impl> impl_;
};
/// 全局工作窃取调度器
///
/// @return 全局共享的 WorkStealingScheduler 实例
///
/// @ingroup core
[[nodiscard]] WorkStealingScheduler& work_stealing_scheduler();
// ═══════════════════════════════════════════════════════════════════════════
// 全局内存池集成
// ═══════════════════════════════════════════════════════════════════════════
/// 内存池统计数据
struct MemoryPoolStats {
size_t total_allocations = 0; ///< 总分配次数
size_t total_deallocations = 0; ///< 总释放次数
size_t current_bytes = 0; ///< 当前占用字节
size_t peak_bytes = 0; ///< 峰值占用字节
size_t cache_hits = 0; ///< 缓存命中(池中直接分配)
size_t cache_misses = 0; ///< 缓存未命中(需 malloc
};
/// 全局内存池集成
///
/// 单例内存池,为常见大小的 Point3D、Vector3D、AABB 等对象
/// 提供预分配池,减少频繁 malloc/free 的开销。
///
/// 使用方式:
/// @code
/// auto& pool = memory_pool_integration();
/// auto* pt = pool.allocate_point3d();
/// // ... 使用 pt ...
/// pool.deallocate_point3d(pt);
/// @endcode
class MemoryPoolIntegration {
public:
/// 获取单例
[[nodiscard]] static MemoryPoolIntegration& instance();
/// 分配一个 Point3D
[[nodiscard]] Point3D* allocate_point3d();
/// 释放一个 Point3D
void deallocate_point3d(Point3D* p);
/// 分配一个 Vector3D
[[nodiscard]] Vector3D* allocate_vector3d();
/// 释放一个 Vector3D
void deallocate_vector3d(Vector3D* v);
/// 分配指定大小的内存块
[[nodiscard]] void* allocate(size_t bytes);
/// 释放内存块
void deallocate(void* ptr, size_t bytes);
/// 获取统计信息
[[nodiscard]] MemoryPoolStats stats() const;
/// 重置池(释放所有缓存)
void reset();
/// 设置池大小
/// @param pool_size 每种大小的缓存数量
void set_pool_size(size_t pool_size);
/// 预热池(预分配指定数量的对象)
void warm_up(size_t count);
private:
MemoryPoolIntegration();
~MemoryPoolIntegration();
MemoryPoolIntegration(const MemoryPoolIntegration&) = delete;
MemoryPoolIntegration& operator=(const MemoryPoolIntegration&) = delete;
struct Impl;
std::unique_ptr<Impl> impl_;
};
/// 便捷函数:获取全局内存池
///
/// @return 全局 MemoryPoolIntegration 实例
///
/// @ingroup core
[[nodiscard]] inline MemoryPoolIntegration& memory_pool_integration() {
return MemoryPoolIntegration::instance();
}
// ═══════════════════════════════════════════════════════════════════════════
// 缓存优化提示
// ═══════════════════════════════════════════════════════════════════════════
/// 缓存行大小(典型值为 64 字节)
constexpr size_t CACHE_LINE_SIZE = 64;
/// 将值对齐到缓存行
template<typename T>
constexpr size_t cache_aligned_size() {
constexpr size_t s = sizeof(T);
return ((s + CACHE_LINE_SIZE - 1) / CACHE_LINE_SIZE) * CACHE_LINE_SIZE;
}
/// 缓存对齐分配器
template<typename T>
struct CacheAlignedAllocator {
using value_type = T;
CacheAlignedAllocator() = default;
template<typename U>
CacheAlignedAllocator(const CacheAlignedAllocator<U>&) {}
[[nodiscard]] T* allocate(std::size_t n) {
void* ptr = nullptr;
if (posix_memalign(&ptr, CACHE_LINE_SIZE, n * sizeof(T)) != 0) {
throw std::bad_alloc();
}
return static_cast<T*>(ptr);
}
void deallocate(T* ptr, std::size_t) {
free(ptr);
}
};
/// 缓存优化提示
///
/// 返回当前硬件平台的优化建议:
/// - 缓存行大小
/// - 预取距离(以缓存行为单位的步进距离)
/// - NUMA 节点信息(如果可用)
///
struct CacheOptimizationHints {
size_t l1_cache_size = 32 * 1024; ///< L1 数据缓存大小 (bytes)
size_t l2_cache_size = 256 * 1024; ///< L2 缓存大小 (bytes)
size_t l3_cache_size = 8 * 1024 * 1024; ///< L3 缓存大小 (bytes)
size_t cache_line_size = 64; ///< 缓存行大小 (bytes)
int numa_node_count = 1; ///< NUMA 节点数
bool hyperthreading = true; ///< 是否超线程
};
/// 获取缓存优化提示
///
/// @return 当前硬件平台的缓存优化提示
///
/// @ingroup core
[[nodiscard]] CacheOptimizationHints cache_optimization_hints();
/// 预取内存地址到缓存(编译器提示)
///
/// @param addr 要预取的内存地址
///
/// @ingroup core
inline void prefetch(const void* addr) {
__builtin_prefetch(addr, 0, 3);
}
/// 预取写入(使缓存行进入修改状态)
///
/// @param addr 要预取的内存地址
///
/// @ingroup core
inline void prefetch_write(const void* addr) {
__builtin_prefetch(addr, 1, 3);
}
/// 防止假共享的填充字段
///
/// 用法:将共享原子变量放在填充结构体中
/// @code
/// struct alignas(64) PaddedCounter {
/// std::atomic<int> value{0};
/// };
/// @endcode
template<size_t Alignment = CACHE_LINE_SIZE>
struct PaddedAtomic {
std::atomic<int> value{0};
char padding[Alignment - sizeof(std::atomic<int>)]{};
};
static_assert(sizeof(PaddedAtomic<CACHE_LINE_SIZE>) == CACHE_LINE_SIZE,
"PaddedAtomic must be exactly one cache line");
// ═══════════════════════════════════════════════════════════════════════════
// 数据布局优化 (Profile-Guided Layout)
// ═══════════════════════════════════════════════════════════════════════════
/// 访问频率记录
struct AccessRecord {
std::string field_name; ///< 字段名
size_t access_count = 0; ///< 访问次数
size_t cache_misses = 0; ///< 缓存未命中次数
double hotness = 0.0; ///< 热度(访问/总访问)
};
/// SoA (Structure of Arrays) 布局变换方案
///
/// 将 AoS 布局(结构体数组)转换为 SoA 布局(数组结构体)以改善缓存利用率。
/// 适用场景:遍历大量 Point3D/Vector3D 进行坐标变换、碰撞检测等。
struct SoALayoutPlan {
std::vector<std::string> hot_fields; ///< 热字段列表(应放在前面)
std::vector<std::string> cold_fields; ///< 冷字段列表(可放在后面)
size_t stride_bytes = 0; ///< 行跨距 (bytes)
double estimated_improvement = 0.0; ///< 预估性能提升比例
};
/// 基于性能分析的数据布局优化
///
/// 分析给定类型的访问模式,生成 SoA 布局变换方案。
/// 热字段(频繁访问)放在一起以提高缓存命中率,
/// 冷字段(偶尔访问)分离以减少缓存污染。
///
/// @param access_records 各字段的访问记录
/// @param type_name 类型名称
/// @return SoA 布局变换方案
///
/// @ingroup core
[[nodiscard]] SoALayoutPlan profile_guided_layout(
const std::vector<AccessRecord>& access_records,
const std::string& type_name = "");
/// Point3D 的 SoA 布局
struct Point3DSoA {
std::vector<double> x; ///< X 坐标数组
std::vector<double> y; ///< Y 坐标数组
std::vector<double> z; ///< Z 坐标数组
/// 从 AoS 转换为 SoA
static Point3DSoA from_aos(const std::vector<Point3D>& points);
/// 从 SoA 转换为 AoS
std::vector<Point3D> to_aos() const;
/// 点数
[[nodiscard]] size_t size() const { return x.size(); }
/// 清空
void clear() { x.clear(); y.clear(); z.clear(); }
};
} // namespace vde::core
+202
View File
@@ -0,0 +1,202 @@
#pragma once
/**
* @file advanced_intersection.h
* @brief 高级曲面求交 — 鲁棒 SSI(三阶段)、曲线-曲面求交、自交检测
*
* 对标 CGM 的工业级曲面求交算法,提供:
* - 鲁棒曲面-曲面求交(三阶段:AABB细分→Newton精化→奇异点处理)
* - 曲线-曲面求交
* - 曲面自交检测
*
* @ingroup curves
*/
#include "vde/curves/nurbs_curve.h"
#include "vde/curves/nurbs_surface.h"
#include "vde/core/point.h"
#include "vde/core/aabb.h"
#include <vector>
#include <array>
#include <utility>
#include <functional>
#include <limits>
namespace vde::curves {
using core::Point3D;
using core::Vector3D;
using core::AABB3D;
// ═══════════════════════════════════════════════════════════
// Robust SSI — 鲁棒曲面-曲面求交
// ═══════════════════════════════════════════════════════════
/// SSI 交线段(参数空间)
struct SSISegment {
/// 曲面 A 上的参数点 (u,v)
std::vector<std::pair<double, double>> params_a;
/// 曲面 B 上的参数点 (u,v)
std::vector<std::pair<double, double>> params_b;
/// 3D 空间点
std::vector<Point3D> points;
/// 是否为奇异交线(切线接触、重叠等)
bool is_singular = false;
/// 奇异类型描述
std::string singularity_type;
};
/// SSI 选项
struct SSIOptions {
/// 阶段1AABB 细分参数
int max_subdivision_depth = 8; ///< 最大细分深度
double subdivision_tolerance = 1e-3; ///< 细分终止容差
int min_patch_samples = 4; ///< 每子面片最少采样点
/// 阶段2Newton 精化参数
double newton_tolerance = 1e-12; ///< Newton 收敛容差
int max_newton_iter = 30; ///< Newton 最大迭代次数
double step_damping = 0.5; ///< 步长阻尼因子
/// 阶段3:奇异点检测参数
double singular_condition_threshold = 1e-8; ///< 条件数阈值(小于此值判为奇异)
double tangent_contact_angle_tol = 0.01; ///< 切线接触角度容差(弧度)
bool detect_overlap = true; ///< 是否检测重叠面
};
/// SSI 完整结果
struct SSIResult {
/// 交线段列表
std::vector<SSISegment> segments;
/// 阶段统计
int phase1_subdivisions = 0; ///< 细分次数
int phase1_candidates = 0; ///< 候选种子数
int phase2_converged = 0; ///< Newton 收敛数
int phase2_diverged = 0; ///< Newton 发散数
int phase3_singularities = 0; ///< 检测到的奇异点数
double total_time_ms = 0.0; ///< 总耗时(毫秒)
bool success = false; ///< 是否成功完成
};
/**
* @brief 鲁棒曲面-曲面求交(三阶段)
*
* **阶段1:边界盒预筛选 + 自适应细分**
* - 计算两曲面 AABB 盒,快速排除不相交区域
* - 在参数域自适应四叉树细分,定位交线种子点
* - 使用区间算术评估曲面片相交性
*
* **阶段2Newton-Raphson 精化**
* - 从种子点启动 Newton 迭代求解 F(u1,v1,u2,v2)=0
* - 收敛到 1e-12 高精度
* - 沿交线追踪(marching)生成连续交线段
*
* **阶段3:奇异点检测 + 特殊处理**
* - Jacobian 条件数检测:识别切线接触、高阶接触
* - 奇异点处使用 subdivision + 约束优化
* - 重叠面使用采样投票 + 特征值分析
*
* @param surf_a 曲面 A
* @param surf_b 曲面 B
* @param options SSI 选项
* @return 交线结果(含阶段统计)
*
* @note 对标 CGM Robust SSI / ACIS intersector
* @ingroup curves
*/
[[nodiscard]] SSIResult robust_ssi(
const NurbsSurface& surf_a,
const NurbsSurface& surf_b,
const SSIOptions& options = {});
// ═══════════════════════════════════════════════════════════
// Curve-Surface Intersection — 曲线-曲面求交
// ═══════════════════════════════════════════════════════════
/// 曲线-曲面交点
struct CSIntersectionPoint {
double t; ///< 曲线上的参数
double u, v; ///< 曲面上的参数 (u,v)
Point3D position; ///< 3D 交点坐标
double distance; ///< 交点处曲线到曲面的距离
bool tangent_contact = false; ///< 是否为切线接触
int multiplicity = 1; ///< 交点重数
};
/**
* @brief 曲线-曲面求交
*
* 计算 NURBS 曲线与 NURBS 曲面的所有交点。
* 算法:
* 1. 将曲线离散为线性段,建立曲线 AABB 加速结构
* 2. 在曲面参数域使用细分 + Newton 精化
* 3. 对切线接触情况使用更高阶方法
*
* @param curve NURBS 曲线
* @param surf NURBS 曲面
* @param tolerance 收敛容差(默认 1e-10
* @return 交点列表(按曲线参数 t 排序)
*
* @note 对标 CGM Curve-Surface Intersection
* @ingroup curves
*/
[[nodiscard]] std::vector<CSIntersectionPoint> curve_surface_intersection(
const NurbsCurve& curve,
const NurbsSurface& surf,
double tolerance = 1e-10);
// ═══════════════════════════════════════════════════════════
// Self-Intersection Detection — 自交检测
// ═══════════════════════════════════════════════════════════
/// 自交区域
struct SelfIntersectionRegion {
/// 参数空间中检测到自交的子区域范围
double u_min, u_max, v_min, v_max;
/// 自交类型
enum Type {
NONE = 0,
EDGE_OVERLAP = 1, ///< 边界重叠
INTERIOR_CROSS = 2, ///< 内部交叉
TANGENT_CONTACT = 3, ///< 切线接触
LOCAL_LOOP = 4 ///< 局部环
};
Type type = NONE;
/// 3D 空间中最近交点
Point3D closest_intersection;
double min_distance = std::numeric_limits<double>::max();
/// 曲面上最近自交处的法线夹角
double normal_angle_deg = 0.0;
};
/// 自交检测结果
struct SelfIntersectionResult {
bool has_self_intersection = false;
std::vector<SelfIntersectionRegion> regions;
double global_min_distance = std::numeric_limits<double>::max();
int total_checks = 0;
int intersecting_pairs = 0;
double detection_time_ms = 0.0;
};
/**
* @brief 曲面自交检测
*
* 检测 NURBS 曲面是否自交(不同参数值映射到同一点/相近点)。
* 算法:
* 1. 对曲面参数域构建 BVH 加速结构
* 2. 对每对不相邻的 BVH 节点,检测是否在 3D 空间相交
* 3. 对疑似自交区域进行 Newton 精化确认
* 4. 分类自交类型(交叉、重叠、切线接触、局部环)
*
* @param surface NURBS 曲面
* @param tolerance 自交检测容差(3D 空间距离,默认 1e-8)
* @return 自交检测结果
*
* @note 对标 CGM Self-Intersection Check / ACIS self-intersect
* @ingroup curves
*/
[[nodiscard]] SelfIntersectionResult self_intersection_detection(
const NurbsSurface& surface,
double tolerance = 1e-8);
} // namespace vde::curves
+365
View File
@@ -0,0 +1,365 @@
#pragma once
/**
* @file class_a_surfacing.h
* @brief CGM Class-A 级曲面工具 — G3 过渡、曲率匹配、高光线、反射线、等照度、诊断、保形修改
*
* 对标 Dassault CGM 的 Class-A 曲面功能,提供汽车/航空工业级的曲面质量控制:
* - G3 连续性过渡(位置+切平面+曲率+曲率变化率连续)
* - 曲率匹配优化(最小二乘调整控制点使曲率场连续)
* - 高光线/反射线/等照度分析(工业标准曲面光顺检测)
* - 综合曲面诊断报告(多项指标评分)
* - 保形修改(保持特征边界的曲面变形)
*
* @ingroup curves
*/
#include "vde/curves/nurbs_curve.h"
#include "vde/curves/nurbs_surface.h"
#include "vde/core/point.h"
#include <vector>
#include <array>
#include <utility>
#include <string>
#include <functional>
namespace vde::curves {
using core::Point3D;
using core::Vector3D;
// ═══════════════════════════════════════════════════════════
// G3 Blend — G3 连续性过渡曲面
// ═══════════════════════════════════════════════════════════
/// 边参数:定义过渡曲面的公共边方向与范围
struct EdgeParams {
int edge_a = 0; ///< surf_a 的边界索引 (0=umin, 1=umax, 2=vmin, 3=vmax)
int edge_b = 0; ///< surf_b 的边界索引
double blend_width = 0.1; ///< 过渡带宽度(参数域比例)
bool align_orientation = true; ///< 是否自动对齐曲面朝向
};
/// G3 连续性过渡结果
struct G3BlendResult {
NurbsSurface blend_surface; ///< 过渡曲面
double max_position_error = 0.0; ///< 最大位置误差
double max_tangent_error = 0.0; ///< 最大切平面角度误差(弧度)
double max_curvature_error = 0.0; ///< 最大曲率偏差
double max_curvature_derivative_error = 0.0; ///< 最大曲率变化率偏差
bool g0_ok = false;
bool g1_ok = false;
bool g2_ok = false;
bool g3_ok = false;
};
/**
* @brief G3 连续性过渡曲面
*
* 在两面公共边界处构造过渡曲面,使过渡面与两边曲面均达到 G3 连续。
* 算法:
* 1. 检测公共边界,提取边界曲线与跨边界导数(1阶、2阶、3阶)
* 2. 构造 4 排过渡控制点,分别对应位置、切平面、曲率、曲率变化率约束
* 3. 求解最小二乘系统保证 G3 连续
*
* @param surf_a 曲面 A
* @param surf_b 曲面 B
* @param params 边参数(边界索引、过渡宽度等)
* @return G3 过渡结果(含过渡曲面与连续性验证数据)
*
* @note 对标 CGM G3 Filling 功能
* @ingroup curves
*/
[[nodiscard]] G3BlendResult g3_blend(
const NurbsSurface& surf_a,
const NurbsSurface& surf_b,
const EdgeParams& params);
// ═══════════════════════════════════════════════════════════
// Curvature Matching — 曲率匹配优化
// ═══════════════════════════════════════════════════════════
/// 曲率匹配选项
struct CurvatureMatchOptions {
double tolerance = 1e-8; ///< 收敛容差
int max_iterations = 50; ///< 最大迭代次数
int samples_per_edge = 20; ///< 边界采样点数
double regularization = 0.01; ///< Tikhonov 正则化系数
bool preserve_boundary = true; ///< 是否保持非匹配边界不变
};
/// 曲率匹配结果
struct CurvatureMatchResult {
NurbsSurface matched_surface_b; ///< 匹配后的曲面 B
double initial_rms_curvature_diff = 0.0; ///< 初始曲率 RMS 差
double final_rms_curvature_diff = 0.0; ///< 最终曲率 RMS 差
int iterations = 0; ///< 实际迭代次数
bool converged = false; ///< 是否收敛
std::vector<Point3D> displacement; ///< 控制点位移向量
};
/**
* @brief 曲率匹配优化
*
* 调整 surf_b 的控制点使两曲面沿公共边界的曲率场匹配,达到 G2+ 连续。
* 使用 Levenberg-Marquardt 非线性最小二乘优化,约束边界控制点位移最小。
*
* @param surf_a 基准曲面 A(不变)
* @param surf_b 待匹配曲面 B(将被修改)
* @param options 优化选项
* @return 匹配结果(含优化后的曲面 B)
*
* @note 对标 CGM Match Surface 功能
* @ingroup curves
*/
[[nodiscard]] CurvatureMatchResult curvature_matching(
const NurbsSurface& surf_a,
const NurbsSurface& surf_b,
const CurvatureMatchOptions& options = {});
// ═══════════════════════════════════════════════════════════
// Highlight Lines — 高光线分析
// ═══════════════════════════════════════════════════════════
/// 高光线参数
struct HighlightParams {
std::vector<Vector3D> light_directions; ///< 多个光源方向(均自动归一化)
int res_u = 50; ///< u 方向分辨率
int res_v = 50; ///< v 方向分辨率
int num_bands = 8; ///< 光带数量
double band_width = 0.05; ///< 带宽(参数域比例)
};
/// 高光线分析结果
struct HighlightResult {
int res_u, res_v; ///< 网格分辨率
/// 高光线掩码网格 [dir_idx][u][v] ∈ {0,1}
std::vector<std::vector<std::vector<int>>> band_mask;
/// 各方向高光线连续性评分 [0,1]
std::vector<double> continuity_scores;
/// 综合评分
double overall_score = 0.0;
/// 不连续点列表 (u, v, dir_idx)
std::vector<std::tuple<double, double, int>> discontinuities;
};
/**
* @brief 高光线分析
*
* 模拟平行光源在曲面上的反射高光线,检测光线方向的几何不连续。
* 高光线 ≤ C1 的断裂 = 曲面在此处仅有 C1 连续。
* 高光线 C2 断裂 = 曲率不连续。
*
* @param surface NURBS 曲面
* @param light_dirs 光源方向列表
* @param res_u u 方向分辨率
* @param res_v v 方向分辨率
* @param num_bands 光带数量
* @return 高光线分析结果
*
* @note 对标 CGM Highlight Lines Analysis
* @ingroup curves
*/
[[nodiscard]] HighlightResult highlight_lines(
const NurbsSurface& surface,
const std::vector<Vector3D>& light_dirs,
int res_u, int res_v, int num_bands = 8);
// ═══════════════════════════════════════════════════════════
// Reflection Lines — 反射线分析
// ═══════════════════════════════════════════════════════════
/// 反射线分析结果
struct ReflectionResult {
int res_u, res_v; ///< 网格分辨率
/// 反射线方向场 grid[u][v] = 反射光线方向
std::vector<std::vector<Vector3D>> reflection_field;
/// 反射线扭曲度 grid[u][v] ∈ [0,∞)
std::vector<std::vector<double>> distortion;
double max_distortion = 0.0;
double mean_distortion = 0.0;
bool is_fair = false; ///< 是否判定为光顺
};
/**
* @brief 反射线分析
*
* 计算虚拟环境(点光源或平行光)在曲面上的镜面反射线模式。
* 通过计算反射方向场的扭曲度评估曲面光顺性。
*
* 算法:
* law_of_reflection: r = 2(n·l)n - l (入射光方向 l,法线 n)
* 扭曲度 = reflection_field 的方向导数幅值
*
* @param surface NURBS 曲面
* @param eye 观察点位置
* @param light 光源位置(若为平行光则传入方向向量远端)
* @param res_u u 方向分辨率
* @param res_v v 方向分辨率
* @return 反射线分析结果
*
* @note 对标 CGM Reflection Lines / Isophotes Analysis
* @ingroup curves
*/
[[nodiscard]] ReflectionResult reflection_lines(
const NurbsSurface& surface,
const Point3D& eye,
const Point3D& light,
int res_u, int res_v);
// ═══════════════════════════════════════════════════════════
// Iso-Photes — 等照度分析
// ═══════════════════════════════════════════════════════════
/// 等照度线分析结果
struct IsoPhoteResult {
int res_u, res_v; ///< 网格分辨率
/// 照度值网格 ∈ [-1, 1](光源方向·法线的点积)
std::vector<std::vector<double>> illumination;
/// 等照度线密度分布(直方图)
std::vector<double> iso_histogram;
/// 等照度线连续性 — 梯度突变点
std::vector<std::pair<double,double>> gradient_discontinuities;
double grad_max = 0.0;
double grad_mean = 0.0;
};
/**
* @brief 等照度分析
*
* 计算光源照射下曲面上的等照度线(恒定 cosθ 线)。
* 等照度线在 G1 连续处平滑,在仅有 C0 处出现转折。
* 等照度线的质量直接反映曲面光顺度:
* - 间距均匀 → 曲率均匀
* - 无抖动 → 高阶连续性好
*
* @param surface NURBS 曲面
* @param res 分辨率(res × res 采样点)
* @return 等照度分析结果
*
* @note 对标 CGM Iso-Photes Analysis
* @ingroup curves
*/
[[nodiscard]] IsoPhoteResult iso_photes(
const NurbsSurface& surface,
int res);
// ═══════════════════════════════════════════════════════════
// Surface Diagnosis — 综合曲面诊断报告
// ═══════════════════════════════════════════════════════════
/// 诊断等级
enum class DiagnosisGrade {
A_CLASS = 0, ///< A 级曲面 — 通过所有检测
B_CLASS = 1, ///< B 级曲面 — 可接受,有轻微缺陷
C_CLASS = 2, ///< C 级曲面 — 需要修复
FAIL = 3 ///< 不合格
};
/// 子项诊断结果
struct DiagnosisItem {
std::string name; ///< 诊断项名称
double value = 0.0; ///< 测量值
double threshold = 0.0; ///< 阈值
bool pass = false; ///< 是否通过
std::string description; ///< 描述
};
/// 综合曲面诊断报告
struct SurfaceDiagnosisReport {
DiagnosisGrade grade = DiagnosisGrade::FAIL;
/// 高斯曲率诊断
DiagnosisItem gaussian_range; ///< 高斯曲率范围
DiagnosisItem gaussian_continuity; ///< 高斯曲率连续性
/// 平均曲率诊断
DiagnosisItem mean_range; ///< 平均曲率范围
/// 高光线诊断
DiagnosisItem highlight_score; ///< 高光线评分
/// 反射线诊断
DiagnosisItem reflection_distortion; ///< 反射扭曲度
/// 等照度诊断
DiagnosisItem isophote_gradient; ///< 等照度梯度
/// 法线连续性
DiagnosisItem normal_jump; ///< 最大法线跳跃(角度°)
/// 主曲率方向场
DiagnosisItem principal_direction_flow; ///< 主方向场平滑度
/// 可展性
DiagnosisItem developability; ///< 可展面检测
double overall_score = 0.0; ///< 综合评分 [0, 100]
std::string recommendation; ///< 修复建议
};
/**
* @brief 综合曲面诊断报告
*
* 对单张 NURBS 曲面进行多项工业级质量检测,生成诊断报告:
* 1. 高斯/平均曲率范围及连续性
* 2. 高光线分析(4方向)
* 3. 反射线扭曲度
* 4. 等照度梯度
* 5. 法线连续性(内部采样)
* 6. 主曲率方向场流畅度
* 7. 可展面检测
*
* @param surface NURBS 曲面
* @return 综合诊断报告
*
* @note 对标 CGM Surface Diagnosis / CATIA Generative Shape Design
* @ingroup curves
*/
[[nodiscard]] SurfaceDiagnosisReport surface_diagnosis(
const NurbsSurface& surface);
// ═══════════════════════════════════════════════════════════
// Shape Modification — 保形修改
// ═══════════════════════════════════════════════════════════
/// 约束点
struct ShapeConstraint {
Point3D target_point; ///< 目标位置
double u = 0.0; ///< 曲面参数 u
double v = 0.0; ///< 曲面参数 v
double weight = 1.0; ///< 约束权重
bool fix_position = true; ///< true=位置约束, false=仅法向约束
Vector3D target_normal; ///< 目标法向(仅 fix_position=false 时使用)
};
/// 保形修改结果
struct ShapeModificationResult {
NurbsSurface modified_surface; ///< 修改后的曲面
std::vector<Point3D> control_displacements; ///< 控制点位移
double max_displacement = 0.0; ///< 最大控制点位移
double energy_preserved_ratio = 0.0; ///< 应变能保持率 (0~1)
double boundary_deviation = 0.0; ///< 边界偏差
int iterations = 0; ///< 迭代次数
};
/**
* @brief 保形修改
*
* 在约束条件下修改曲面控制点,同时最小化曲面变形能量,
* 保持曲面的整体形状特征(边界、特征线等)。
*
* 算法:基于薄板样条能量最小化的约束优化
* E = Σ (||S(u_i,v_i) - target_i||² · w_i) + λ · bending_energy(S)
*
* @param surface NURBS 曲面
* @param constraints 约束点列表
* @return 修改结果
*
* @note 对标 CGM Shape Modification / Control Point Morphing
* @ingroup curves
*/
[[nodiscard]] ShapeModificationResult shape_modification(
const NurbsSurface& surface,
const std::vector<ShapeConstraint>& constraints);
} // namespace vde::curves