From 74bbca90e3113063c11c7a4ceb93414eaa805bd8 Mon Sep 17 00:00:00 2001 From: chenjw28 <792430652@qq.com> Date: Mon, 11 May 2026 18:05:27 +0800 Subject: [PATCH] x --- src/core/base_mold_generator.py | 149 ++++++++++++++++++++++++-------- 1 file changed, 113 insertions(+), 36 deletions(-) diff --git a/src/core/base_mold_generator.py b/src/core/base_mold_generator.py index 8cdea28..4b41449 100644 --- a/src/core/base_mold_generator.py +++ b/src/core/base_mold_generator.py @@ -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 +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.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeHalfSpace 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]: """ - 用分型面将模具块切分为A板(上模/型腔)和B板(下模/型芯), - 然后从每个板中减去产品形状的对应部分。 + 分离型腔和型芯 — 完全嵌入 + 突出贴合方式。 - 流程: - 1. 创建完整模具块(产品包围盒 + 全方向余量) - 2. 用分型面将模具块切分为 A板 和 B板 - 3. A板 - 产品 = 型腔(凹模) - 4. B板 - 产品 = 型芯(凸模) + 型腔(凹模)= 完整模具块 - 产品 → 产品形状完全嵌入型腔块中 + 型芯(凸模)= 底座平板 + 产品融合 → 产品从底座面突出,与型腔凹入完美贴合 + + 不再将模具块沿分型面一分为二。 """ try: bbox = Bnd_Box() @@ -254,33 +252,109 @@ class BaseMoldGenerator: 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)) - 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: - cavity = self._subtract_product_from_plate(a_plate, shape, "型腔(A板)") - core = self._subtract_product_from_plate(b_plate, shape, "型芯(B板)") + core = self._build_core_with_base( + shape, mold_block, parting_plane, + 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("型腔/型芯分离完成(分型面切分+布尔减)") - 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) + logger.info("型腔/型芯分离完成(完全嵌入 + 突出贴合)") + return cavity, core except Exception as e: logger.error(f"型腔分离失败: {e}") 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]: """从分型面提取平面方程""" try: @@ -373,9 +447,9 @@ class BaseMoldGenerator: def _split_cavity_core_fallback(self, shape: Any, mold_block: Optional[Any] = None) -> Tuple[Any, Any]: """ - 分模回退方案:用边界框中心面作为分型面切分模具块。 + 分模回退方案:完全嵌入 + 突出贴合,用 Z 中心面做分型基准。 """ - logger.warning("使用分模回退方案") + logger.warning("使用分模回退方案(完全嵌入 + 突出贴合)") try: bbox = Bnd_Box() @@ -389,19 +463,22 @@ 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) - 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 + core = self._build_core_with_base( + shape, mold_block, parting_plane, + xmin - margin, ymin - margin, zmin - margin, + xmax + margin, ymax + margin, zmax + margin, + xmin, ymin, zmin, xmax, ymax, zmax + ) - cavity = self._subtract_product_from_plate(mold_block, shape, "型腔(兜底)") - return cavity or mold_block, shape + logger.info("回退方案型腔/型芯分离完成") + return cavity or mold_block, core except Exception as e: logger.error(f"分模回退方案失败: {e}")