feat: 扩展Face保持关系编辑语义
This commit is contained in:
@@ -34,6 +34,8 @@ def _execute(model: StepModel, operation: str, args: list[object]) -> str:
|
||||
return model.resize_face_area(int(args[0]), float(args[1]))
|
||||
if operation == "resize_face_size_local":
|
||||
return model.resize_face_size_local(int(args[0]), float(args[1]), str(args[2]))
|
||||
if operation == "resize_face_size_local_keep_relations":
|
||||
return model.resize_face_size_local_keep_relations(int(args[0]), float(args[1]), str(args[2]))
|
||||
if operation == "resize_face_size_owning_scale":
|
||||
return model.resize_face_size_owning_scale(int(args[0]), float(args[1]), str(args[2]))
|
||||
if operation == "move_face_center_local":
|
||||
@@ -44,6 +46,14 @@ def _execute(model: StepModel, operation: str, args: list[object]) -> str:
|
||||
int(args[0]),
|
||||
(float(center[0]), float(center[1]), float(center[2])),
|
||||
)
|
||||
if operation == "move_face_center_local_keep_relations":
|
||||
center = list(args[1])
|
||||
if len(center) != 3:
|
||||
raise ValueError("move_face_center_local_keep_relations requires a 3D target center.")
|
||||
return model.move_face_center_local_keep_relations(
|
||||
int(args[0]),
|
||||
(float(center[0]), float(center[1]), float(center[2])),
|
||||
)
|
||||
if operation == "resize_shell_thickness":
|
||||
return model.resize_shell_thickness(int(args[0]), float(args[1]))
|
||||
if operation == "resize_shell_thickness_owning_scale":
|
||||
|
||||
+134
-11
@@ -262,6 +262,8 @@ class OperationMixin:
|
||||
self,
|
||||
face_id: int,
|
||||
plan: dict[str, object],
|
||||
*,
|
||||
operation_label: str = "拉伸/切除",
|
||||
) -> dict[str, object]:
|
||||
relation_status = str(plan.get("first_level_planar_relation_status") or "")
|
||||
relation_scope = str(plan.get("first_level_planar_relation_scope") or "")
|
||||
@@ -313,10 +315,13 @@ class OperationMixin:
|
||||
)
|
||||
else:
|
||||
summary = (
|
||||
"Face保持关系:可按拉伸/切除执行并反查一级平面关系;"
|
||||
f"Face保持关系:可按{operation_label}执行并反查一级平面关系;"
|
||||
f"平行 {parallel_count},垂直 {perpendicular_count}。"
|
||||
)
|
||||
return {
|
||||
"face_planar_relation_constraint_requested": True,
|
||||
"face_planar_relation_constraint_label": "保持一级平面关系",
|
||||
"face_planar_relation_constraint_operation": operation_label,
|
||||
"face_push_pull_planar_relation_constraint_requested": True,
|
||||
"face_push_pull_planar_relation_constraint_label": "保持一级平面关系",
|
||||
"face_push_pull_planar_constraint_status": "blocked" if blockers else "ready",
|
||||
@@ -339,16 +344,23 @@ class OperationMixin:
|
||||
),
|
||||
}
|
||||
|
||||
def push_pull_keep_relations_plan(self, face_id: int, distance: float) -> dict[str, object]:
|
||||
plan = self.push_pull_plan(face_id, distance)
|
||||
constraint_fields = self._face_push_pull_planar_relation_constraint_fields(face_id, plan)
|
||||
plan.update(constraint_fields)
|
||||
plan["resize_strategy"] = "push-pull-planar-face-keep-relations"
|
||||
plan["edit_strategy_label"] = "保持一级平面关系的拉伸/切除"
|
||||
plan["edit_semantics"] = (
|
||||
"沿当前 Face 法向拉伸/切除,同时要求当前 Face 与共享边一级相邻平面的平行/垂直关系"
|
||||
"在执行前可验证,并在执行后反查。"
|
||||
def _with_face_planar_relation_constraint(
|
||||
self,
|
||||
face_id: int,
|
||||
plan: dict[str, object],
|
||||
*,
|
||||
operation_label: str,
|
||||
edit_strategy_label: str,
|
||||
edit_semantics: str,
|
||||
) -> dict[str, object]:
|
||||
constraint_fields = self._face_push_pull_planar_relation_constraint_fields(
|
||||
face_id,
|
||||
plan,
|
||||
operation_label=operation_label,
|
||||
)
|
||||
plan.update(constraint_fields)
|
||||
plan["edit_strategy_label"] = edit_strategy_label
|
||||
plan["edit_semantics"] = edit_semantics
|
||||
if plan["status"] != "blocked" and constraint_fields["face_push_pull_planar_constraint_status"] == "blocked":
|
||||
blockers = str(constraint_fields.get("face_push_pull_planar_constraint_blockers") or "")
|
||||
plan["status"] = "blocked"
|
||||
@@ -368,6 +380,21 @@ class OperationMixin:
|
||||
plan["message"] = str(constraint_fields["face_push_pull_planar_constraint_summary"])
|
||||
return plan
|
||||
|
||||
def push_pull_keep_relations_plan(self, face_id: int, distance: float) -> dict[str, object]:
|
||||
plan = self.push_pull_plan(face_id, distance)
|
||||
self._with_face_planar_relation_constraint(
|
||||
face_id,
|
||||
plan,
|
||||
operation_label="拉伸/切除",
|
||||
edit_strategy_label="保持一级平面关系的拉伸/切除",
|
||||
edit_semantics=(
|
||||
"沿当前 Face 法向拉伸/切除,同时要求当前 Face 与共享边一级相邻平面的平行/垂直关系"
|
||||
"在执行前可验证,并在执行后反查。"
|
||||
),
|
||||
)
|
||||
plan["resize_strategy"] = "push-pull-planar-face-keep-relations"
|
||||
return plan
|
||||
|
||||
def _multistep_prismatic_plan_blocker(self, face_id: int, operation_label: str) -> str:
|
||||
try:
|
||||
quick_info = self.quick_face_info(face_id)
|
||||
@@ -4070,6 +4097,23 @@ class OperationMixin:
|
||||
),
|
||||
}
|
||||
|
||||
def face_center_local_move_keep_relations_plan(
|
||||
self,
|
||||
face_id: int,
|
||||
target_center: tuple[float, float, float],
|
||||
) -> dict[str, object]:
|
||||
plan = self.face_center_owning_translation_plan(face_id, target_center)
|
||||
return self._with_face_planar_relation_constraint(
|
||||
face_id,
|
||||
plan,
|
||||
operation_label="中心移动",
|
||||
edit_strategy_label="保持一级平面关系的中心移动",
|
||||
edit_semantics=(
|
||||
"把目标中心换算成平移量并移动所属特征或 Solid,同时要求当前 Face 与共享边一级相邻平面的"
|
||||
"平行/垂直关系在执行前可验证,并在执行后反查;不做单面局部扭曲。"
|
||||
),
|
||||
)
|
||||
|
||||
def existing_chamfer_resize_plan(self, face_id: int, target_distance: float) -> dict[str, object]:
|
||||
if face_id < 0 or face_id >= len(self.faces):
|
||||
raise ValueError(f"Unknown face id {face_id}")
|
||||
@@ -4604,6 +4648,26 @@ class OperationMixin:
|
||||
),
|
||||
}
|
||||
|
||||
def face_size_local_resize_keep_relations_plan(
|
||||
self,
|
||||
face_id: int,
|
||||
target_size: float,
|
||||
axis: str = "width",
|
||||
) -> dict[str, object]:
|
||||
axis_key = "height" if str(axis).strip().lower() in {"height", "h", "v", "y"} else "width"
|
||||
axis_label = "面内宽度" if axis_key == "height" else "面内长度"
|
||||
plan = self.face_size_owning_scale_plan(face_id, target_size, axis_key)
|
||||
return self._with_face_planar_relation_constraint(
|
||||
face_id,
|
||||
plan,
|
||||
operation_label=f"{axis_label}修改",
|
||||
edit_strategy_label=f"保持一级平面关系的{axis_label}修改",
|
||||
edit_semantics=(
|
||||
f"沿当前 Face 的{axis_label}方向缩放所属特征或 Solid,同时要求当前 Face 与共享边一级相邻平面的"
|
||||
"平行/垂直关系在执行前可验证,并在执行后反查;不做单面局部扭曲。"
|
||||
),
|
||||
)
|
||||
|
||||
def _rectangular_prismatic_size_resize_plan(
|
||||
self,
|
||||
*,
|
||||
@@ -8144,6 +8208,35 @@ class OperationMixin:
|
||||
f"risk={plan['risk']}. {result_check}"
|
||||
)
|
||||
|
||||
def move_face_center_local_keep_relations(
|
||||
self,
|
||||
face_id: int,
|
||||
target_center: tuple[float, float, float],
|
||||
) -> str:
|
||||
plan = self.face_center_local_move_keep_relations_plan(face_id, target_center)
|
||||
if plan["status"] == "blocked":
|
||||
raise ValueError(str(plan["message"]))
|
||||
|
||||
self._remember_face_target_logical_id(plan, face_id)
|
||||
vector = tuple(plan["translation_vector"])
|
||||
result, result_check = self._run_checked_face_edit(
|
||||
plan,
|
||||
lambda: (
|
||||
self.translate_solid(int(plan["solid_id"]), vector)
|
||||
if plan.get("target_kind") == "solid"
|
||||
else self.translate_part(int(plan["part_id"]), vector)
|
||||
),
|
||||
)
|
||||
return (
|
||||
"Face center move completed with first-level planar relations: "
|
||||
f"face {face_id}, "
|
||||
f"current_center={plan.get('current_face_center')}, "
|
||||
f"target_center={plan.get('target_face_center')}, "
|
||||
f"move={plan.get('face_center_move_vector')}, "
|
||||
f"target={plan.get('target_kind')}, "
|
||||
f"risk={plan['risk']}. {result_check} {result}"
|
||||
)
|
||||
|
||||
def face_area_local_resize_preview_polydata(
|
||||
self,
|
||||
face_id: int,
|
||||
@@ -8243,6 +8336,33 @@ class OperationMixin:
|
||||
f"risk={plan['risk']}. {result_check}"
|
||||
)
|
||||
|
||||
def resize_face_size_local_keep_relations(self, face_id: int, target_size: float, axis: str = "width") -> str:
|
||||
plan = self.face_size_local_resize_keep_relations_plan(face_id, target_size, axis)
|
||||
if plan["status"] == "blocked":
|
||||
raise ValueError(str(plan["message"]))
|
||||
|
||||
self._remember_face_target_logical_id(plan, face_id)
|
||||
_action_result, result_check = self._run_checked_face_edit(
|
||||
plan,
|
||||
lambda: (
|
||||
self._apply_local_face_deform(plan)
|
||||
if plan.get("owning_face_size_rebuild_mode") == "planar-rebuild"
|
||||
else self._apply_edge_length_affine_transform(plan)
|
||||
),
|
||||
)
|
||||
return (
|
||||
"Face owning size resize completed with first-level planar relations: "
|
||||
f"face {face_id}, "
|
||||
f"axis={plan.get('face_size_axis')}, "
|
||||
f"current_size={float(plan['current_face_size']):g}, "
|
||||
f"target_size={float(plan['target_face_size']):g}, "
|
||||
f"delta={float(plan['face_size_delta']):g}, "
|
||||
f"scale={float(plan['face_size_scale']):g}, "
|
||||
f"rebuild_mode={plan.get('owning_face_size_rebuild_mode')}, "
|
||||
f"target={plan.get('affine_target_kind')}, "
|
||||
f"risk={plan['risk']}. {result_check}"
|
||||
)
|
||||
|
||||
def face_size_owning_scale_preview_polydata(
|
||||
self,
|
||||
face_id: int,
|
||||
@@ -8318,7 +8438,10 @@ class OperationMixin:
|
||||
matched_face_id: int,
|
||||
facts: dict[str, object],
|
||||
) -> str:
|
||||
if plan.get("face_push_pull_planar_relation_constraint_requested") is not True:
|
||||
if (
|
||||
plan.get("face_planar_relation_constraint_requested") is not True
|
||||
and plan.get("face_push_pull_planar_relation_constraint_requested") is not True
|
||||
):
|
||||
return ""
|
||||
if str(plan.get("face_push_pull_planar_constraint_status") or "") != "ready":
|
||||
raise RuntimeError("Face planar relation check was requested but the original constraint plan is not ready.")
|
||||
|
||||
@@ -1507,10 +1507,13 @@ class WindowActionMixin:
|
||||
"面面积(缩放特征)",
|
||||
"面内长度(局部重建)",
|
||||
"面内宽度(局部重建)",
|
||||
"面内长度(保持关系)",
|
||||
"面内宽度(保持关系)",
|
||||
"面内长度(缩放特征)",
|
||||
"面内宽度(缩放特征)",
|
||||
"偏移(局部重建)",
|
||||
"中心(局部重建)",
|
||||
"中心(保持关系)",
|
||||
"圆柱高度调整",
|
||||
"高度(缩放特征)缩放所属对象",
|
||||
}
|
||||
@@ -1531,8 +1534,10 @@ class WindowActionMixin:
|
||||
"resize_face_area_local",
|
||||
"resize_face_area",
|
||||
"resize_face_size_local",
|
||||
"resize_face_size_local_keep_relations",
|
||||
"resize_face_size_owning_scale",
|
||||
"move_face_center_local",
|
||||
"move_face_center_local_keep_relations",
|
||||
"resize_shell_thickness",
|
||||
"resize_shell_thickness_owning_scale",
|
||||
"resize_cylindrical_height",
|
||||
@@ -5920,10 +5925,16 @@ class WindowActionMixin:
|
||||
)
|
||||
|
||||
def resize_face_width_local(self) -> None:
|
||||
self._resize_face_size_local("width")
|
||||
self._resize_face_size_local("width", keep_relations=False)
|
||||
|
||||
def resize_face_height_local(self) -> None:
|
||||
self._resize_face_size_local("height")
|
||||
self._resize_face_size_local("height", keep_relations=False)
|
||||
|
||||
def resize_face_width_keep_relations(self) -> None:
|
||||
self._resize_face_size_local("width", keep_relations=True)
|
||||
|
||||
def resize_face_height_keep_relations(self) -> None:
|
||||
self._resize_face_size_local("height", keep_relations=True)
|
||||
|
||||
def resize_face_width_owning_scale(self) -> None:
|
||||
self._resize_face_size_owning_scale("width")
|
||||
@@ -5931,12 +5942,13 @@ class WindowActionMixin:
|
||||
def resize_face_height_owning_scale(self) -> None:
|
||||
self._resize_face_size_owning_scale("height")
|
||||
|
||||
def _resize_face_size_local(self, axis: str) -> None:
|
||||
def _resize_face_size_local(self, axis: str, *, keep_relations: bool) -> None:
|
||||
if self.model is None:
|
||||
return
|
||||
axis_key = "height" if str(axis).lower() == "height" else "width"
|
||||
axis_label = "面内宽度" if axis_key == "height" else "面内长度"
|
||||
if self._edit_busy(f"请等待当前编辑完成后再修改{axis_label}(局部重建)。"):
|
||||
mode_label = f"{axis_label}(保持关系)" if keep_relations else f"{axis_label}(局部重建)"
|
||||
if self._edit_busy(f"请等待当前编辑完成后再修改{mode_label}。"):
|
||||
return
|
||||
if self.selected_face_id is None:
|
||||
QMessageBox.information(self, "未选择Face", "请先选择一个平面 Face。")
|
||||
@@ -5953,10 +5965,13 @@ class WindowActionMixin:
|
||||
face_id = self.selected_face_id
|
||||
plan = self._quick_blocked_face_size_local_plan(face_id, target_size, axis_key)
|
||||
if plan is None:
|
||||
plan = self.model.face_size_local_resize_plan(face_id, target_size, axis_key)
|
||||
if keep_relations:
|
||||
plan = self.model.face_size_local_resize_keep_relations_plan(face_id, target_size, axis_key)
|
||||
else:
|
||||
plan = self.model.face_size_local_resize_plan(face_id, target_size, axis_key)
|
||||
lines = [
|
||||
f"Face: {face_id}",
|
||||
f"修改对象: {axis_label}(局部重建)",
|
||||
f"修改对象: {mode_label}",
|
||||
f"当前面内长度: {_format_value(plan.get('current_face_width'))}",
|
||||
f"目标面内长度: {_format_value(plan.get('target_face_width'))}",
|
||||
f"当前面内宽度: {_format_value(plan.get('current_face_height'))}",
|
||||
@@ -5970,21 +5985,23 @@ class WindowActionMixin:
|
||||
f"影响目标: {_format_value(plan.get('local_face_deform_target_kind'))}",
|
||||
]
|
||||
if not self._confirm_quick_edit_plan(
|
||||
f"{axis_label}(局部重建)",
|
||||
mode_label,
|
||||
plan,
|
||||
lines,
|
||||
f"{axis_label}(局部重建)已阻止",
|
||||
f"已取消{axis_label}(局部重建)",
|
||||
f"{mode_label}已阻止",
|
||||
f"已取消{mode_label}",
|
||||
):
|
||||
return
|
||||
self.clear_edit_preview(render=False)
|
||||
|
||||
def action():
|
||||
if keep_relations:
|
||||
return self.model.resize_face_size_local_keep_relations(face_id, target_size, axis_key)
|
||||
return self.model.resize_face_size_local(face_id, target_size, axis_key)
|
||||
|
||||
self._run_edit_action(
|
||||
action,
|
||||
operation_name=f"修改{axis_label}(局部重建)",
|
||||
operation_name=f"修改{mode_label}",
|
||||
target=f"Face {face_id}",
|
||||
parameters={
|
||||
"face_id": face_id,
|
||||
@@ -6013,6 +6030,11 @@ class WindowActionMixin:
|
||||
"resize_strategy": plan.get("resize_strategy"),
|
||||
"edit_strategy_label": plan.get("edit_strategy_label"),
|
||||
"edit_semantics": plan.get("edit_semantics"),
|
||||
"face_planar_relation_constraint_requested": plan.get("face_planar_relation_constraint_requested"),
|
||||
"face_push_pull_planar_constraint_summary": plan.get("face_push_pull_planar_constraint_summary"),
|
||||
"face_push_pull_planar_constraint_parallel_count": plan.get("face_push_pull_planar_constraint_parallel_count"),
|
||||
"face_push_pull_planar_constraint_perpendicular_count": plan.get("face_push_pull_planar_constraint_perpendicular_count"),
|
||||
"face_push_pull_planar_constraint_angled_count": plan.get("face_push_pull_planar_constraint_angled_count"),
|
||||
"resize_status": plan.get("status"),
|
||||
"resize_risk": plan.get("risk"),
|
||||
"resize_message": plan.get("message"),
|
||||
@@ -6022,7 +6044,11 @@ class WindowActionMixin:
|
||||
},
|
||||
target_kind="face",
|
||||
target_id=face_id,
|
||||
isolation=self._isolation_for_plan(plan, "resize_face_size_local", [face_id, target_size, axis_key]),
|
||||
isolation=self._isolation_for_plan(
|
||||
plan,
|
||||
"resize_face_size_local_keep_relations" if keep_relations else "resize_face_size_local",
|
||||
[face_id, target_size, axis_key],
|
||||
),
|
||||
)
|
||||
|
||||
def _resize_face_size_owning_scale(self, axis: str) -> None:
|
||||
@@ -6361,9 +6387,16 @@ class WindowActionMixin:
|
||||
)
|
||||
|
||||
def move_selected_face_center_local(self) -> None:
|
||||
self._move_selected_face_center_local(keep_relations=False)
|
||||
|
||||
def move_selected_face_center_keep_relations(self) -> None:
|
||||
self._move_selected_face_center_local(keep_relations=True)
|
||||
|
||||
def _move_selected_face_center_local(self, *, keep_relations: bool) -> None:
|
||||
if self.model is None:
|
||||
return
|
||||
if self._edit_busy("请等待当前编辑完成后再执行中心(局部重建)。"):
|
||||
mode_label = "中心(保持关系)" if keep_relations else "中心(局部重建)"
|
||||
if self._edit_busy(f"请等待当前编辑完成后再执行{mode_label}。"):
|
||||
return
|
||||
if self.selected_face_id is None:
|
||||
QMessageBox.information(self, "未选择Face", "请先选择一个平面 Face。")
|
||||
@@ -6378,9 +6411,9 @@ class WindowActionMixin:
|
||||
current_center = self._selected_face_center_for_translation(face_id)
|
||||
if current_center is None:
|
||||
self._show_immediate_cannot_edit_message(
|
||||
"中心(局部重建)",
|
||||
mode_label,
|
||||
"当前 Face 缺少稳定中心坐标。",
|
||||
"中心(局部重建)已阻止",
|
||||
f"{mode_label}已阻止",
|
||||
)
|
||||
return
|
||||
target_center = (
|
||||
@@ -6390,7 +6423,10 @@ class WindowActionMixin:
|
||||
)
|
||||
plan = self._quick_blocked_face_center_local_plan(face_id, target_center)
|
||||
if plan is None:
|
||||
plan = self.model.face_center_local_move_plan(face_id, target_center)
|
||||
if keep_relations:
|
||||
plan = self.model.face_center_local_move_keep_relations_plan(face_id, target_center)
|
||||
else:
|
||||
plan = self.model.face_center_local_move_plan(face_id, target_center)
|
||||
lines = [
|
||||
f"Face: {face_id}",
|
||||
f"当前 Face 中心: {_format_value(plan.get('current_face_center'))}",
|
||||
@@ -6403,21 +6439,23 @@ class WindowActionMixin:
|
||||
f"影响目标: {_format_value(plan.get('local_face_deform_target_kind'))}",
|
||||
]
|
||||
if not self._confirm_quick_edit_plan(
|
||||
"中心(局部重建)",
|
||||
mode_label,
|
||||
plan,
|
||||
lines,
|
||||
"中心(局部重建)已阻止",
|
||||
"已取消中心(局部重建)",
|
||||
f"{mode_label}已阻止",
|
||||
f"已取消{mode_label}",
|
||||
):
|
||||
return
|
||||
self.clear_edit_preview(render=False)
|
||||
|
||||
def action():
|
||||
if keep_relations:
|
||||
return self.model.move_face_center_local_keep_relations(face_id, target_center)
|
||||
return self.model.move_face_center_local(face_id, target_center)
|
||||
|
||||
self._run_edit_action(
|
||||
action,
|
||||
operation_name="中心(局部重建)",
|
||||
operation_name=mode_label,
|
||||
target=f"Face {face_id}",
|
||||
parameters={
|
||||
"face_id": face_id,
|
||||
@@ -6436,6 +6474,11 @@ class WindowActionMixin:
|
||||
"resize_strategy": plan.get("resize_strategy"),
|
||||
"edit_strategy_label": plan.get("edit_strategy_label"),
|
||||
"edit_semantics": plan.get("edit_semantics"),
|
||||
"face_planar_relation_constraint_requested": plan.get("face_planar_relation_constraint_requested"),
|
||||
"face_push_pull_planar_constraint_summary": plan.get("face_push_pull_planar_constraint_summary"),
|
||||
"face_push_pull_planar_constraint_parallel_count": plan.get("face_push_pull_planar_constraint_parallel_count"),
|
||||
"face_push_pull_planar_constraint_perpendicular_count": plan.get("face_push_pull_planar_constraint_perpendicular_count"),
|
||||
"face_push_pull_planar_constraint_angled_count": plan.get("face_push_pull_planar_constraint_angled_count"),
|
||||
"resize_status": plan.get("status"),
|
||||
"resize_risk": plan.get("risk"),
|
||||
"resize_message": plan.get("message"),
|
||||
@@ -6445,7 +6488,11 @@ class WindowActionMixin:
|
||||
},
|
||||
target_kind="face",
|
||||
target_id=face_id,
|
||||
isolation=self._isolation_for_plan(plan, "move_face_center_local", [face_id, list(target_center)]),
|
||||
isolation=self._isolation_for_plan(
|
||||
plan,
|
||||
"move_face_center_local_keep_relations" if keep_relations else "move_face_center_local",
|
||||
[face_id, list(target_center)],
|
||||
),
|
||||
)
|
||||
|
||||
def move_selected_axis_center_by_translation(self) -> None:
|
||||
|
||||
@@ -3427,6 +3427,43 @@ class WindowStateMixin:
|
||||
_triple_or_none(action_info.get("area_center"))
|
||||
or _triple_or_none(action_info.get("bbox_center"))
|
||||
)
|
||||
keep_relation_fields_present = any(
|
||||
key in action_info
|
||||
for key in (
|
||||
"first_level_planar_relation_status",
|
||||
"first_level_planar_relation_count",
|
||||
"first_level_planar_relation_angled_count",
|
||||
"first_level_planar_relation_non_planar_face_ids",
|
||||
"first_level_adjacent_surface_types",
|
||||
)
|
||||
)
|
||||
face_keep_relation_enabled = bool(is_plane)
|
||||
face_keep_relation_disabled_tip = "当前对象不是平面 Face,不能保持一级平面关系。"
|
||||
if face_keep_relation_enabled and keep_relation_fields_present:
|
||||
relation_status = str(action_info.get("first_level_planar_relation_status") or "")
|
||||
relation_count = _int_or_none(action_info.get("first_level_planar_relation_count")) or 0
|
||||
angled_count = _int_or_none(action_info.get("first_level_planar_relation_angled_count")) or 0
|
||||
non_planar_face_ids = _int_values(action_info.get("first_level_planar_relation_non_planar_face_ids"))
|
||||
adjacent_surfaces = tuple(action_info.get("first_level_adjacent_surface_types") or ())
|
||||
non_plane_adjacent_surfaces = tuple(
|
||||
item
|
||||
for item in adjacent_surfaces
|
||||
if isinstance(item, (tuple, list))
|
||||
and len(item) >= 2
|
||||
and str(item[1]) != "plane"
|
||||
)
|
||||
if non_planar_face_ids or non_plane_adjacent_surfaces:
|
||||
face_keep_relation_enabled = False
|
||||
face_keep_relation_disabled_tip = "一级相邻 Face 中包含非平面/曲面,当前“保持关系”只支持平面邻域。"
|
||||
elif angled_count > 0:
|
||||
face_keep_relation_enabled = False
|
||||
face_keep_relation_disabled_tip = "一级相邻平面中存在斜交关系,当前“保持关系”只支持平行/垂直。"
|
||||
elif relation_status != "ready":
|
||||
face_keep_relation_enabled = False
|
||||
face_keep_relation_disabled_tip = "当前一级平面关系还不可验证,不能使用“保持关系”。"
|
||||
elif relation_count <= 0:
|
||||
face_keep_relation_enabled = False
|
||||
face_keep_relation_disabled_tip = "当前一级邻域没有识别到可保持的平行/垂直平面关系。"
|
||||
if is_plane:
|
||||
current_face_width = _float_or_none(action_info.get("local_face_width"))
|
||||
current_face_height = _float_or_none(action_info.get("local_face_height"))
|
||||
@@ -3461,6 +3498,31 @@ class WindowStateMixin:
|
||||
),
|
||||
"range_hint": f"{face_size_tip} {relative_range_hint(current_face_width, 0.25, 0.8, face_linear_hard_limit)}",
|
||||
},
|
||||
"keep_relations": {
|
||||
"label": "保持关系",
|
||||
"action": "resize_face_width_keep_relations",
|
||||
"target_attr": "face_width_input",
|
||||
"enabled": bool(
|
||||
current_face_width is not None
|
||||
and current_face_width > 0
|
||||
and current_face_center is not None
|
||||
and (self.selected_part_id is not None or self.selected_solid_id is not None)
|
||||
and face_keep_relation_enabled
|
||||
),
|
||||
"enabled_tip": (
|
||||
"输入目标面内长度;程序会沿该方向缩放所属特征或 Solid,"
|
||||
"并要求一级相邻平面的平行/垂直关系在执行前可验证、执行后可反查。"
|
||||
),
|
||||
"disabled_tip": (
|
||||
face_keep_relation_disabled_tip
|
||||
if not face_keep_relation_enabled
|
||||
else "当前 Face 缺少稳定面内长度、中心坐标或所属对象,不能保持关系地修改面内长度。"
|
||||
),
|
||||
"range_hint": (
|
||||
"保持关系会把面内长度修改转换为所属对象单向缩放,并在结果上反查一级平面关系;"
|
||||
f"{relative_range_hint(current_face_width, 0.25, 0.8, face_linear_hard_limit)}"
|
||||
),
|
||||
},
|
||||
"owning": {
|
||||
"label": "缩放特征",
|
||||
"action": "resize_face_width_owning_scale",
|
||||
@@ -3503,6 +3565,31 @@ class WindowStateMixin:
|
||||
),
|
||||
"range_hint": f"{face_size_tip} {relative_range_hint(current_face_height, 0.25, 0.8, face_linear_hard_limit)}",
|
||||
},
|
||||
"keep_relations": {
|
||||
"label": "保持关系",
|
||||
"action": "resize_face_height_keep_relations",
|
||||
"target_attr": "face_height_input",
|
||||
"enabled": bool(
|
||||
current_face_height is not None
|
||||
and current_face_height > 0
|
||||
and current_face_center is not None
|
||||
and (self.selected_part_id is not None or self.selected_solid_id is not None)
|
||||
and face_keep_relation_enabled
|
||||
),
|
||||
"enabled_tip": (
|
||||
"输入目标面内宽度;程序会沿该方向缩放所属特征或 Solid,"
|
||||
"并要求一级相邻平面的平行/垂直关系在执行前可验证、执行后可反查。"
|
||||
),
|
||||
"disabled_tip": (
|
||||
face_keep_relation_disabled_tip
|
||||
if not face_keep_relation_enabled
|
||||
else "当前 Face 缺少稳定面内宽度、中心坐标或所属对象,不能保持关系地修改面内宽度。"
|
||||
),
|
||||
"range_hint": (
|
||||
"保持关系会把面内宽度修改转换为所属对象单向缩放,并在结果上反查一级平面关系;"
|
||||
f"{relative_range_hint(current_face_height, 0.25, 0.8, face_linear_hard_limit)}"
|
||||
),
|
||||
},
|
||||
"owning": {
|
||||
"label": "缩放特征",
|
||||
"action": "resize_face_height_owning_scale",
|
||||
@@ -3549,6 +3636,33 @@ class WindowStateMixin:
|
||||
"transform_context": {"current_center": current_face_center},
|
||||
**face_vector_move_limit(current_face_center),
|
||||
},
|
||||
"keep_relations": {
|
||||
"label": "保持关系",
|
||||
"action": "move_selected_face_center_keep_relations",
|
||||
"target_attrs": ("translate_x_input", "translate_y_input", "translate_z_input"),
|
||||
"enabled": bool(
|
||||
is_plane
|
||||
and current_face_center is not None
|
||||
and (self.selected_part_id is not None or self.selected_solid_id is not None)
|
||||
and face_keep_relation_enabled
|
||||
),
|
||||
"enabled_tip": (
|
||||
"输入这个 Face 中心要移动到的目标 X, Y, Z 坐标;程序会平移所属特征或 Solid,"
|
||||
"并要求一级相邻平面的平行/垂直关系在执行前可验证、执行后可反查。"
|
||||
),
|
||||
"disabled_tip": (
|
||||
face_keep_relation_disabled_tip
|
||||
if not face_keep_relation_enabled
|
||||
else "当前 Face 缺少稳定中心坐标或所属对象,不能保持关系地修改中心位置。"
|
||||
),
|
||||
"range_hint": (
|
||||
"保持关系会把中心修改转换为所属对象平移,并在结果上反查一级平面关系;"
|
||||
f"{translation_hint()} {face_center_hard_limit}"
|
||||
),
|
||||
"target_transform": "target_center_to_translation",
|
||||
"transform_context": {"current_center": current_face_center},
|
||||
**face_vector_move_limit(current_face_center),
|
||||
},
|
||||
"owning": {
|
||||
"label": "移动特征",
|
||||
"action": "move_selected_face_center",
|
||||
|
||||
Reference in New Issue
Block a user