feat(v10): tolerant modeling + Class-A deep + hex mesh + constraint solver + drawing standards
v10.1 — Tolerant Modeling (对标 Parasolid): - tolerant_modeling.h/.cpp: TolerantVertex/Edge, merge_within_tolerance (BFS) - gap_bridging (free edge detection → triangle filling) - overlap_resolution (normal+centroid+AABB detection) - tolerant_boolean (heal→degenerate detect→boolean→heal) + BooleanDiagnostic - import_heal_pipeline (STEP one-shot repair) - ssi_boolean enhanced: coplanar/collinear/tangent detection, GMP on all classify paths - step_import enhanced: broken file recovery, non-standard entity mapping, diagnostic report - 30 tests, 4112 total lines v10.2 — Class-A Deep + Hex Mesh (对标 CGM + ANSYS): - class_a_surfacing enhanced: g3_blend_with_constraints, surface_energy_minimization - curvature_continuity_optimization, reflection_line_discontinuity (+720 lines) - fea_mesh enhanced: mapped_hex, submapped_hex, multi_block_hex (TFI), hex_quality_optimization (+522 lines) - 22 tests v10.3 — Constraint Solver + Drawing Standards (对标 D-Cubed + AutoCAD): - constraint_solver enhanced: DOFAnalyzer, RedundancyDetector, ConstraintPropagator, KinematicChainSolver - drawing_standards.h/.cpp: IsoStandard (ISO 128/129), AnsiStandard (ASME Y14.5), JisStandard (JIS B 0001) - 12 tests 12 files, ~5000 lines, 64 tests. Target: 87% → 93%
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
namespace vde::brep {
|
||||
|
||||
@@ -350,6 +351,251 @@ private:
|
||||
const Eigen::VectorXd& f) const;
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// DOFAnalyzer — 详细自由度分析器
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// DOF 分解方向描述
|
||||
struct DOFDirection {
|
||||
/// 平移方向:x, y, z 是否被约束
|
||||
bool tx_free = true, ty_free = true, tz_free = true;
|
||||
/// 旋转方向:绕 x, y, z 是否被约束
|
||||
bool rx_free = true, ry_free = true, rz_free = true;
|
||||
};
|
||||
|
||||
/// DOF 分析详细结果
|
||||
struct DOFDetailedResult {
|
||||
int node_index = -1;
|
||||
std::string node_name;
|
||||
int translational_dof_remaining = 3; ///< 剩余平移自由度
|
||||
int rotational_dof_remaining = 3; ///< 剩余旋转自由度
|
||||
DOFDirection free_directions; ///< 哪些方向未约束
|
||||
std::vector<int> constraints_used; ///< 涉及约束索引
|
||||
bool is_fully_constrained = false; ///< 完全约束
|
||||
bool is_over_constrained = false; ///< 过度约束
|
||||
std::string summary; ///< 可读摘要
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 零件自由度分析器
|
||||
*
|
||||
* 将每个零件的 6 个 DOF 分解为平移(3)和旋转(3),
|
||||
* 根据约束类型计算每个方向上的自由/约束状态。
|
||||
*
|
||||
* @ingroup brep
|
||||
*/
|
||||
class DOFAnalyzer {
|
||||
public:
|
||||
/// 执行全图 DOF 分析
|
||||
[[nodiscard]] std::vector<DOFDetailedResult> analyze(const ConstraintGraph& graph) const;
|
||||
|
||||
/// 获取单个零件的自由方向
|
||||
[[nodiscard]] DOFDirection free_directions(const ConstraintGraph& graph, int node_idx) const;
|
||||
|
||||
/// 列出零件剩余的自由运动方向描述
|
||||
[[nodiscard]] std::vector<std::string> free_direction_names(
|
||||
const ConstraintGraph& graph, int node_idx) const;
|
||||
|
||||
/// 分析所有约束后的全局 DOF 状态
|
||||
[[nodiscard]] std::string global_dof_summary(const ConstraintGraph& graph) const;
|
||||
|
||||
private:
|
||||
/// 根据约束类型,返回对 node_a 的平移/旋转约束影响
|
||||
static void constraint_impact(ConstraintType type, bool is_node_a,
|
||||
int& trans_count, int& rot_count,
|
||||
DOFDirection& dir);
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// RedundancyDetector — 冗余约束检测器
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 冗余约束建议
|
||||
struct RedundancySuggestion {
|
||||
int constraint_index = -1; ///< 冗余约束索引
|
||||
int node_index = -1; ///< 受影响的节点
|
||||
std::string reason; ///< 原因描述
|
||||
int dof_impact = 0; ///< 移除后释放的 DOF 数
|
||||
std::string action; ///< 建议操作(删除/修改/保留)
|
||||
};
|
||||
|
||||
/// 约束冲突信息
|
||||
struct ConstraintConflict {
|
||||
int constraint_a = -1;
|
||||
int constraint_b = -1;
|
||||
int shared_node = -1; ///< 冲突所在的公共节点
|
||||
std::string description;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 冗余约束检测器
|
||||
*
|
||||
* 检测约束图中的冗余约束和约束冲突:
|
||||
* - 类型级冗余:同节点对之间存在多个相同类型的约束
|
||||
* - 拓扑级冗余:约束消除的 DOF 总量超出 6
|
||||
* - 语义冲突:约束类型相互矛盾(如 Coincident + Distance ≠ 0)
|
||||
*
|
||||
* @ingroup brep
|
||||
*/
|
||||
class RedundancyDetector {
|
||||
public:
|
||||
/// 全图检测冗余
|
||||
[[nodiscard]] std::vector<RedundancySuggestion> detect(const ConstraintGraph& graph) const;
|
||||
|
||||
/// 针对特定节点检测
|
||||
[[nodiscard]] std::vector<RedundancySuggestion> detect_for_node(
|
||||
const ConstraintGraph& graph, int node_idx) const;
|
||||
|
||||
/// 检测约束冲突
|
||||
[[nodiscard]] std::vector<ConstraintConflict> detect_conflicts(
|
||||
const ConstraintGraph& graph) const;
|
||||
|
||||
/// 生成可读报告
|
||||
[[nodiscard]] std::string report(const ConstraintGraph& graph) const;
|
||||
|
||||
private:
|
||||
/// 判断两个约束是否冲突
|
||||
static bool are_conflicting(ConstraintType a, ConstraintType b);
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// ConstraintPropagator — 约束传播器
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 传播结果
|
||||
struct PropagateResult {
|
||||
bool success = false;
|
||||
std::vector<int> affected_nodes; ///< 受影响的节点索引
|
||||
std::vector<int> affected_constraints; ///< 受影响的约束索引
|
||||
std::vector<std::string> changes; ///< 变更描述
|
||||
std::string message; ///< 可读消息
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 约束传播器
|
||||
*
|
||||
* 修改一个约束后,沿依赖图传播更新:
|
||||
* 1. 计算图拓扑排序(BFS 从固定节点出发)
|
||||
* 2. 标记受影响的下游节点
|
||||
* 3. 增量重新求解受影响的部分
|
||||
*
|
||||
* @ingroup brep
|
||||
*/
|
||||
class ConstraintPropagator {
|
||||
public:
|
||||
/**
|
||||
* @brief 修改约束并传播
|
||||
*
|
||||
* @param graph 约束图
|
||||
* @param assembly 装配体
|
||||
* @param constraint_idx 被修改约束索引
|
||||
* @param new_value 新值
|
||||
* @param new_type 新类型(可选:不修改则设为相同值)
|
||||
* @param solver 求解器(可选:用于增量求解)
|
||||
* @return 传播结果
|
||||
*/
|
||||
[[nodiscard]] PropagateResult propagate(
|
||||
ConstraintGraph& graph,
|
||||
Assembly& assembly,
|
||||
int constraint_idx,
|
||||
double new_value,
|
||||
ConstraintType new_type,
|
||||
NewtonRaphsonSolver* solver = nullptr);
|
||||
|
||||
/// 计算依赖传播顺序(BFS)
|
||||
[[nodiscard]] std::vector<int> compute_dependency_order(
|
||||
const ConstraintGraph& graph, int start_node) const;
|
||||
|
||||
/// 获取约束之间的依赖深度
|
||||
[[nodiscard]] int dependency_depth(
|
||||
const ConstraintGraph& graph, int a_idx, int b_idx) const;
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// KinematicChainSolver — 闭环机构求解器
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 运动学链的连杆描述
|
||||
struct ChainLink {
|
||||
int node_index = -1; ///< 对应的约束图节点
|
||||
double length = 1.0; ///< 连杆长度(相对于前一节点)
|
||||
double twist_angle = 0.0; ///< 扭转角(弧度)
|
||||
double offset = 0.0; ///< 偏距
|
||||
std::string label; ///< 标签
|
||||
};
|
||||
|
||||
/// 闭环条件
|
||||
struct LoopClosure {
|
||||
int start_node = -1; ///< 环路起始节点
|
||||
int end_node = -1; ///< 环路终止节点
|
||||
ConstraintType closure_type = ConstraintType::Coincident;
|
||||
double closure_value = 0.0; ///< 目标间距/角度
|
||||
double tolerance = 1e-6; ///< 容差
|
||||
};
|
||||
|
||||
/// 运动学求解结果
|
||||
struct KinematicResult {
|
||||
bool solved = false;
|
||||
int iterations = 0;
|
||||
double final_error = 0.0;
|
||||
std::vector<double> joint_angles; ///< 求解出的关节角度
|
||||
std::vector<core::Transform3D> poses; ///< 求解出的位姿
|
||||
std::string message;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 闭环机构求解器
|
||||
*
|
||||
* 求解闭环运动学链的关节角度:
|
||||
* - 将闭环约束表示为非线性方程组
|
||||
* - 使用 Newton-Raphson 迭代求解
|
||||
* - 支持任意长度的串行链 + 末端闭合条件
|
||||
*
|
||||
* @ingroup brep
|
||||
*/
|
||||
class KinematicChainSolver {
|
||||
public:
|
||||
/** @brief DH 参数法:单个连杆变换(公开,供测试使用) */
|
||||
static core::Transform3D dh_transform(double theta, double d,
|
||||
double a, double alpha);
|
||||
|
||||
/** @brief 求解闭环运动学链 */
|
||||
[[nodiscard]] KinematicResult solve_closed_chain(
|
||||
ConstraintGraph& graph,
|
||||
Assembly& assembly,
|
||||
const std::vector<ChainLink>& links,
|
||||
const LoopClosure& closure);
|
||||
|
||||
/** @brief 前向运动学:给定关节角 → 位姿 */
|
||||
[[nodiscard]] std::vector<core::Transform3D> forward_kinematics(
|
||||
const Assembly& assembly,
|
||||
const std::vector<ChainLink>& links,
|
||||
const std::vector<double>& joint_angles) const;
|
||||
|
||||
/** @brief 逆向运动学:给定目标位姿 → 关节角 */
|
||||
[[nodiscard]] std::vector<double> inverse_kinematics(
|
||||
const Assembly& assembly,
|
||||
const std::vector<ChainLink>& links,
|
||||
const core::Transform3D& target_pose) const;
|
||||
|
||||
/** @brief 检查链是否可达 */
|
||||
[[nodiscard]] bool is_reachable(
|
||||
const std::vector<ChainLink>& links,
|
||||
const core::Point3D& target) const;
|
||||
|
||||
private:
|
||||
/// DH 参数法:单个连杆变换
|
||||
static core::Transform3D dh_transform(double theta, double d,
|
||||
double a, double alpha);
|
||||
|
||||
/// 评估闭环残差
|
||||
static double evaluate_closure(
|
||||
const Assembly& assembly,
|
||||
const std::vector<ChainLink>& links,
|
||||
const std::vector<double>& angles,
|
||||
const LoopClosure& closure);
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// 向后兼容 API(保留旧接口)
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file drawing_standards.h
|
||||
* @brief 工程制图标准 — ISO 128/129, ASME Y14.5, JIS B 0001
|
||||
*
|
||||
* 提供三大国际制图标准的完整规则配置:
|
||||
* - IsoStandard: ISO 128/129(线型/字体/箭头/公差格式)
|
||||
* - AnsiStandard: ASME Y14.5-2018(尺寸与公差标注)
|
||||
* - JisStandard: JIS B 0001(机械制图)
|
||||
*
|
||||
* 支持一键应用标准(apply_standard/apply_standard_by_name)
|
||||
* 自动配置尺寸样式、视图投影角度(第一角/第三角)
|
||||
*
|
||||
* @ingroup brep
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
namespace vde::brep {
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// 线型枚举
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 标准线型(对应 ISO 128-20 / ASME Y14.2 / JIS B 0001)
|
||||
enum class LineType {
|
||||
Continuous, ///< 实线(可见轮廓线)— ISO 01.1 / ASME visible
|
||||
Dashed, ///< 虚线(隐藏线)— ISO 02.1 / ASME hidden
|
||||
Chain, ///< 点划线(中心线)— ISO 04.1 / ASME center
|
||||
DoubleChain, ///< 双点划线(假想线/相邻零件轮廓)— ISO 05.1
|
||||
Dotted, ///< 点线 — ISO 07.1
|
||||
ContinuousThin, ///< 细实线(尺寸线/指引线/剖面线)
|
||||
ContinuousThick, ///< 粗实线(可见轮廓线,主视图)
|
||||
ContinuousFreehand ///< 徒手线(断裂线)
|
||||
};
|
||||
|
||||
/// 线型名称
|
||||
[[nodiscard]] inline const char* line_type_name(LineType lt) {
|
||||
switch (lt) {
|
||||
case LineType::Continuous: return "Continuous";
|
||||
case LineType::Dashed: return "Dashed";
|
||||
case LineType::Chain: return "Chain";
|
||||
case LineType::DoubleChain: return "DoubleChain";
|
||||
case LineType::Dotted: return "Dotted";
|
||||
case LineType::ContinuousThin: return "ContinuousThin";
|
||||
case LineType::ContinuousThick: return "ContinuousThick";
|
||||
case LineType::ContinuousFreehand: return "ContinuousFreehand";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// 样式枚举
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 字体样式
|
||||
enum class FontStyle {
|
||||
Normal,
|
||||
Italic,
|
||||
Bold
|
||||
};
|
||||
|
||||
/// 箭头样式
|
||||
enum class ArrowStyle {
|
||||
Filled, ///< 实心箭头(ISO/ANSI 默认)
|
||||
Open, ///< 空心箭头(ISO 128-22 允许)
|
||||
Oblique, ///< 斜线标记(建筑图常用)
|
||||
Architectural, ///< 建筑标记(短线)
|
||||
Dot, ///< 圆点
|
||||
Integral ///< 积分标记(原点指示)
|
||||
};
|
||||
|
||||
/// 公差格式
|
||||
enum class ToleranceFormat {
|
||||
None, ///< 无公差(仅基本尺寸)
|
||||
Symmetric, ///< ±x 对称公差
|
||||
Deviation, ///< 上下偏差(+x / -y)
|
||||
Limits, ///< 极限尺寸(Max / Min)
|
||||
Basic, ///< 基本尺寸(方框 — ASME Y14.5 理论正确尺寸)
|
||||
Reference ///< 参考尺寸(圆括号 — 仅供参考)
|
||||
};
|
||||
|
||||
/// 投影角度
|
||||
enum class ProjectionAngle {
|
||||
FirstAngle, ///< 第一角投影(ISO / JIS / GB)
|
||||
ThirdAngle ///< 第三角投影(ASME / ANSI)
|
||||
};
|
||||
|
||||
/// 尺寸单位
|
||||
enum class DimensionUnit {
|
||||
Millimeter,
|
||||
Inch,
|
||||
Centimeter
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// DimensionStyle — 尺寸样式
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 完整的尺寸标注样式配置
|
||||
struct DimensionStyle {
|
||||
// ── 文字 ──
|
||||
double text_height = 3.5; ///< 文字高度(mm)
|
||||
FontStyle text_font = FontStyle::Normal;
|
||||
double text_width_factor = 0.7; ///< 文字宽高比
|
||||
double text_gap = 0.5; ///< 文字与尺寸线间距
|
||||
|
||||
// ── 箭头 ──
|
||||
double arrow_length = 3.5; ///< 箭头长度(mm)
|
||||
double arrow_width = 1.0; ///< 箭头宽度(mm)
|
||||
double arrow_angle = 15.0; ///< 箭头夹角(°)
|
||||
ArrowStyle arrow_style = ArrowStyle::Filled;
|
||||
|
||||
// ── 线宽(mm)─ 对应 ISO 128 线宽系列 ──
|
||||
double line_width_thin = 0.25; ///< 细线(尺寸线/指引线)
|
||||
double line_width_thick = 0.50; ///< 粗线(可见轮廓线)
|
||||
double line_width_medium = 0.35; ///< 中线(隐藏线)
|
||||
|
||||
// ── 尺寸界线 ──
|
||||
double extension_line_offset = 1.0; ///< 尺寸界线起点偏移(mm)
|
||||
double extension_line_extend = 2.0; ///< 尺寸界线超出(mm)
|
||||
|
||||
// ── 线型 ──
|
||||
LineType visible_line = LineType::Continuous;
|
||||
LineType hidden_line = LineType::Dashed;
|
||||
LineType center_line = LineType::Chain;
|
||||
LineType phantom_line = LineType::DoubleChain;
|
||||
LineType dimension_line = LineType::ContinuousThin;
|
||||
LineType leader_line = LineType::ContinuousThin;
|
||||
LineType section_line = LineType::ContinuousThin;
|
||||
LineType cutting_plane = LineType::DoubleChain;
|
||||
|
||||
// ── 公差 ──
|
||||
ToleranceFormat tolerance_format = ToleranceFormat::None;
|
||||
int decimal_places = 2; ///< 小数位数
|
||||
double tolerance_upper = 0.0; ///< 上偏差(mm)
|
||||
double tolerance_lower = 0.0; ///< 下偏差(mm)
|
||||
bool show_trailing_zeros = true; ///< 显示末尾零(ASME 要求)
|
||||
bool use_basic_box = true; ///< 基本尺寸方框
|
||||
|
||||
// ── 投影 ──
|
||||
ProjectionAngle projection_angle = ProjectionAngle::FirstAngle;
|
||||
|
||||
// ── 单位 ──
|
||||
DimensionUnit unit = DimensionUnit::Millimeter;
|
||||
bool show_unit_symbol = false; ///< 是否标注 mm 符号
|
||||
|
||||
// ── 显示控制 ──
|
||||
bool show_hidden_lines = true;
|
||||
bool show_center_lines = true;
|
||||
bool show_center_marks = true;
|
||||
bool show_threads_simplified = true;
|
||||
double center_mark_size = 3.0;
|
||||
double gap_between_dimension_lines = 7.0; ///< 尺寸线间距
|
||||
|
||||
// ── 页面 ──
|
||||
double drawing_scale = 1.0;
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// StandardOptions — 标准选项
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 应用标准时的配置选项
|
||||
struct StandardOptions {
|
||||
std::string paper_size = "A4"; ///< 图纸大小 A0-A4, Letter等
|
||||
double scale = 1.0; ///< 缩放比例
|
||||
bool apply_to_dimensions = true; ///< 应用到尺寸标注
|
||||
bool apply_to_views = true; ///< 应用到视图配置
|
||||
std::string revision = "A"; ///< 修订版本
|
||||
std::string title; ///< 图纸标题
|
||||
std::string author; ///< 作者
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// IsoStandard — ISO 128/129 标准
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief ISO 128/129 制图标准
|
||||
*
|
||||
* ISO 128: 技术制图的一般表示原则
|
||||
* - Part 20: 线型基本规定(01-15系列线型编号)
|
||||
* - Part 22: 指引线和参考线
|
||||
* - Part 24: 机械工程制图用线
|
||||
* - Part 30: 视图基本规定
|
||||
* - Part 34: 机械工程制图视图
|
||||
* - Part 40: 剖视图和断面图
|
||||
* - Part 50: 尺寸标注
|
||||
*
|
||||
* ISO 129: 技术制图 — 尺寸和公差的标注方法
|
||||
* - 线性尺寸标注规则
|
||||
* - 角度尺寸标注规则
|
||||
* - 圆弧半径/直径标注规则
|
||||
*
|
||||
* 默认配置:
|
||||
* - 第一角投影
|
||||
* - 文字高度 3.5mm(ISO 3098 B型)
|
||||
* - 线宽系列 0.25/0.35/0.50mm
|
||||
* - 空心箭头或实心填充箭头
|
||||
*/
|
||||
class IsoStandard {
|
||||
public:
|
||||
/// 创建 ISO 标准样式
|
||||
[[nodiscard]] static DimensionStyle create_style();
|
||||
|
||||
/// ISO 标准描述
|
||||
[[nodiscard]] static std::string description();
|
||||
|
||||
/// ISO 128 线宽系列(mm):0.13, 0.18, 0.25, 0.35, 0.5, 0.7, 1.0, 1.4, 2.0
|
||||
/// @param group 线宽组索引 0-8
|
||||
[[nodiscard]] static double line_width_group(int group);
|
||||
|
||||
/// ISO 128 线型编号名称
|
||||
/// @param lt 线型
|
||||
/// @return ISO 128 编号描述(如 "01.1" 表示连续细线)
|
||||
[[nodiscard]] static std::string line_type_iso_name(LineType lt);
|
||||
|
||||
/// ISO 3098 字体尺寸系列
|
||||
[[nodiscard]] static std::vector<double> text_height_series();
|
||||
|
||||
/// ISO 7200 标题栏尺寸(A4)
|
||||
[[nodiscard]] static std::string title_block_spec();
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// AnsiStandard — ASME Y14.5 标准
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief ASME Y14.5-2018 尺寸与公差标注标准
|
||||
*
|
||||
* 核心规则:
|
||||
* - 第三角投影
|
||||
* - 英寸/毫米双单位支持
|
||||
* - 包容原则(Rule #1: Envelope Principle)
|
||||
* - 不依赖原则的独立标注(Rule #2)
|
||||
* - MMC/LMC/RFS 材料条件修饰符
|
||||
* - 基准参考框架(DRF)6个自由度约束
|
||||
* - 特征控制框格式
|
||||
*
|
||||
* Y14.5 公差原则:
|
||||
* - Form controls: Straightness, Flatness, Circularity, Cylindricity
|
||||
* - Orientation: Parallelism, Perpendicularity, Angularity
|
||||
* - Location: Position, Concentricity, Symmetry
|
||||
* - Runout: Circular runout, Total runout
|
||||
* - Profile: Profile of a line, Profile of a surface
|
||||
*/
|
||||
class AnsiStandard {
|
||||
public:
|
||||
/// 创建 ASME Y14.5 标准样式
|
||||
[[nodiscard]] static DimensionStyle create_style();
|
||||
|
||||
/// ASME Y14.5 标准描述
|
||||
[[nodiscard]] static std::string description();
|
||||
|
||||
/// 包容原则(Rule #1)是否默认启用
|
||||
[[nodiscard]] static bool envelope_principle_default();
|
||||
|
||||
/// MMC(最大实体条件)是否默认标注
|
||||
[[nodiscard]] static bool mmc_default();
|
||||
|
||||
/// ASME Y14.5 符号表
|
||||
[[nodiscard]] static std::string gdt_symbols_summary();
|
||||
|
||||
/// 特征控制框格式规范
|
||||
[[nodiscard]] static std::string feature_control_frame_format();
|
||||
|
||||
/// ASME Y14.2 线型对 ASME Y14.5 的映射
|
||||
[[nodiscard]] static std::string line_type_spec(LineType lt);
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// JisStandard — JIS B 0001 标准
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief JIS B 0001 机械制图标准
|
||||
*
|
||||
* 核心规则:
|
||||
* - 第一角投影(日本采用的投影法)
|
||||
* - 公制单位(mm)
|
||||
* - 表面粗糙度符号(▽ 旧/JIS B 0601 → Ra/Rz 新)
|
||||
* - 焊接符号(JIS Z 3021)
|
||||
* - 螺纹简化画法
|
||||
* - JIS B 0401 公差等级
|
||||
*
|
||||
* 与 ISO 的对应关系:
|
||||
* - JIS B 0001 积极向 ISO 128 靠拢
|
||||
* - 尺寸标注规则与 ISO 129 基本一致
|
||||
* - 表面粗糙度: JIS B 0601 (对应 ISO 1302)
|
||||
*/
|
||||
class JisStandard {
|
||||
public:
|
||||
/// 创建 JIS B 0001 标准样式
|
||||
[[nodiscard]] static DimensionStyle create_style();
|
||||
|
||||
/// JIS B 0001 标准描述
|
||||
[[nodiscard]] static std::string description();
|
||||
|
||||
/// JIS 表面粗糙度符号
|
||||
[[nodiscard]] static std::string surface_texture_symbol();
|
||||
|
||||
/// JIS B 0001 推荐缩放比例
|
||||
[[nodiscard]] static std::vector<double> preferred_scales();
|
||||
|
||||
/// JIS 公差等级对应(h7, H7 等)
|
||||
[[nodiscard]] static std::string tolerance_grade_desc(const std::string& grade);
|
||||
|
||||
/// JIS B 0001 图纸尺寸系列(A0-A4 的毫米尺寸)
|
||||
[[nodiscard]] static std::string paper_size_spec(const std::string& size_name);
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Drawing(前向声明)
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
struct DrawSegment;
|
||||
struct ProjectionView;
|
||||
|
||||
/// 制图标准命名空间
|
||||
namespace drawing {
|
||||
|
||||
/// 应用标准后的制图上下文
|
||||
struct DrawingContext {
|
||||
std::vector<ProjectionView> views;
|
||||
DimensionStyle style;
|
||||
StandardOptions options;
|
||||
std::string standard_name; ///< "ISO", "ANSI", "JIS"
|
||||
ProjectionAngle view_projection = ProjectionAngle::FirstAngle;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 一键应用标准到制图
|
||||
*
|
||||
* 根据标准自动配置:
|
||||
* - 尺寸样式
|
||||
* - 视图投影角度(第一角/第三角)
|
||||
* - 线型/字体/箭头样式
|
||||
*
|
||||
* @param views 制图视图
|
||||
* @param style 样式配置
|
||||
* @param options 标准选项
|
||||
* @return DrawingContext 应用后的制图上下文
|
||||
*/
|
||||
[[nodiscard]] DrawingContext apply_standard(
|
||||
const std::vector<ProjectionView>& views,
|
||||
const DimensionStyle& style,
|
||||
const StandardOptions& options);
|
||||
|
||||
/**
|
||||
* @brief 按标准名称一键应用
|
||||
*
|
||||
* @param views 制图视图
|
||||
* @param standard_name "ISO", "ANSI", "JIS"
|
||||
* @param options 标准选项
|
||||
* @return DrawingContext
|
||||
*/
|
||||
[[nodiscard]] DrawingContext apply_standard_by_name(
|
||||
const std::vector<ProjectionView>& views,
|
||||
const std::string& standard_name,
|
||||
const StandardOptions& options);
|
||||
|
||||
/// 验证样式是否符合指定标准
|
||||
[[nodiscard]] std::vector<std::string> validate_style(
|
||||
const DimensionStyle& style, const std::string& standard_name);
|
||||
|
||||
/// 列出所有支持的标准
|
||||
[[nodiscard]] std::vector<std::string> available_standards();
|
||||
|
||||
/// 获取标准描述
|
||||
[[nodiscard]] std::string standard_description(const std::string& standard_name);
|
||||
|
||||
} // namespace drawing
|
||||
|
||||
} // namespace vde::brep
|
||||
@@ -125,4 +125,48 @@ enum class StepError {
|
||||
*/
|
||||
[[nodiscard]] const std::string& step_last_error_message();
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Import diagnostics (new in v3.3)
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief STEP 导入诊断报告
|
||||
*
|
||||
* 记录最近一次 STEP 导入的详细诊断信息,包括:
|
||||
* - 跳过的损坏实体数
|
||||
* - 跳过的非标实体数
|
||||
* - 近似处理的曲面数
|
||||
* - 从破损数据中恢复的面数
|
||||
* - 警告消息列表
|
||||
*/
|
||||
struct StepImportReport {
|
||||
int total_entities = 0; ///< 成功解析的实体总数
|
||||
int skipped_damaged = 0; ///< 跳过的损坏实体数
|
||||
int skipped_unsupported = 0; ///< 跳过的非标实体数
|
||||
int approximated_surfaces = 0; ///< 近似处理的曲面数
|
||||
int recovered_faces = 0; ///< 从破损数据中恢复的面数
|
||||
std::vector<std::string> warnings; ///< 警告消息列表
|
||||
|
||||
/// 是否有任何异常
|
||||
[[nodiscard]] bool has_issues() const {
|
||||
return skipped_damaged > 0 || skipped_unsupported > 0 ||
|
||||
approximated_surfaces > 0 || recovered_faces > 0 ||
|
||||
!warnings.empty();
|
||||
}
|
||||
|
||||
/// 生成可读的诊断报告
|
||||
[[nodiscard]] std::string report() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取最近一次 STEP 导入的诊断报告
|
||||
*
|
||||
* 线程安全:返回当前线程最近一次导入的诊断信息。
|
||||
*
|
||||
* @return StepImportReport 诊断报告
|
||||
*
|
||||
* @see step_last_error 获取错误码
|
||||
*/
|
||||
[[nodiscard]] StepImportReport step_import_diagnostic();
|
||||
|
||||
} // namespace vde::brep
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file tolerant_modeling.h
|
||||
* @brief 容错建模 — 对标 Parasolid 的容差感知 B-Rep 操作
|
||||
*
|
||||
* 提供带容差范围的拓扑元素、自适应合并、间隙桥接、重叠面检测、
|
||||
* 容差感知布尔运算和 STEP 导入一站式修复流水线。
|
||||
*
|
||||
* ## 核心能力
|
||||
*
|
||||
* 1. **TolerantVertex/TolerantEdge** — 带容差范围的拓扑元素
|
||||
* 2. **merge_within_tolerance** — BFS 自适应顶点合并
|
||||
* 3. **gap_bridging** — 间隙检测 + 自动三角填充
|
||||
* 4. **overlap_resolution** — 重叠面检测 + 移除
|
||||
* 5. **tolerant_boolean** — 容差感知布尔 (heal → boolean → heal)
|
||||
* 6. **import_heal_pipeline** — STEP 导入一站式修复
|
||||
*
|
||||
* @ingroup brep
|
||||
*/
|
||||
#include "vde/brep/brep.h"
|
||||
#include "vde/brep/brep_heal.h"
|
||||
#include "vde/brep/tolerance.h"
|
||||
#include "vde/core/point.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
namespace vde::brep {
|
||||
|
||||
using core::Point3D;
|
||||
using core::Vector3D;
|
||||
using core::AABB3D;
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// TolerantVertex / TolerantEdge
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief 带容差范围的拓扑顶点
|
||||
*
|
||||
* 除了基本坐标外,额外存储:
|
||||
* - tolerance: 该顶点的合并容差(可独立于全局配置)
|
||||
* - merged_from: 若此顶点由多个原始顶点合并而来,记录合并数
|
||||
* - is_degenerate: 标记退化顶点(如切触引起的退化边端点)
|
||||
*/
|
||||
struct TolerantVertex {
|
||||
int id; ///< 顶点 ID(对应 BrepModel 中的索引)
|
||||
Point3D point; ///< 三维坐标
|
||||
double tolerance = 1e-6; ///< 该顶点的独立容差
|
||||
int merged_from = 1; ///< 合并来源顶点数(1 = 未合并)
|
||||
bool is_degenerate = false; ///< 是否属于退化拓扑
|
||||
|
||||
/// 从普通 TopoVertex 构造
|
||||
static TolerantVertex from_topo(const TopoVertex& tv) {
|
||||
TolerantVertex res;
|
||||
res.id = tv.id;
|
||||
res.point = tv.point;
|
||||
res.tolerance = tv.tolerance;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 带容差范围的拓扑边
|
||||
*
|
||||
* 额外存储:
|
||||
* - tolerance: 边的曲线拟合容差
|
||||
* - is_degenerate: 退化边(两端点重合或长度<tolerance)
|
||||
* - gap_flag: 标记此边参与间隙桥接
|
||||
*/
|
||||
struct TolerantEdge {
|
||||
int id; ///< 边 ID
|
||||
int v_start, v_end; ///< 端点顶点 ID
|
||||
double tolerance = 1e-6; ///< 曲线拟合容差
|
||||
bool is_degenerate = false; ///< 退化边(长度 < tolerance)
|
||||
bool gap_flag = false; ///< 参与间隙桥接
|
||||
bool is_tangent_contact = false; ///< 切触边(奇异性处理)
|
||||
|
||||
/// 从普通 TopoEdge 构造
|
||||
static TolerantEdge from_topo(const TopoEdge& te) {
|
||||
TolerantEdge res;
|
||||
res.id = te.id;
|
||||
res.v_start = te.v_start;
|
||||
res.v_end = te.v_end;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// 判断是否为退化边
|
||||
[[nodiscard]] bool check_degenerate(const BrepModel& body) const {
|
||||
const auto& v0 = body.vertex(v_start);
|
||||
const auto& v1 = body.vertex(v_end);
|
||||
return (v1.point - v0.point).norm() < tolerance;
|
||||
}
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// BooleanDiagnostic — 布尔运算失败面诊断报告
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief 布尔运算失败面的诊断信息
|
||||
*
|
||||
* 记录每个失败面的原因、位置和容差建议。
|
||||
*/
|
||||
struct FailedFaceInfo {
|
||||
int face_id = -1; ///< 失败的面 ID
|
||||
std::string reason; ///< 失败原因描述
|
||||
int related_face_id = -1; ///< 关联面 ID(如有)
|
||||
double suggested_tolerance = 0.0; ///< 建议的容差增大值
|
||||
Point3D location; ///< 失败位置(近似)
|
||||
bool is_coplanar = false; ///< 共面退化
|
||||
bool is_tangent = false; ///< 切触退化
|
||||
bool is_near_miss = false; ///< 接近但未精确相交
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 容差感知布尔运算的诊断结果
|
||||
*
|
||||
* 包含布尔运算的完整诊断信息,包括预处理/后处理统计、
|
||||
* 失败面列表和建议修复方案。
|
||||
*/
|
||||
struct BooleanDiagnostic {
|
||||
bool success = false; ///< 布尔运算是否成功
|
||||
BrepModel result; ///< 结果模型
|
||||
|
||||
// ── 预处理统计 ──
|
||||
int pre_heal_merged_vertices = 0; ///< 预处理合并的顶点数
|
||||
int pre_heal_closed_gaps = 0; ///< 预处理闭合的间隙数
|
||||
int pre_heal_removed_slivers = 0; ///< 预处理移除的退化面数
|
||||
|
||||
// ── 布尔运算统计 ──
|
||||
int degeneracy_detections = 0; ///< 检测到的退化情况数
|
||||
int coplanar_pairs = 0; ///< 共面对数量
|
||||
int tangent_contacts = 0; ///< 切触对数量
|
||||
int exact_predicate_upgrades = 0; ///< 升级到精确谓词的次数
|
||||
|
||||
// ── 后处理统计 ──
|
||||
int post_heal_merged_vertices = 0; ///< 后处理合并的顶点数
|
||||
int post_heal_bridged_gaps = 0; ///< 后处理桥接的间隙数
|
||||
int post_heal_resolved_overlaps = 0;///< 后处理解决的重叠面数
|
||||
|
||||
// ── 失败诊断 ──
|
||||
std::vector<FailedFaceInfo> failed_faces; ///< 失败面列表
|
||||
std::string error_message; ///< 错误信息
|
||||
|
||||
/// 诊断是否包含失败面
|
||||
[[nodiscard]] bool has_failures() const {
|
||||
return !failed_faces.empty() || !error_message.empty();
|
||||
}
|
||||
|
||||
/// 生成可读的诊断报告
|
||||
[[nodiscard]] std::string report() const;
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Public API
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief BFS 自适应顶点合并
|
||||
*
|
||||
* 与 heal_gaps 类似,但支持:
|
||||
* - 每顶点独立容差(TolerantVertex::tolerance)
|
||||
* - 自适应容差:根据局部几何特征动态调整合并阈值
|
||||
* - 退化顶点检测:标记切触产生的退化顶点
|
||||
*
|
||||
* @param body 待修复的 B-Rep 模型(原地修改)
|
||||
* @param tolerance 全局合并容差,默认 1e-6
|
||||
* @return 合并的顶点对数
|
||||
*/
|
||||
int merge_within_tolerance(BrepModel& body, double tolerance = 1e-6);
|
||||
|
||||
/**
|
||||
* @brief 间隙检测 + 自动三角填充
|
||||
*
|
||||
* 检测面之间的微小间隙(距离 < max_gap),
|
||||
* 自动生成三角填充面以桥接间隙。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 遍历所有边,查找自由边(仅属于一个面)
|
||||
* 2. 对自由边配对:距离 < max_gap 的边视为间隙边界
|
||||
* 3. 对每对自由边生成三角填充面
|
||||
*
|
||||
* @param body 待修复的 B-Rep 模型(原地修改)
|
||||
* @param max_gap 最大间隙尺寸,默认 1e-4
|
||||
* @return 填充的间隙数
|
||||
*/
|
||||
int gap_bridging(BrepModel& body, double max_gap = 1e-4);
|
||||
|
||||
/**
|
||||
* @brief 重叠面检测 + 移除
|
||||
*
|
||||
* 检测并移除重叠/重复的面:
|
||||
* 1. 计算每对面的法向量和位置相似度
|
||||
* 2. 共面且重叠 → 保留面积较大的面,移除较小的面
|
||||
* 3. 更新壳的面引用
|
||||
*
|
||||
* @param body 待修复的 B-Rep 模型(原地修改)
|
||||
* @return 移除的重叠面数
|
||||
*/
|
||||
int overlap_resolution(BrepModel& body);
|
||||
|
||||
/**
|
||||
* @brief 容差感知布尔运算
|
||||
*
|
||||
* 完整流水线:heal → boolean → heal
|
||||
* 1. 预处理:对 A 和 B 分别执行 heal_topology
|
||||
* 2. 退化检测:共面/共线/切触 → 记录诊断信息
|
||||
* 3. 执行布尔运算(委托给 ssi_boolean_*)
|
||||
* 4. 后处理:gap_bridging + overlap_resolution + heal_topology
|
||||
*
|
||||
* @param a 第一个 B-Rep 实体
|
||||
* @param b 第二个 B-Rep 实体
|
||||
* @param op 布尔操作类型:0=union, 1=intersection, 2=difference
|
||||
* @return BooleanDiagnostic 含结果模型和诊断信息
|
||||
*/
|
||||
[[nodiscard]] BooleanDiagnostic tolerant_boolean(
|
||||
const BrepModel& a, const BrepModel& b, int op);
|
||||
|
||||
/**
|
||||
* @brief STEP 导入一站式修复流水线
|
||||
*
|
||||
* 导入 STEP 数据后自动执行完整修复:
|
||||
* 1. 导入 STEP(内部调用 import_step_from_string)
|
||||
* 2. 对每个 body 执行 merge_within_tolerance
|
||||
* 3. 执行 gap_bridging 闭合微小间隙
|
||||
* 4. 执行 overlap_resolution 移除重复面
|
||||
* 5. 执行 heal_orientation 统一方向
|
||||
* 6. 验证最终结果
|
||||
*
|
||||
* @param step_data STEP 文件内容(字符串形式)
|
||||
* @return 修复后的 B-Rep 体列表
|
||||
*
|
||||
* @note 与直接调用 import_step_from_string() + heal_topology() 不同,
|
||||
* 此函数按容错建模流水线顺序执行,包含 gap_bridging 和
|
||||
* overlap_resolution 步骤。
|
||||
*/
|
||||
[[nodiscard]] std::vector<BrepModel> import_heal_pipeline(const std::string& step_data);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Internal utilities(跨编译单元可见)
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 检测两个面是否为退化共面对
|
||||
[[nodiscard]] bool detect_coplanar_faces(
|
||||
const BrepModel& body, int face_a, int face_b, double tolerance = 1e-6);
|
||||
|
||||
/// 检测两个面是否为退化切触对
|
||||
[[nodiscard]] bool detect_tangent_contact(
|
||||
const BrepModel& body, int face_a, int face_b, double tolerance = 1e-6);
|
||||
|
||||
/// 检测边是否为退化边(长度 < tolerance)
|
||||
[[nodiscard]] bool detect_degenerate_edge(
|
||||
const BrepModel& body, int edge_id, double tolerance = 1e-6);
|
||||
|
||||
/// 构建 TolerantVertex 映射表
|
||||
[[nodiscard]] std::vector<TolerantVertex> build_tolerant_vertices(
|
||||
const BrepModel& body, double global_tolerance = 1e-6);
|
||||
|
||||
/// 构建 TolerantEdge 映射表
|
||||
[[nodiscard]] std::vector<TolerantEdge> build_tolerant_edges(
|
||||
const BrepModel& body, double global_tolerance = 1e-6);
|
||||
|
||||
} // namespace vde::brep
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "vde/core/point.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
@@ -362,4 +363,205 @@ struct ShapeModificationResult {
|
||||
const NurbsSurface& surface,
|
||||
const std::vector<ShapeConstraint>& constraints);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// G3 Blend with Constraints — 带约束的 G3 过渡
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// G0/G1/G2/G3 连续性约束边参数
|
||||
struct G3ConstraintEdges {
|
||||
EdgeParams g0_edge; ///< G0 位置约束边
|
||||
EdgeParams g1_edge; ///< G1 切平面约束边
|
||||
EdgeParams g2_edge; ///< G2 曲率约束边
|
||||
EdgeParams g3_edge; ///< G3 曲率变化率约束边
|
||||
bool enforce_g0 = true;
|
||||
bool enforce_g1 = true;
|
||||
bool enforce_g2 = true;
|
||||
bool enforce_g3 = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 带约束的 G3 过渡曲面
|
||||
*
|
||||
* 在两面之间构造过渡曲面,并精确满足指定的 G0/G1/G2/G3 约束。
|
||||
* 与 g3_blend 相比,此函数允许用户显式指定每条边的连续性等级。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 根据各约束边采样控制点
|
||||
* 2. 构造最小二乘系统满足 G0→G3 逐级约束
|
||||
* 3. 使用 Lagrange 乘子法确保约束精确满足
|
||||
*
|
||||
* @param surf_a 曲面 A
|
||||
* @param surf_b 曲面 B
|
||||
* @param edges 显式 G0/G1/G2/G3 约束边参数
|
||||
* @return G3 过渡结果
|
||||
*
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] G3BlendResult g3_blend_with_constraints(
|
||||
const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
const G3ConstraintEdges& edges);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Surface Energy Minimization — 薄板能量最小化
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 能量最小化选项
|
||||
struct EnergyMinimizationOptions {
|
||||
double bending_weight = 1.0; ///< 弯曲能量权重
|
||||
double membrane_weight = 0.1; ///< 薄膜能量权重
|
||||
double constraint_weight = 10.0; ///< 约束满足权重
|
||||
int max_iterations = 100; ///< 最大迭代次数
|
||||
double tolerance = 1e-6; ///< 收敛容差
|
||||
double regularization = 1e-4; ///< Tikhonov 正则化
|
||||
bool preserve_boundary = true; ///< 是否保持边界不变
|
||||
};
|
||||
|
||||
/// 能量最小化结果
|
||||
struct EnergyMinimizationResult {
|
||||
NurbsSurface optimized_surface; ///< 优化后的曲面
|
||||
double initial_bending_energy = 0.0; ///< 初始弯曲能量
|
||||
double final_bending_energy = 0.0; ///< 最终弯曲能量
|
||||
double initial_membrane_energy = 0.0; ///< 初始薄膜能量
|
||||
double final_membrane_energy = 0.0; ///< 最终薄膜能量
|
||||
int iterations = 0; ///< 实际迭代次数
|
||||
bool converged = false; ///< 是否收敛
|
||||
std::vector<Point3D> control_displacements; ///< 控制点位移
|
||||
double max_displacement = 0.0; ///< 最大控制点位移
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 薄板能量最小化曲面优化
|
||||
*
|
||||
* 最小化薄板弯曲能量(二阶导数平方积分)和薄膜能量(一阶导数平方积分),
|
||||
* 同时满足约束条件,实现曲面的全局光顺。
|
||||
*
|
||||
* 能量泛函:
|
||||
* E = w_bend * ∫(κ₁² + κ₂²)dA + w_membrane * ∫(‖∂S/∂u‖² + ‖∂S/∂v‖²)dA
|
||||
* + w_constraint * Σ‖S(u_i, v_i) - target_i‖²
|
||||
*
|
||||
* 算法:基于控制点的 Gauss-Newton 非线性最小二乘优化。
|
||||
*
|
||||
* @param surface 输入 NURBS 曲面
|
||||
* @param constraints 约束点列表(可为空,仅做光顺)
|
||||
* @param options 优化选项
|
||||
* @return 能量最小化结果
|
||||
*
|
||||
* @note 对标 ICEM Surf / Alias AutoStudio 的 Surface Fairing
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] EnergyMinimizationResult surface_energy_minimization(
|
||||
const NurbsSurface& surface,
|
||||
const std::vector<ShapeConstraint>& constraints,
|
||||
const EnergyMinimizationOptions& options = {});
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Curvature Continuity Optimization — 曲率连续性迭代精化
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 曲率连续性优化选项
|
||||
struct CurvatureContinuityOptions {
|
||||
double position_tolerance = 1e-7; ///< 位置连续性容差
|
||||
double tangent_tolerance = 1e-5; ///< 切平面角度容差 (rad)
|
||||
double curvature_tolerance = 1e-4; ///< 曲率偏差容差
|
||||
int max_iterations = 50; ///< 最大迭代次数
|
||||
int boundary_samples = 30; ///< 边界采样点数
|
||||
double step_size = 0.05; ///< 步长因子
|
||||
bool optimize_both_surfaces = false; ///< 是否同时优化两面
|
||||
};
|
||||
|
||||
/// 曲率连续性优化结果
|
||||
struct CurvatureContinuityResult {
|
||||
NurbsSurface optimized_a; ///< 优化后的曲面 A(若 optimize_both_surfaces=true)
|
||||
NurbsSurface optimized_b; ///< 优化后的曲面 B
|
||||
double initial_g0_error = 0.0; ///< 初始 G0 误差
|
||||
double final_g0_error = 0.0; ///< 最终 G0 误差
|
||||
double initial_g1_error = 0.0; ///< 初始 G1 误差 (rad)
|
||||
double final_g1_error = 0.0; ///< 最终 G1 误差 (rad)
|
||||
double initial_g2_error = 0.0; ///< 初始 G2 误差
|
||||
double final_g2_error = 0.0; ///< 最终 G2 误差
|
||||
int iterations = 0; ///< 实际迭代次数
|
||||
bool converged = false; ///< 是否收敛
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 曲率连续性迭代精化优化
|
||||
*
|
||||
* 在两曲面公共边界处迭代调整控制点,逐步提升 G0→G1→G2 连续性。
|
||||
* 每次迭代沿公共边界采样,计算当前连续性误差,梯度下降调整影响区域控制点。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 检测公共边界
|
||||
* 2. 沿边界采样,计算各点 G0/G1/G2 误差
|
||||
* 3. 梯度下降调整边界面附近控制点
|
||||
* 4. 重新评估,调整步长(adaptive step size)
|
||||
* 5. 收敛检测
|
||||
*
|
||||
* @param surf_a 曲面 A
|
||||
* @param surf_b 曲面 B
|
||||
* @param options 优化选项
|
||||
* @return 优化结果(含优化后的曲面和收敛历史)
|
||||
*
|
||||
* @note 对标 CATIA GSD Join / ICEM Surf Match
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] CurvatureContinuityResult curvature_continuity_optimization(
|
||||
const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
const CurvatureContinuityOptions& options = {});
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Reflection Line Discontinuity — 反射线不连续检测+修复
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 反射线不连续检测参数
|
||||
struct ReflectionDiscontinuityParams {
|
||||
Vector3D light_direction; ///< 光源方向(归一化)
|
||||
int res_u = 40; ///< u 方向分辨率
|
||||
int res_v = 40; ///< v 方向分辨率
|
||||
double discontinuity_threshold = 0.05; ///< 不连续判定阈值(方向变化率)
|
||||
int max_fix_iterations = 20; ///< 最大修复迭代次数
|
||||
double fix_strength = 0.1; ///< 修复强度
|
||||
bool auto_fix = true; ///< 是否自动修复
|
||||
};
|
||||
|
||||
/// 反射线不连续检测结果
|
||||
struct ReflectionDiscontinuityResult {
|
||||
int res_u = 0, res_v = 0; ///< 网格分辨率
|
||||
/// 反射场 grid
|
||||
std::vector<std::vector<Vector3D>> reflection_field;
|
||||
/// 不连续强度网格 ∈ [0, ∞)
|
||||
std::vector<std::vector<double>> discontinuity_map;
|
||||
/// 不连续点列表 (u, v, intensity)
|
||||
std::vector<std::tuple<double, double, double>> discontinuities;
|
||||
int total_discontinuities = 0; ///< 不连续点总数
|
||||
double max_discontinuity = 0.0; ///< 最大不连续强度
|
||||
double mean_discontinuity = 0.0; ///< 平均不连续强度
|
||||
bool is_smooth = false; ///< 是否判定为光顺
|
||||
NurbsSurface fixed_surface; ///< 修复后的曲面(若 auto_fix=true)
|
||||
bool fixed = false; ///< 是否已修复
|
||||
double fix_residual = 0.0; ///< 修复残差
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 反射线不连续检测与修复
|
||||
*
|
||||
* 计算曲面在给定光源方向下的反射线场,检测反射方向的局部突变点,
|
||||
* 并可选择性地自动修复(通过局部控制点微调消除不连续)。
|
||||
*
|
||||
* 算法:
|
||||
* - 检测:计算反射方向场的梯度幅值,超过阈值的标记为不连续
|
||||
* - 修复:对不连续区域的控制点施加局部高斯加权偏移,最小化反射梯度
|
||||
*
|
||||
* @param surface NURBS 曲面
|
||||
* @param params 检测参数(光源方向、分辨率、阈值、修复选项)
|
||||
* @return 反射线不连续检测与修复结果
|
||||
*
|
||||
* @note 对标 CGM Reflection Line Analysis + Repair
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] ReflectionDiscontinuityResult reflection_line_discontinuity(
|
||||
const NurbsSurface& surface,
|
||||
const ReflectionDiscontinuityParams& params);
|
||||
|
||||
} // namespace vde::curves
|
||||
|
||||
+136
-1
@@ -282,8 +282,143 @@ FEAMesh boundary_layer_mesh(const brep::BrepModel& body,
|
||||
FEAMesh hexahedral_mesh(const brep::BrepModel& body,
|
||||
const HexMeshParams& params = {});
|
||||
|
||||
// ════════════════════════════════════════════════════════
|
||||
// 高级六面体网格生成 API
|
||||
// ════════════════════════════════════════════════════════
|
||||
|
||||
/// 六面体质量优化选项
|
||||
struct HexOptimizationParams {
|
||||
double min_scaled_jacobian = 0.3; ///< 最小可接受雅可比
|
||||
double max_aspect_ratio = 10.0; ///< 最大长宽比
|
||||
int max_iterations = 50; ///< 最大优化迭代次数
|
||||
double convergence_tol = 1e-4; ///< 收敛容差
|
||||
bool untangle = true; ///< 是否翻转修复(untangle inverted elements)
|
||||
bool laplacian_smooth = true; ///< 是否 Laplacian 光顺
|
||||
bool optimization_based_smooth = true; ///< 是否基于优化的光顺
|
||||
};
|
||||
|
||||
/// 六面体质量优化结果
|
||||
struct HexOptimizationResult {
|
||||
FEAMesh optimized_mesh; ///< 优化后的网格
|
||||
FEAQualityReport initial_quality; ///< 初始质量报告
|
||||
FEAQualityReport final_quality; ///< 最终质量报告
|
||||
int iterations = 0; ///< 实际迭代次数
|
||||
int inverted_fixed = 0; ///< 修复的反转单元数
|
||||
int degenerate_fixed = 0; ///< 修复的退化单元数
|
||||
bool converged = false; ///< 是否收敛
|
||||
};
|
||||
|
||||
/// 面标识结构
|
||||
struct FaceRegion {
|
||||
std::vector<int> face_indices; ///< 面的顶点索引列表
|
||||
std::string name; ///< 面名称
|
||||
};
|
||||
|
||||
/// 多块分区定义
|
||||
struct BlockRegion {
|
||||
std::vector<Point3D> corner_vertices; ///< 8个角顶点(i,j,k 顺序)
|
||||
int n_i = 2; ///< i方向分段数
|
||||
int n_j = 2; ///< j方向分段数
|
||||
int n_k = 2; ///< k方向分段数
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 自适应网格细化
|
||||
* @brief 映射法六面体网格生成
|
||||
*
|
||||
* 给定 B-Rep 实体的源面和目标面,使用映射法生成结构化六面体网格。
|
||||
* 核心思路:将源面四边形网格通过坐标映射变换到目标面,
|
||||
* 并在中间层线性插值,形成规则的六面体网格。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 在源面生成四边形网格(重心映射或栅格映射)
|
||||
* 2. 在目标面生成对应的四边形网格
|
||||
* 3. 沿 sweep 方向线性插值生成中间层
|
||||
* 4. 连接各层为六面体单元
|
||||
*
|
||||
* @param body B-Rep实体模型
|
||||
* @param source_face 源面标识
|
||||
* @param target_face 目标面标识
|
||||
* @param layers 层数(默认 4)
|
||||
* @return FEAMesh 六面体网格 (Hex8)
|
||||
*
|
||||
* @note 对标 Ansys ICEM CFD Blocking / Pointwise
|
||||
* @ingroup mesh
|
||||
*/
|
||||
[[nodiscard]] FEAMesh mapped_hex_mesh(
|
||||
const brep::BrepModel& body,
|
||||
const FaceRegion& source_face,
|
||||
const FaceRegion& target_face,
|
||||
int layers = 4);
|
||||
|
||||
/**
|
||||
* @brief 子映射法六面体网格生成
|
||||
*
|
||||
* 自动将复杂几何体分区为多个可映射子区域,
|
||||
* 然后在每个子区域内用映射法生成六面体网格,
|
||||
* 最后缝合各子区域网格。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 分析几何体的拓扑特征(角点、棱边)
|
||||
* 2. 自动分区为可扫掠(sweepable)子区域
|
||||
* 3. 对每个子区域执行映射法六面体化
|
||||
* 4. 合并子区域网格,保证界面节点一致
|
||||
*
|
||||
* @param body B-Rep实体模型
|
||||
* @return FEAMesh 六面体网格 (Hex8)
|
||||
*
|
||||
* @note 对标 Ansys Workbench MultiZone / CUBIT Submap
|
||||
* @ingroup mesh
|
||||
*/
|
||||
[[nodiscard]] FEAMesh submapped_hex_mesh(
|
||||
const brep::BrepModel& body);
|
||||
|
||||
/**
|
||||
* @brief 多块结构化六面体网格生成
|
||||
*
|
||||
* 对几何体进行显式多块分解,每个块独立生成结构化六面体网格,
|
||||
* 确保块间界面节点一一对应。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 根据用户定义或自动识别的块分区
|
||||
* 2. 每个块内使用 transfinite interpolation (TFI) 生成节点
|
||||
* 3. 块间共享面节点,保证 conformal 连接
|
||||
* 4. 组装块为整体网格
|
||||
*
|
||||
* @param body B-Rep实体模型
|
||||
* @param blocks 块分区定义列表
|
||||
* @return FEAMesh 六面体网格 (Hex8)
|
||||
*
|
||||
* @note 对标 Ansys ICEM CFD Hexa Blocking / TrueGrid
|
||||
* @ingroup mesh
|
||||
*/
|
||||
[[nodiscard]] FEAMesh multi_block_hex_mesh(
|
||||
const brep::BrepModel& body,
|
||||
const std::vector<BlockRegion>& blocks);
|
||||
|
||||
/**
|
||||
* @brief 六面体网格质量优化与翻转修复
|
||||
*
|
||||
* 对六面体网格进行质量优化,包括反转变形修复(untangling)、
|
||||
* Laplacian 光顺和基于优化的光顺。
|
||||
*
|
||||
* 算法:
|
||||
* - untangling: 检测负雅可比单元,通过解局部优化问题翻转节点
|
||||
* - Laplacian 光顺: 将内部节点移到邻域质心
|
||||
* - 优化光顺: 最小化目标函数(扭曲度+体积变化)
|
||||
*
|
||||
* @param mesh 输入 FEA 六面体网格
|
||||
* @param params 优化参数
|
||||
* @return HexOptimizationResult 优化结果(含优化前后质量报告)
|
||||
*
|
||||
* @note 对标 CUBIT MeshGems / Pointwise T-Rex Quality
|
||||
* @ingroup mesh
|
||||
*/
|
||||
[[nodiscard]] HexOptimizationResult hex_quality_optimization(
|
||||
const FEAMesh& mesh,
|
||||
const HexOptimizationParams& params = {});
|
||||
|
||||
// ════════════════════════════════════════════════════════
|
||||
// 自适应细化
|
||||
*
|
||||
* 基于误差估计函数对高误差区域进行局部细分。
|
||||
* 支持边中点分裂细化(适用于Tet4→4×Tet4子单元)。
|
||||
|
||||
Reference in New Issue
Block a user