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
|
||||
Reference in New Issue
Block a user