feat: 完善参数化编辑语义和槽孔中心距
This commit is contained in:
@@ -97,6 +97,7 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
self.edge_part_ids: list[int] = []
|
||||
self.edge_solid_ids: list[int] = []
|
||||
self.solids: list[tuple[int, TopoDS_Shape]] = []
|
||||
self._quick_face_info_cache: dict[int, dict[str, object]] = {}
|
||||
self._face_info_cache: dict[int, dict[str, object]] = {}
|
||||
self._feature_info_cache: dict[int, dict[str, object]] = {}
|
||||
self._edge_info_cache: dict[int, dict[str, object]] = {}
|
||||
@@ -176,6 +177,7 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
self.edge_part_ids.clear()
|
||||
self.edge_solid_ids.clear()
|
||||
self.solids.clear()
|
||||
self._quick_face_info_cache.clear()
|
||||
self._face_info_cache.clear()
|
||||
self._feature_info_cache.clear()
|
||||
self._edge_info_cache.clear()
|
||||
@@ -269,10 +271,128 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
logical_ids = snapshot.get(SNAPSHOT_FACE_LOGICAL_IDS_KEY)
|
||||
if isinstance(logical_ids, (list, tuple)) and len(logical_ids) == len(self.faces):
|
||||
self.face_logical_ids = [int(item) for item in logical_ids]
|
||||
self._quick_face_info_cache.clear()
|
||||
self._face_info_cache.clear()
|
||||
self._feature_info_cache.clear()
|
||||
self._same_domain_face_ids_cache.clear()
|
||||
|
||||
def quick_face_info(self, face_id: int) -> dict[str, object]:
|
||||
if face_id < 0 or face_id >= len(self.faces):
|
||||
raise ValueError(f"Unknown face id {face_id}")
|
||||
full_info = self._face_info_cache.get(face_id)
|
||||
if full_info is not None:
|
||||
return dict(full_info)
|
||||
cached = self._quick_face_info_cache.get(face_id)
|
||||
if cached is not None:
|
||||
return dict(cached)
|
||||
|
||||
face = self.faces[face_id]
|
||||
props = GProp_GProps()
|
||||
brepgprop.SurfaceProperties(face, props)
|
||||
surf = BRepAdaptor_Surface(face)
|
||||
surface_type = surf.GetType()
|
||||
surface_label = SURFACE_TYPES.get(surface_type, f"type {surface_type}")
|
||||
info: dict[str, object] = {
|
||||
"kind": "face",
|
||||
"face_id": face_id,
|
||||
"topological_face_id": face_id,
|
||||
"logical_face_id": self.face_logical_id(face_id),
|
||||
"part_id": self.face_part_ids[face_id],
|
||||
"solid_id": self.face_solid_ids[face_id],
|
||||
"orientation": _orientation_name(face.Orientation()),
|
||||
"surface": surface_label,
|
||||
"area": props.Mass(),
|
||||
"area_center": _point_tuple(props.CentreOfMass()),
|
||||
"u_range": (surf.FirstUParameter(), surf.LastUParameter()),
|
||||
"v_range": (surf.FirstVParameter(), surf.LastVParameter()),
|
||||
"boundary_edges": len(self._face_boundary_edge_ids(face_id)),
|
||||
"selection_info_mode": "quick",
|
||||
"selection_info_note": "快速选择信息;同域面、端盖、底面等深层识别会在执行编辑计划或手动扫描时再计算。",
|
||||
}
|
||||
info.update(_shape_bounds_info(face))
|
||||
if surface_type == GeomAbs_Plane:
|
||||
plane = surf.Plane()
|
||||
direction = plane.Axis().Direction()
|
||||
push_pull_direction = self._plane_push_pull_direction(face_id, surf)
|
||||
info["plane_origin"] = _point_tuple(plane.Location())
|
||||
info["normal"] = _dir_tuple(direction)
|
||||
info["oriented_normal"] = _oriented_dir_tuple(direction, face)
|
||||
info["push_pull_outward_direction"] = push_pull_direction["outward_direction"]
|
||||
info["push_pull_inward_direction"] = push_pull_direction["inward_direction"]
|
||||
info["push_pull_plus_side"] = push_pull_direction["plus_side_state"]
|
||||
info["push_pull_minus_side"] = push_pull_direction["minus_side_state"]
|
||||
info["push_pull_confidence"] = push_pull_direction["confidence"]
|
||||
info["push_pull_note"] = push_pull_direction["note"]
|
||||
info["push_pull_status"] = "candidate"
|
||||
info["feature_type"] = "可推拉平面候选"
|
||||
info["feature_source_face_id"] = face_id
|
||||
info["feature_highlight_face_ids"] = (face_id,)
|
||||
info["feature_edit_actions"] = "推拉平面"
|
||||
info.update(
|
||||
self._local_face_plane_size_info(
|
||||
face_id,
|
||||
face=face,
|
||||
surf=surf,
|
||||
center=_tuple_or_none(info.get("area_center")),
|
||||
)
|
||||
)
|
||||
elif surface_type == GeomAbs_Cylinder:
|
||||
cyl = surf.Cylinder()
|
||||
axis = cyl.Axis()
|
||||
radius = cyl.Radius()
|
||||
u_span = abs(surf.LastUParameter() - surf.FirstUParameter())
|
||||
swept_area = max(radius * max(u_span, 1e-9), 1e-9)
|
||||
classification = self._classify_cylindrical_face(face_id, surf, detailed=False)
|
||||
info["radius"] = radius
|
||||
info["diameter"] = radius * 2.0
|
||||
info["axis_point"] = _point_tuple(axis.Location())
|
||||
info["axis"] = _dir_tuple(axis.Direction())
|
||||
info["angular_span"] = u_span
|
||||
info["is_full_cylinder"] = u_span >= math.tau * 0.98
|
||||
info["height_estimate"] = props.Mass() / swept_area
|
||||
info["feature_guess"] = classification["feature_guess"]
|
||||
info["confidence"] = classification["confidence"]
|
||||
info["material_toward_axis"] = classification["toward_axis"]
|
||||
info["material_away_axis"] = classification["away_axis"]
|
||||
info["material_vote_summary"] = classification["vote_summary"]
|
||||
info["material_sample_count"] = classification["sample_count"]
|
||||
info["note"] = classification["note"]
|
||||
info["feature_source_face_id"] = face_id
|
||||
info["feature_highlight_face_ids"] = (face_id,)
|
||||
if u_span < math.tau * 0.92:
|
||||
info["slot_kind"] = "partial-cylindrical-groove"
|
||||
info["slot_angular_span"] = u_span
|
||||
info["slot_open_angle"] = max(math.tau - u_span, 0.0)
|
||||
info["slot_chord_width_estimate"] = 2.0 * radius * math.sin(min(u_span, math.tau) * 0.5)
|
||||
info["slot_sagitta_depth_estimate"] = radius * (1.0 - math.cos(min(u_span, math.tau) * 0.5))
|
||||
info["slot_arc_length_estimate"] = radius * u_span
|
||||
elif surface_type == GeomAbs_Cone:
|
||||
cone = surf.Cone()
|
||||
info["axis_point"] = _point_tuple(cone.Location())
|
||||
info["axis"] = _dir_tuple(cone.Axis().Direction())
|
||||
info["reference_radius"] = cone.RefRadius()
|
||||
info["semi_angle"] = cone.SemiAngle()
|
||||
info["feature_reference_radius"] = cone.RefRadius()
|
||||
info["feature_reference_diameter"] = cone.RefRadius() * 2.0
|
||||
elif surface_type == GeomAbs_Sphere:
|
||||
sphere = surf.Sphere()
|
||||
info["center"] = _point_tuple(sphere.Location())
|
||||
info["radius"] = sphere.Radius()
|
||||
info["diameter"] = sphere.Radius() * 2.0
|
||||
info["feature_sphere_radius"] = sphere.Radius()
|
||||
info["feature_sphere_diameter"] = sphere.Radius() * 2.0
|
||||
elif surface_type == GeomAbs_Torus:
|
||||
torus = surf.Torus()
|
||||
info["center"] = _point_tuple(torus.Location())
|
||||
info["axis"] = _dir_tuple(torus.Axis().Direction())
|
||||
info["major_radius"] = torus.MajorRadius()
|
||||
info["minor_radius"] = torus.MinorRadius()
|
||||
info["feature_torus_major_radius"] = torus.MajorRadius()
|
||||
info["feature_torus_minor_radius"] = torus.MinorRadius()
|
||||
|
||||
self._quick_face_info_cache[face_id] = dict(info)
|
||||
return dict(info)
|
||||
|
||||
def face_info(self, face_id: int) -> dict[str, object]:
|
||||
if face_id in self._face_info_cache:
|
||||
return dict(self._face_info_cache[face_id])
|
||||
@@ -313,6 +433,14 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
info["push_pull_minus_side"] = push_pull_direction["minus_side_state"]
|
||||
info["push_pull_confidence"] = push_pull_direction["confidence"]
|
||||
info["push_pull_note"] = push_pull_direction["note"]
|
||||
info.update(
|
||||
self._local_face_plane_size_info(
|
||||
face_id,
|
||||
face=face,
|
||||
surf=surf,
|
||||
center=_tuple_or_none(info.get("area_center")),
|
||||
)
|
||||
)
|
||||
elif surface_type == GeomAbs_Cylinder:
|
||||
cyl = surf.Cylinder()
|
||||
axis = cyl.Axis()
|
||||
@@ -389,6 +517,10 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def cached_feature_info(self, face_id: int) -> dict[str, object] | None:
|
||||
cached = self._feature_info_cache.get(face_id)
|
||||
return dict(cached) if cached is not None else None
|
||||
|
||||
def feature_info(self, face_id: int) -> dict[str, object]:
|
||||
if face_id < 0 or face_id >= len(self.faces):
|
||||
raise ValueError(f"Unknown face id {face_id}")
|
||||
@@ -1030,6 +1162,7 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
return
|
||||
for face_id in valid_face_ids:
|
||||
self.face_logical_ids[face_id] = int(logical_id)
|
||||
self._quick_face_info_cache.pop(face_id, None)
|
||||
self._face_info_cache.pop(face_id, None)
|
||||
self._feature_info_cache.pop(face_id, None)
|
||||
|
||||
@@ -1492,6 +1625,8 @@ class StepModel(FeatureMixin, ExportMixin, TransformMixin, OperationMixin, Polyd
|
||||
ellipse = curve.Ellipse()
|
||||
info["center"] = _point_tuple(ellipse.Location())
|
||||
info["axis"] = _dir_tuple(ellipse.Axis().Direction())
|
||||
info["major_axis"] = _dir_tuple(ellipse.XAxis().Direction())
|
||||
info["minor_axis"] = _dir_tuple(ellipse.YAxis().Direction())
|
||||
info["major_radius"] = ellipse.MajorRadius()
|
||||
info["minor_radius"] = ellipse.MinorRadius()
|
||||
adjacent_face_ids = self._edge_adjacent_face_ids(edge_id)
|
||||
|
||||
Reference in New Issue
Block a user