67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
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
|
|
|
|
|
|
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 _assert_plan(label: str, plan: dict[str, object], status: str, risk: str | None = None) -> None:
|
|
actual_status = str(plan.get("status", ""))
|
|
actual_risk = str(plan.get("risk", ""))
|
|
if actual_status != status:
|
|
raise SystemExit(f"{label} expected status={status}, got {actual_status}: {plan}")
|
|
if risk is not None and actual_risk != risk:
|
|
raise SystemExit(f"{label} expected risk={risk}, got {actual_risk}: {plan}")
|
|
|
|
|
|
def main() -> int:
|
|
model = StepModel.load(DEFAULT_MODEL)
|
|
face_id = _first_plane_face(model)
|
|
|
|
shallow = model.push_pull_plan(face_id, -1.0)
|
|
_assert_plan("shallow inward cut", shallow, "ready", "low")
|
|
if abs(float(shallow.get("push_pull_inward_material_depth") or 0.0) - 10.0) > 1e-5:
|
|
raise SystemExit(f"shallow cut should report 10mm inward material depth: {shallow}")
|
|
if abs(float(shallow.get("push_pull_inward_cut_ratio") or 0.0) - 0.1) > 1e-5:
|
|
raise SystemExit(f"shallow cut should report 0.1 inward cut ratio: {shallow}")
|
|
|
|
near_through = model.push_pull_plan(face_id, -9.0)
|
|
_assert_plan("near-through inward cut", near_through, "caution", "high")
|
|
if float(near_through.get("push_pull_inward_cut_ratio") or 0.0) < 0.85:
|
|
raise SystemExit(f"near-through cut should report a high inward cut ratio: {near_through}")
|
|
|
|
through = model.push_pull_plan(face_id, -10.0)
|
|
_assert_plan("through inward cut", through, "blocked", "blocked")
|
|
message = str(through.get("message") or through.get("blockers") or "")
|
|
if "材料厚度" not in message and "切空" not in message:
|
|
raise SystemExit(f"through cut blocker should explain material depth: {through}")
|
|
try:
|
|
model.push_pull_face(face_id, -10.0)
|
|
except ValueError:
|
|
pass
|
|
else:
|
|
raise SystemExit("push_pull_face should reject an inward cut that reaches full material depth")
|
|
|
|
print("Face push/pull limit guards ok")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|