feat: 完善 Face 参数化编辑和隔离执行
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
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())
|
||||
Reference in New Issue
Block a user