x
This commit is contained in:
@@ -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:
|
||||||
"""计算产品重量"""
|
"""计算产品重量"""
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user