From b13155cbbf44784835ed6fa9b3c4db2334dcaedb Mon Sep 17 00:00:00 2001 From: Brennen Herbruck Date: Wed, 21 Oct 2026 05:54:30 -0400 Subject: [PATCH] kernel-cases: sheet-metal cut-out, flange and refusal cases from #296, #1095, #1280, #1295, #1311, #1979, #3078, #3234, #3324, #3353 Cut-outs folded and refolded, a hole square to a 45 degree flange, a slot that parts a flange from its base, an inside flange on a plate turned 62 degrees, cuts after cuts, a hole beside two adjacent flanges and a flange on a flange's side edge; refusals for a flange on a bend line and a flat pattern after a fillet; a mirrored sheet body that must stay sheet metal. Volumes by hand (K = 0.5 folds: flat area * t; otherwise bend volumes). Co-Authored-By: Claude Sonnet 5.5 --- .../expected.json | 10 + .../recipe.json | 112 +++++++ .../expected.json | 10 + .../recipe.json | 74 ++++ .../expected.json | 12 + .../recipe.json | 102 ++++++ .../expected.json | 10 + .../recipe.json | 77 +++++ .../expected.json | 11 + .../recipe.json | 316 ++++++++++++++++++ .../expected.json | 10 + .../recipe.json | 107 ++++++ .../expected.json | 22 ++ .../recipe.json | 86 +++++ .../expected.json | 10 + .../recipe.json | 73 ++++ .../expected.json | 11 + .../recipe.json | 62 ++++ .../expected.json | 11 + .../recipe.json | 122 +++++++ 20 files changed, 1248 insertions(+) create mode 100644 tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/expected.json create mode 100644 tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/expected.json create mode 100644 tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/expected.json create mode 100644 tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/expected.json create mode 100644 tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/expected.json create mode 100644 tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/expected.json create mode 100644 tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/expected.json create mode 100644 tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/expected.json create mode 100644 tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/expected.json create mode 100644 tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/recipe.json create mode 100644 tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/expected.json create mode 100644 tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/recipe.json diff --git a/tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/expected.json b/tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/expected.json new file mode 100644 index 0000000000..82ac43b538 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/expected.json @@ -0,0 +1,10 @@ +{ + "sources": [ + "tangency-labs/solidcraft#1095" + ], + "what": "a flange unfolded, a triangular cut-out with a corner on the sheet's own edge at the middle of the bend zone, refolded: sew failed (this wire is not simple)", + "source": "analytic", + "method": "T = 2, R = 2, K = 0.5. Flat area: base 100 x (60 - 4) + bend 100*BA with BA = (pi/2)(2 + 1) + flange straight 100*(20 - 4) = 7671.2389; the triangle (0, yc), (3, yc-1), (3, yc+1) has area 3 and lies inside it. K = 0.5, so the folded volume is the flat area times t: V = 2*(7671.2389 - 3)", + "body_count": 1, + "volume_mm3": 15336.477796076937 +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/recipe.json b/tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/recipe.json new file mode 100644 index 0000000000..03abe6cd25 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1095-refold-a-cutout-with-a-corner-on-the-sheets-edge-at-a-bend/recipe.json @@ -0,0 +1,112 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "Rule", + "thickness": "2 mm", + "active": true, + "bend_radius": "2 mm", + "k_factor": 0.5 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Plate" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 100, + 60 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Plate" + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 50, + 60, + 2 + ] + ], + "height": 20, + "angle": 90 + } + }, + { + "command": "sheet.unfold", + "params": {} + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Cutout" + } + }, + { + "command": "sketch.line", + "params": { + "points": [ + [ + 0, + 58.356194 + ], + [ + 3, + 57.356194 + ], + [ + 3, + 59.356194 + ] + ], + "closed": true + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Cutout", + "through_all": true, + "direction": "symmetric", + "operation": "cut" + } + }, + { + "command": "sheet.refold", + "params": {} + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/expected.json b/tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/expected.json new file mode 100644 index 0000000000..e51e15a271 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/expected.json @@ -0,0 +1,10 @@ +{ + "sources": [ + "tangency-labs/solidcraft#1280" + ], + "what": "a 5 mm hole drilled square to the face of a 45 degree flange: the drill cap's certificate refused it by 1e-11 mm", + "source": "analytic", + "method": "T = 2.5, R = 2.5, K = 0.44, 100 x 60 base and a 15 mm flange at 45 degrees, setback s = 5*tan(22.5 deg) = 2.0711: V45 = 100*(60 - s)*2.5 + 100*(15 - s)*2.5 + (pi/4)(25 - 6.25)*100/2 = 18450.78; the hole removes pi*2.5^2*2.5 = 49.087 of the flange: V = V45 - 15.625*pi", + "body_count": 1, + "volume_mm3": 18401.68948704003 +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/recipe.json b/tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/recipe.json new file mode 100644 index 0000000000..8d49006dc5 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1280-hole-square-to-a-45-degree-flange/recipe.json @@ -0,0 +1,74 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "Steel (mm)", + "thickness": "2.5 mm", + "active": true, + "bend_radius": "2.5 mm", + "k_factor": 0.44 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 100, + 60 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "sheet.flange", + "params": { + "edges": [ + [ + 50, + 0, + 2.5 + ] + ], + "height": 15, + "angle": 45 + } + }, + { + "command": "solid.hole", + "params": { + "position": [ + 50, + -5.656854, + 5.656854 + ], + "diameter": 5 + } + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/expected.json b/tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/expected.json new file mode 100644 index 0000000000..e769d242ff --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/expected.json @@ -0,0 +1,12 @@ +{ + "sources": [ + "tangency-labs/solidcraft#1295", + "tangency-labs/solidcraft#1338" + ], + "what": "a 100 x 60 sheet with a 45 degree 40 mm flange and a slot cut across the flange just past its bend: the rest of the flange keeps no material joining it to the base", + "source": "analytic", + "method": "T = 2.5, R = 2.5, setback s = (R+T)tan(22.5 deg) = 2.0711: base 100*(60 - s)*2.5, leg 100*(40 - s)*2.5, bend (pi/4)((R+T)^2 - R^2)*100/2; V0 = 24700.7. The slot (110 x 1.5 drawn, 100 x 1.5 over the sheet) lies in the flat flange panel past the bend zone and removes 100*1.5*2.5 = 375. A cut keeps every piece of material it leaves, so the rest of the flange stays in the body as a shell of its own: V = V0 - 375 (valid is false because the body then has two shells)", + "body_count": 1, + "volume_mm3": 24325.77687225237, + "valid": false +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/recipe.json b/tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/recipe.json new file mode 100644 index 0000000000..13deb32a48 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1295-a-slot-across-a-flange-leaves-the-rest-of-it-as-a-loose-piece/recipe.json @@ -0,0 +1,102 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "Steel (mm)", + "thickness": "2.5 mm", + "active": true, + "bend_radius": "2.5 mm", + "k_factor": 0.44 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 100, + 60 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "sheet.flange", + "params": { + "edges": [ + [ + 50, + 0, + 2.5 + ] + ], + "height": 40, + "angle": 45 + } + }, + { + "command": "sketch.create", + "params": { + "plane": { + "face": [ + 50, + -11.4645, + 15 + ] + }, + "name": "Slot" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + -5, + -3 + ], + "p1": [ + 105, + -1.5 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Slot", + "through_all": true, + "direction": "negative", + "operation": "cut" + } + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/expected.json b/tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/expected.json new file mode 100644 index 0000000000..f089986aef --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/expected.json @@ -0,0 +1,10 @@ +{ + "sources": [ + "tangency-labs/solidcraft#1311" + ], + "what": "a 100 x 60 plate turned 62 degrees about the origin with a 90 degree inside flange on one edge: the trimmed corner falls on the sew grid and the flange failed to close", + "source": "analytic", + "method": "T = 2, R = 1, K = 0.5, setback R + T = 3. Plate 100 x 57 x 2 after the setback = 11400; the bend is a quarter annulus of radii 1 and 3 over 100 mm = (pi/4)(9 - 1)*100*... = (pi/2)(9-1)*100/2 = 628.319; the leg 20 - 3 = 17 long: 17*2*100 = 3400. V = 11400 + 628.319 + 3400", + "body_count": 1, + "volume_mm3": 15428.31853071796 +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/recipe.json b/tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/recipe.json new file mode 100644 index 0000000000..2423693666 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1311-inside-flange-on-a-plate-turned-62-degrees/recipe.json @@ -0,0 +1,77 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "Steel 2", + "thickness": "2 mm", + "active": true, + "bend_radius": "1 mm", + "k_factor": 0.5 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Plate" + } + }, + { + "command": "sketch.line", + "params": { + "points": [ + [ + 0.0, + 0.0 + ], + [ + 46.947156279, + 88.294759286 + ], + [ + -6.029699293, + 116.463053053 + ], + [ + -52.976855572, + 28.168293767 + ] + ], + "closed": true + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Plate" + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 23.473578139, + 44.147379643, + 2 + ] + ], + "height": 20, + "angle": 90, + "radius": 1, + "position": "inside" + } + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/expected.json b/tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/expected.json new file mode 100644 index 0000000000..f1b8c959e0 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/expected.json @@ -0,0 +1,11 @@ +{ + "sources": [ + "tangency-labs/solidcraft#1979", + "tangency-labs/solidcraft#1980" + ], + "what": "on a folded sheet a rectangular cut-out and then twenty 4 mm holes in one sketch: a cut after a cut was dropped without a word, and many holes ran out of budget", + "source": "analytic", + "method": "T = 2, R = 2: base 60 x 36 + flange straight 16, 60 wide, bend (pi/2)(16-4)*60/2 = 565.487: V0 = 60*2*(36 + 16) + 565.487. Cuts through the flat base, clear of each other and of the bend: a 7 x 6 rectangle (42 mm2) and twenty holes of radius 2 (20*pi*4 mm2), each removing area*2. V = V0 - 2*(42 + 80*pi)", + "body_count": 1, + "volume_mm3": 6218.831853071796 +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/recipe.json b/tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/recipe.json new file mode 100644 index 0000000000..c595d5f38f --- /dev/null +++ b/tests/kernel-cases/sheet-metal/1979-every-cut-after-a-cut-machines-the-sheet/recipe.json @@ -0,0 +1,316 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "S", + "thickness": "2 mm", + "active": true, + "bend_radius": "2 mm", + "k_factor": 0.4 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 60, + 40 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 30, + 0, + 2 + ] + ], + "height": 20 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Slot" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 50, + 14 + ], + "p1": [ + 57, + 20 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Slot", + "through_all": true, + "direction": "symmetric", + "operation": "cut" + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Holes" + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 8, + 10 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 8, + 18 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 8, + 26 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 8, + 34 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 17, + 10 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 17, + 18 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 17, + 26 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 17, + 34 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 26, + 10 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 26, + 18 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 26, + 26 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 26, + 34 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 35, + 10 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 35, + 18 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 35, + 26 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 35, + 34 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 44, + 10 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 44, + 18 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 44, + 26 + ], + "radius": 2 + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 44, + 34 + ], + "radius": 2 + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Holes", + "through_all": true, + "direction": "symmetric", + "operation": "cut" + } + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/expected.json b/tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/expected.json new file mode 100644 index 0000000000..7b3b863b02 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/expected.json @@ -0,0 +1,10 @@ +{ + "sources": [ + "tangency-labs/solidcraft#296", + "tangency-labs/solidcraft#355" + ], + "what": "an 80 x 40 base with a 30 mm flange on the y = 0 edge and a 15 mm flange on the x = 80 edge, and a round hole through the base beside them: sew failed with a non-manifold edge contact", + "source": "invariants", + "method": "the hole is cut straight through the flat base, clear of both bends and of the corner, so it must give one valid closed body; the corner geometry of two adjacent flanges has no simple closed form, so no volume is graded", + "body_count": 1 +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/recipe.json b/tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/recipe.json new file mode 100644 index 0000000000..9b090f2948 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/296-hole-in-a-base-with-two-adjacent-edge-flanges/recipe.json @@ -0,0 +1,107 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "S", + "thickness": "2 mm", + "active": true, + "bend_radius": "2 mm", + "k_factor": 0.4 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 80, + 40 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 40, + 0, + 2 + ] + ], + "height": 30 + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 80, + 20, + 2 + ] + ], + "height": 15 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Hole" + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 25, + 20 + ], + "radius": 3 + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Hole", + "through_all": true, + "direction": "symmetric", + "operation": "cut" + } + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/expected.json b/tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/expected.json new file mode 100644 index 0000000000..95405011a9 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/expected.json @@ -0,0 +1,22 @@ +{ + "sources": [ + "tangency-labs/solidcraft#3078", + "tangency-labs/solidcraft#3274" + ], + "what": "an edge flange on the side edge of an existing wall, meeting a flange on the base across the existing bend with a round corner relief (not supported yet: a flange on the side of another flange)", + "source": "invariants", + "method": "one valid closed body: a 120 x 90 base with a 30 mm wall on its y = 0 edge and a 20 mm flange on its x = 120 edge, plus a flange on the wall's side edge (x = 120) that mitres with it. The outer faces stand on the base's outline and the tallest wall is 30 high, so the bounding box is 120 x 90 x 30 (x 0..120, y 0..90, z 0..30)", + "body_count": 1, + "bbox": { + "min": [ + 0, + 0, + 0 + ], + "max": [ + 120, + 90, + 30 + ] + } +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/recipe.json b/tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/recipe.json new file mode 100644 index 0000000000..cd70e1fe28 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3078-flange-on-the-side-edge-of-a-flange/recipe.json @@ -0,0 +1,86 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "Sheet 2 mm", + "thickness": "2 mm", + "active": true, + "bend_radius": "1 mm", + "k_factor": 0.5, + "gap": "0.5 mm" + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 120, + 90 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "sheet.flange", + "params": { + "edges": [ + [ + 60, + 0, + 2 + ] + ], + "height": "30 mm", + "angle": "90 deg" + } + }, + { + "command": "sheet.flange", + "params": { + "edges": [ + [ + 120, + 45, + 2 + ], + [ + 120, + 2, + 16.5 + ] + ], + "height": "20 mm", + "angle": "90 deg", + "position": "inside", + "corner_relief_shape": "round", + "corner_relief": "4 mm" + } + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/expected.json b/tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/expected.json new file mode 100644 index 0000000000..1082837964 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/expected.json @@ -0,0 +1,10 @@ +{ + "sources": [ + "tangency-labs/solidcraft#3234", + "tangency-labs/solidcraft#3273" + ], + "what": "a second edge flange picked on the bend line of an existing flange made a doubled flange with a gap and two shells in one body", + "source": "invariants", + "method": "the base's edge at y = 5 (the setback R + T = 5 from the first flange) is the bend line of the existing flange, not a free edge; a flange there would stand on material the first bend already occupies. The right behaviour is a clean refusal that leaves the sheet unchanged", + "outcome": "refused" +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/recipe.json b/tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/recipe.json new file mode 100644 index 0000000000..6388f997b6 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3234-edge-flange-on-the-bend-line-refused/recipe.json @@ -0,0 +1,73 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "Steel", + "thickness": "2.5 mm", + "active": true, + "bend_radius": "2.5 mm", + "k_factor": 0.44 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 100, + 60 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 50, + 0, + 2.5 + ] + ], + "height": 20 + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 50, + 5, + 2.5 + ] + ], + "height": 10 + } + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/expected.json b/tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/expected.json new file mode 100644 index 0000000000..543c0b763f --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/expected.json @@ -0,0 +1,11 @@ +{ + "sources": [ + "tangency-labs/solidcraft#3324", + "tangency-labs/solidcraft#3325", + "tangency-labs/solidcraft#3418" + ], + "what": "a fillet on a sheet metal corner changes the body but not its sheet model, so the flat pattern would be a sharp rectangle: it must refuse", + "source": "invariants", + "method": "after Fillet R10 on a corner of a 100 x 60 sheet the body has a round, and a flat pattern written from the sheet model would be the sharp 100 x 60 rectangle, a different part from the design; the right behaviour is a clean refusal naming the feature", + "outcome": "refused" +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/recipe.json b/tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/recipe.json new file mode 100644 index 0000000000..c5841ade0f --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3324-flat-pattern-refused-after-a-fillet-on-the-sheet/recipe.json @@ -0,0 +1,62 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "S", + "thickness": "2 mm", + "active": true, + "bend_radius": "2 mm", + "k_factor": 0.4 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 100, + 60 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "solid.fillet", + "params": { + "edges": [ + [ + 100, + 60, + 1 + ] + ], + "radius": 10 + } + }, + { + "command": "sheet.flat_pattern", + "params": {} + } + ] +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/expected.json b/tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/expected.json new file mode 100644 index 0000000000..4e15519436 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/expected.json @@ -0,0 +1,11 @@ +{ + "sources": [ + "tangency-labs/solidcraft#3353", + "tangency-labs/solidcraft#3354" + ], + "what": "a sheet metal body mirrored into a new body must still be sheet metal (flat pattern, bend table): it was a plain solid", + "source": "analytic", + "method": "T = 2, R = 2, K = 0.4, setback 4. One body: base 100 x 52, flanges 20 and 15 high (straights 16 and 11), all 100 wide, 2 thick, two bends of (pi/2)(16 - 4)*100/2 = 942.478 each, a 10 mm hole through the base (pi*25*2). V1 = 2*100*(52 + 16 + 11) + 2*942.478 - 50*pi. The mirror copy is congruent: two bodies, total 2*V1. The flat pattern of the copy must exist", + "body_count": 2, + "volume_mm3": 35055.75191894878 +} \ No newline at end of file diff --git a/tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/recipe.json b/tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/recipe.json new file mode 100644 index 0000000000..e0b587e2e1 --- /dev/null +++ b/tests/kernel-cases/sheet-metal/3353-mirrored-sheet-body-keeps-its-flat-pattern/recipe.json @@ -0,0 +1,122 @@ +{ + "commands": [ + { + "command": "sheet.manage_rules", + "params": { + "name": "S", + "thickness": "2 mm", + "active": true, + "bend_radius": "2 mm", + "k_factor": 0.4 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Base" + } + }, + { + "command": "sketch.rectangle.two_point", + "params": { + "p0": [ + 0, + 0 + ], + "p1": [ + 100, + 60 + ] + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "sheet.flange", + "params": { + "type": "base", + "sketch": "Base" + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 50, + 0, + 2 + ] + ], + "height": 20 + } + }, + { + "command": "sheet.flange", + "params": { + "type": "edge", + "edges": [ + [ + 50, + 60, + 2 + ] + ], + "height": 15 + } + }, + { + "command": "sketch.create", + "params": { + "plane": "XY", + "name": "Hole" + } + }, + { + "command": "sketch.circle.center", + "params": { + "center": [ + 50, + 30 + ], + "radius": 5 + } + }, + { + "command": "sketch.finish", + "params": {} + }, + { + "command": "solid.extrude", + "params": { + "sketch": "Hole", + "through_all": true, + "direction": "symmetric", + "operation": "cut" + } + }, + { + "command": "solid.mirror", + "params": { + "bodies": [ + "Body1" + ], + "plane": "YZ" + } + }, + { + "command": "sheet.flat_pattern", + "params": { + "body": "Body1 (2)" + } + }, + { + "command": "inspect.measure", + "params": {} + } + ] +} \ No newline at end of file