This commit is contained in:
2026-04-21 14:41:58 +08:00
parent 5b7bbccce0
commit f8f034552a
2 changed files with 97 additions and 63 deletions
+39 -47
View File
@@ -247,9 +247,12 @@ class AluminumFoamMoldGenerator:
"manufacturing_info": { "manufacturing_info": {
"estimated_mold_size": self._calculate_mold_size(analysis), "estimated_mold_size": self._calculate_mold_size(analysis),
"estimated_clamping_force": self._calculate_clamping_force(analysis), "estimated_clamping_force": self._calculate_clamping_force(analysis),
"clamping_force_formula": "投影面积(cm²) × 0.3 (泡沫材料系数)",
"recommended_material": material_info.get("description", "Aluminum Foam Mold"), "recommended_material": material_info.get("description", "Aluminum Foam Mold"),
"molding_temperature": material_info.get("molding_temp", 380), "molding_temperature": material_info.get("molding_temp", 380),
"expansion_ratio": material_info.get("expansion_ratio", 2.5) "expansion_ratio": material_info.get("expansion_ratio", 2.5),
"parting_direction": "Z",
"parting_description": "Z轴上下开模,分型面位于包围盒Z中心",
}, },
"quality_checks": { "quality_checks": {
"undercut_regions": cavity_data.get("undercut_regions", []), "undercut_regions": cavity_data.get("undercut_regions", []),
@@ -436,7 +439,11 @@ class AluminumFoamMoldGenerator:
def _detect_parting_surfaces(self, shape: Any, analysis: Dict) -> Dict[str, Any]: def _detect_parting_surfaces(self, shape: Any, analysis: Dict) -> Dict[str, Any]:
""" """
检测分型面(支持多分型面) 检测分型面(泡沫模具专用)
规则:
1. 优先选择 Z 轴方向分型(上下开模)
2. 分型面位置选在产品的最大轮廓处,即包围盒的 Z 方向中心
""" """
# 1. 尝试 AI 模型 # 1. 尝试 AI 模型
if self.ai_parting_detector is not None: if self.ai_parting_detector is not None:
@@ -447,57 +454,36 @@ class AluminumFoamMoldGenerator:
except Exception as e: except Exception as e:
logger.warning(f"AI 分型面检测失败: {e}") logger.warning(f"AI 分型面检测失败: {e}")
# 2. 法向量分析确定主方向 # 2. 泡沫模具强制 Z 轴方向分型(上下开模)
normal_stats = analysis.get("normal_statistics", {})
primary_direction = normal_stats.get("primary_direction", [0, 0, 1])
# 3. 创建主分型面
bbox = analysis["bounding_box"] bbox = analysis["bounding_box"]
center = bbox["center"] center = bbox["center"]
primary_direction = [0, 0, 1] # Z 轴方向
# 沿主方向创建分型面 # 分型面位于包围盒 Z 方向中心(最大轮廓处)
dir_obj = gp_Dir(primary_direction[0], primary_direction[1], primary_direction[2]) parting_z = center[2]
parting_plane = gp_Pln(gp_Pnt(center[0], center[1], center[2]), dir_obj) parting_plane = gp_Pln(gp_Pnt(center[0], center[1], parting_z), gp_Dir(0, 0, 1))
try: try:
parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face() parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face()
except Exception: except Exception:
# 回退到默认平面 # 回退到默认平面
parting_plane = gp_Pln(gp_Pnt(0, 0, center[2]), gp_Dir(0, 0, 1)) parting_plane = gp_Pln(gp_Pnt(0, 0, parting_z), gp_Dir(0, 0, 1))
parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face() parting_surface = BRepBuilderAPI_MakeFace(parting_plane).Face()
# 4. 计算分型线 logger.info(f"泡沫模具 Z 轴分型面: Z={parting_z:.2f} mm (包围盒中心)")
# 3. 计算分型线
parting_line = self._calculate_parting_line(shape, parting_surface) parting_line = self._calculate_parting_line(shape, parting_surface)
# 5. 检测是否需要多分型面(基于产品复杂度)
additional_surfaces = []
# 检查产品高度方向的比例
dims = bbox["dimensions"]
max_dim = max(dims)
min_dim = min(dims)
# 如果产品非常扁平,可能需要水平分型面
if 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 { return {
"primary_surface": parting_surface, "primary_surface": parting_surface,
"primary_line": parting_line, "primary_line": parting_line,
"primary_direction": primary_direction, "primary_direction": primary_direction,
"confidence": normal_stats.get("confidence", 0.5), "confidence": 0.95, # Z 轴分型置信度高
"additional_surfaces": additional_surfaces, "additional_surfaces": [],
"surface_count": 1 + len(additional_surfaces) "surface_count": 1,
"parting_direction": "Z",
"parting_position_z": parting_z,
} }
def _detect_undercut_regions(self, shape: Any, parting_surface: Any) -> List[Dict]: def _detect_undercut_regions(self, shape: Any, parting_surface: Any) -> List[Dict]:
@@ -904,17 +890,23 @@ class AluminumFoamMoldGenerator:
} }
def _calculate_clamping_force(self, analysis: Dict) -> str: def _calculate_clamping_force(self, analysis: Dict) -> str:
"""估算锁模力""" """
volume_cm3 = analysis.get("volume", 0) / 1000 估算锁模力(泡沫模具专用)
if volume_cm3 < 10: 公式: 锁模力(吨) = 投影面积(cm²) × 0.3 (泡沫材料系数)
return "30-50 吨" 投影面积 = 长度 × 宽度 (Z轴开模)
elif volume_cm3 < 50: """
return "50-100 吨" bbox = analysis.get("bounding_box", {})
elif volume_cm3 < 200: dims = bbox.get("dimensions", [0, 0, 0])
return "100-200 吨"
else: # 投影面积 = 长度 × 宽度 (mm² → cm²)
return "200+ 吨" 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: def _calculate_product_weight(self, analysis: Dict) -> str:
"""计算产品重量""" """计算产品重量"""
+48 -6
View File
@@ -18,11 +18,27 @@ class CalculationService:
return volume_cm3 * density return volume_cm3 * density
@staticmethod @staticmethod
def calculate_projected_area(bbox_dims: List[float]) -> float: def calculate_projected_area(bbox_dims: List[float], parting_direction: str = "Z") -> float:
"""计算投影面积(cm²),取 X、Y 方向""" """
if len(bbox_dims) >= 2: 计算投影面积(cm²)
return (bbox_dims[0] * bbox_dims[1]) / 100
Args:
bbox_dims: [长度, 宽度, 高度] (mm)
parting_direction: 开模方向,"Z" 表示上下开模(投影到XY平面),
"Y" 表示前后开模(投影到XZ平面),
"X" 表示左右开模(投影到YZ平面)
"""
if len(bbox_dims) < 3:
return 0.0 return 0.0
if parting_direction == "Z":
# Z轴开模 → 投影面积 = 长度 × 宽度
return (bbox_dims[0] * bbox_dims[1]) / 100
elif parting_direction == "Y":
return (bbox_dims[0] * bbox_dims[2]) / 100
elif parting_direction == "X":
return (bbox_dims[1] * bbox_dims[2]) / 100
# 默认 Z 轴
return (bbox_dims[0] * bbox_dims[1]) / 100
@staticmethod @staticmethod
def calculate_cavity_count(product_weight_g: float, projected_area_cm2: float) -> int: def calculate_cavity_count(product_weight_g: float, projected_area_cm2: float) -> int:
@@ -55,12 +71,25 @@ class CalculationService:
cavity_count: int, cavity_count: int,
runner_ratio: float = 0.20, runner_ratio: float = 0.20,
injection_pressure: float = 700, injection_pressure: float = 700,
is_foam: bool = False,
) -> int: ) -> int:
""" """
计算所需夹紧力(吨) 计算所需夹紧力(吨)
塑料模具: 锁模力 = 投影面积 × 型腔数 × (1+流道比) × 注塑压力 / 1000
泡沫模具: 锁模力 = 投影面积(cm²) × 0.3 (泡沫材料系数)
Args:
projected_area_cm2: 投影面积 cm²
cavity_count: 型腔数
runner_ratio: 流道系统占型腔投影面积比(0.15-0.25) runner_ratio: 流道系统占型腔投影面积比(0.15-0.25)
injection_pressure: 注塑压力 kg/cm² injection_pressure: 注塑压力 kg/cm²
is_foam: 是否泡沫材料
""" """
if is_foam:
# 泡沫模具: 锁模力(吨) = 投影面积(cm²) × 0.3
clamping_force_ton = int(projected_area_cm2 * 0.3)
else:
total_projected_area = projected_area_cm2 * cavity_count * (1 + runner_ratio) total_projected_area = projected_area_cm2 * cavity_count * (1 + runner_ratio)
clamping_force_ton = int(total_projected_area * injection_pressure / 1000) clamping_force_ton = int(total_projected_area * injection_pressure / 1000)
return max(50, min(clamping_force_ton, 3000)) return max(50, min(clamping_force_ton, 3000))
@@ -165,13 +194,19 @@ class CalculationService:
material_density = material["density"] material_density = material["density"]
shrinkage_rate = material["shrinkage"] shrinkage_rate = material["shrinkage"]
is_foam = material.get("is_foam", False)
# 泡沫模具优先 Z 轴开模(上下开模)
parting_direction = "Z"
# 各项计算 # 各项计算
volume_cm3 = volume_mm3 / 1000 volume_cm3 = volume_mm3 / 1000
product_weight_g = cls.calculate_product_weight(volume_mm3, material_density) product_weight_g = cls.calculate_product_weight(volume_mm3, material_density)
projected_area_cm2 = cls.calculate_projected_area(bbox_dims) projected_area_cm2 = cls.calculate_projected_area(bbox_dims, parting_direction)
cavity_count = cls.calculate_cavity_count(product_weight_g, projected_area_cm2) cavity_count = cls.calculate_cavity_count(product_weight_g, projected_area_cm2)
clamping_force_ton = cls.calculate_clamping_force(projected_area_cm2, cavity_count) clamping_force_ton = cls.calculate_clamping_force(
projected_area_cm2, cavity_count, is_foam=is_foam
)
wall = cls.calculate_wall_thickness(volume_mm3, surface_area_mm2) wall = cls.calculate_wall_thickness(volume_mm3, surface_area_mm2)
complexity_score = cls.calculate_complexity(wall["avg_thickness_mm"]) complexity_score = cls.calculate_complexity(wall["avg_thickness_mm"])
mold_size = cls.calculate_mold_size(bbox_dims, cavity_count) mold_size = cls.calculate_mold_size(bbox_dims, cavity_count)
@@ -187,6 +222,8 @@ class CalculationService:
"shrinkage_rate": shrinkage_rate, "shrinkage_rate": shrinkage_rate,
"draft_angle": 2.0, "draft_angle": 2.0,
"selected_material": material["name"], "selected_material": material["name"],
"is_foam": is_foam,
"parting_direction": parting_direction,
}, },
"product_analysis": { "product_analysis": {
"volume": volume_mm3, "volume": volume_mm3,
@@ -197,6 +234,10 @@ class CalculationService:
"recommended_material": material["name"], "recommended_material": material["name"],
"material_density": f"{material_density} g/cm³", "material_density": f"{material_density} g/cm³",
"estimated_clamping_force": f"{clamping_force_ton} 吨", "estimated_clamping_force": f"{clamping_force_ton} 吨",
"clamping_force_formula": (
"投影面积(cm²) × 0.3" if is_foam
else "投影面积 × 型腔数 × (1+流道比) × 注塑压力 / 1000"
),
"estimated_mold_size": { "estimated_mold_size": {
"length": int(mold_size["length"]), "length": int(mold_size["length"]),
"width": int(mold_size["width"]), "width": int(mold_size["width"]),
@@ -208,6 +249,7 @@ class CalculationService:
"parting_line_length": f"{parting_line_length:.2f} mm", "parting_line_length": f"{parting_line_length:.2f} mm",
"estimated_cycle_time": f"{cycle_time} 秒", "estimated_cycle_time": f"{cycle_time} 秒",
"injection_pressure": f"{injection_pressure} kg/cm²", "injection_pressure": f"{injection_pressure} kg/cm²",
"parting_direction": parting_direction,
}, },
"mold_cavities": { "mold_cavities": {
"cavity_count": cavity_count, "cavity_count": cavity_count,