Files
pythonocc-step-editor/scripts/verify_edge_target_guards.py
T

119 lines
5.5 KiB
Python
Raw Normal View History

from __future__ import annotations
from pathlib import Path
import sys
import tempfile
PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
SCRIPTS_ROOT = PROJECT_ROOT / "scripts"
if str(SCRIPTS_ROOT) not in sys.path:
sys.path.insert(0, str(SCRIPTS_ROOT))
from step_editor.model import StepModel
from verify_edge_coordinate_edit import _tuple3
from verify_edge_length_resize import _line_edge_ids_near_length
from verify_ellipse_edge_resize import _ellipse_edge_ids, _write_ellipse_face_model
from verify_hole_resize import _write_through_hole_model
DEFAULT_CUBE = PROJECT_ROOT / "assets" / "models" / "cube_10mm.step"
def _assert_blocked(plan: dict[str, object], label: str) -> None:
if str(plan.get("status") or "") != "blocked" or str(plan.get("risk") or "") != "blocked":
raise AssertionError(f"{label} should be blocked, got status={plan.get('status')}, plan={plan}")
message = str(plan.get("message") or plan.get("blockers") or "")
if not message.strip():
raise AssertionError(f"{label} should explain why it is blocked: {plan}")
def _cube_edge(model: StepModel) -> int:
edge_ids = _line_edge_ids_near_length(model, 10.0, 1e-5)
if not edge_ids:
raise AssertionError("cube has no 10mm line Edge")
return edge_ids[0]
def _verify_straight_edge_guards() -> None:
model = StepModel.load(DEFAULT_CUBE)
edge_id = _cube_edge(model)
info = model.edge_info(edge_id)
current_length = float(info.get("length") or 0.0)
start = _tuple3(info.get("start_point"), "edge start")
end = _tuple3(info.get("end_point"), "edge end")
center = _tuple3(info.get("length_center"), "edge center")
_assert_blocked(model.general_edge_length_plan(edge_id, current_length), "same Edge length")
_assert_blocked(model.general_edge_length_plan(edge_id, 0.0), "zero Edge length")
_assert_blocked(model.general_edge_length_plan(edge_id, -1.0), "negative Edge length")
_assert_blocked(model.edge_endpoint_move_plan(edge_id, "start", start), "same start point")
_assert_blocked(model.edge_endpoint_move_plan(edge_id, "end", end), "same end point")
_assert_blocked(model.edge_endpoint_move_plan(edge_id, "start", end), "collapsed endpoint")
_assert_blocked(model.edge_center_move_plan(edge_id, center), "same Edge center")
_assert_blocked(model.edge_fillet_plan(edge_id, 0.0), "zero Edge fillet radius")
_assert_blocked(model.edge_fillet_plan(edge_id, current_length * 0.45), "oversized Edge fillet radius")
_assert_blocked(model.edge_chamfer_plan(edge_id, 0.0), "zero Edge chamfer distance")
_assert_blocked(model.edge_chamfer_plan(edge_id, current_length * 0.45), "oversized Edge chamfer distance")
_assert_blocked(model.edge_asymmetric_chamfer_plan(edge_id, 0.0, 0.5), "zero asymmetric chamfer distance")
_assert_blocked(
model.edge_asymmetric_chamfer_plan(edge_id, current_length * 0.45, 0.5),
"oversized asymmetric chamfer distance",
)
_assert_blocked(model.edge_distance_angle_chamfer_plan(edge_id, 0.0, 45.0), "zero distance-angle chamfer")
_assert_blocked(model.edge_distance_angle_chamfer_plan(edge_id, 0.5, 0.0), "zero distance-angle angle")
_assert_blocked(model.edge_distance_angle_chamfer_plan(edge_id, 0.5, 90.0), "too large distance-angle angle")
print("straight Edge target guards ok")
def _verify_ellipse_guards() -> None:
with tempfile.TemporaryDirectory(prefix="geom_param_edge_guard_ellipse_") as temp_dir:
model_path = Path(temp_dir) / "ellipse.step"
_write_ellipse_face_model(model_path)
model = StepModel.load(model_path)
edge_ids = _ellipse_edge_ids(model)
if not edge_ids:
raise AssertionError("ellipse model has no ellipse Edge")
edge_id = edge_ids[0]
info = model.edge_info(edge_id)
major = float(info.get("major_radius") or 0.0)
minor = float(info.get("minor_radius") or 0.0)
_assert_blocked(model.ellipse_edge_axis_radius_plan(edge_id, major, axis_kind="major"), "same ellipse major radius")
_assert_blocked(model.ellipse_edge_axis_radius_plan(edge_id, minor, axis_kind="minor"), "same ellipse minor radius")
_assert_blocked(model.ellipse_edge_axis_radius_plan(edge_id, 0.0, axis_kind="major"), "zero ellipse major radius")
_assert_blocked(model.ellipse_edge_axis_radius_plan(edge_id, -1.0, axis_kind="minor"), "negative ellipse minor radius")
print("ellipse Edge target guards ok")
def _verify_circular_axis_guard() -> None:
with tempfile.TemporaryDirectory(prefix="geom_param_edge_guard_circle_") as temp_dir:
model_path = Path(temp_dir) / "hole.step"
_write_through_hole_model(model_path)
model = StepModel.load(model_path)
for edge_id in range(len(model.edges)):
info = model.edge_info(edge_id)
if info.get("curve") != "circle":
continue
center = info.get("center")
if center is None:
continue
_assert_blocked(model.circular_edge_axis_move_plan(edge_id, center), "same circular Edge center")
print("circular Edge axis target guard ok")
return
raise AssertionError("hole model has no circular Edge with center")
def main() -> int:
_verify_straight_edge_guards()
_verify_ellipse_guards()
_verify_circular_axis_guard()
print("Edge target guard suite passed.")
return 0
if __name__ == "__main__":
raise SystemExit(main())