From 838604fddf947f934cd718bdd723bfbbc4f1421c Mon Sep 17 00:00:00 2001 From: chenjw28 <792430652@qq.com> Date: Thu, 30 Apr 2026 16:06:15 +0800 Subject: [PATCH] x --- src/core/aluminum_foam_mold.py | 30 +++++++++++++++++++++ src/core/base_mold_generator.py | 28 ++++++++++++++++++++ src/core/mold_generator.py | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/src/core/aluminum_foam_mold.py b/src/core/aluminum_foam_mold.py index 90dae93..06825c3 100644 --- a/src/core/aluminum_foam_mold.py +++ b/src/core/aluminum_foam_mold.py @@ -298,6 +298,36 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): result["normal_statistics"] = self._analyze_parting_direction(shape) return result + def _analyze_parting_direction(self, shape: Any) -> Dict[str, float]: + """分析产品法向量分布,按面积加权统计各轴方向强度""" + stats = {"X": 0.0, "Y": 0.0, "Z": 0.0} + explorer = TopExp_Explorer(shape, TopAbs_FACE) + + while explorer.More(): + face = TopoDS_Face(explorer.Current()) + explorer.Next() + try: + normal = self._get_face_normal(face) + if normal is None: + continue + props = GProp_GProps() + brepgprop.SurfaceProperties(face, props) + area = max(float(props.Mass()), 1.0) + stats["X"] += abs(float(normal.X())) * area + stats["Y"] += abs(float(normal.Y())) * area + stats["Z"] += abs(float(normal.Z())) * area + except Exception: + continue + + total = stats["X"] + stats["Y"] + stats["Z"] + if total <= 0: + return {"X": 33.3, "Y": 33.3, "Z": 33.4} + + return { + axis: round(value / total * 100, 2) + for axis, value in stats.items() + } + def _split_cavity_core(self, shape: Any, parting_surface: Any) -> Tuple[Any, Any]: """分离型腔和型芯(铝泡沫使用更大余量)""" return super()._split_cavity_core(shape, parting_surface, margin=25) diff --git a/src/core/base_mold_generator.py b/src/core/base_mold_generator.py index 98feff9..3e99e2d 100644 --- a/src/core/base_mold_generator.py +++ b/src/core/base_mold_generator.py @@ -578,6 +578,34 @@ class BaseMoldGenerator: "face_count": 0, } + def _extract_plane_metadata(self, surface: Any) -> Dict[str, Any]: + """从分型面提取平面元数据(法向量、原点、边界)""" + metadata = { + "normal": [0.0, 0.0, 1.0], + "origin": [0.0, 0.0, 0.0], + "bounds": {"min": [0.0, 0.0, 0.0], "max": [0.0, 0.0, 0.0]}, + } + try: + surface_adaptor = BRepAdaptor_Surface(surface) + if surface_adaptor.GetType() == 0: + plane = surface_adaptor.Plane() + axis = plane.Axis() + normal = axis.Direction() + origin = plane.Location() + metadata["normal"] = [float(normal.X()), float(normal.Y()), float(normal.Z())] + metadata["origin"] = [float(origin.X()), float(origin.Y()), float(origin.Z())] + + bbox = Bnd_Box() + brepbndlib.Add(surface, bbox) + xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get() + metadata["bounds"] = { + "min": [float(xmin), float(ymin), float(zmin)], + "max": [float(xmax), float(ymax), float(zmax)], + } + except Exception as e: + logger.warning(f"提取平面元数据失败: {e}") + return metadata + def _calculate_product_weight(self, analysis: Dict) -> str: volume_cm3 = analysis.get("volume", 0) / 1000 weight_g = volume_cm3 * self.material_density diff --git a/src/core/mold_generator.py b/src/core/mold_generator.py index a9c3a57..a409202 100644 --- a/src/core/mold_generator.py +++ b/src/core/mold_generator.py @@ -219,6 +219,52 @@ class MoldCavityGenerator(BaseMoldGenerator): logger.info("使用简化方法检测分型面") return self._simple_parting_surface(shape, analysis) + def _detect_primary_parting(self, shape: Any, analysis: Dict) -> Dict[str, Any]: + """检测主分型面(AI优先 → 几何法向量 → 简化回退)""" + if self.ai_parting_detector is not None: + try: + ai_result = self.ai_parting_detector.detect(shape, analysis) + if ai_result is not None: + surface, line = self._create_parting_surface_from_ai(ai_result, analysis, shape) + return { + "surface": surface, + "line": line, + "direction": ai_result.get("normal", [0, 0, 1]), + "method": ai_result.get("method", "ai"), + "confidence": ai_result.get("confidence", 0.8), + } + except Exception as e: + logger.warning(f"AI 分型面检测失败: {e}") + + try: + normal_dir = self._analyze_face_normals(shape) + parting_plane = self._create_optimal_parting_plane(shape, analysis, normal_dir) + dims = analysis.get("bounding_box", {}).get("dimensions", [100, 100, 100]) + span = max(dims) * 1.5 + 30 + parting_surface = BRepBuilderAPI_MakeFace( + parting_plane, -span, span, -span, span + ).Face() + parting_surface = self.extend_parting_surface(parting_surface, shape, extension=30.0) + parting_line = self._calculate_parting_line(shape, parting_surface) + return { + "surface": parting_surface, + "line": parting_line, + "direction": [float(normal_dir.X()), float(normal_dir.Y()), float(normal_dir.Z())], + "method": "face_normal_analysis", + "confidence": 0.85, + } + except Exception as e: + logger.warning(f"法向量分析失败,使用简化方法:{e}") + + surface, line = self._simple_parting_surface(shape, analysis) + return { + "surface": surface, + "line": line, + "direction": [0, 0, 1], + "method": "simple", + "confidence": 0.6, + } + def _build_undercut_regions(self, undercut_analysis: Dict[str, Any]) -> List[Dict[str, Any]]: """将侧向机构分析结果转换为兼容旧结构的倒扣区域列表。""" undercut_faces = undercut_analysis.get("undercut_faces", [])