feat: 增加Face偏移保持一级关系策略

This commit is contained in:
2026-08-10 15:26:35 +08:00
parent 83c44265ba
commit 415e8a0f27
9 changed files with 357 additions and 16 deletions
+28 -4
View File
@@ -25,6 +25,7 @@ FACE_CASES = (
("offset", "local", "width"),
("offset", "owning", "width"),
("offset", "push_pull", "width"),
("offset", "keep_relations", "width"),
)
@@ -170,7 +171,7 @@ def main() -> int:
parser.add_argument("--target-area", type=float, default=144.0)
parser.add_argument("--center-offset", default="2,0,3")
parser.add_argument("--offset-distance", type=float, default=1.0)
parser.add_argument("--strategy", default="local", choices=["local", "owning", "push_pull"])
parser.add_argument("--strategy", default="local", choices=["local", "owning", "push_pull", "keep_relations"])
parser.add_argument("--tolerance", type=float, default=1e-5)
args = parser.parse_args()
@@ -182,8 +183,8 @@ def main() -> int:
before = model.stats()
current_info = model.face_info(face_id)
if args.strategy == "push_pull" and args.property != "offset":
raise SystemExit("--strategy push_pull is only valid with --property offset")
if args.strategy in {"push_pull", "keep_relations"} and args.property != "offset":
raise SystemExit("--strategy push_pull/keep_relations is only valid with --property offset")
if args.property == "size" and args.strategy == "local":
plan = model.face_size_local_resize_plan(face_id, args.target_size, args.axis)
@@ -259,7 +260,7 @@ def main() -> int:
plan = model.face_plane_offset_owning_translation_plan(face_id, args.offset_distance)
result = model.translate_face_plane_offset_owning(face_id, args.offset_distance)
expected_strategy = "translate-owning-shape-from-plane-offset"
else:
elif args.property == "offset" and args.strategy == "push_pull":
frame = model.face_plane_offset_frame(face_id)
if frame is None:
raise SystemExit("selected Face does not have a stable plane offset frame")
@@ -275,12 +276,35 @@ def main() -> int:
plan = model.push_pull_plan(face_id, args.offset_distance)
result = model.push_pull_face(face_id, args.offset_distance)
expected_strategy = "push-pull-planar-face"
else:
frame = model.face_plane_offset_frame(face_id)
if frame is None:
raise SystemExit("selected Face does not have a stable plane offset frame")
current_center = current_info.get("area_center") or current_info.get("bbox_center")
if not isinstance(current_center, tuple) or len(current_center) != 3:
raise SystemExit("selected Face does not have a stable center")
_origin, direction, _position = frame
target_center = (
float(current_center[0]) + direction[0] * args.offset_distance,
float(current_center[1]) + direction[1] * args.offset_distance,
float(current_center[2]) + direction[2] * args.offset_distance,
)
plan = model.push_pull_keep_relations_plan(face_id, args.offset_distance)
result = model.push_pull_face_keep_relations(face_id, args.offset_distance)
expected_strategy = "push-pull-planar-face-keep-relations"
resolved_strategy = str(plan.get("resize_strategy", ""))
if args.property == "offset" and args.strategy == "push_pull":
resolved_strategy = "push-pull-planar-face"
if resolved_strategy != expected_strategy:
raise SystemExit(f"expected {expected_strategy}, got {resolved_strategy or '<none>'}")
if args.property == "offset" and args.strategy == "keep_relations":
if plan.get("face_push_pull_planar_relation_constraint_requested") is not True:
raise SystemExit(f"keep-relations plan should record requested relation constraint: {plan}")
if plan.get("face_push_pull_planar_constraint_status") != "ready":
raise SystemExit(f"keep-relations plan should be ready on cube Face: {plan}")
if "Planar relation check: ok" not in result:
raise SystemExit(f"keep-relations result should include planar relation check, got: {result}")
if "Face result check:" not in result:
raise SystemExit(f"Face edit result message should include a result check, got: {result}")
if "First-level check:" not in result:
@@ -14,6 +14,7 @@ if str(PROJECT_ROOT) not in sys.path:
EXPECTED_FACE_ISOLATED_OPERATIONS = {
"push_pull_face",
"push_pull_face_keep_relations",
"move_face_plane_offset_local",
"resize_face_area_local",
"resize_face_area",
@@ -122,6 +123,7 @@ def _assert_same(label: str, actual: set[str], expected: set[str]) -> None:
PROPERTY_FACE_ACTION_TO_ISOLATED_OPERATION = {
"push_pull_face": "push_pull_face",
"push_pull_face_keep_relations": "push_pull_face_keep_relations",
"move_selected_face_plane_position_local": "move_face_plane_offset_local",
"resize_face_width_local": "resize_face_size_local",
"resize_face_height_local": "resize_face_size_local",
@@ -151,6 +153,8 @@ PROPERTY_FACE_ACTIONS_ALLOWED_IN_MAIN_THREAD = {
ACTION_IMPLEMENTATION_METHOD = {
"push_pull_face": "_push_pull_face_action",
"push_pull_face_keep_relations": "_push_pull_face_action",
"resize_face_width_local": "_resize_face_size_local",
"resize_face_height_local": "_resize_face_size_local",
"resize_face_width_owning_scale": "_resize_face_size_owning_scale",
+14 -1
View File
@@ -491,6 +491,19 @@ def main() -> int:
_assert_label(plane_specs, "local_face_width", "面内长度")
_assert_label(plane_specs, "local_face_height", "面内宽度")
_assert_label(plane_specs, "face_target_normal_position", "偏移")
offset_keep_relations = _scope_mode(plane_specs, "face_target_normal_position", "keep_relations")
if str(offset_keep_relations.get("label") or "") != "保持关系":
raise SystemExit(f"Face plane-offset keep-relations scope should be labelled clearly: {offset_keep_relations}")
if str(offset_keep_relations.get("action") or "") != "push_pull_face_keep_relations":
raise SystemExit(f"Face plane-offset keep-relations scope should use its own action: {offset_keep_relations}")
if not bool(offset_keep_relations.get("enabled", False)):
raise SystemExit(f"Face plane-offset keep-relations scope should be available on simple planar Face: {offset_keep_relations}")
_assert_scoped_hint_fragments(
plane_specs,
"face_target_normal_position",
"keep_relations",
("一级", "平行/垂直", "会直接阻止"),
)
_assert_actionable_rows_first(
plane_info,
(
@@ -575,7 +588,7 @@ def main() -> int:
mode,
("5%", "5 倍", "会被阻止"),
)
for mode in ("push_pull", "local", "owning"):
for mode in ("push_pull", "keep_relations", "local", "owning"):
_assert_scoped_hint_fragments(
plane_specs,
"face_target_normal_position",