x
This commit is contained in:
+113
-36
@@ -2,7 +2,7 @@ from typing import Dict, List, Any, Tuple, Optional
|
|||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_DraftAngle
|
from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_DraftAngle
|
||||||
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut, BRepAlgoAPI_Section, BRepAlgoAPI_Common
|
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut, BRepAlgoAPI_Section, BRepAlgoAPI_Common, BRepAlgoAPI_Fuse
|
||||||
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace, BRepBuilderAPI_Transform
|
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace, BRepBuilderAPI_Transform
|
||||||
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeHalfSpace
|
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeHalfSpace
|
||||||
from OCC.Core.gp import gp_Pln, gp_Dir, gp_Pnt, gp_Trsf, gp_Ax2
|
from OCC.Core.gp import gp_Pln, gp_Dir, gp_Pnt, gp_Trsf, gp_Ax2
|
||||||
@@ -226,14 +226,12 @@ class BaseMoldGenerator:
|
|||||||
|
|
||||||
def _split_cavity_core(self, shape: Any, parting_surface: Any, margin: int = 20) -> Tuple[Any, Any]:
|
def _split_cavity_core(self, shape: Any, parting_surface: Any, margin: int = 20) -> Tuple[Any, Any]:
|
||||||
"""
|
"""
|
||||||
用分型面将模具块切分为A板(上模/型腔)和B板(下模/型芯),
|
分离型腔和型芯 — 完全嵌入 + 突出贴合方式。
|
||||||
然后从每个板中减去产品形状的对应部分。
|
|
||||||
|
|
||||||
流程:
|
型腔(凹模)= 完整模具块 - 产品 → 产品形状完全嵌入型腔块中
|
||||||
1. 创建完整模具块(产品包围盒 + 全方向余量)
|
型芯(凸模)= 底座平板 + 产品融合 → 产品从底座面突出,与型腔凹入完美贴合
|
||||||
2. 用分型面将模具块切分为 A板 和 B板
|
|
||||||
3. A板 - 产品 = 型腔(凹模)
|
不再将模具块沿分型面一分为二。
|
||||||
4. B板 - 产品 = 型芯(凸模)
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
bbox = Bnd_Box()
|
bbox = Bnd_Box()
|
||||||
@@ -254,33 +252,109 @@ class BaseMoldGenerator:
|
|||||||
|
|
||||||
parting_plane = self._get_parting_plane(parting_surface, shape)
|
parting_plane = self._get_parting_plane(parting_surface, shape)
|
||||||
if parting_plane is None:
|
if parting_plane is None:
|
||||||
logger.warning("无法提取分型面平面,使用回退方案")
|
|
||||||
center_z = (zmin + zmax) / 2
|
center_z = (zmin + zmax) / 2
|
||||||
parting_plane = gp_Pln(gp_Pnt(0, 0, center_z), gp_Dir(0, 0, 1))
|
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)
|
cavity = self._subtract_product_from_plate(mold_block, shape, "型腔")
|
||||||
|
if cavity is None:
|
||||||
|
cavity = mold_block
|
||||||
|
|
||||||
if a_plate is not None and b_plate is not None:
|
core = self._build_core_with_base(
|
||||||
cavity = self._subtract_product_from_plate(a_plate, shape, "型腔(A板)")
|
shape, mold_block, parting_plane,
|
||||||
core = self._subtract_product_from_plate(b_plate, shape, "型芯(B板)")
|
mold_xmin, mold_ymin, mold_zmin,
|
||||||
|
mold_xmax, mold_ymax, mold_zmax,
|
||||||
|
xmin, ymin, zmin, xmax, ymax, zmax
|
||||||
|
)
|
||||||
|
|
||||||
if cavity is not None and core is not None:
|
logger.info("型腔/型芯分离完成(完全嵌入 + 突出贴合)")
|
||||||
logger.info("型腔/型芯分离完成(分型面切分+布尔减)")
|
return cavity, core
|
||||||
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:
|
except Exception as e:
|
||||||
logger.error(f"型腔分离失败: {e}")
|
logger.error(f"型腔分离失败: {e}")
|
||||||
return self._split_cavity_core_fallback(shape, None)
|
return self._split_cavity_core_fallback(shape, None)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _extract_parting_normal(parting_surface: Any) -> List[float]:
|
||||||
|
"""从分型面提取法向量"""
|
||||||
|
try:
|
||||||
|
surface = BRepAdaptor_Surface(parting_surface)
|
||||||
|
if surface.GetType() == 0:
|
||||||
|
plane = surface.Plane()
|
||||||
|
n = plane.Axis().Direction()
|
||||||
|
return [float(n.X()), float(n.Y()), float(n.Z())]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return [0.0, 0.0, 1.0]
|
||||||
|
|
||||||
|
def _build_core_with_base(
|
||||||
|
self,
|
||||||
|
shape: Any,
|
||||||
|
mold_block: Any,
|
||||||
|
parting_plane: gp_Pln,
|
||||||
|
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,
|
||||||
|
) -> Any:
|
||||||
|
"""
|
||||||
|
构建带底座的型芯:底座平板 + 产品突出体融合。
|
||||||
|
|
||||||
|
底座从模具边界延伸到分型面(沿分型方向),
|
||||||
|
并略微伸入产品体积以确保布尔融合成功。
|
||||||
|
"""
|
||||||
|
normal = parting_plane.Axis().Direction()
|
||||||
|
origin = parting_plane.Location()
|
||||||
|
nx, ny, nz = float(normal.X()), float(normal.Y()), float(normal.Z())
|
||||||
|
|
||||||
|
prod_extent = (xmax - xmin) + (ymax - ymin) + (zmax - zmin)
|
||||||
|
overlap = max(prod_extent * 0.01, 0.5)
|
||||||
|
|
||||||
|
base_p1 = [mold_xmin, mold_ymin, mold_zmin]
|
||||||
|
base_p2 = [mold_xmax, mold_ymax, mold_zmax]
|
||||||
|
|
||||||
|
for i, (n, o, lo, hi) in enumerate(zip(
|
||||||
|
[nx, ny, nz],
|
||||||
|
[float(origin.X()), float(origin.Y()), float(origin.Z())],
|
||||||
|
[mold_xmin, mold_ymin, mold_zmin],
|
||||||
|
[mold_xmax, mold_ymax, mold_zmax],
|
||||||
|
)):
|
||||||
|
if abs(n) < 0.001:
|
||||||
|
continue
|
||||||
|
if n > 0:
|
||||||
|
base_p2[i] = o + overlap
|
||||||
|
else:
|
||||||
|
base_p1[i] = o - overlap
|
||||||
|
|
||||||
|
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(mold_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]:
|
def _get_parting_plane(self, parting_surface: Any, shape: Any) -> Optional[gp_Pln]:
|
||||||
"""从分型面提取平面方程"""
|
"""从分型面提取平面方程"""
|
||||||
try:
|
try:
|
||||||
@@ -373,9 +447,9 @@ class BaseMoldGenerator:
|
|||||||
def _split_cavity_core_fallback(self, shape: Any,
|
def _split_cavity_core_fallback(self, shape: Any,
|
||||||
mold_block: Optional[Any] = None) -> Tuple[Any, Any]:
|
mold_block: Optional[Any] = None) -> Tuple[Any, Any]:
|
||||||
"""
|
"""
|
||||||
分模回退方案:用边界框中心面作为分型面切分模具块。
|
分模回退方案:完全嵌入 + 突出贴合,用 Z 中心面做分型基准。
|
||||||
"""
|
"""
|
||||||
logger.warning("使用分模回退方案")
|
logger.warning("使用分模回退方案(完全嵌入 + 突出贴合)")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bbox = Bnd_Box()
|
bbox = Bnd_Box()
|
||||||
@@ -389,19 +463,22 @@ class BaseMoldGenerator:
|
|||||||
gp_Pnt(xmax + margin, ymax + margin, zmax + margin)
|
gp_Pnt(xmax + margin, ymax + margin, zmax + margin)
|
||||||
).Shape()
|
).Shape()
|
||||||
|
|
||||||
|
cavity = self._subtract_product_from_plate(mold_block, shape, "型腔(回退)")
|
||||||
|
if cavity is None:
|
||||||
|
cavity = mold_block
|
||||||
|
|
||||||
center_z = (zmin + zmax) / 2
|
center_z = (zmin + zmax) / 2
|
||||||
parting_plane = gp_Pln(gp_Pnt(0, 0, center_z), gp_Dir(0, 0, 1))
|
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)
|
|
||||||
|
|
||||||
if a_plate is not None and b_plate is not None:
|
core = self._build_core_with_base(
|
||||||
cavity = self._subtract_product_from_plate(a_plate, shape, "型腔(回退)")
|
shape, mold_block, parting_plane,
|
||||||
core = self._subtract_product_from_plate(b_plate, shape, "型芯(回退)")
|
xmin - margin, ymin - margin, zmin - margin,
|
||||||
if cavity is not None and core is not None:
|
xmax + margin, ymax + margin, zmax + margin,
|
||||||
logger.info("回退方案型腔/型芯分离完成")
|
xmin, ymin, zmin, xmax, ymax, zmax
|
||||||
return cavity, core
|
)
|
||||||
|
|
||||||
cavity = self._subtract_product_from_plate(mold_block, shape, "型腔(兜底)")
|
logger.info("回退方案型腔/型芯分离完成")
|
||||||
return cavity or mold_block, shape
|
return cavity or mold_block, core
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"分模回退方案失败: {e}")
|
logger.error(f"分模回退方案失败: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user