312 lines
11 KiB
C++
312 lines
11 KiB
C++
|
|
#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
|