"""End miter / bevel angled cuts.""" import json import pytest from woodshop.scene import Scene def test_add_miter_defaults_to_45_on_end(): s = Scene() s.place("2x4", 24) f = s.add_feature("p1", "miter") # no angle given assert f.kind == "miter" and f.face == "end_b" and f.miter_deg == 45.0 def test_miter_forced_to_end_face(): s = Scene() s.place("2x4", 24) f = s.add_feature("p1", "miter", face="top", miter_deg=30) # top is invalid for miter assert f.face == "end_b" and f.miter_deg == 30 def test_miter_roundtrips_through_json(): s = Scene() s.place("2x4", 24) s.add_feature("p1", "miter", miter_deg=45, bevel_deg=15) s2 = Scene.from_dict(json.loads(json.dumps(s.to_dict()))) f = s2.get_part("p1").features[0] assert f.kind == "miter" and f.miter_deg == 45 and f.bevel_deg == 15 def test_cutlist_notes_the_miter(): from woodshop.cutplan import build_cut_plan s = Scene() s.place("2x4", 24) s.add_feature("p1", "miter", miter_deg=45) note = build_cut_plan(s).items[0].note assert "miter 45" in note def test_instructions_describe_miter(): from woodshop.instructions import build_steps, format_steps s = Scene() s.place("2x4", 24) s.add_feature("p1", "miter", miter_deg=45, bevel_deg=10) text = format_steps(build_steps(s)) assert "miter 45" in text and "bevel 10" in text def test_jigs_suggest_miter_sled_for_repeats(): from woodshop.jigs import suggest_jigs s = Scene() for _ in range(4): s.place("2x4", 24) for pid in ("p1", "p2", "p3", "p4"): s.add_feature(pid, "miter", miter_deg=45) kinds = [j.kind for j in suggest_jigs(s)] assert "miter-sled" in kinds def test_miter_geometry_removes_material(): pytest.importorskip("build123d") from woodshop.geometry import part_solid s = Scene() s.place("2x4", 24) square_vol = part_solid(s.get_part("p1")).volume s.add_feature("p1", "miter", miter_deg=45) mitered_vol = part_solid(s.get_part("p1")).volume assert mitered_vol < square_vol # a wedge was cut off def test_miter_preview_is_a_wedge_not_a_box(): pytest.importorskip("pyvista") pytest.importorskip("build123d") from woodshop.viewer import feature_preview_mesh s = Scene() s.place("2x4", 24) feat = s.add_feature("p1", "miter", miter_deg=45) mesh = feature_preview_mesh(s.get_part("p1"), feat) assert mesh is not None and mesh.n_points > 0 # the wedge sits at the mitered end (x≈24), not a 1" box at the end centre xmax = mesh.bounds[1] assert xmax > 20 # spans out to the board end, like the real cut