from __future__ import annotations from pathlib import Path import sys import tempfile from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox PROJECT_ROOT = Path(__file__).resolve().parent.parent if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from step_editor.model import StepModel from step_editor.step_io import _write_step DEFAULT_MODEL = PROJECT_ROOT / "assets" / "models" / "cube_10mm.step" def _first_plane_face(model: StepModel) -> int: for face_id in range(len(model.faces)): info = model.face_info(face_id) if info.get("surface") == "plane": return face_id raise SystemExit("no plane Face found") def _first_shell_face(model: StepModel, thickness: float, tolerance: float) -> int: candidates: list[tuple[int, int]] = [] for face_id in range(len(model.faces)): info = model.feature_info(face_id) if info.get("surface") != "plane": continue if info.get("shell_region_status") != "candidate": continue current = float(info.get("shell_thickness_estimate") or 0.0) if abs(current - thickness) > tolerance: continue confidence_rank = {"high": 0, "medium": 1, "low": 2}.get(str(info.get("shell_confidence")), 3) candidates.append((confidence_rank, face_id)) if not candidates: raise SystemExit(f"no shell thickness candidate near {thickness:g}") candidates.sort() return candidates[0][1] def _assert_positive_target_blocked(label: str, plan: dict[str, object]) -> None: status = str(plan.get("status", "")) message = str(plan.get("message") or plan.get("blockers") or "") if status != "blocked": raise SystemExit(f"{label} invalid target was not blocked: status={status}, message={message}") if "大于 0" not in message and "大于0" not in message: raise SystemExit(f"{label} invalid target should explain the positive range: {message}") def _assert_blocked(label: str, plan: dict[str, object]) -> None: status = str(plan.get("status", "")) message = str(plan.get("message") or plan.get("blockers") or "") if status != "blocked": raise SystemExit(f"{label} invalid target was not blocked: status={status}, message={message}") def _run_cube_invalid_targets() -> None: model = StepModel.load(DEFAULT_MODEL) face_id = _first_plane_face(model) for target in (0.0, -1.0): _assert_positive_target_blocked( f"Face area current face target={target:g}", model.face_area_local_resize_plan(face_id, target), ) _assert_positive_target_blocked( f"Face area owning feature target={target:g}", model.face_area_scale_plan(face_id, target), ) for axis in ("width", "height"): _assert_positive_target_blocked( f"Face {axis} current face target={target:g}", model.face_size_local_resize_plan(face_id, target, axis), ) _assert_positive_target_blocked( f"Face {axis} owning feature target={target:g}", model.face_size_owning_scale_plan(face_id, target, axis), ) _assert_blocked("Face area current face non-numeric target", model.face_area_local_resize_plan(face_id, "abc")) _assert_blocked("Face area owning feature non-numeric target", model.face_area_scale_plan(face_id, "abc")) for axis in ("width", "height"): _assert_blocked( f"Face {axis} current face non-numeric target", model.face_size_local_resize_plan(face_id, "abc", axis), ) _assert_blocked( f"Face {axis} owning feature non-numeric target", model.face_size_owning_scale_plan(face_id, "abc", axis), ) def _run_shell_invalid_targets() -> None: with tempfile.TemporaryDirectory(prefix="geom_param_face_invalid_shell_") as temp_dir: model_path = Path(temp_dir) / "plate.step" _write_step(BRepPrimAPI_MakeBox(30.0, 20.0, 2.0).Shape(), model_path) model = StepModel.load(model_path) face_id = _first_shell_face(model, 2.0, 2e-4) for target in (0.0, -1.0): _assert_positive_target_blocked( f"thin wall current face target={target:g}", model.shell_thickness_plan(face_id, target), ) _assert_positive_target_blocked( f"thin wall owning feature target={target:g}", model.shell_thickness_owning_scale_plan(face_id, target), ) _assert_blocked("thin wall current face non-numeric target", model.shell_thickness_plan(face_id, "abc")) _assert_blocked( "thin wall owning feature non-numeric target", model.shell_thickness_owning_scale_plan(face_id, "abc"), ) def main() -> int: _run_cube_invalid_targets() _run_shell_invalid_targets() print("Face invalid target guards ok") return 0 if __name__ == "__main__": raise SystemExit(main())