feat: 完善 Face 一级编辑与隔离计算
This commit is contained in:
+46
-19
@@ -149,9 +149,9 @@ class WindowCoreMixin:
|
||||
self.interactor.AddObserver("StartInteractionEvent", self.on_camera_interaction_start)
|
||||
self.interactor.AddObserver("EndInteractionEvent", self.on_camera_interaction_end)
|
||||
if hasattr(self.interactor, "SetDesiredUpdateRate"):
|
||||
self.interactor.SetDesiredUpdateRate(24.0)
|
||||
self.interactor.SetDesiredUpdateRate(60.0)
|
||||
if hasattr(self.interactor, "SetStillUpdateRate"):
|
||||
self.interactor.SetStillUpdateRate(0.2)
|
||||
self.interactor.SetStillUpdateRate(1.0)
|
||||
|
||||
light = vtk.vtkLight()
|
||||
light.SetLightTypeToHeadlight()
|
||||
@@ -252,7 +252,8 @@ class WindowCoreMixin:
|
||||
"show_internal_edges": show_internal_edges,
|
||||
}
|
||||
if build_polydata:
|
||||
result["model_polydata"] = new_model.build_face_polydata(deflection=deflection)
|
||||
face_polydata = new_model.build_face_polydata(deflection=deflection)
|
||||
result["model_polydata"] = _smooth_surface_polydata(face_polydata)
|
||||
result["edge_polydata"] = new_model.build_edge_polydata(
|
||||
deflection=deflection,
|
||||
show_same_domain_internal_edges=show_internal_edges,
|
||||
@@ -297,8 +298,8 @@ class WindowCoreMixin:
|
||||
@Slot(object)
|
||||
def _start_initial_load_worker(self, expected_path: Path) -> None:
|
||||
# Qt/VTK/OCCT visualization objects are not safe to construct from this
|
||||
# worker path in the current PySide build. Keep the old entry point as a
|
||||
# main-thread fallback so stale signal paths cannot crash the process.
|
||||
# worker path in the current PySide build. Keep this as a main-thread
|
||||
# fallback so stale signal paths cannot crash the process.
|
||||
self._run_deferred_initial_load(expected_path)
|
||||
|
||||
def _load_step_sync(
|
||||
@@ -348,7 +349,7 @@ class WindowCoreMixin:
|
||||
if polydata is None:
|
||||
return None
|
||||
copied = vtk.vtkPolyData()
|
||||
copied.DeepCopy(polydata)
|
||||
copied.ShallowCopy(polydata)
|
||||
return copied
|
||||
|
||||
def _detach_worker_polydata_result(self, result: dict[str, object]) -> dict[str, object]:
|
||||
@@ -1027,8 +1028,14 @@ class WindowCoreMixin:
|
||||
self.renderer.RemoveAllViewProps()
|
||||
self.renderer.SetBackground(*VIEW_BACKGROUND_COLOR)
|
||||
self.scene_isolated = False
|
||||
self.highlight_signature = None
|
||||
|
||||
self.model_polydata = _smooth_surface_polydata(model_polydata)
|
||||
point_normals = None
|
||||
try:
|
||||
point_normals = model_polydata.GetPointData().GetNormals()
|
||||
except Exception:
|
||||
point_normals = None
|
||||
self.model_polydata = model_polydata if point_normals is not None else _smooth_surface_polydata(model_polydata)
|
||||
self.model_face_id_array = self.model_polydata.GetCellData().GetArray("face_id")
|
||||
self.model_part_id_array = self.model_polydata.GetCellData().GetArray("part_id")
|
||||
self.model_solid_id_array = self.model_polydata.GetCellData().GetArray("solid_id")
|
||||
@@ -1569,7 +1576,7 @@ class WindowCoreMixin:
|
||||
elif action == "resize_shell_thickness":
|
||||
self._set_selection_mode("Feature")
|
||||
self.select_feature(int(target_id))
|
||||
self.statusBar().showMessage(f"已选择可调整薄壁厚度候选Face {target_id}")
|
||||
self.statusBar().showMessage(f"已选择可调整壳体厚度候选Face {target_id}")
|
||||
elif action == "suppress_cylinder":
|
||||
self._set_selection_mode("Feature")
|
||||
self.select_feature(int(target_id))
|
||||
@@ -1601,7 +1608,7 @@ class WindowCoreMixin:
|
||||
else:
|
||||
self._set_selection_mode("Face")
|
||||
self.select_face(int(target_id))
|
||||
self.statusBar().showMessage(f"已选择可推拉平面Face {target_id}")
|
||||
self.statusBar().showMessage(f"已选择可拉伸/切除平面Face {target_id}")
|
||||
|
||||
def select_by_id(self, kind: str | None = None) -> None:
|
||||
if self.model is None:
|
||||
@@ -1712,18 +1719,23 @@ class WindowCoreMixin:
|
||||
highlight_face_ids = _int_values(info.get("feature_highlight_face_ids")) or [face_id]
|
||||
else:
|
||||
highlight_face_ids = [face_id]
|
||||
logical_id = int(info.get("logical_face_id", face_id))
|
||||
selection_fields = self._selection_identity_fields(
|
||||
face_id,
|
||||
"特征来源 Face" if feature_mode else "Face",
|
||||
)
|
||||
logical_id = int(selection_fields["selection_display_id"])
|
||||
input_info = dict(info)
|
||||
input_info.update(selection_fields)
|
||||
self._sync_cylindrical_edit_inputs(input_info)
|
||||
self.selected_part_id = int(info["part_id"])
|
||||
self.selected_solid_id = int(info["solid_id"]) if int(info["solid_id"]) >= 0 else None
|
||||
self._highlight_faces(face_ids=highlight_face_ids or [face_id])
|
||||
self._show_pick_marker(pick_position)
|
||||
self._sync_id_picker("Feature" if feature_mode else "Face", face_id if feature_mode else logical_id)
|
||||
self._sync_id_picker("Feature" if feature_mode else "Face", logical_id)
|
||||
self.set_info(self._with_pick_info(input_info, pick_position))
|
||||
self._update_action_states()
|
||||
raw_note = f"(拓扑Face {face_id})" if not feature_mode and logical_id != face_id else ""
|
||||
message = f"已选择Face {logical_id}{raw_note}" if not feature_mode else f"已选择特征来源Face {face_id}"
|
||||
raw_note = f"(当前拓扑 Face {face_id})" if logical_id != face_id else ""
|
||||
message = f"已选择Face {logical_id}{raw_note}" if not feature_mode else f"已选择特征来源 Face {logical_id}{raw_note}"
|
||||
self.statusBar().showMessage(self._selection_status(message, pick_position))
|
||||
|
||||
def select_feature(self, face_id: int, pick_position: tuple[float, float, float] | None = None) -> None:
|
||||
@@ -1733,6 +1745,9 @@ class WindowCoreMixin:
|
||||
return
|
||||
info = self._feature_context_info(face_id)
|
||||
info["kind"] = "feature"
|
||||
selection_fields = self._selection_identity_fields(face_id, "特征来源 Face")
|
||||
logical_id = int(selection_fields["selection_display_id"])
|
||||
info.update(selection_fields)
|
||||
self._reset_selection(clear_highlight=False, clear_info=False)
|
||||
self.selected_kind = "feature"
|
||||
self.selected_face_id = face_id
|
||||
@@ -1743,11 +1758,12 @@ class WindowCoreMixin:
|
||||
highlight_face_ids = _int_values(info.get("feature_highlight_face_ids"))
|
||||
self._highlight_faces(face_ids=highlight_face_ids or [face_id])
|
||||
self._show_pick_marker(pick_position)
|
||||
self._sync_id_picker("Feature", face_id)
|
||||
self._sync_id_picker("Feature", logical_id)
|
||||
self.set_info(self._with_pick_info(info, pick_position))
|
||||
feature_type = str(info.get("feature_type", "特征候选"))
|
||||
self._update_action_states()
|
||||
self.statusBar().showMessage(self._selection_status(f"已选择 {feature_type},来源Face {face_id}", pick_position))
|
||||
raw_note = f"(当前拓扑 Face {face_id})" if logical_id != face_id else ""
|
||||
self.statusBar().showMessage(self._selection_status(f"已选择 {feature_type},来源 Face {logical_id}{raw_note}", pick_position))
|
||||
|
||||
def _sync_cylindrical_edit_inputs(self, info: dict[str, object]) -> None:
|
||||
fillet_radius_suggestion: str | None = None
|
||||
@@ -1927,8 +1943,13 @@ class WindowCoreMixin:
|
||||
def _highlight_faces(self, face_ids=None, part_ids=None) -> None:
|
||||
if self.model is None:
|
||||
return
|
||||
face_key = _int_tuple_or_none(face_ids)
|
||||
part_key = _int_tuple_or_none(part_ids)
|
||||
signature = ("faces", face_key, part_key)
|
||||
if signature == getattr(self, "highlight_signature", None) and self.highlight_actor is not None:
|
||||
return
|
||||
self._clear_highlight()
|
||||
polydata = self._cached_face_overlay_polydata(face_ids=face_ids, part_ids=part_ids, smooth=True)
|
||||
polydata = self._cached_face_overlay_polydata(face_ids=face_key, part_ids=part_key, smooth=True)
|
||||
if polydata is None:
|
||||
return
|
||||
mapper = vtk.vtkPolyDataMapper()
|
||||
@@ -1945,12 +1966,16 @@ class WindowCoreMixin:
|
||||
actor.GetProperty().SetLineWidth(2)
|
||||
self._offset_overlay_actor_toward_camera(actor, scale=0.00035)
|
||||
self.highlight_actor = actor
|
||||
self.highlight_signature = signature
|
||||
self.renderer.AddActor(actor)
|
||||
self.render_window.Render()
|
||||
|
||||
def _highlight_edge(self, edge_id: int) -> None:
|
||||
if self.model is None:
|
||||
return
|
||||
signature = ("edge", int(edge_id))
|
||||
if signature == getattr(self, "highlight_signature", None) and self.edge_highlight_actor is not None:
|
||||
return
|
||||
self._clear_highlight()
|
||||
polydata = self._cached_edge_overlay_polydata(edge_id)
|
||||
if polydata is None:
|
||||
@@ -1965,6 +1990,7 @@ class WindowCoreMixin:
|
||||
actor.GetProperty().SetDiffuse(0.8)
|
||||
actor.GetProperty().SetLineWidth(5)
|
||||
self.edge_highlight_actor = actor
|
||||
self.highlight_signature = signature
|
||||
self.renderer.AddActor(actor)
|
||||
self.render_window.Render()
|
||||
|
||||
@@ -2090,6 +2116,7 @@ class WindowCoreMixin:
|
||||
if self.pick_marker_actor is not None:
|
||||
self.renderer.RemoveActor(self.pick_marker_actor)
|
||||
self.pick_marker_actor = None
|
||||
self.highlight_signature = None
|
||||
|
||||
def clear_edit_preview(self, render: bool = True) -> None:
|
||||
if self.edit_preview_timer is not None:
|
||||
@@ -2138,7 +2165,7 @@ class WindowCoreMixin:
|
||||
if polydata is None:
|
||||
raise RuntimeError("当前显示网格里没有可复用的选中 Face 预览数据")
|
||||
except Exception as exc:
|
||||
self.statusBar().showMessage(f"推拉预览不可用:{exc}")
|
||||
self.statusBar().showMessage(f"拉伸/切除预览不可用:{exc}")
|
||||
return
|
||||
if distance >= 0:
|
||||
color = (0.0, 0.86, 0.34)
|
||||
@@ -2172,9 +2199,9 @@ class WindowCoreMixin:
|
||||
if polydata is None:
|
||||
polydata = self._cached_face_overlay_polydata(face_ids=[face_id], smooth=False)
|
||||
if polydata is None:
|
||||
raise RuntimeError("当前显示网格里没有可复用的薄壁预览数据")
|
||||
raise RuntimeError("当前显示网格里没有可复用的壳体预览数据")
|
||||
except Exception as exc:
|
||||
self.statusBar().showMessage(f"薄壁厚度调整预览不可用:{exc}")
|
||||
self.statusBar().showMessage(f"壳体厚度调整预览不可用:{exc}")
|
||||
return
|
||||
movement = _triple_or_none(plan.get("shell_desired_movement_vector")) if isinstance(plan, dict) else None
|
||||
if movement is None and isinstance(plan, dict):
|
||||
|
||||
Reference in New Issue
Block a user