feat: 推进SCDM-first后端接入和大模型编辑优化
This commit is contained in:
+75
-3
@@ -226,6 +226,62 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
info.update(_shape_volume_info(self.shape))
|
||||
return info
|
||||
|
||||
def scdm_local_face_signatures(self) -> list[dict[str, object]]:
|
||||
"""Return cheap geometry hints used to map SCDM raw objects back to local Face IDs."""
|
||||
signatures: list[dict[str, object]] = []
|
||||
for face_id, face in enumerate(self.faces):
|
||||
try:
|
||||
surf = BRepAdaptor_Surface(face)
|
||||
surface_type = surf.GetType()
|
||||
except Exception:
|
||||
continue
|
||||
signature: dict[str, object] = {
|
||||
"faceId": int(face_id),
|
||||
"logicalFaceId": self.face_logical_id(face_id),
|
||||
"surfaceType": SURFACE_TYPES.get(surface_type, f"type {surface_type}"),
|
||||
}
|
||||
try:
|
||||
if surface_type == GeomAbs_Plane:
|
||||
plane = surf.Plane()
|
||||
origin = _point_tuple(plane.Location())
|
||||
normal = _dir_tuple(plane.Axis().Direction())
|
||||
signature["center"] = origin
|
||||
signature["axis"] = normal
|
||||
signature["planeOffset"] = (
|
||||
origin[0] * normal[0]
|
||||
+ origin[1] * normal[1]
|
||||
+ origin[2] * normal[2]
|
||||
)
|
||||
elif surface_type == GeomAbs_Cylinder:
|
||||
cylinder = surf.Cylinder()
|
||||
axis = cylinder.Axis()
|
||||
radius = cylinder.Radius()
|
||||
signature["center"] = _point_tuple(axis.Location())
|
||||
signature["axis"] = _dir_tuple(axis.Direction())
|
||||
signature["radius"] = radius
|
||||
signature["diameter"] = radius * 2.0
|
||||
elif surface_type == GeomAbs_Cone:
|
||||
cone = surf.Cone()
|
||||
signature["center"] = _point_tuple(cone.Location())
|
||||
signature["axis"] = _dir_tuple(cone.Axis().Direction())
|
||||
signature["radius"] = cone.RefRadius()
|
||||
elif surface_type == GeomAbs_Sphere:
|
||||
sphere = surf.Sphere()
|
||||
radius = sphere.Radius()
|
||||
signature["center"] = _point_tuple(sphere.Location())
|
||||
signature["radius"] = radius
|
||||
signature["diameter"] = radius * 2.0
|
||||
elif surface_type == GeomAbs_Torus:
|
||||
torus = surf.Torus()
|
||||
signature["center"] = _point_tuple(torus.Location())
|
||||
signature["axis"] = _dir_tuple(torus.Axis().Direction())
|
||||
signature["majorRadius"] = torus.MajorRadius()
|
||||
signature["minorRadius"] = torus.MinorRadius()
|
||||
except Exception:
|
||||
pass
|
||||
signatures.append(signature)
|
||||
return signatures
|
||||
|
||||
def refresh_topology(self) -> None:
|
||||
self._topology_refresh_generation = int(getattr(self, "_topology_refresh_generation", 0)) + 1
|
||||
self.shape = _compound_from_shapes([p.shape for p in self.display_parts()])
|
||||
@@ -746,7 +802,8 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
|
||||
This intentionally avoids material-side sampling. It only combines
|
||||
directly connected co-cylindrical fragments and uses face orientation as
|
||||
a hint, so full edit plans still recompute and guard the real feature
|
||||
a hint. It must not trigger Analysis Situs or the internal recognition
|
||||
graph; full edit plans still recompute and guard the real feature
|
||||
semantics before changing geometry.
|
||||
"""
|
||||
radius = _float_or_none(info.get("radius")) or 0.0
|
||||
@@ -765,7 +822,7 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
same_domain_note = "快速识别:当前圆柱没有检测到直接相接的同域碎面。"
|
||||
axis_range: dict[str, object] | None = None
|
||||
try:
|
||||
side_face_ids = self.connected_same_domain_face_ids(face_id) or [face_id]
|
||||
side_face_ids = self._connected_cocylindrical_face_ids(face_id) or [face_id]
|
||||
spans: list[float] = []
|
||||
for side_id in side_face_ids:
|
||||
side_surf = BRepAdaptor_Surface(self.faces[side_id])
|
||||
@@ -1044,6 +1101,21 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def face_plane_position_along(self, face_id: int, direction: tuple[float, float, float]) -> tuple[float, tuple[float, float, float]] | None:
|
||||
if face_id < 0 or face_id >= len(self.faces):
|
||||
return None
|
||||
try:
|
||||
surf = BRepAdaptor_Surface(self.faces[face_id])
|
||||
if surf.GetType() != GeomAbs_Plane:
|
||||
return None
|
||||
plane = surf.Plane()
|
||||
origin = _point_tuple(plane.Location())
|
||||
normal = _dir_tuple(plane.Axis().Direction())
|
||||
value = origin[0] * direction[0] + origin[1] * direction[1] + origin[2] * direction[2]
|
||||
return float(value), normal
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _recognition_summary_fields(self, info: dict[str, object]) -> dict[str, object]:
|
||||
surface = str(info.get("surface") or "")
|
||||
user_priority = feature_recognition_priority(info)
|
||||
@@ -4663,7 +4735,7 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
return list(self._internal_hole_region_cache.get(face_id, ()))
|
||||
|
||||
def _can_use_internal_recognition_graph(self) -> bool:
|
||||
return bool(self.faces)
|
||||
return bool(self.faces) and len(self.faces) <= 1000
|
||||
|
||||
def _load_internal_hole_regions(self) -> None:
|
||||
self._internal_hole_regions_attempted = True
|
||||
|
||||
Reference in New Issue
Block a user