x
This commit is contained in:
@@ -224,6 +224,180 @@ class BaseMoldGenerator:
|
||||
logger.error(f"产品几何分析失败: {e}")
|
||||
raise
|
||||
|
||||
def _analyze_parting_direction(self, shape: Any) -> Dict[str, Any]:
|
||||
"""
|
||||
分析主分型方向。
|
||||
|
||||
使用面积加权的面法向统计,作为普通模具与铝泡沫模具的统一几何回退。
|
||||
"""
|
||||
face_normals = []
|
||||
face_areas = []
|
||||
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
|
||||
|
||||
face_props = GProp_GProps()
|
||||
brepgprop.SurfaceProperties(face, face_props)
|
||||
area = max(float(face_props.Mass()), 1e-6)
|
||||
|
||||
face_normals.append(np.array([normal.X(), normal.Y(), normal.Z()], dtype=np.float64))
|
||||
face_areas.append(area)
|
||||
except Exception as e:
|
||||
logger.debug(f"分型方向面分析失败: {e}")
|
||||
|
||||
if not face_normals:
|
||||
return {
|
||||
"primary_direction": [0.0, 0.0, 1.0],
|
||||
"confidence": 0.5,
|
||||
"face_count": 0,
|
||||
}
|
||||
|
||||
normals = np.array(face_normals, dtype=np.float64)
|
||||
areas = np.array(face_areas, dtype=np.float64)
|
||||
total_area = float(areas.sum())
|
||||
if total_area > 1e-6:
|
||||
weights = areas / total_area
|
||||
weighted_normal = np.sum(normals * weights[:, np.newaxis], axis=0)
|
||||
else:
|
||||
weighted_normal = np.mean(normals, axis=0)
|
||||
|
||||
norm = np.linalg.norm(weighted_normal)
|
||||
if norm > 1e-6:
|
||||
weighted_normal /= norm
|
||||
else:
|
||||
weighted_normal = np.array([0.0, 0.0, 1.0], dtype=np.float64)
|
||||
|
||||
confidence = float(np.mean(np.abs(np.dot(normals, weighted_normal))))
|
||||
|
||||
return {
|
||||
"primary_direction": weighted_normal.tolist(),
|
||||
"confidence": confidence,
|
||||
"face_count": len(face_normals),
|
||||
"normal_distribution": normals.tolist(),
|
||||
}
|
||||
|
||||
def _create_parting_surface_from_direction(
|
||||
self,
|
||||
shape: Any,
|
||||
analysis: Dict[str, Any],
|
||||
direction: Any,
|
||||
extension: float = 10.0,
|
||||
) -> Any:
|
||||
"""按给定方向创建覆盖产品边界的分型面。"""
|
||||
bbox = analysis.get("bounding_box", {})
|
||||
center = bbox.get("center", [0.0, 0.0, 0.0])
|
||||
dims = bbox.get("dimensions", [100.0, 100.0, 100.0])
|
||||
|
||||
dir_obj = self._normalize_direction(direction)
|
||||
plane = gp_Pln(gp_Pnt(center[0], center[1], center[2]), dir_obj)
|
||||
|
||||
span = max(max(dims), 1.0) + extension * 2
|
||||
try:
|
||||
return BRepBuilderAPI_MakeFace(plane, -span, span, -span, span).Face()
|
||||
except Exception:
|
||||
return BRepBuilderAPI_MakeFace(plane).Face()
|
||||
|
||||
def _normalize_direction(self, direction: Any) -> gp_Dir:
|
||||
"""归一化分型方向,异常时回退到 Z 轴。"""
|
||||
try:
|
||||
if isinstance(direction, gp_Dir):
|
||||
return direction
|
||||
|
||||
if isinstance(direction, np.ndarray):
|
||||
values = direction.tolist()
|
||||
else:
|
||||
values = list(direction)
|
||||
|
||||
if len(values) < 3:
|
||||
raise ValueError("direction 维度不足")
|
||||
|
||||
vec = np.array(values[:3], dtype=np.float64)
|
||||
norm = np.linalg.norm(vec)
|
||||
if norm <= 1e-6:
|
||||
raise ValueError("direction 长度为 0")
|
||||
|
||||
vec /= norm
|
||||
return gp_Dir(float(vec[0]), float(vec[1]), float(vec[2]))
|
||||
except Exception:
|
||||
return gp_Dir(0, 0, 1)
|
||||
|
||||
def _detect_primary_parting(self, shape: Any, analysis: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
统一主分型面检测。
|
||||
|
||||
返回统一结构,便于子类按需追加多分型面、倒扣与平滑逻辑。
|
||||
"""
|
||||
if self.ai_parting_detector is not None:
|
||||
try:
|
||||
ai_result = self.ai_parting_detector.detect(shape, analysis)
|
||||
if ai_result:
|
||||
parting_surface = self._create_parting_surface_from_direction(
|
||||
shape,
|
||||
analysis,
|
||||
ai_result.get("normal", [0, 0, 1]),
|
||||
)
|
||||
parting_line = ai_result.get("parting_line") or self._calculate_parting_line(shape, parting_surface)
|
||||
return {
|
||||
"surface": parting_surface,
|
||||
"line": parting_line,
|
||||
"direction": ai_result.get("normal", [0, 0, 1]),
|
||||
"confidence": ai_result.get("confidence", 0.8),
|
||||
"method": ai_result.get("method", "ai"),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.warning(f"AI 分型面检测失败,回退到几何方法:{e}")
|
||||
|
||||
normal_stats = self._analyze_parting_direction(shape)
|
||||
parting_surface = self._create_parting_surface_from_direction(
|
||||
shape,
|
||||
analysis,
|
||||
normal_stats.get("primary_direction", [0, 0, 1]),
|
||||
)
|
||||
parting_line = self._calculate_parting_line(shape, parting_surface)
|
||||
|
||||
return {
|
||||
"surface": parting_surface,
|
||||
"line": parting_line,
|
||||
"direction": normal_stats.get("primary_direction", [0, 0, 1]),
|
||||
"confidence": normal_stats.get("confidence", 0.5),
|
||||
"method": "geometric",
|
||||
}
|
||||
|
||||
def _extract_plane_metadata(self, surface: Any, analysis: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
||||
"""提取分型面法向、原点和参数范围。"""
|
||||
default_origin = [0.0, 0.0, 0.0]
|
||||
if analysis:
|
||||
default_origin = analysis.get("bounding_box", {}).get("center", default_origin)
|
||||
|
||||
try:
|
||||
adaptor = BRepAdaptor_Surface(surface)
|
||||
plane = adaptor.Plane()
|
||||
origin = plane.Location()
|
||||
normal = plane.Axis().Direction()
|
||||
|
||||
return {
|
||||
"normal": [float(normal.X()), float(normal.Y()), float(normal.Z())],
|
||||
"origin": [float(origin.X()), float(origin.Y()), float(origin.Z())],
|
||||
"bounds": {
|
||||
"u_range": [float(adaptor.FirstUParameter()), float(adaptor.LastUParameter())],
|
||||
"v_range": [float(adaptor.FirstVParameter()), float(adaptor.LastVParameter())],
|
||||
},
|
||||
}
|
||||
except Exception as e:
|
||||
logger.warning(f"分型面几何提取失败,使用默认值: {e}")
|
||||
return {
|
||||
"normal": [0.0, 0.0, 1.0],
|
||||
"origin": [float(default_origin[0]), float(default_origin[1]), float(default_origin[2])],
|
||||
"bounds": {"u_range": [-200.0, 200.0], "v_range": [-200.0, 200.0]},
|
||||
}
|
||||
|
||||
def _split_cavity_core(self, shape: Any, parting_surface: Any, margin: int = 20) -> Tuple[Any, Any]:
|
||||
"""
|
||||
分离型腔和型芯
|
||||
|
||||
Reference in New Issue
Block a user