x
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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", [])
|
||||
|
||||
Reference in New Issue
Block a user