#pragma once /** * @file draft_analysis.h * @brief 拔模分析 * * 模具设计中的关键分析工具: * - 计算每个面相对于拔模方向的拔模角 * - 分类面:正拔模 / 负拔模 / 零拔模 / 倒扣 * - 生成拔模面 * * @ingroup brep */ #include "vde/brep/brep.h" #include "vde/core/point.h" #include "vde/core/aabb.h" #include #include #include namespace vde::brep { // ═══════════════════════════════════════════════════════════ // Draft Result Types // ═══════════════════════════════════════════════════════════ /// 拔模面分类 enum class DraftFaceType { Positive, ///< 正拔模:角度 > min_draft_angle Negative, ///< 负拔模:角度 < -min_draft_angle ZeroDraft, ///< 零拔模:|角度| ≤ min_draft_angle(平行于拔模方向) Undercut, ///< 倒扣:面法线与拔模方向法向分量不一致(侧面障碍) }; /// 单个面的拔模分析结果 struct DraftFaceResult { int face_id = -1; ///< 面ID double draft_angle = 0.0; ///< 拔模角(弧度),正值 = 向外张开 DraftFaceType classification = DraftFaceType::ZeroDraft; core::Vector3D face_normal; ///< 面法线(近似) double face_area = 0.0; ///< 面面积(用于加权统计) }; /// 全模型拔模分析结果 struct DraftAnalysisResult { /// 拔模方向(输入) core::Vector3D pull_direction{0, 0, 1}; /// 最小允许拔模角(弧度) double min_draft_angle = 0.0; /// 每个面的拔模分析 std::vector faces; // ─── 汇总统计 ─── /// 面分类统计 int positive_count = 0; int negative_count = 0; int zero_draft_count = 0; int undercut_count = 0; /// 面积加权平均拔模角 double area_weighted_angle = 0.0; /// 最小/最大拔模角(正拔模面) double min_positive_angle = std::numeric_limits::max(); double max_positive_angle = -std::numeric_limits::max(); /// 是否有倒扣(模具无法脱出) [[nodiscard]] bool has_undercut() const { return undercut_count > 0; } /// 是否全部可脱模 [[nodiscard]] bool is_moldable() const { return undercut_count == 0; } /// 拔模角分布:角度区间 → 面数量(用于热力图) [[nodiscard]] std::map angle_distribution(int bins = 18) const; }; // ═══════════════════════════════════════════════════════════ // Draft Analysis Functions // ═══════════════════════════════════════════════════════════ /** * @brief 计算单个面的近似拔模角 * * 拔模角 = π/2 - arccos(|n·d|),其中 n 为面法线,d 为拔模方向。 * 正值表示面沿拔模方向向外张开。 * * @param body B-Rep 实体 * @param face_id 面ID * @param pull_dir 拔模方向(会被归一化) * @return 拔模角(弧度),范围 [-π/2, π/2] */ [[nodiscard]] double draft_angle(const BrepModel& body, int face_id, const core::Vector3D& pull_dir); /** * @brief 全模型拔模分析 * * 对 B-Rep 实体的每个面计算拔模角并分类。 * * @param body B-Rep 实体 * @param pull_dir 拔模方向 * @param min_draft_angle 最小允许拔模角(弧度),默认 1° (≈0.0175 rad) * @return 完整分析结果 */ [[nodiscard]] DraftAnalysisResult analyze_draft(const BrepModel& body, const core::Vector3D& pull_dir, double min_draft_angle = 0.0174533); /** * @brief 创建拔模面 * * 沿拔模方向偏转面,使其达到指定拔模角度。 * (基础实现:沿边界旋转面法线) * * @param body B-Rep 实体(会被修改) * @param face_id 面ID * @param pull_dir 拔模方向 * @param angle 目标拔模角(弧度,正值 = 向外) * @return 是否成功 */ [[nodiscard]] bool create_draft_face(BrepModel& body, int face_id, const core::Vector3D& pull_dir, double angle); /** * @brief 批量应用拔模 * * 对指定面列表创建拔模面。 * * @param body B-Rep 实体(会被修改) * @param face_ids 面ID列表 * @param pull_dir 拔模方向 * @param angle 目标拔模角(弧度) * @return 成功应用拔模的面数量 */ [[nodiscard]] int apply_draft(BrepModel& body, const std::vector& face_ids, const core::Vector3D& pull_dir, double angle); /** * @brief 拔模分析报告(人类可读字符串) * * @param result 分析结果 * @return 格式化报告 */ [[nodiscard]] std::string draft_report(const DraftAnalysisResult& result); } // namespace vde::brep