feat: 增强一级关系识别与保持关系策略
This commit is contained in:
@@ -146,6 +146,62 @@ def assert_rectangular_feature_ui(
|
||||
raise AssertionError(f"unexpected rectangular feature UI parameters: {actual}")
|
||||
|
||||
|
||||
def find_multistep_transition_face(model: StepModel) -> tuple[int, dict[str, object]]:
|
||||
matches: list[tuple[int, dict[str, object]]] = []
|
||||
for face_id in range(len(model.faces)):
|
||||
info = model.feature_info(face_id)
|
||||
if info.get("multistep_prismatic_status") != "blocked":
|
||||
continue
|
||||
center = info.get("area_center")
|
||||
z_value = float(center[2]) if isinstance(center, (list, tuple)) and len(center) >= 3 else -1.0
|
||||
matches.append((face_id, info | {"_z_sort": z_value}))
|
||||
if not matches:
|
||||
raise AssertionError("expected at least one blocked multistep transition face")
|
||||
matches.sort(key=lambda item: float(item[1].get("_z_sort", -1.0)), reverse=True)
|
||||
face_id, info = matches[0]
|
||||
info.pop("_z_sort", None)
|
||||
return face_id, info
|
||||
|
||||
|
||||
def assert_multistep_transition_guard(model: StepModel) -> None:
|
||||
face_id, info = find_multistep_transition_face(model)
|
||||
blockers = str(info.get("multistep_prismatic_blockers") or info.get("recognition_blockers") or "")
|
||||
if "多台阶" not in blockers or "暂不支持" not in blockers:
|
||||
raise AssertionError(f"multistep transition blocker should explain unsupported scope: {info}")
|
||||
if "复杂多台阶凸台" not in str(info.get("feature_type")):
|
||||
raise AssertionError(f"unexpected multistep transition label: {info.get('feature_type')}")
|
||||
if feature_dimension_rows(model, face_id, info) != ():
|
||||
raise AssertionError("blocked multistep transition face should not expose editable dimensions")
|
||||
|
||||
target_center = info.get("area_center")
|
||||
if not isinstance(target_center, (list, tuple)) or len(target_center) != 3:
|
||||
raise AssertionError(f"multistep transition face lacks a stable center: {info}")
|
||||
center_target = (float(target_center[0]) + 0.5, float(target_center[1]), float(target_center[2]))
|
||||
plans = (
|
||||
model.push_pull_plan(face_id, 1.0),
|
||||
model.shell_thickness_plan(face_id, 2.5),
|
||||
model.face_size_local_resize_plan(face_id, 9.0, "width"),
|
||||
model.face_center_local_move_plan(face_id, center_target),
|
||||
)
|
||||
for plan in plans:
|
||||
if plan.get("status") != "blocked":
|
||||
raise AssertionError(f"multistep transition plan should be blocked: {plan}")
|
||||
message = str(plan.get("message") or plan.get("blockers") or "")
|
||||
if "多台阶" not in message or "暂不支持" not in message:
|
||||
raise AssertionError(f"multistep transition plan should explain unsupported scope: {plan}")
|
||||
|
||||
leaked_entries = [
|
||||
item
|
||||
for item in model.editable_feature_candidates(limit=80, detailed=False)
|
||||
if int(item.get("target_id", -1)) == face_id
|
||||
and str(item.get("operation_key") or "") in {"push_pull_plane", "resize_shell_thickness"}
|
||||
]
|
||||
if leaked_entries:
|
||||
raise AssertionError(
|
||||
f"blocked multistep transition face should not leak editable scan entries: {leaked_entries}"
|
||||
)
|
||||
|
||||
|
||||
def assert_prismatic_feature_display_labels() -> None:
|
||||
state = object.__new__(WindowStateMixin)
|
||||
if state._feature_display_label("矩形口袋候选") != "矩形槽/口袋":
|
||||
@@ -432,6 +488,7 @@ def main() -> int:
|
||||
multistep_path = temp_path / "rectangular-multistep-boss.step"
|
||||
write_rectangular_multistep_boss_model(multistep_path)
|
||||
multistep_model = StepModel.load(multistep_path)
|
||||
assert_multistep_transition_guard(multistep_model)
|
||||
multistep_face_id, multistep_info = find_prismatic_semantics(multistep_model, "additive-boss")
|
||||
assert_prismatic_sizes(multistep_info, 6.0, 4.0, 2.0)
|
||||
assert_rectangular_feature_ui(
|
||||
|
||||
Reference in New Issue
Block a user