This commit is contained in:
2026-05-11 09:34:50 +08:00
parent 79ca3613ae
commit 5e1d475a22
14 changed files with 336 additions and 264 deletions
+41 -114
View File
@@ -2,7 +2,7 @@ from typing import Dict, List, Any, Tuple, Optional
import math
import numpy as np
from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_DraftAngle
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut, BRepAlgoAPI_Section, BRepAlgoAPI_Common, BRepAlgoAPI_Fuse
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut, BRepAlgoAPI_Section, BRepAlgoAPI_Common
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace, BRepBuilderAPI_Transform
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeHalfSpace
from OCC.Core.gp import gp_Pln, gp_Dir, gp_Pnt, gp_Trsf, gp_Ax2
@@ -226,14 +226,14 @@ class BaseMoldGenerator:
def _split_cavity_core(self, shape: Any, parting_surface: Any, margin: int = 20) -> Tuple[Any, Any]:
"""
分离型腔和型芯 — 完全嵌入 + 突出贴合方式
用分型面将模具块切分为A板(上模/型腔)和B板(下模/型芯),
然后从每个板中减去产品形状的对应部分。
流程:
1. 创建完整模具块(产品包围盒 + 全方向余量)
2. 型腔(凹模)= 模具块 - 产品 → 产品完全嵌入型腔块中
3. 型芯(凸模)= 产品形状突出体 → 从芯块面突出贴合
不再使用分型面中间切开产品的方式。
2. 用分型面将模具块切分为 A板 和 B板
3. A板 - 产品 = 型腔(凹模)
4. B板 - 产品 = 型芯(凸模)
"""
try:
bbox = Bnd_Box()
@@ -247,110 +247,40 @@ class BaseMoldGenerator:
mold_ymax = ymax + margin
mold_zmax = zmax + margin
cavity_block = BRepPrimAPI_MakeBox(
mold_block = BRepPrimAPI_MakeBox(
gp_Pnt(mold_xmin, mold_ymin, mold_zmin),
gp_Pnt(mold_xmax, mold_ymax, mold_zmax)
).Shape()
cavity = self._subtract_product_from_plate(cavity_block, shape, "型腔")
if cavity is None:
logger.warning("型腔布尔减运算失败,使用原始模具块")
cavity = cavity_block
parting_plane = self._get_parting_plane(parting_surface, shape)
if parting_plane is None:
logger.warning("无法提取分型面平面,使用回退方案")
center_z = (zmin + zmax) / 2
parting_plane = gp_Pln(gp_Pnt(0, 0, center_z), gp_Dir(0, 0, 1))
parting_normal = self._extract_parting_normal(parting_surface)
a_plate, b_plate = self._split_mold_block_by_plane(mold_block, parting_plane)
core = self._build_protruding_core(
shape, cavity_block,
mold_xmin, mold_ymin, mold_zmin,
mold_xmax, mold_ymax, mold_zmax,
xmin, ymin, zmin, xmax, ymax, zmax,
parting_normal
)
if a_plate is not None and b_plate is not None:
cavity = self._subtract_product_from_plate(a_plate, shape, "型腔(A板)")
core = self._subtract_product_from_plate(b_plate, shape, "型芯(B板)")
logger.info("型腔/型芯分离完成(完全嵌入+突出贴合)")
return cavity, core
if cavity is not None and core is not None:
logger.info("型腔/型芯分离完成(分型面切分+布尔减)")
return cavity, core
elif cavity is not None:
logger.warning("型芯生成失败,使用产品形状")
return cavity, shape
elif core is not None:
logger.warning("型腔生成失败,使用模具块")
return mold_block, core
logger.warning("A/B板切分不完全,回退到原方案")
return self._split_cavity_core_fallback(shape, mold_block)
except Exception as e:
logger.error(f"型腔分离失败: {e}")
return self._split_cavity_core_fallback(shape, None)
def _extract_parting_normal(self, parting_surface: Any) -> List[float]:
"""从分型面提取法向量方向"""
try:
surface = BRepAdaptor_Surface(parting_surface)
if surface.GetType() == 0:
plane = surface.Plane()
normal = plane.Axis().Direction()
return [float(normal.X()), float(normal.Y()), float(normal.Z())]
except Exception:
pass
return [0.0, 0.0, 1.0]
def _build_protruding_core(
self,
shape: Any,
cavity_block: Any,
mold_xmin: float, mold_ymin: float, mold_zmin: float,
mold_xmax: float, mold_ymax: float, mold_zmax: float,
xmin: float, ymin: float, zmin: float,
xmax: float, ymax: float, zmax: float,
parting_normal: List[float] = None,
) -> Any:
"""
构建突出贴合式型芯。
型芯 = 底座平板 + 产品形状突出体。
底座平板沿分型方向位于产品下方,产品形状融合在底座之上,
与型腔的凹入形状完美贴合。
"""
nx, ny, nz = (parting_normal or [0.0, 0.0, 1.0])
mold_min = [mold_xmin, mold_ymin, mold_zmin]
mold_max = [mold_xmax, mold_ymax, mold_zmax]
prod_min = [xmin, ymin, zmin]
prod_max = [xmax, ymax, zmax]
base_p1 = list(mold_min)
base_p2 = list(mold_max)
for i in range(3):
prod_span = prod_max[i] - prod_min[i]
overlap = max(prod_span * 0.03, 0.5)
if parting_normal[i] > 0:
base_p2[i] = prod_min[i] + overlap
elif parting_normal[i] < 0:
base_p1[i] = prod_max[i] - overlap
base_plate = None
try:
base_plate = BRepPrimAPI_MakeBox(
gp_Pnt(base_p1[0], base_p1[1], base_p1[2]),
gp_Pnt(base_p2[0], base_p2[1], base_p2[2])
).Shape()
logger.info("型芯底座平板构建完成")
except Exception as e:
logger.warning(f"底座平板构建失败: {e}")
return shape
try:
fuse_op = BRepAlgoAPI_Fuse(base_plate, shape)
if fuse_op.IsDone():
core = fuse_op.Shape()
logger.info("型芯(底座+产品突出体)融合成功")
return core
except Exception as e:
logger.warning(f"底座与产品融合失败: {e}")
try:
cut_op = BRepAlgoAPI_Cut(cavity_block, shape)
if cut_op.IsDone():
logger.info("型芯通过布尔减回退构建")
return cut_op.Shape()
except Exception:
pass
logger.info("型芯最终回退为产品形状")
return shape
def _get_parting_plane(self, parting_surface: Any, shape: Any) -> Optional[gp_Pln]:
"""从分型面提取平面方程"""
try:
@@ -443,12 +373,9 @@ class BaseMoldGenerator:
def _split_cavity_core_fallback(self, shape: Any,
mold_block: Optional[Any] = None) -> Tuple[Any, Any]:
"""
分模回退方案:完全嵌入+突出贴合,不切分模具块。
1. 创建完整模具块 → 型腔 = 模具块 - 产品(产品完全嵌入)
2. 型芯 = 产品形状突出体(突出贴合)
分模回退方案:用边界框中心面作为分型面切分模具块。
"""
logger.warning("使用分模回退方案(完全嵌入+突出贴合)")
logger.warning("使用分模回退方案")
try:
bbox = Bnd_Box()
@@ -462,19 +389,19 @@ class BaseMoldGenerator:
gp_Pnt(xmax + margin, ymax + margin, zmax + margin)
).Shape()
cavity = self._subtract_product_from_plate(mold_block, shape, "型腔(回退)")
if cavity is None:
cavity = mold_block
center_z = (zmin + zmax) / 2
parting_plane = gp_Pln(gp_Pnt(0, 0, center_z), gp_Dir(0, 0, 1))
a_plate, b_plate = self._split_mold_block_by_plane(mold_block, parting_plane)
core = self._build_protruding_core(
shape, mold_block,
xmin - margin, ymin - margin, zmin - margin,
xmax + margin, ymax + margin, zmax + margin,
xmin, ymin, zmin, xmax, ymax, zmax
)
if a_plate is not None and b_plate is not None:
cavity = self._subtract_product_from_plate(a_plate, shape, "型腔(回退)")
core = self._subtract_product_from_plate(b_plate, shape, "型芯(回退)")
if cavity is not None and core is not None:
logger.info("回退方案型腔/型芯分离完成")
return cavity, core
logger.info("回退方案型腔/型芯分离完成")
return cavity or mold_block, core
cavity = self._subtract_product_from_plate(mold_block, shape, "型腔(兜底)")
return cavity or mold_block, shape
except Exception as e:
logger.error(f"分模回退方案失败: {e}")