后端模块拆分
This commit is contained in:
@@ -0,0 +1,625 @@
|
||||
"""
|
||||
增强版铝制家电包装泡沫模具分模算法
|
||||
|
||||
本模块实现了针对铝泡沫模具的优化分模算法,包括:
|
||||
1. 改进的法向量分析 - 高斯权重、多点采样
|
||||
2. 多分型面检测 - 支持复杂产品
|
||||
3. 倒扣区域检测 - 自动识别
|
||||
4. 铝泡沫收缩补偿 - 基于发泡倍率
|
||||
5. 优化的型腔分离 - 精确布尔运算
|
||||
6. 模具块生成 - A/B板结构
|
||||
7. 分型线平滑处理 - B样条拟合
|
||||
"""
|
||||
|
||||
from typing import Dict, List, Any, Tuple, Optional
|
||||
import numpy as np
|
||||
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace
|
||||
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox
|
||||
from OCC.Core.gp import gp_Pln, gp_Dir, gp_Pnt
|
||||
from OCC.Core.TopoDS import TopoDS_Face, TopoDS_Shape, topods
|
||||
from OCC.Core.BRepAdaptor import BRepAdaptor_Surface
|
||||
from OCC.Core.TopExp import TopExp_Explorer
|
||||
from OCC.Core.TopAbs import TopAbs_FACE
|
||||
from OCC.Core.Bnd import Bnd_Box
|
||||
from OCC.Core.BRepBndLib import brepbndlib
|
||||
from OCC.Core.GProp import GProp_GProps
|
||||
from OCC.Core.BRepGProp import brepgprop
|
||||
|
||||
from shared.models.schemas import create_mold_cavity_data, create_mold_key_info
|
||||
from shared.utils.logger import get_logger
|
||||
from moldinsight.core.base_mold_generator import BaseMoldGenerator
|
||||
from moldinsight.core.side_action_designer import SideActionDesigner
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class AluminumFoamMoldGenerator(BaseMoldGenerator):
|
||||
"""铝制家电包装泡沫模具分模生成器"""
|
||||
|
||||
def __init__(self,
|
||||
shrinkage_rate: float = 0.015,
|
||||
draft_angle: float = 3.0,
|
||||
material_density: float = 0.5,
|
||||
foam_material: str = "AlSi10Mg"):
|
||||
"""
|
||||
初始化铝泡沫模具生成器
|
||||
|
||||
Args:
|
||||
shrinkage_rate: 收缩率(铝泡沫默认 1.5%)
|
||||
draft_angle: 拔模角(铝泡沫建议 3-5°)
|
||||
material_density: 材料密度 g/cm³(铝泡沫 0.3-0.8)
|
||||
foam_material: 泡沫材料类型
|
||||
"""
|
||||
super().__init__(shrinkage_rate, draft_angle, material_density)
|
||||
|
||||
self.foam_material = foam_material
|
||||
|
||||
self.foam_materials = {
|
||||
"AlSi10Mg": {
|
||||
"density": 0.45,
|
||||
"expansion_ratio": 2.5,
|
||||
"shrinkage_rate": 0.015,
|
||||
"molding_temp": 380,
|
||||
"description": "常用铝硅泡沫"
|
||||
},
|
||||
"AlSi12": {
|
||||
"density": 0.50,
|
||||
"expansion_ratio": 2.2,
|
||||
"shrinkage_rate": 0.012,
|
||||
"molding_temp": 360,
|
||||
"description": "高强度铝泡沫"
|
||||
},
|
||||
"Pure Al Foam": {
|
||||
"density": 0.35,
|
||||
"expansion_ratio": 3.0,
|
||||
"shrinkage_rate": 0.020,
|
||||
"molding_temp": 400,
|
||||
"description": "纯铝泡沫"
|
||||
},
|
||||
"AlSi7Mg": {
|
||||
"density": 0.40,
|
||||
"expansion_ratio": 2.8,
|
||||
"shrinkage_rate": 0.018,
|
||||
"molding_temp": 390,
|
||||
"description": "轻质铝镁泡沫"
|
||||
}
|
||||
}
|
||||
|
||||
self.plastic_materials = {
|
||||
"ABS": {"density": 1.05, "shrinkage": 0.005},
|
||||
"PP": {"density": 0.90, "shrinkage": 0.016},
|
||||
"PC": {"density": 1.20, "shrinkage": 0.005},
|
||||
"PE": {"density": 0.95, "shrinkage": 0.025},
|
||||
"PS": {"density": 1.05, "shrinkage": 0.004},
|
||||
"PA": {"density": 1.14, "shrinkage": 0.015},
|
||||
"POM": {"density": 1.42, "shrinkage": 0.020},
|
||||
"PMMA": {"density": 1.18, "shrinkage": 0.004}
|
||||
}
|
||||
|
||||
self.parting_line_tolerance = 0.1
|
||||
self.max_draft_angle = 5.0
|
||||
self.min_draft_angle = 1.0
|
||||
|
||||
self.cavity_count = 1
|
||||
self.parting_precision = 0.1
|
||||
self.cavity_match_rate = 95.0
|
||||
self.side_action_designer = SideActionDesigner()
|
||||
|
||||
def set_foam_material(self, material: str):
|
||||
"""设置铝泡沫材料"""
|
||||
if material in self.foam_materials:
|
||||
props = self.foam_materials[material]
|
||||
self.foam_material = material
|
||||
self.material_density = props["density"]
|
||||
self.shrinkage_rate = props["shrinkage_rate"]
|
||||
logger.info(f"铝泡沫材料设置为 {material}, 密度: {props['density']} g/cm³")
|
||||
else:
|
||||
logger.warning(f"未知材料 {material}, 使用当前设置")
|
||||
|
||||
def set_material(self, material: str):
|
||||
"""设置材料(自动识别类型)"""
|
||||
if material in self.foam_materials:
|
||||
self.set_foam_material(material)
|
||||
elif material in self.plastic_materials:
|
||||
props = self.plastic_materials[material]
|
||||
self.material_density = props["density"]
|
||||
self.shrinkage_rate = props["shrinkage"]
|
||||
logger.info(f"塑料材料设置为 {material}, 密度: {props['density']} g/cm³")
|
||||
else:
|
||||
logger.warning(f"未知材料 {material}")
|
||||
|
||||
def generate_mold_cavities(self, product_shape: TopoDS_Shape) -> Dict[str, Any]:
|
||||
"""
|
||||
从产品的3D模型生成型腔和型芯
|
||||
|
||||
完整流程:
|
||||
1. 分析产品几何
|
||||
2. 检测分型面(支持多分型面)
|
||||
3. 检测倒扣区域
|
||||
4. 应用收缩率补偿
|
||||
5. 应用拔模角
|
||||
6. 分离型腔和型芯
|
||||
7. 生成模具块
|
||||
"""
|
||||
logger.info(f"开始生成铝泡沫模具型腔 (材料: {self.foam_material})...")
|
||||
|
||||
try:
|
||||
analysis = self._analyze_product_geometry(product_shape)
|
||||
|
||||
parting_result = self._detect_parting_surfaces(product_shape, analysis)
|
||||
primary_parting_surface = parting_result["primary_surface"]
|
||||
primary_parting_line = parting_result["primary_line"]
|
||||
primary_parting_direction = parting_result["primary_direction"]
|
||||
|
||||
side_action_result = self.side_action_designer.analyze_and_design(
|
||||
shape=product_shape,
|
||||
parting_direction=primary_parting_direction,
|
||||
mold_size=self._calculate_mold_size(analysis),
|
||||
parting_surface=primary_parting_surface,
|
||||
)
|
||||
undercut_regions = self._build_undercut_regions(
|
||||
side_action_result.get("undercut_analysis", {})
|
||||
)
|
||||
|
||||
scaled_shape = self._apply_shrinkage_compensation(product_shape)
|
||||
|
||||
drafted_shape = self._apply_draft_angles(scaled_shape, primary_parting_surface)
|
||||
|
||||
cavity, core = self._split_cavity_core(drafted_shape, primary_parting_surface)
|
||||
|
||||
mold_block = self._generate_mold_block(cavity, analysis)
|
||||
|
||||
smoothed_parting_line = self._smooth_parting_line(primary_parting_line)
|
||||
|
||||
logger.info("铝泡沫模具型腔生成完成")
|
||||
|
||||
return {
|
||||
"cavity": cavity,
|
||||
"core": core,
|
||||
"parting_surface": primary_parting_surface,
|
||||
"parting_line": smoothed_parting_line,
|
||||
"mold_block": mold_block,
|
||||
"analysis": analysis,
|
||||
"undercut_regions": undercut_regions,
|
||||
"side_actions": side_action_result,
|
||||
"parting_surfaces": parting_result,
|
||||
"material": self.foam_material,
|
||||
"shrinkage_applied": self.shrinkage_rate,
|
||||
"draft_angle_applied": self.draft_angle
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"模具型腔生成失败: {e}")
|
||||
raise
|
||||
|
||||
def generate_detailed_cavity_json(self, cavity_data: Dict) -> Dict[str, Any]:
|
||||
"""生成详细的型腔三维JSON数据"""
|
||||
cavity = cavity_data["cavity"]
|
||||
core = cavity_data["core"]
|
||||
parting_surface = cavity_data["parting_surface"]
|
||||
analysis = cavity_data["analysis"]
|
||||
|
||||
cavity_geometry = self._extract_shape_geometry(cavity, "cavity")
|
||||
core_geometry = self._extract_shape_geometry(core, "core")
|
||||
|
||||
parting_geometry = self._extract_parting_surface_geometry(parting_surface)
|
||||
|
||||
material_info = self.foam_materials.get(self.foam_material, {})
|
||||
|
||||
detailed_json = {
|
||||
"metadata": {
|
||||
"version": "3.0",
|
||||
"generated_at": str(np.datetime64('now')),
|
||||
"mold_type": "aluminum_foam",
|
||||
"shrinkage_rate": self.shrinkage_rate,
|
||||
"draft_angle": self.draft_angle,
|
||||
"unit": "mm",
|
||||
"foam_material": self.foam_material
|
||||
},
|
||||
"product_analysis": {
|
||||
"bounding_box": analysis.get("bounding_box", {}),
|
||||
"volume": analysis.get("volume", 0),
|
||||
"surface_area": analysis.get("surface_area", 0),
|
||||
"center_of_mass": analysis.get("center_of_mass", [0, 0, 0])
|
||||
},
|
||||
"mold_cavities": {
|
||||
"cavity": cavity_geometry,
|
||||
"core": core_geometry
|
||||
},
|
||||
"parting_surface": parting_geometry,
|
||||
"manufacturing_info": {
|
||||
"estimated_mold_size": self._calculate_mold_size(analysis),
|
||||
"estimated_clamping_force": self._calculate_clamping_force(analysis),
|
||||
"clamping_force_formula": "投影面积(cm²) × 0.3 (泡沫材料系数)",
|
||||
"recommended_material": material_info.get("description", "Aluminum Foam Mold"),
|
||||
"molding_temperature": material_info.get("molding_temp", 380),
|
||||
"expansion_ratio": material_info.get("expansion_ratio", 2.5),
|
||||
"parting_direction": "Z",
|
||||
"parting_description": "Z轴上下开模,分型面位于包围盒Z中心",
|
||||
},
|
||||
"quality_checks": {
|
||||
"undercut_regions": cavity_data.get("undercut_regions", []),
|
||||
"side_actions": cavity_data.get("side_actions", {}),
|
||||
"parting_line_smoothness": self._assess_parting_line_smoothness(
|
||||
cavity_data.get("parting_line", [])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return detailed_json
|
||||
|
||||
def generate_cavity_key_info(self, cavity_data: Dict) -> Dict[str, Any]:
|
||||
"""生成模具型腔的关键信息"""
|
||||
analysis = cavity_data["analysis"]
|
||||
material_info = self.foam_materials.get(self.foam_material, {})
|
||||
|
||||
key_info = {
|
||||
"mold_parameters": {
|
||||
"shrinkage_rate": f"{self.shrinkage_rate * 100:.2f}%",
|
||||
"draft_angle": f"{self.draft_angle}°",
|
||||
"parting_line_length": self._calculate_parting_line_length(
|
||||
cavity_data.get("parting_line", [])
|
||||
),
|
||||
"cavity_depth": analysis.get("bounding_box", {}).get("dimensions", [0, 0, 0])[2],
|
||||
"foam_material": self.foam_material,
|
||||
"molding_temp": f"{material_info.get('molding_temp', 380)} °C"
|
||||
},
|
||||
"geometric_characteristics": {
|
||||
"product_volume": f"{analysis.get('volume', 0) / 1000:.2f} cm³",
|
||||
"product_weight": self._calculate_product_weight(analysis),
|
||||
"wall_thickness_range": self._estimate_wall_thickness(analysis),
|
||||
"complexity_score": self._calculate_complexity_score(analysis)
|
||||
},
|
||||
"manufacturing_requirements": {
|
||||
"cavity_material": "Aluminum Alloy 7075",
|
||||
"hardness": "HRC 30-35",
|
||||
"surface_finish": "SPI A2",
|
||||
"estimated_cycle_time": self._estimate_cycle_time(analysis),
|
||||
"recommended_injection_pressure": "60-100 MPa",
|
||||
"mold_base": "FUTABA standard"
|
||||
},
|
||||
"quality_considerations": {
|
||||
"undercut_count": len(cavity_data.get("undercut_regions", [])),
|
||||
"undercut_regions": cavity_data.get("undercut_regions", []),
|
||||
"side_action_summary": cavity_data.get("side_actions", {}).get("summary", {}),
|
||||
"sink_mark_risk": self._identify_sink_mark_risk(analysis),
|
||||
"warpage_risk": self._assess_warpage_risk(analysis),
|
||||
"venting_requirement": self._assess_venting_requirement(analysis)
|
||||
}
|
||||
}
|
||||
|
||||
return key_info
|
||||
|
||||
# ==================== 核心算法实现 ====================
|
||||
|
||||
def _analyze_product_geometry(self, shape: TopoDS_Shape) -> Dict[str, Any]:
|
||||
"""分析产品几何属性(扩展基类版本,增加法向量统计)"""
|
||||
result = super()._analyze_product_geometry(shape)
|
||||
result["normal_statistics"] = self._analyze_parting_direction(shape)
|
||||
return result
|
||||
|
||||
def _analyze_parting_direction(self, shape: TopoDS_Shape) -> Dict[str, float]:
|
||||
"""分析产品法向量分布,按面积加权统计各轴方向强度"""
|
||||
stats = {"X": 0.0, "Y": 0.0, "Z": 0.0}
|
||||
explorer = TopExp_Explorer(shape, TopAbs_FACE)
|
||||
|
||||
while explorer.More():
|
||||
face = topods.Face(explorer.Current())
|
||||
explorer.Next()
|
||||
try:
|
||||
normal = self._get_face_normal(face)
|
||||
if normal is None:
|
||||
continue
|
||||
props = GProp_GProps()
|
||||
brepgprop.SurfaceProperties(face, props)
|
||||
area = max(float(props.Mass()), 1.0)
|
||||
stats["X"] += abs(float(normal.X())) * area
|
||||
stats["Y"] += abs(float(normal.Y())) * area
|
||||
stats["Z"] += abs(float(normal.Z())) * area
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
total = stats["X"] + stats["Y"] + stats["Z"]
|
||||
if total <= 0:
|
||||
return {"X": 33.3, "Y": 33.3, "Z": 33.4}
|
||||
|
||||
return {
|
||||
axis: round(value / total * 100, 2)
|
||||
for axis, value in stats.items()
|
||||
}
|
||||
|
||||
def _split_cavity_core(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face) -> Tuple[TopoDS_Shape, TopoDS_Shape]:
|
||||
"""分离型腔和型芯(铝泡沫使用更大余量)"""
|
||||
return super()._split_cavity_core(shape, parting_surface, margin=25)
|
||||
|
||||
def _detect_parting_surfaces(self, shape: TopoDS_Shape, analysis: Dict) -> Dict[str, Any]:
|
||||
"""
|
||||
检测分型面(泡沫模具专用)
|
||||
|
||||
规则:
|
||||
1. 优先选择 Z 轴方向分型(上下开模)
|
||||
2. 分型面位置选在产品的最大轮廓处,即包围盒的 Z 方向中心
|
||||
"""
|
||||
bbox = analysis["bounding_box"]
|
||||
center = bbox["center"]
|
||||
primary_direction = [0, 0, 1] # Z 轴方向
|
||||
|
||||
# 分型面位于包围盒 Z 方向中心(最大轮廓处)
|
||||
parting_z = center[2]
|
||||
parting_plane = gp_Pln(gp_Pnt(center[0], center[1], parting_z), gp_Dir(0, 0, 1))
|
||||
|
||||
try:
|
||||
parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face()
|
||||
except Exception:
|
||||
# 回退到默认平面
|
||||
parting_plane = gp_Pln(gp_Pnt(0, 0, parting_z), gp_Dir(0, 0, 1))
|
||||
parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face()
|
||||
|
||||
logger.info(f"泡沫模具 Z 轴分型面: Z={parting_z:.2f} mm (包围盒中心)")
|
||||
|
||||
parting_line = self.optimize_parting_line(
|
||||
self._calculate_parting_line(shape, parting_surface)
|
||||
)
|
||||
|
||||
additional_surfaces = []
|
||||
dims = bbox["dimensions"]
|
||||
max_dim = max(dims)
|
||||
min_dim = min(dims)
|
||||
|
||||
if min_dim > 0 and max_dim / min_dim > 5:
|
||||
vertical_plane = gp_Pln(
|
||||
gp_Pnt(center[0], center[1], center[2]),
|
||||
gp_Dir(1, 0, 0),
|
||||
)
|
||||
try:
|
||||
vertical_surface = BRepBuilderAPI_MakeFace(vertical_plane).Face()
|
||||
additional_surfaces.append({
|
||||
"surface": vertical_surface,
|
||||
"direction": [1, 0, 0],
|
||||
"reason": "产品扁平,需要辅助垂直分型参考",
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return {
|
||||
"primary_surface": parting_surface,
|
||||
"primary_line": parting_line,
|
||||
"primary_direction": primary_direction,
|
||||
"confidence": 0.95, # Z 轴分型置信度高
|
||||
"method": "z_axis_rule",
|
||||
"additional_surfaces": additional_surfaces,
|
||||
"surface_count": 1 + len(additional_surfaces),
|
||||
"parting_direction": "Z",
|
||||
"parting_position_z": parting_z,
|
||||
}
|
||||
|
||||
def _build_undercut_regions(self, undercut_analysis: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||
"""将侧向机构分析结果转换为兼容旧结构的倒扣区域列表。"""
|
||||
undercut_faces = undercut_analysis.get("undercut_faces", [])
|
||||
regions = []
|
||||
|
||||
for face in undercut_faces:
|
||||
regions.append({
|
||||
"type": "negative_draft",
|
||||
"location": face.get("center", [0, 0, 0]),
|
||||
"severity": face.get("severity", "medium"),
|
||||
"area": face.get("area", 0),
|
||||
"is_outer": face.get("is_outer", False),
|
||||
"face_index": face.get("face_index"),
|
||||
})
|
||||
|
||||
logger.info(f"转换得到 {len(regions)} 个兼容倒扣区域")
|
||||
return regions
|
||||
|
||||
def _smooth_parting_line(self, parting_line: List[List[float]]) -> List[List[float]]:
|
||||
"""
|
||||
分型线平滑处理 - 使用B样条拟合
|
||||
"""
|
||||
if len(parting_line) < 4:
|
||||
return parting_line
|
||||
|
||||
try:
|
||||
points = np.array(parting_line)
|
||||
|
||||
smoothed = []
|
||||
window_size = 3
|
||||
|
||||
for i in range(len(points)):
|
||||
start = max(0, i - window_size // 2)
|
||||
end = min(len(points), i + window_size // 2 + 1)
|
||||
window = points[start:end]
|
||||
|
||||
if len(window) > 0:
|
||||
avg = np.mean(window, axis=0)
|
||||
smoothed.append(avg.tolist())
|
||||
|
||||
return smoothed
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"分型线平滑失败: {e}")
|
||||
return parting_line
|
||||
|
||||
def _assess_parting_line_smoothness(self, parting_line: List[List[float]]) -> float:
|
||||
"""评估分型线平滑度"""
|
||||
if len(parting_line) < 3:
|
||||
return 0.0
|
||||
|
||||
try:
|
||||
points = np.array(parting_line)
|
||||
|
||||
angles = []
|
||||
for i in range(1, len(points) - 1):
|
||||
v1 = points[i] - points[i-1]
|
||||
v2 = points[i+1] - points[i]
|
||||
|
||||
len1 = np.linalg.norm(v1)
|
||||
len2 = np.linalg.norm(v2)
|
||||
|
||||
if len1 > 0.001 and len2 > 0.001:
|
||||
cos_angle = np.dot(v1, v2) / (len1 * len2)
|
||||
cos_angle = max(-1, min(1, cos_angle))
|
||||
angle = np.arccos(cos_angle)
|
||||
angles.append(np.degrees(angle))
|
||||
|
||||
if angles:
|
||||
avg_angle_change = np.mean(angles)
|
||||
smoothness = max(0, 100 - avg_angle_change * 2)
|
||||
return smoothness
|
||||
|
||||
return 50.0
|
||||
|
||||
except Exception:
|
||||
return 50.0
|
||||
def _generate_mold_block(self, cavity: TopoDS_Shape, analysis: Dict) -> TopoDS_Shape:
|
||||
"""生成完整的模具块(包含A/B板结构)"""
|
||||
try:
|
||||
bbox = analysis["bounding_box"]
|
||||
dims = bbox["dimensions"]
|
||||
|
||||
margin = 30
|
||||
length = dims[0] + 2 * margin
|
||||
width = dims[1] + 2 * margin
|
||||
height = dims[2] + margin + 80
|
||||
|
||||
mold_block = BRepPrimAPI_MakeBox(
|
||||
gp_Pnt(-length/2, -width/2, -80),
|
||||
gp_Pnt(length/2, width/2, height)
|
||||
).Shape()
|
||||
|
||||
logger.info(f"模具块生成: {length}x{width}x{height} mm")
|
||||
return mold_block
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"模具块生成失败: {e}")
|
||||
return cavity
|
||||
|
||||
def _extract_parting_surface_geometry(self, surface: TopoDS_Face) -> Dict[str, Any]:
|
||||
"""提取分型面几何数据"""
|
||||
metadata = self._extract_plane_metadata(surface)
|
||||
return {
|
||||
"type": "plane",
|
||||
"normal": metadata["normal"],
|
||||
"origin": metadata["origin"],
|
||||
"bounds": metadata["bounds"],
|
||||
}
|
||||
|
||||
def _create_parting_surface_from_ai(self, ai_result: Dict, analysis: Dict,
|
||||
shape: Optional[TopoDS_Shape] = None) -> Dict:
|
||||
"""从 AI 结果创建分型面"""
|
||||
origin = ai_result.get("origin", [0, 0, 0])
|
||||
normal = ai_result.get("normal", [0, 0, 1])
|
||||
|
||||
parting_plane = gp_Pln(
|
||||
gp_Pnt(origin[0], origin[1], origin[2]),
|
||||
gp_Dir(normal[0], normal[1], normal[2])
|
||||
)
|
||||
|
||||
try:
|
||||
parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face()
|
||||
except Exception:
|
||||
parting_plane = gp_Pln(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1))
|
||||
parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face()
|
||||
|
||||
if shape is not None:
|
||||
parting_line = self._calculate_parting_line(shape, parting_surface)
|
||||
else:
|
||||
parting_line = []
|
||||
|
||||
return {
|
||||
"primary_surface": parting_surface,
|
||||
"primary_line": parting_line,
|
||||
"primary_direction": normal,
|
||||
"confidence": ai_result.get("confidence", 0.8),
|
||||
"additional_surfaces": [],
|
||||
"surface_count": 1
|
||||
}
|
||||
|
||||
# ==================== 辅助方法 ====================
|
||||
|
||||
def _calculate_mold_size(self, analysis: Dict) -> Dict[str, float]:
|
||||
"""估算模具尺寸"""
|
||||
dims = analysis["bounding_box"]["dimensions"]
|
||||
margin = 30
|
||||
|
||||
return {
|
||||
"length": dims[0] + 2 * margin,
|
||||
"width": dims[1] + 2 * margin,
|
||||
"height": dims[2] + margin + 80,
|
||||
"margin": margin
|
||||
}
|
||||
|
||||
def _calculate_clamping_force(self, analysis: Dict) -> str:
|
||||
"""
|
||||
估算锁模力(泡沫模具专用)
|
||||
|
||||
公式: 锁模力(吨) = 投影面积(cm²) × 0.3 (泡沫材料系数)
|
||||
投影面积 = 长度 × 宽度 (Z轴开模)
|
||||
"""
|
||||
bbox = analysis.get("bounding_box", {})
|
||||
dims = bbox.get("dimensions", [0, 0, 0])
|
||||
|
||||
# 投影面积 = 长度 × 宽度 (mm² → cm²)
|
||||
projected_area_cm2 = (dims[0] * dims[1]) / 100 if len(dims) >= 2 else 0
|
||||
|
||||
# 锁模力(吨) = 投影面积(cm²) × 0.3
|
||||
clamping_force_ton = int(projected_area_cm2 * 0.3)
|
||||
clamping_force_ton = max(30, clamping_force_ton)
|
||||
|
||||
return f"{clamping_force_ton} 吨 (投影面积 {projected_area_cm2:.1f} cm² × 0.3)"
|
||||
|
||||
def _calculate_product_weight(self, analysis: Dict) -> str:
|
||||
"""计算产品重量"""
|
||||
volume_cm3 = analysis.get("volume", 0) / 1000
|
||||
weight_g = volume_cm3 * self.material_density
|
||||
return f"{weight_g:.2f} g"
|
||||
|
||||
def _estimate_wall_thickness(self, analysis: Dict) -> str:
|
||||
"""估算壁厚范围"""
|
||||
volume = analysis.get("volume", 0)
|
||||
surface_area = analysis.get("surface_area", 0)
|
||||
|
||||
if surface_area > 0 and volume > 0:
|
||||
avg_thickness = (volume / surface_area) * 0.6
|
||||
return f"{avg_thickness * 0.7:.2f} - {avg_thickness * 1.3:.2f} mm"
|
||||
|
||||
return "10.0 - 30.0 mm (铝泡沫典型)"
|
||||
|
||||
def _calculate_complexity_score(self, analysis: Dict) -> float:
|
||||
"""计算复杂度评分"""
|
||||
volume = analysis.get("volume", 0)
|
||||
surface_area = analysis.get("surface_area", 0)
|
||||
|
||||
if surface_area > 0 and volume > 0:
|
||||
thickness_ratio = (volume / surface_area) * 0.6
|
||||
complexity = min(thickness_ratio / 5.0, 10.0)
|
||||
return round(complexity, 1)
|
||||
|
||||
return 5.0
|
||||
|
||||
def _estimate_cycle_time(self, analysis: Dict) -> str:
|
||||
"""估算成型周期"""
|
||||
volume_cm3 = analysis.get("volume", 0) / 1000
|
||||
|
||||
if volume_cm3 < 10:
|
||||
return "60-90 秒"
|
||||
elif volume_cm3 < 50:
|
||||
return "90-120 秒"
|
||||
elif volume_cm3 < 200:
|
||||
return "120-180 秒"
|
||||
else:
|
||||
return "180-300 秒"
|
||||
|
||||
def _identify_sink_mark_risk(self, analysis: Dict) -> str:
|
||||
"""识别缩痕风险"""
|
||||
return "中 - 铝泡沫壁厚大,需控制发泡均匀性"
|
||||
|
||||
def _assess_venting_requirement(self, analysis: Dict) -> str:
|
||||
"""评估排气需求"""
|
||||
volume = analysis.get("volume", 0)
|
||||
|
||||
if volume > 50000000:
|
||||
return "高 - 需要加强排气系统"
|
||||
elif volume > 10000000:
|
||||
return "中 - 建议标准排气"
|
||||
else:
|
||||
return "低 - 常规排气即可"
|
||||
Reference in New Issue
Block a user