423 lines
15 KiB
Python
423 lines
15 KiB
Python
"""
|
|
铝泡沫模具质量检测模块
|
|
|
|
提供分模面质量检测、模具结构合理性评估、生产可行性分析等功能
|
|
"""
|
|
|
|
from typing import Dict, List, Any, Tuple
|
|
import numpy as np
|
|
from OCC.Core.BRep import BRep_Tool
|
|
from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh
|
|
from OCC.Core.TopExp import TopExp_Explorer
|
|
from OCC.Core.TopAbs import TopAbs_FACE, TopAbs_EDGE
|
|
from OCC.Core.BRepAdaptor import BRepAdaptor_Surface, BRepAdaptor_Curve
|
|
from OCC.Core.Bnd import Bnd_Box
|
|
from OCC.Core.BRepBndLib import brepbndlib_Add
|
|
from OCC.Core.gp import gp_Dir
|
|
|
|
from utils.logger import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
class AluminumFoamMoldQualityInspector:
|
|
"""铝泡沫模具质量检测器"""
|
|
|
|
def __init__(self):
|
|
self.quality_threshold = {
|
|
"smoothness_score": 80.0,
|
|
"continuity_score": 95.0,
|
|
"structure_score": 90.0
|
|
}
|
|
|
|
def inspect_mold(self, cavity_data: Dict, params: Dict) -> Dict[str, Any]:
|
|
"""
|
|
完整的模具质量检测
|
|
|
|
Args:
|
|
cavity_data: 模具型腔数据
|
|
params: 分模参数
|
|
|
|
Returns:
|
|
质量检测报告
|
|
"""
|
|
logger.info("开始模具质量检测...")
|
|
|
|
report = {
|
|
"surface_quality": self.inspect_surface_quality(cavity_data),
|
|
"structure_quality": self.inspect_structure_quality(cavity_data, params),
|
|
"feasibility": self.assess_production_feasibility(cavity_data, params),
|
|
"overall_score": 0.0,
|
|
"passed": False,
|
|
"warnings": [],
|
|
"recommendations": []
|
|
}
|
|
|
|
# 计算综合评分
|
|
scores = [
|
|
report["surface_quality"]["overall_score"],
|
|
report["structure_quality"]["overall_score"],
|
|
report["feasibility"]["score"]
|
|
]
|
|
report["overall_score"] = sum(scores) / len(scores)
|
|
report["passed"] = report["overall_score"] >= 80.0
|
|
|
|
logger.info(f"质量检测完成,综合评分: {report['overall_score']:.1f}%")
|
|
|
|
return report
|
|
|
|
def inspect_surface_quality(self, cavity_data: Dict) -> Dict[str, Any]:
|
|
"""
|
|
检测分模面质量
|
|
|
|
检测项目:
|
|
- 平滑度:曲率分析
|
|
- 连续性:边界检查
|
|
- 完整性:破面检测
|
|
"""
|
|
parting_line = cavity_data.get("parting_line", [])
|
|
parting_surface = cavity_data.get("parting_surface")
|
|
|
|
# 1. 平滑度检测
|
|
smoothness = self._check_smoothness(parting_line)
|
|
|
|
# 2. 连续性检测
|
|
continuity = self._check_continuity(parting_line)
|
|
|
|
# 3. 完整性检测
|
|
completeness = self._check_completeness(cavity_data)
|
|
|
|
overall = (smoothness["score"] * 0.4 +
|
|
continuity["score"] * 0.3 +
|
|
completeness["score"] * 0.3)
|
|
|
|
return {
|
|
"smoothness": smoothness,
|
|
"continuity": continuity,
|
|
"completeness": completeness,
|
|
"overall_score": overall,
|
|
"passed": overall >= self.quality_threshold["smoothness_score"]
|
|
}
|
|
|
|
def _check_smoothness(self, parting_line: List) -> Dict[str, Any]:
|
|
"""检查分型线平滑度"""
|
|
if len(parting_line) < 3:
|
|
return {"score": 50.0, "issues": ["分型线点数不足"]}
|
|
|
|
try:
|
|
points = np.array(parting_line)
|
|
|
|
# 计算相邻线段角度变化
|
|
angle_changes = []
|
|
for i in range(1, len(points) - 1):
|
|
v1 = points[i] - points[i-1]
|
|
v2 = points[i+1] - points[i]
|
|
|
|
len1, len2 = np.linalg.norm(v1), np.linalg.norm(v2)
|
|
if len1 > 0.001 and len2 > 0.001:
|
|
cos_angle = np.clip(np.dot(v1, v2) / (len1 * len2), -1, 1)
|
|
angle = np.degrees(np.arccos(cos_angle))
|
|
angle_changes.append(angle)
|
|
|
|
if not angle_changes:
|
|
return {"score": 70.0, "issues": []}
|
|
|
|
# 计算角度变化统计
|
|
max_angle = max(angle_changes)
|
|
avg_angle = np.mean(angle_changes)
|
|
|
|
# 评分:角度变化越小越好
|
|
score = max(0, 100 - avg_angle * 2 - max_angle * 0.5)
|
|
|
|
issues = []
|
|
if max_angle > 30:
|
|
issues.append(f"存在尖角,最大角度变化: {max_angle:.1f}°")
|
|
if avg_angle > 15:
|
|
issues.append(f"分型线不够平滑,平均角度变化: {avg_angle:.1f}°")
|
|
|
|
return {"score": score, "issues": issues, "max_angle": max_angle, "avg_angle": avg_angle}
|
|
|
|
except Exception as e:
|
|
logger.warning(f"平滑度检测失败: {e}")
|
|
return {"score": 50.0, "issues": ["检测过程出错"]}
|
|
|
|
def _check_continuity(self, parting_line: List) -> Dict[str, Any]:
|
|
"""检查分型线连续性"""
|
|
if len(parting_line) < 2:
|
|
return {"score": 0.0, "issues": ["分型线不完整"]}
|
|
|
|
try:
|
|
# 检查是否有明显的间隙
|
|
points = np.array(parting_line)
|
|
gaps = []
|
|
|
|
for i in range(1, len(points)):
|
|
gap = np.linalg.norm(points[i] - points[i-1])
|
|
if gap > 10.0: # 10mm 以上认为有间隙
|
|
gaps.append(gap)
|
|
|
|
# 评分
|
|
if not gaps:
|
|
score = 100.0
|
|
issues = []
|
|
elif len(gaps) == 1 and max(gaps) < 20:
|
|
score = 80.0
|
|
issues = [f"存在轻微间隙: {max(gaps):.1f}mm"]
|
|
else:
|
|
score = max(0, 100 - len(gaps) * 20)
|
|
issues = [f"存在 {len(gaps)} 处间隙"]
|
|
|
|
return {"score": score, "issues": issues, "gap_count": len(gaps)}
|
|
|
|
except Exception as e:
|
|
logger.warning(f"连续性检测失败: {e}")
|
|
return {"score": 50.0, "issues": ["检测过程出错"]}
|
|
|
|
def _check_completeness(self, cavity_data: Dict) -> Dict[str, Any]:
|
|
"""检查分模完整性"""
|
|
issues = []
|
|
|
|
# 检查必要的组件是否存在
|
|
required_keys = ["cavity", "core", "parting_surface", "parting_line"]
|
|
missing = [k for k in required_keys if k not in cavity_data]
|
|
|
|
if missing:
|
|
issues.append(f"缺少组件: {', '.join(missing)}")
|
|
return {"score": 0.0, "issues": issues}
|
|
|
|
# 检查分型线点数
|
|
parting_line = cavity_data.get("parting_line", [])
|
|
if len(parting_line) < 4:
|
|
issues.append("分型线点数不足")
|
|
score = len(parting_line) * 20
|
|
else:
|
|
score = 100.0
|
|
|
|
return {"score": score, "issues": issues}
|
|
|
|
def inspect_structure_quality(self, cavity_data: Dict, params: Dict) -> Dict[str, Any]:
|
|
"""
|
|
检测模具结构合理性
|
|
|
|
检测项目:
|
|
- 模具尺寸
|
|
- 壁厚
|
|
- 拔模角
|
|
- 倒扣处理
|
|
"""
|
|
analysis = cavity_data.get("analysis", {})
|
|
bbox = analysis.get("bounding_box", {}).get("dimensions", [0, 0, 0])
|
|
|
|
issues = []
|
|
recommendations = []
|
|
|
|
# 1. 模具尺寸检查
|
|
mold_size = cavity_data.get("mold_block")
|
|
if mold_size:
|
|
# 检查尺寸是否足够
|
|
min_dimension = min(bbox)
|
|
if min_dimension < 20:
|
|
issues.append("产品尺寸过小,可能影响模具强度")
|
|
recommendations.append("建议增加产品尺寸或使用嵌件")
|
|
|
|
# 2. 拔模角检查
|
|
draft_angle = params.get("draft_angle", 0)
|
|
if draft_angle < 2.0:
|
|
issues.append("拔模角偏小,可能导致脱模困难")
|
|
recommendations.append("建议增大拔模角到 2-5°")
|
|
|
|
# 3. 倒扣区域检查
|
|
undercut_regions = cavity_data.get("undercut_regions", [])
|
|
if undercut_regions:
|
|
issues.append(f"存在 {len(undercut_regions)} 个倒扣区域")
|
|
recommendations.append("建议添加滑块或斜顶机构")
|
|
|
|
# 4. 铝泡沫特殊检查
|
|
foam_material = params.get("foam_material", "")
|
|
if foam_material:
|
|
# 检查排气系统需求
|
|
volume = analysis.get("volume", 0)
|
|
if volume > 50000000: # > 50 cm³
|
|
issues.append("大型铝泡沫产品,需要加强排气系统")
|
|
recommendations.append("建议增加排气槽或排气针")
|
|
|
|
# 评分
|
|
issue_count = len(issues)
|
|
score = max(0, 100 - issue_count * 15)
|
|
|
|
return {
|
|
"score": score,
|
|
"issues": issues,
|
|
"recommendations": recommendations,
|
|
"overall_score": score,
|
|
"passed": score >= self.quality_threshold["structure_score"]
|
|
}
|
|
|
|
def assess_production_feasibility(self, cavity_data: Dict, params: Dict) -> Dict[str, Any]:
|
|
"""
|
|
评估生产可行性
|
|
|
|
评估项目:
|
|
- 注塑压力
|
|
- 锁模力
|
|
- 成型周期
|
|
- 材料利用率
|
|
"""
|
|
analysis = cavity_data.get("analysis", {})
|
|
|
|
# 计算投影面积 (mm²)
|
|
bbox = analysis.get("bounding_box", {}).get("dimensions", [0, 0, 0])
|
|
projected_area = bbox[0] * bbox[1] # X * Y
|
|
|
|
# 体积 (mm³)
|
|
volume = analysis.get("volume", 0)
|
|
volume_cm3 = volume / 1000
|
|
|
|
# 1. 注塑压力估算 (MPa)
|
|
injection_pressure = 30 + projected_area / 1000 # 简化估算
|
|
|
|
# 2. 锁模力估算 (吨)
|
|
# 铝泡沫需要较低的压力
|
|
clamping_force_ton = projected_area * 0.0015 # 简化估算
|
|
|
|
# 3. 成型周期估算 (秒)
|
|
# 铝泡沫成型周期较长
|
|
if volume_cm3 < 10:
|
|
cycle_time = 60
|
|
elif volume_cm3 < 50:
|
|
cycle_time = 90
|
|
elif volume_cm3 < 200:
|
|
cycle_time = 120
|
|
else:
|
|
cycle_time = 180
|
|
|
|
# 4. 材料利用率
|
|
material_utilization = min(95, 85 + volume_cm3 / 10)
|
|
|
|
# 评估结果
|
|
feasibility_items = []
|
|
|
|
if injection_pressure < 100:
|
|
feasibility_items.append({
|
|
"item": "注塑压力",
|
|
"value": f"{injection_pressure:.1f} MPa",
|
|
"status": "ok",
|
|
"message": "压力在设备范围内"
|
|
})
|
|
else:
|
|
feasibility_items.append({
|
|
"item": "注塑压力",
|
|
"value": f"{injection_pressure:.1f} MPa",
|
|
"status": "warning",
|
|
"message": "压力较高,需要高压设备"
|
|
})
|
|
|
|
if clamping_force_ton < 300:
|
|
feasibility_items.append({
|
|
"item": "锁模力",
|
|
"value": f"{clamping_force_ton:.1f} 吨",
|
|
"status": "ok",
|
|
"message": "锁模力在设备范围内"
|
|
})
|
|
else:
|
|
feasibility_items.append({
|
|
"item": "锁模力",
|
|
"value": f"{clamping_force_ton:.1f} 吨",
|
|
"status": "warning",
|
|
"message": "需要大型注塑机"
|
|
})
|
|
|
|
feasibility_items.append({
|
|
"item": "成型周期",
|
|
"value": f"{cycle_time} 秒",
|
|
"status": "ok",
|
|
"message": "周期正常"
|
|
})
|
|
|
|
feasibility_items.append({
|
|
"item": "材料利用率",
|
|
"value": f"{material_utilization:.1f}%",
|
|
"status": "ok",
|
|
"message": "材料利用率良好" if material_utilization > 80 else "材料利用率偏低"
|
|
})
|
|
|
|
# 综合评分
|
|
ok_count = sum(1 for item in feasibility_items if item["status"] == "ok")
|
|
score = (ok_count / len(feasibility_items)) * 100
|
|
|
|
return {
|
|
"items": feasibility_items,
|
|
"score": score,
|
|
"projected_area": f"{projected_area:.0f} mm²",
|
|
"volume": f"{volume_cm3:.1f} cm³",
|
|
"injection_pressure": f"{injection_pressure:.1f} MPa",
|
|
"clamping_force": f"{clamping_force_ton:.1f} 吨",
|
|
"cycle_time": f"{cycle_time} 秒",
|
|
"material_utilization": f"{material_utilization:.1f}%",
|
|
"passed": score >= 75.0
|
|
}
|
|
|
|
def generate_quality_report(self, cavity_data: Dict, params: Dict) -> str:
|
|
"""
|
|
生成质量检测报告文本
|
|
|
|
Returns:
|
|
Markdown 格式的报告文本
|
|
"""
|
|
report = self.inspect_mold(cavity_data, params)
|
|
|
|
lines = [
|
|
"# 铝泡沫模具质量检测报告",
|
|
"",
|
|
f"**综合评分**: {report['overall_score']:.1f}%",
|
|
f"**检测结果**: {'✅ 通过' if report['passed'] else '❌ 未通过'}",
|
|
"",
|
|
"## 一、分模面质量",
|
|
"",
|
|
f"- 平滑度: {report['surface_quality']['smoothness']['score']:.1f}分",
|
|
f"- 连续性: {report['surface_quality']['continuity']['score']:.1f}分",
|
|
f"- 完整性: {report['surface_quality']['completeness']['score']:.1f}分",
|
|
"",
|
|
]
|
|
|
|
# 添加问题列表
|
|
if report["surface_quality"]["smoothness"].get("issues"):
|
|
lines.append("**发现的问题**:")
|
|
for issue in report["surface_quality"]["smoothness"]["issues"]:
|
|
lines.append(f"- {issue}")
|
|
lines.append("")
|
|
|
|
# 添加结构质量
|
|
lines.extend([
|
|
"## 二、模具结构质量",
|
|
"",
|
|
f"- 评分: {report['structure_quality']['score']:.1f}分",
|
|
"",
|
|
])
|
|
|
|
if report["structure_quality"].get("issues"):
|
|
lines.append("**结构问题**:")
|
|
for issue in report["structure_quality"]["issues"]:
|
|
lines.append(f"- {issue}")
|
|
lines.append("")
|
|
|
|
if report["structure_quality"].get("recommendations"):
|
|
lines.append("**改进建议**:")
|
|
for rec in report["structure_quality"]["recommendations"]:
|
|
lines.append(f"- {rec}")
|
|
lines.append("")
|
|
|
|
# 添加生产可行性
|
|
lines.extend([
|
|
"## 三、生产可行性",
|
|
"",
|
|
])
|
|
|
|
for item in report["feasibility"]["items"]:
|
|
status_icon = "✅" if item["status"] == "ok" else "⚠️"
|
|
lines.append(f"{status_icon} **{item['item']}**: {item['value']} - {item['message']}")
|
|
|
|
lines.append("")
|
|
|
|
return "\n".join(lines)
|