x
This commit is contained in:
@@ -503,7 +503,7 @@ class BaseMoldGenerator:
|
||||
)
|
||||
|
||||
logger.info("回退方案型腔/型芯分离完成")
|
||||
return cavity or mold_block, core
|
||||
return cavity, core
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"分模回退方案失败: {e}")
|
||||
|
||||
@@ -244,44 +244,41 @@ class RoughingToolpathGenerator:
|
||||
tool: Dict, cutting_params: Dict,
|
||||
stock_allowance: float = 0.5) -> Dict[str, Any]:
|
||||
"""
|
||||
Z层等高粗加工
|
||||
Z层等高粗加工 — 生成真实刀路坐标点。
|
||||
|
||||
策略:从顶面逐层向下铣削,每层切深为 axial_depth
|
||||
|
||||
Args:
|
||||
stock_bbox: 毛坯边界框
|
||||
cavity_bbox: 型腔边界框
|
||||
tool: 刀具参数
|
||||
cutting_params: 切削参数
|
||||
stock_allowance: 精加工余量 mm
|
||||
|
||||
Returns:
|
||||
粗加工刀路方案
|
||||
策略:从顶面逐层向下铣削,每层在型腔边界框内往复走刀。
|
||||
"""
|
||||
z_min = cavity_bbox.get("min", [0, 0, 0])[2]
|
||||
z_max = cavity_bbox.get("max", [0, 0, 0])[2]
|
||||
total_depth = z_max - z_min
|
||||
cx_min, cy_min, cz_min = cavity_bbox.get("min", [0, 0, 0])
|
||||
cx_max, cy_max, cz_max = cavity_bbox.get("max", [0, 0, 0])
|
||||
total_depth = cz_max - cz_min
|
||||
|
||||
axial_depth = cutting_params["axial_depth_mm"]
|
||||
num_levels = max(1, math.ceil(total_depth / axial_depth))
|
||||
|
||||
actual_depth = total_depth / num_levels
|
||||
|
||||
stepover = cutting_params["radial_depth_mm"]
|
||||
|
||||
levels = []
|
||||
path_points = []
|
||||
|
||||
for i in range(num_levels):
|
||||
z_level = z_max - (i + 1) * actual_depth + stock_allowance
|
||||
z_level = cz_max - (i + 1) * actual_depth + stock_allowance
|
||||
rounded_z = round(z_level, 2)
|
||||
levels.append({
|
||||
"z": round(z_level, 2),
|
||||
"z": rounded_z,
|
||||
"depth": round(actual_depth, 2),
|
||||
"level_index": i + 1,
|
||||
})
|
||||
layer_points = self._generate_roughing_layer_points(
|
||||
x_min=cx_min, x_max=cx_max,
|
||||
y_min=cy_min, y_max=cy_max,
|
||||
z=rounded_z,
|
||||
stepover=stepover,
|
||||
)
|
||||
path_points.extend(layer_points)
|
||||
|
||||
toolpath_length = self._estimate_roughing_length(
|
||||
cavity_bbox, num_levels, stepover
|
||||
)
|
||||
|
||||
machining_time = CuttingParamsCalculator.estimate_machining_time(
|
||||
toolpath_length, cutting_params["feed_rate_mm_min"]
|
||||
)
|
||||
@@ -298,8 +295,35 @@ class RoughingToolpathGenerator:
|
||||
"estimated_time_min": round(machining_time, 1),
|
||||
"approach_type": "helical_ramp",
|
||||
"ramp_angle": 2.0,
|
||||
"path_points": path_points,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _generate_roughing_layer_points(
|
||||
x_min: float, x_max: float,
|
||||
y_min: float, y_max: float,
|
||||
z: float, stepover: float,
|
||||
) -> List[List[float]]:
|
||||
"""为单个 Z 层生成往复走刀坐标点序列。"""
|
||||
points = []
|
||||
y_positions = []
|
||||
y = y_min
|
||||
while y <= y_max + 0.001:
|
||||
y_positions.append(round(y, 2))
|
||||
y += stepover
|
||||
|
||||
for idx, y_pos in enumerate(y_positions):
|
||||
if idx % 2 == 0:
|
||||
# 正向走刀: x_min → x_max
|
||||
points.append([round(x_min, 2), y_pos, z])
|
||||
points.append([round(x_max, 2), y_pos, z])
|
||||
else:
|
||||
# 反向走刀: x_max → x_min
|
||||
points.append([round(x_max, 2), y_pos, z])
|
||||
points.append([round(x_min, 2), y_pos, z])
|
||||
|
||||
return points
|
||||
|
||||
def _estimate_roughing_length(self, cavity_bbox: Dict, num_levels: int,
|
||||
stepover: float) -> float:
|
||||
"""估算粗加工刀路总长度"""
|
||||
@@ -313,6 +337,70 @@ class RoughingToolpathGenerator:
|
||||
|
||||
return length_per_level * num_levels
|
||||
|
||||
def generate_core_roughing(self, stock_bbox: Dict, core_bbox: Dict,
|
||||
tool: Dict, cutting_params: Dict,
|
||||
stock_allowance: float = 0.5) -> Dict[str, Any]:
|
||||
"""
|
||||
型芯粗加工 — 从外轮廓向内逐层等高铣削。
|
||||
|
||||
型芯是凸出的几何体,策略是从毛坯外边界向内逐层收缩切削,
|
||||
每层保持同一 Z 高度,环绕型芯轮廓走刀。
|
||||
"""
|
||||
sx_min, sy_min, sz_min = stock_bbox.get("min", [0, 0, 0])
|
||||
sx_max, sy_max, sz_max = stock_bbox.get("max", [0, 0, 0])
|
||||
cx_min, cy_min, cz_min = core_bbox.get("min", [0, 0, 0])
|
||||
cx_max, cy_max, cz_max = core_bbox.get("max", [0, 0, 0])
|
||||
|
||||
axial_depth = cutting_params["axial_depth_mm"]
|
||||
radial_depth = cutting_params["radial_depth_mm"]
|
||||
total_depth = cz_max - cz_min
|
||||
num_levels = max(1, math.ceil(total_depth / axial_depth))
|
||||
|
||||
levels = [{
|
||||
"z": round(cz_max - (i + 1) * total_depth / num_levels, 2),
|
||||
"depth": round(total_depth / num_levels, 2),
|
||||
"level_index": i + 1,
|
||||
} for i in range(num_levels)]
|
||||
|
||||
path_points = []
|
||||
margin = 1.0
|
||||
for level in levels:
|
||||
z = level["z"]
|
||||
outer_xmin, outer_xmax = sx_min + margin, sx_max - margin
|
||||
outer_ymin, outer_ymax = sy_min + margin, sy_max - margin
|
||||
num_contours = max(1, int(min(outer_xmax - cx_max, outer_ymax - cy_max) / radial_depth))
|
||||
for c in range(num_contours):
|
||||
inset = c * radial_depth
|
||||
x0 = max(cx_min, outer_xmin + inset)
|
||||
x1 = min(cx_max, outer_xmax - inset)
|
||||
y0 = max(cy_min, outer_ymin + inset)
|
||||
y1 = min(cy_max, outer_ymax - inset)
|
||||
contour = [
|
||||
[round(x0, 2), round(y0, 2), z],
|
||||
[round(x1, 2), round(y0, 2), z],
|
||||
[round(x1, 2), round(y1, 2), z],
|
||||
[round(x0, 2), round(y1, 2), z],
|
||||
]
|
||||
path_points.extend(contour)
|
||||
|
||||
dims = core_bbox.get("dimensions", [100, 100, 50])
|
||||
toolpath_length = num_levels * 2 * (dims[0] + dims[1]) * 2.0
|
||||
machining_time = CuttingParamsCalculator.estimate_machining_time(
|
||||
toolpath_length, cutting_params["feed_rate_mm_min"]
|
||||
)
|
||||
|
||||
return {
|
||||
"strategy": "core_roughing",
|
||||
"tool": cutting_params,
|
||||
"levels": levels,
|
||||
"num_levels": num_levels,
|
||||
"stepover": radial_depth,
|
||||
"stock_allowance": stock_allowance,
|
||||
"estimated_toolpath_length": round(toolpath_length, 1),
|
||||
"estimated_time_min": round(machining_time, 1),
|
||||
"path_points": path_points,
|
||||
}
|
||||
|
||||
|
||||
class FinishingToolpathGenerator:
|
||||
"""精加工刀路生成器"""
|
||||
@@ -322,30 +410,36 @@ class FinishingToolpathGenerator:
|
||||
stepover: float = 0.3,
|
||||
angle: float = 0.0) -> Dict[str, Any]:
|
||||
"""
|
||||
平行铣削精加工
|
||||
平行铣削精加工 — 生成真实刀路坐标点。
|
||||
|
||||
Args:
|
||||
cavity_bbox: 型腔边界框
|
||||
tool: 刀具参数
|
||||
cutting_params: 切削参数
|
||||
stepover: 步距 mm
|
||||
angle: 加工角度
|
||||
|
||||
Returns:
|
||||
精加工刀路方案
|
||||
在型腔顶部沿 Y 方向往复走刀,覆盖整个型腔 XY 区域。
|
||||
"""
|
||||
dims = cavity_bbox.get("dimensions", [100, 100, 50])
|
||||
cx_min, cy_min, cz_min = cavity_bbox.get("min", [0, 0, 0])
|
||||
cx_max, cy_max, cz_max = cavity_bbox.get("max", [0, 0, 0])
|
||||
width = dims[0]
|
||||
length = dims[1]
|
||||
finish_z = cz_max - 0.1 # 型腔顶面
|
||||
|
||||
num_passes = max(1, int(width / stepover) + 1)
|
||||
path_points = []
|
||||
|
||||
y = cy_min
|
||||
for i in range(num_passes):
|
||||
y_pos = round(y + i * stepover, 2)
|
||||
if y_pos > cy_max:
|
||||
y_pos = round(cy_max, 2)
|
||||
if i % 2 == 0:
|
||||
path_points.append([round(cx_min, 2), y_pos, finish_z])
|
||||
path_points.append([round(cx_max, 2), y_pos, finish_z])
|
||||
else:
|
||||
path_points.append([round(cx_max, 2), y_pos, finish_z])
|
||||
path_points.append([round(cx_min, 2), y_pos, finish_z])
|
||||
|
||||
surface_roughness = self._estimate_surface_roughness(
|
||||
tool["diameter"], stepover
|
||||
)
|
||||
|
||||
toolpath_length = num_passes * length * 1.05
|
||||
|
||||
machining_time = CuttingParamsCalculator.estimate_machining_time(
|
||||
toolpath_length, cutting_params["feed_rate_mm_min"]
|
||||
)
|
||||
@@ -361,6 +455,7 @@ class FinishingToolpathGenerator:
|
||||
"estimated_time_min": round(machining_time, 1),
|
||||
"cutting_direction": "one_way",
|
||||
"stepover_type": "scallop",
|
||||
"path_points": path_points,
|
||||
}
|
||||
|
||||
def generate_contour_finishing(self, cavity_bbox: Dict, tool: Dict,
|
||||
@@ -411,6 +506,62 @@ class FinishingToolpathGenerator:
|
||||
h = stepover ** 2 / (8 * r) if r > 0 else stepover
|
||||
return h * 0.25
|
||||
|
||||
def generate_3d_surface_finishing(self, cavity_bbox: Dict, tool: Dict,
|
||||
cutting_params: Dict,
|
||||
stepover: float = 0.5,
|
||||
angle: float = 0.0) -> Dict[str, Any]:
|
||||
"""
|
||||
Ballnose 三维曲面精加工 — Z 随形走刀。
|
||||
|
||||
在型腔边界框内,沿 Y 方向逐行走刀,Z 高度按余弦曲线随 Y 变化,
|
||||
模拟曲面轮廓加工。适用于球头刀对型腔底面的随形精加工。
|
||||
"""
|
||||
dims = cavity_bbox.get("dimensions", [100, 100, 50])
|
||||
cx_min, cy_min, cz_min = cavity_bbox.get("min", [0, 0, 0])
|
||||
cx_max, cy_max, cz_max = cavity_bbox.get("max", [0, 0, 0])
|
||||
width = dims[0]
|
||||
length = dims[1]
|
||||
depth = dims[2]
|
||||
mid_y = (cy_min + cy_max) / 2.0
|
||||
|
||||
num_passes = max(1, int(width / stepover) + 1)
|
||||
path_points = []
|
||||
|
||||
y = cy_min
|
||||
for i in range(num_passes):
|
||||
y_pos = round(y + i * stepover, 2)
|
||||
if y_pos > cy_max:
|
||||
y_pos = round(cy_max, 2)
|
||||
# Z 随 Y 位置按余弦曲线变化,模拟中心最深、边缘最浅的曲面
|
||||
ratio = (y_pos - mid_y) / max((cy_max - cy_min) / 2, 1.0)
|
||||
z_depth = cz_max - depth * 0.85 * (1.0 - min(abs(ratio), 1.0))
|
||||
z_finish = round(max(cz_min + 0.1, z_depth), 2)
|
||||
if i % 2 == 0:
|
||||
path_points.append([round(cx_min, 2), y_pos, z_finish])
|
||||
path_points.append([round(cx_max, 2), y_pos, z_finish])
|
||||
else:
|
||||
path_points.append([round(cx_max, 2), y_pos, z_finish])
|
||||
path_points.append([round(cx_min, 2), y_pos, z_finish])
|
||||
|
||||
surface_roughness = self._estimate_surface_roughness(tool["diameter"], stepover)
|
||||
toolpath_length = num_passes * length * 1.1
|
||||
machining_time = CuttingParamsCalculator.estimate_machining_time(
|
||||
toolpath_length, cutting_params["feed_rate_mm_min"]
|
||||
)
|
||||
|
||||
return {
|
||||
"strategy": "3d_surface_finishing",
|
||||
"tool": cutting_params,
|
||||
"stepover": stepover,
|
||||
"angle": angle,
|
||||
"num_passes": num_passes,
|
||||
"surface_roughness_ra": round(surface_roughness, 3),
|
||||
"estimated_toolpath_length": round(toolpath_length, 1),
|
||||
"estimated_time_min": round(machining_time, 1),
|
||||
"note": "3D 曲面随形加工,Z 高度沿 Y 方向余弦变化",
|
||||
"path_points": path_points,
|
||||
}
|
||||
|
||||
|
||||
class GCodePostProcessor:
|
||||
"""G代码后处理器"""
|
||||
@@ -487,31 +638,66 @@ class GCodePostProcessor:
|
||||
|
||||
feed = tool_info.get("feed_rate_mm_min", 500)
|
||||
levels = op.get("levels", [])
|
||||
path_points = op.get("path_points", [])
|
||||
|
||||
if strategy == "z_level_roughing" and levels:
|
||||
for level in levels:
|
||||
z = level["z"]
|
||||
lines.append(f"(--- Z层 {level['level_index']}: Z={z:.2f} ---)")
|
||||
lines.append(f"{d['linear']} Z{z:.2f} F{int(feed * 0.5)}")
|
||||
lines.append(f"{d['linear']} X50.0 Y30.0 F{feed}")
|
||||
lines.append(f"{d['linear']} X-50.0 Y30.0")
|
||||
lines.append(f"{d['linear']} X-50.0 Y-30.0")
|
||||
lines.append(f"{d['linear']} X50.0 Y-30.0")
|
||||
# 筛选当前 Z 层的刀路点
|
||||
layer_points = [p for p in path_points if abs(p[2] - z) < 0.01]
|
||||
if layer_points:
|
||||
for pt in layer_points:
|
||||
lines.append(f"{d['linear']} X{pt[0]:.2f} Y{pt[1]:.2f} F{feed}")
|
||||
else:
|
||||
# 无精细刀路点时退化为矩形扫面
|
||||
cx_min = min(p[0] for p in path_points) if path_points else -50.0
|
||||
cx_max = max(p[0] for p in path_points) if path_points else 50.0
|
||||
cy_min = min(p[1] for p in path_points) if path_points else -30.0
|
||||
cy_max = max(p[1] for p in path_points) if path_points else 30.0
|
||||
lines.append(f"{d['linear']} X{cx_max:.2f} Y{cy_min:.2f} F{feed}")
|
||||
lines.append(f"{d['linear']} X{cx_min:.2f} Y{cy_min:.2f}")
|
||||
lines.append(f"{d['linear']} X{cx_min:.2f} Y{cy_max:.2f}")
|
||||
lines.append(f"{d['linear']} X{cx_max:.2f} Y{cy_max:.2f}")
|
||||
lines.append(f"{d['rapid']} Z10.0")
|
||||
lines.append("")
|
||||
|
||||
elif strategy in ("parallel_finishing", "contour_finishing"):
|
||||
num_passes = op.get("num_passes", 10)
|
||||
stepover = op.get("stepover", 0.3)
|
||||
|
||||
for i in range(num_passes):
|
||||
y = i * stepover - 30
|
||||
lines.append(f"{d['linear']} Z-5.0 F{int(feed * 0.3)}")
|
||||
lines.append(f"{d['linear']} X50.0 Y{y:.2f} F{feed}")
|
||||
lines.append(f"{d['linear']} X-50.0 Y{y:.2f}")
|
||||
finish_z = path_points[0][2] if path_points else -5.0
|
||||
lines.append(f"{d['linear']} Z{finish_z:.2f} F{int(feed * 0.3)}")
|
||||
if path_points:
|
||||
for pt in path_points:
|
||||
lines.append(f"{d['linear']} X{pt[0]:.2f} Y{pt[1]:.2f} F{feed}")
|
||||
else:
|
||||
num_passes = op.get("num_passes", 10)
|
||||
stepover = op.get("stepover", 0.3)
|
||||
for i in range(num_passes):
|
||||
y = i * stepover - 30
|
||||
lines.append(f"{d['linear']} X50.0 Y{y:.2f} F{feed}")
|
||||
lines.append(f"{d['linear']} X-50.0 Y{y:.2f}")
|
||||
lines.append(f"{d['rapid']} Z5.0")
|
||||
lines.append("")
|
||||
|
||||
elif strategy == "core_roughing" and levels:
|
||||
for level in levels:
|
||||
z = level["z"]
|
||||
lines.append(f"(--- 型芯Z层 {level['level_index']}: Z={z:.2f} ---)")
|
||||
lines.append(f"{d['linear']} Z{z:.2f} F{int(feed * 0.5)}")
|
||||
layer_points = [p for p in path_points if abs(p[2] - z) < 0.01]
|
||||
for pt in layer_points:
|
||||
lines.append(f"{d['linear']} X{pt[0]:.2f} Y{pt[1]:.2f} F{feed}")
|
||||
lines.append(f"{d['rapid']} Z10.0")
|
||||
lines.append("")
|
||||
|
||||
elif strategy == "3d_surface_finishing":
|
||||
lines.append(f"(--- 3D 曲面精加工,球头刀随形 ---)")
|
||||
if path_points:
|
||||
for pt in path_points:
|
||||
lines.append(f"{d['linear']} X{pt[0]:.2f} Y{pt[1]:.2f} Z{pt[2]:.2f} F{feed}")
|
||||
lines.append(f"{d['rapid']} Z10.0")
|
||||
lines.append("")
|
||||
|
||||
else:
|
||||
lines.append(f"(策略 {strategy} 的刀路数据)")
|
||||
lines.append("")
|
||||
@@ -540,25 +726,50 @@ class MoldCAMDesigner:
|
||||
self.roughing_gen = RoughingToolpathGenerator()
|
||||
self.finishing_gen = FinishingToolpathGenerator()
|
||||
self.post_processor = GCodePostProcessor()
|
||||
self._collision_detector = None
|
||||
self._toolpath_optimizer = None
|
||||
self._edm_designer = None
|
||||
self._machining_simulator = None
|
||||
|
||||
def _get_collision_detector(self):
|
||||
if self._collision_detector is None:
|
||||
from moldinsight.core.mold_machining import CollisionDetector
|
||||
self._collision_detector = CollisionDetector()
|
||||
return self._collision_detector
|
||||
|
||||
def _get_toolpath_optimizer(self):
|
||||
if self._toolpath_optimizer is None:
|
||||
from moldinsight.core.mold_machining import ToolpathOptimizer
|
||||
self._toolpath_optimizer = ToolpathOptimizer()
|
||||
return self._toolpath_optimizer
|
||||
|
||||
def _get_edm_designer(self):
|
||||
if self._edm_designer is None:
|
||||
from moldinsight.core.mold_machining import EDMElectrodeDesigner
|
||||
self._edm_designer = EDMElectrodeDesigner()
|
||||
return self._edm_designer
|
||||
|
||||
def _get_machining_simulator(self):
|
||||
if self._machining_simulator is None:
|
||||
from moldinsight.core.mold_machining import MachiningSimulator
|
||||
self._machining_simulator = MachiningSimulator()
|
||||
return self._machining_simulator
|
||||
|
||||
def design_mold_cam(self, cavity_bbox: Dict, stock_bbox: Dict,
|
||||
mold_steel: str = "P20",
|
||||
surface_quality: str = "standard",
|
||||
controller: str = "fanuc",
|
||||
program_number: int = 1000) -> Dict[str, Any]:
|
||||
program_number: int = 1000,
|
||||
core_bbox: Optional[Dict] = None,
|
||||
undercut_regions: Optional[List[Dict]] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
综合设计模具CAM方案
|
||||
综合设计模具CAM方案(型腔 + 型芯 + 3D 曲面 + EDM + 仿真)。
|
||||
|
||||
Args:
|
||||
cavity_bbox: 型腔边界框
|
||||
stock_bbox: 毛坯边界框
|
||||
mold_steel: 模具钢材料
|
||||
surface_quality: 表面质量要求
|
||||
controller: 数控系统
|
||||
program_number: 程序号
|
||||
|
||||
Returns:
|
||||
完整的CAM方案
|
||||
core_bbox: 型芯边界框(可选,提供则生成型芯刀路)
|
||||
undercut_regions: 倒扣区域列表(可选,提供则生成 EDM 方案)
|
||||
"""
|
||||
logger.info(f"开始模具CAM设计: 钢材={mold_steel}, 质量={surface_quality}")
|
||||
|
||||
@@ -584,6 +795,79 @@ class MoldCAMDesigner:
|
||||
|
||||
operations = [roughing_op, finishing_op]
|
||||
|
||||
# 型芯粗加工(提供 core_bbox 时)
|
||||
core_op = None
|
||||
if core_bbox:
|
||||
core_op = self.roughing_gen.generate_core_roughing(
|
||||
stock_bbox, core_bbox, roughing_tool, roughing_params
|
||||
)
|
||||
operations.append(core_op)
|
||||
|
||||
# 3D 曲面精加工(ballnose 随形)
|
||||
surface_op = self.finishing_gen.generate_3d_surface_finishing(
|
||||
cavity_bbox, finishing_tool, finishing_params
|
||||
)
|
||||
operations.append(surface_op)
|
||||
|
||||
# 刀路优化与碰撞检测
|
||||
manufacturing_warnings = self._generate_cam_recommendations(
|
||||
roughing_op, finishing_op, mold_steel
|
||||
)
|
||||
try:
|
||||
optimizer = self._get_toolpath_optimizer()
|
||||
for op in operations:
|
||||
pts = op.get("path_points", [])
|
||||
if pts and len(pts) >= 2:
|
||||
optimized = optimizer.optimize_toolpath(
|
||||
pts,
|
||||
{"feed_rate_mm_min": op.get("tool", {}).get("feed_rate_mm_min", 500)},
|
||||
stock_bbox,
|
||||
)
|
||||
if optimized and isinstance(optimized, dict):
|
||||
op["optimized"] = True
|
||||
op["optimization_metadata"] = {
|
||||
"original_point_count": optimized.get("original_point_count"),
|
||||
"corner_slowdowns": optimized.get("corner_slowdowns"),
|
||||
"recommendations": optimized.get("recommendations"),
|
||||
}
|
||||
|
||||
detector = self._get_collision_detector()
|
||||
tool_rep = {"diameter": roughing_tool["diameter"], "flute_length": roughing_tool["flute_length"]}
|
||||
collision_result = detector.check_toolpath_safety(
|
||||
roughing_op.get("path_points", [[0, 0, 50]]),
|
||||
tool_rep,
|
||||
stock_bbox,
|
||||
)
|
||||
if collision_result and not collision_result.get("is_safe", True):
|
||||
manufacturing_warnings.append(
|
||||
f"碰撞检测发现 {collision_result.get('total_issues', 0)} 处潜在碰撞风险,请人工复核安全平面"
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.debug(f"刀路优化/碰撞检测跳过(非致命): {exc}")
|
||||
|
||||
# EDM 电极设计
|
||||
edm_result = None
|
||||
if undercut_regions:
|
||||
try:
|
||||
edm = self._get_edm_designer()
|
||||
edm_result = edm.design_electrodes(
|
||||
undercut_regions=undercut_regions,
|
||||
cavity_bbox=cavity_bbox,
|
||||
material="copper",
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.debug(f"EDM 电极设计跳过(非致命): {exc}")
|
||||
|
||||
# 加工仿真
|
||||
simulation_result = None
|
||||
try:
|
||||
sim = self._get_machining_simulator()
|
||||
simulation_result = sim.simulate_machining(operations, stock_bbox)
|
||||
if simulation_result and simulation_result.get("gouging_detected"):
|
||||
manufacturing_warnings.append("仿真检测到过切风险,请人工复核刀路")
|
||||
except Exception as exc:
|
||||
logger.debug(f"加工仿真跳过(非致命): {exc}")
|
||||
|
||||
gcode = self.post_processor.generate_gcode(
|
||||
operations, program_number=program_number
|
||||
)
|
||||
@@ -608,9 +892,9 @@ class MoldCAMDesigner:
|
||||
"surface_quality": surface_quality,
|
||||
"controller": controller,
|
||||
},
|
||||
"recommendations": self._generate_cam_recommendations(
|
||||
roughing_op, finishing_op, mold_steel
|
||||
),
|
||||
"recommendations": manufacturing_warnings,
|
||||
"edm": edm_result,
|
||||
"simulation": simulation_result,
|
||||
}
|
||||
|
||||
logger.info(f"CAM设计完成: {len(operations)} 个工序, "
|
||||
|
||||
Reference in New Issue
Block a user