Shell rig: the drain floors, the rounded opening and the arc-sided plate as cases

The shell unit tests that checked geometry become shell rig cases built through
commands: the trough and the pocket whose floors fall 1 deg to a central drain
(the pyramid made as two triangular prisms intersected, in place of
convex_polyhedron; the cavity integrated exactly over the cells where each moved
facet is highest, sharp inner corners as the ladder's tier 09), the box opened at
a bottom rounded R2 and R2.4 (refused: the rim would have no thickness) and R1.5
(built, exact volume), and the plate with a hole through its arc side. Four
action-matrix shells that regressed (issue-616's lid, the ring-cut frame, the
filleted shelled box shelled again, the up-down join) get small cases too. The
ones that fail today are on KNOWN_FAILING with their cause, and the unit tests are
removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-30 06:56:46 -04:00
committed by Irakli Kourtis
parent ebd1b15098
commit 06f7fa501a
23 changed files with 1214 additions and 133 deletions
-15
View File
@@ -39,21 +39,6 @@ fn shell_with_a_shallow_arc_side() {
]));
}
/// Shell of a plate with a hole whose wall meets the plate's arc side: the edge where the two
/// cylinders meet is neither a line nor an arc, and is rebuilt through its moved points.
#[test]
fn shell_with_a_hole_through_a_curved_side() {
script(json!([
{"command": "sketch.create", "params": {"plane": "XY"}},
{"command": "sketch.line", "params": {"points": [[0, 0], [42.5, 0], [42.5, 20.0], [0, 20.0]]}},
{"command": "sketch.arc.three_point", "params": {"end": [0, 0], "start": [0, 20.0], "through": [-10.0, 10.0]}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.extrude", "params": {"distance": 27.5}},
{"command": "solid.cylinder", "params": {"axis": [1.0, 0.0, 0.0], "base": [-10.000000000000002, 12.5, 12.5], "height": 17.5, "operation": "cut", "radius": 5.0}},
{"command": "solid.shell", "params": {"faces": [[42.5, 10.0, 13.75]], "thickness": 2.0}}
]));
}
/// A cut whose end only touches the plate's arc side (#897, robustness seed 14): the end lies
/// tangent to the arc at its apex, the direct boolean fails, and the last-resort nudge used to
/// push the end into the arc, leaving a sliver of it a tenth of a millimetre wide that a shell
-118
View File
@@ -2407,124 +2407,6 @@ fn orientation_mesh_reuses_missing_face_check_at_matching_tolerance() {
}
}
/// A trough whose floor falls about 1° toward a central drain, the fall starting right at the
/// trough edges: four faces meet at each bottom corner (two walls, two fall facets) and at the
/// drain (four facets). A tab on one end makes the body non-convex. The moved planes of four
/// faces don't meet at one point, so each such corner of the cavity becomes two corners joined
/// by a short edge. Checked against the volume integrated by hand.
#[test]
fn shell_where_four_faces_meet_at_a_corner() {
let (w, l, ht, t) = (100.0, 60.0, 40.0, 2.0);
// Drain depth: the long facets fall 1°.
let h = 30.0 * 1f64.to_radians().tan();
let facet = |n: Vec3, p: Vec3| {
let n = n.normalized().unwrap();
HalfSpace { n, d: n.dot(p) }
};
let facets = [
facet(Vec3::new(0.0, -h, -30.0), Vec3::ZERO),
facet(Vec3::new(0.0, h, -30.0), Vec3::new(0.0, l, 0.0)),
facet(Vec3::new(-h, 0.0, -50.0), Vec3::ZERO),
facet(Vec3::new(h, 0.0, -50.0), Vec3::new(w, 0.0, 0.0)),
];
let mut hs = vec![
HalfSpace { n: -Vec3::X, d: 0.0 },
HalfSpace { n: Vec3::X, d: w },
HalfSpace { n: -Vec3::Y, d: 0.0 },
HalfSpace { n: Vec3::Y, d: l },
HalfSpace { n: Vec3::Z, d: ht },
];
hs.extend(facets);
let trough = convex_polyhedron(&hs).unwrap();
let pyramid = w * l * h / 3.0;
assert!(rel(measure(&trough).unwrap().volume, w * l * ht + pyramid) < 1e-9);
let tab = box_solid(Vec3::new(w, 20.0, 20.0), Vec3::new(w + 20.0, 40.0, ht)).unwrap();
let body = boolean(&trough, &tab, BoolOp::Union).unwrap().unwrap();
let s = shell(&body, &[Vec3::new(50.0, 30.0, ht)], t).unwrap();
// The cavity: the walls in by t, above the floor facets moved in by t (midpoint rule; the
// floor is linear between its creases).
let floor = |x: f64, y: f64| facets.iter().map(|f| (f.d - t - f.n.x * x - f.n.y * y) / f.n.z).fold(f64::NEG_INFINITY, f64::max);
let (nx, ny) = (960, 560);
let (dx, dy) = ((w - 2.0 * t) / nx as f64, (l - 2.0 * t) / ny as f64);
let mut cavity = 0.0;
for i in 0..nx {
for j in 0..ny {
cavity += (ht - floor(t + (i as f64 + 0.5) * dx, t + (j as f64 + 0.5) * dy)) * dx * dy;
}
}
let tab_cavity = 20.0 * (20.0 - 2.0 * t) * (20.0 - t);
let want = w * l * ht + pyramid + 8000.0 - cavity - tab_cavity;
let m = measure(&s).unwrap();
assert!(rel(m.volume, want) < 1e-5, "{} vs {want}", m.volume);
}
/// The same trough cut as a pocket into a slab (four faces meet at each concave corner of the
/// pocket floor), shelled with its top open.
#[test]
fn shell_of_a_pocket_whose_floor_falls_to_a_drain() {
let (px, py, pw, pl, top, depth, t) = (20.0, 15.0, 100.0, 60.0, 50.0, 30.0, 3.0);
let h = 30.0 * 1f64.to_radians().tan();
let z0 = top - depth;
let facet = |n: Vec3, p: Vec3| {
let n = n.normalized().unwrap();
HalfSpace { n, d: n.dot(p) }
};
let facets = [
facet(Vec3::new(0.0, -h, -30.0), Vec3::new(px, py, z0)),
facet(Vec3::new(0.0, h, -30.0), Vec3::new(px, py + pl, z0)),
facet(Vec3::new(-h, 0.0, -50.0), Vec3::new(px, py, z0)),
facet(Vec3::new(h, 0.0, -50.0), Vec3::new(px + pw, py, z0)),
];
let mut hs = vec![
HalfSpace { n: -Vec3::X, d: -px },
HalfSpace { n: Vec3::X, d: px + pw },
HalfSpace { n: -Vec3::Y, d: -py },
HalfSpace { n: Vec3::Y, d: py + pl },
HalfSpace { n: Vec3::Z, d: top + 10.0 },
];
hs.extend(facets);
let pocket = convex_polyhedron(&hs).unwrap();
let slab = box_solid(Vec3::ZERO, Vec3::new(140.0, 90.0, top)).unwrap();
let basin = boolean(&slab, &pocket, BoolOp::Cut).unwrap().unwrap();
let pocket_vol = pw * pl * depth + pw * pl * h / 3.0;
assert!(rel(measure(&basin).unwrap().volume, 140.0 * 90.0 * top - pocket_vol) < 1e-9);
let s = shell(&basin, &[Vec3::new(5.0, 5.0, top)], t).unwrap();
// The cavity's columns: from t up to the top, or up to the pocket floor moved down by t
// inside the pocket's walls moved out by t.
let floor = |x: f64, y: f64| facets.iter().map(|f| (f.d + t - f.n.x * x - f.n.y * y) / f.n.z).fold(f64::NEG_INFINITY, f64::max);
let (nx, ny) = (1340, 840);
let (dx, dy) = ((140.0 - 2.0 * t) / nx as f64, (90.0 - 2.0 * t) / ny as f64);
let mut cavity = 0.0;
for i in 0..nx {
for j in 0..ny {
let (x, y) = (t + (i as f64 + 0.5) * dx, t + (j as f64 + 0.5) * dy);
let inside = x > px - t && x < px + pw + t && y > py - t && y < py + pl + t;
let roof = if inside { floor(x, y) } else { top };
cavity += (roof - t) * dx * dy;
}
}
let want = 140.0 * 90.0 * top - pocket_vol - cavity;
let m = measure(&s).unwrap();
assert!(rel(m.volume, want) < 1e-4, "{} vs {want}", m.volume);
}
#[test]
fn shell_open_beside_a_round_as_large_as_the_wall_is_refused() {
// Opening the bottom of a box whose bottom outline is rounded: the cavity's side walls stand
// the thickness in from the outside, where a round at least that large meets the bottom, so
// the rim would have no thickness. Smaller rounds leave a rim.
let b = box_solid(Vec3::ZERO, Vec3::new(40.0, 30.0, 10.0)).unwrap();
let loop_ = [Vec3::new(20.0, 0.0, 0.0), Vec3::new(40.0, 15.0, 0.0), Vec3::new(20.0, 30.0, 0.0), Vec3::new(0.0, 15.0, 0.0)];
let bottom = [Vec3::new(20.0, 15.0, 0.0)];
for r in [2.0, 2.4] {
let f = fillet(&b, &loop_, r).unwrap();
let e = shell(&f, &bottom, 2.0).unwrap_err();
assert!(e.to_string().starts_with("the operation failed: not supported yet: the rim"), "{r}: {e}");
}
let f = fillet(&b, &loop_, 1.5).unwrap();
assert!(shell(&f, &bottom, 2.0).unwrap().validity().is_empty());
}
#[test]
fn loft_joined_onto_a_box_top_is_one_shell() {
// #396: a loft from a Ø12 circle on the box top (z = 20) to a hexagon at z = 35. The union
@@ -0,0 +1,10 @@
{
"sources": [
"tangency-labs/solidcraft#316"
],
"what": "a 40 x 30 x 10 box, its bottom outline rounded R2.4, shelled 2 mm open at the bottom: the cavity's walls stand 2 in, where the round meets the bottom, so the rim would have no thickness: refused, naming the rim",
"source": "analytic",
"method": "the open bottom's rim runs from the round's contact with the bottom (r = 2.4 in from the outside) to the cavity's wall (2 in): the round's contact lies past the wall, so there is no rim; refused",
"outcome": "refused",
"refusal": "not supported yet: the rim"
}
@@ -0,0 +1,54 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 40,
"width": 30,
"height": 10
}
},
{
"command": "solid.fillet",
"params": {
"edges": [
[
20,
0,
0
],
[
40,
15,
0
],
[
20,
30,
0
],
[
0,
15,
0
]
],
"radius": 2.4,
"tangent_chain": false
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
20,
15,
0
]
],
"thickness": 2
}
}
]
}
@@ -0,0 +1,10 @@
{
"sources": [
"tangency-labs/solidcraft#316"
],
"what": "a 40 x 30 x 10 box, its bottom outline rounded R2, shelled 2 mm open at the bottom: the cavity's walls stand 2 in, where the round meets the bottom, so the rim would have no thickness: refused, naming the rim",
"source": "analytic",
"method": "the open bottom's rim runs from the round's contact with the bottom (r = 2 in from the outside) to the cavity's wall (2 in): 0 wide, so there is no rim; refused",
"outcome": "refused",
"refusal": "not supported yet: the rim"
}
@@ -0,0 +1,54 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 40,
"width": 30,
"height": 10
}
},
{
"command": "solid.fillet",
"params": {
"edges": [
[
20,
0,
0
],
[
40,
15,
0
],
[
20,
30,
0
],
[
0,
15,
0
]
],
"radius": 2,
"tangent_chain": false
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
20,
15,
0
]
],
"thickness": 2
}
}
]
}
@@ -0,0 +1,10 @@
{
"sources": [
"tangency-labs/solidcraft#316"
],
"what": "a 40 x 30 x 10 box, its bottom outline rounded R1.5, shelled 2 mm open at the bottom: the round is smaller than the wall, so a 0.5 mm rim is left",
"source": "analytic",
"method": "outside: the box less its mitred bottom round, (1-pi/4) 1.5^2 (140 - 8c), c = 1.5 (10-3pi)/(3(4-pi)). The round's inward offset by 2 vanishes (1.5 < 2), so the cavity is the sharp box x 2..38, y 2..28, z 0..8 open at the bottom, 7488: V = 4445.694671",
"body_count": 1,
"volume_mm3": 4445.694671058465
}
@@ -0,0 +1,54 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 40,
"width": 30,
"height": 10
}
},
{
"command": "solid.fillet",
"params": {
"edges": [
[
20,
0,
0
],
[
40,
15,
0
],
[
20,
30,
0
],
[
0,
15,
0
]
],
"radius": 1.5,
"tangent_chain": false
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
20,
15,
0
]
],
"thickness": 2
}
}
]
}
@@ -0,0 +1,9 @@
{
"sources": [
"tangency-labs/solidcraft#545"
],
"what": "the frame of examples/regressions/ring_cut_below_recess_thin_floor (a recess from the top, a ring cut from the bottom, a 0.5 mm floor between) shelled 0.5 mm open at the ring cut's outer wall (action matrix (apps/solidcraft-cli/tests/action_matrix.rs): regressions/ring_cut_below_recess_thin_floor, Frame/F6:side:l2 face.shell)",
"source": "invariants",
"method": "every wall of the frame is at least 0.5 thick except the 0.5 mm floor, which a 0.5 shell hollows to nothing there: whether that floor's cavity closes is the offset's choice, so no closed form: one closed valid solid is the right answer",
"body_count": 1
}
@@ -0,0 +1,143 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": "XY",
"offset": 0,
"name": "Block"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
0
],
"p1": [
100.0,
100.0
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "Block",
"distance": 30,
"body_name": "Frame"
}
},
{
"command": "sketch.create",
"params": {
"plane": "XY",
"offset": 30,
"name": "Recess"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
6.0,
6.0
],
"p1": [
94.0,
94.0
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "Recess",
"distance": -12,
"operation": "cut",
"targets": [
"Frame"
]
}
},
{
"command": "sketch.create",
"params": {
"plane": "XY",
"offset": 0,
"name": "Ring"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
2.5,
2.5
],
"p1": [
97.5,
97.5
]
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
16.0,
16.0
],
"p1": [
84.0,
84.0
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "Ring",
"distance": 17.5,
"operation": "cut",
"targets": [
"Frame"
],
"profiles": [
{
"point": [
9.25,
50.0
]
}
]
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
97.5,
10.416666666666666,
5.833333333333333
]
],
"thickness": 0.5
}
}
]
}
@@ -0,0 +1,9 @@
{
"sources": [
"tangency-labs/solidcraft#616"
],
"what": "#616's lid (a 2.4 mm plate with R3 corners, a 3 mm skirt, three openings and four 1.6 mm ribs, all boxes) shelled 0.5 mm with a rib's outer side face open (action matrix (apps/solidcraft-cli/tests/action_matrix.rs): corpus/issue-616-lid-ribs, Lid/F8:-x face.shell)",
"source": "invariants",
"method": "every wall is at least 1.4 thick, so a 0.5 shell fits everywhere; the cavity's corners at the openings and the R3 rounds' offsets make the volume long but not unknown, and the case guards the build: one closed valid solid is the right answer",
"body_count": 1
}
@@ -0,0 +1,186 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 76.8,
"width": 89.3,
"height": 2.4,
"corner": [
100,
0,
0
],
"body_name": "Lid"
}
},
{
"command": "solid.fillet",
"params": {
"edges": [
[
100,
0,
1.2
],
[
176.8,
0,
1.2
],
[
100,
89.3,
1.2
],
[
176.8,
89.3,
1.2
]
],
"radius": 3
}
},
{
"command": "solid.box",
"params": {
"length": 71.5,
"width": 84,
"height": 3,
"corner": [
102.65,
2.65,
2.4
],
"operation": "join",
"targets": [
"Lid"
]
}
},
{
"command": "solid.box",
"params": {
"length": 68,
"width": 61,
"height": 8,
"corner": [
104.4,
5.4,
-1
],
"operation": "cut"
}
},
{
"command": "solid.box",
"params": {
"length": 44,
"width": 10,
"height": 8,
"corner": [
116.4,
72,
-1
],
"operation": "cut"
}
},
{
"command": "solid.box",
"params": {
"length": 22,
"width": 6,
"height": 4,
"corner": [
127.4,
84,
2.4
],
"operation": "cut"
}
},
{
"command": "solid.box",
"params": {
"length": 1.6,
"width": 6,
"height": 11.7,
"corner": [
102.8,
14,
2.4
],
"operation": "join",
"targets": [
"Lid"
]
}
},
{
"command": "solid.box",
"params": {
"length": 1.6,
"width": 6,
"height": 11.7,
"corner": [
102.8,
48,
2.4
],
"operation": "join",
"targets": [
"Lid"
]
}
},
{
"command": "solid.box",
"params": {
"length": 1.6,
"width": 6,
"height": 11.7,
"corner": [
172.4,
14,
2.4
],
"operation": "join",
"targets": [
"Lid"
]
}
},
{
"command": "solid.box",
"params": {
"length": 1.6,
"width": 6,
"height": 11.7,
"corner": [
172.4,
48,
2.4
],
"operation": "join",
"targets": [
"Lid"
]
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
102.8,
17,
6.85
]
],
"thickness": 0.5
}
}
]
}
+9
View File
@@ -2,3 +2,12 @@
# rig gate (.github/workflows/kernel-rig.yml) fails on a case that fails and is not listed here,
# and on a listed case that passes: a fix removes its line in the same pull request.
# Baseline: 45f69c0e5 with SMLib 60b1c6a, aarch64 Linux.
316-shell-open-beside-a-bottom-round-r2-4-as-large-as-the-wall-refused builds a shell where the rim has no thickness instead of refusing it
316-shell-open-beside-a-bottom-round-r2-as-large-as-the-wall-refused builds a shell where the rim has no thickness instead of refusing it
545-shell-ring-cut-frame-open-at-an-outer-wall SMLib status 1001
616-shell-open-a-rib-side-face-of-a-lid SMLib status 1001
cov-shell-again-open-at-an-inner-wall-of-a-shelled-box SMLib status 1001
cov-shell-plate-with-a-hole-through-its-arc-side SMLib status 1001 where the hole's wall meets the arc side
cov-shell-pocket-whose-floor-falls-to-a-drain SMLib status 1001 where four faces meet at the pocket floor's corners
cov-shell-trough-whose-floor-falls-to-a-drain SMLib status 1001 where four faces meet at a corner
cov-shell-up-down-joined-squares-open-at-a-side-wall SMLib status 1001
@@ -0,0 +1,7 @@
{
"sources": [],
"what": "a 70 x 50 x 30 box with R6 vertical rounds shelled 2 mm open on top, shelled again 0.5 mm open at an inner wall: its 2 mm walls hollowed (action matrix (apps/solidcraft-cli/tests/action_matrix.rs): typical/filleted-shelled-box, Body1/F4:inner:F2:side:l1 face.shell)",
"source": "invariants",
"method": "the 2 mm walls take a 0.5 shell (a 1 mm cavity inside them, open at the picked inner wall); the rounds' offsets are concentric, but the rim and the open faces' cavity ends are the offset's own: one closed valid solid is the right answer",
"body_count": 1
}
@@ -0,0 +1,102 @@
{
"commands": [
{
"command": "parameters.change",
"params": {
"name": "height",
"expression": "30 mm"
}
},
{
"command": "parameters.change",
"params": {
"name": "wall",
"expression": "2 mm"
}
},
{
"command": "sketch.create",
"params": {
"plane": "XY",
"name": "Outline"
}
},
{
"command": "sketch.rectangle.center",
"params": {
"center": [
0,
0
],
"corner": [
35,
25
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"distance": "height"
}
},
{
"command": "solid.fillet",
"params": {
"edges": [
[
35,
25,
15
],
[
-35,
25,
15
],
[
35,
-25,
15
],
[
-35,
-25,
15
]
],
"radius": 6
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
0,
0,
30
]
],
"thickness": "wall"
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
-24.166666666667016,
-22.999999915917346,
4.666666666666665
]
],
"thickness": 0.5
}
}
]
}
@@ -0,0 +1,7 @@
{
"sources": [],
"what": "a 42.5 x 20 x 27.5 plate closed by a half-round side (r10), a blind hole r5 drilled in through that side, shelled 2 mm open at the far end: the edge where the hole's wall meets the arc side is neither a line nor an arc",
"source": "invariants",
"method": "the hole's wall moved 2 out meets the arc side moved 2 in along a curve of two cylinders; whether the cavity's corner at the hole's bottom is sharp or rounded is the offset's choice, so no closed form: one closed valid solid is the right answer",
"body_count": 1
}
@@ -0,0 +1,91 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": "XY"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
42.5,
0
],
[
42.5,
20.0
],
[
0,
20.0
]
]
}
},
{
"command": "sketch.arc.three_point",
"params": {
"end": [
0,
0
],
"start": [
0,
20.0
],
"through": [
-10.0,
10.0
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"distance": 27.5
}
},
{
"command": "solid.cylinder",
"params": {
"radius": 5.0,
"height": 17.5,
"base": [
-10.0,
12.5,
12.5
],
"axis": [
1.0,
0.0,
0.0
],
"operation": "cut"
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
42.5,
10.0,
13.75
]
],
"thickness": 2.0
}
}
]
}
@@ -0,0 +1,11 @@
{
"sources": [],
"what": "a slab 140 x 90 x 50 with a 30 mm pocket whose floor falls 1 deg from its edges to a central drain (four faces meet at each of the pocket floor's concave corners), shelled 3 mm open at the top",
"source": "analytic",
"method": "The floor below z = 0 is a pyramid, apex at the centre h = 30 tan 1 deg = 0.523652 below: two triangular prisms (a triangle on XZ swept along y, one on YZ swept along x) intersected. Slab 140 x 90 x 50 less the pocket x 20..120, y 15..75 down to z = 20 and the pyramid below it: V0 = 630000 - (100 60 30 + 100 60 h/3). Shell 3 open at the top, offset faces extended to meet: the cavity is x 3..137, y 3..87 from z = 3 up to the top, except over the pocket's walls moved 3 out (x 17..123, y 12..78), where it rises only to the pocket's floor facets moved 3 down (their max, exactly over the cells where each is highest): cavity 297136.906075. V = 151815.790029",
"body_count": 1,
"volume_mm3": 151815.7900294403,
"tolerance": {
"rel": 1e-05
}
}
@@ -0,0 +1,151 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 140.0,
"width": 90.0,
"height": 50.0,
"body_name": "Slab"
}
},
{
"command": "solid.box",
"params": {
"length": 100.0,
"width": 60.0,
"height": 40,
"corner": [
20.0,
15.0,
20.0
],
"body_name": "Pocket"
}
},
{
"command": "sketch.create",
"params": {
"plane": "XZ",
"name": "FallX"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
20.0,
-20.0
],
[
120.0,
-20.0
],
[
70.0,
-19.476348052153472
]
],
"closed": true
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "FallX",
"distance": 75.0,
"operation": "new",
"body_name": "FallX"
}
},
{
"command": "sketch.create",
"params": {
"plane": "YZ",
"name": "FallY"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
15.0,
20.0
],
[
75.0,
20.0
],
[
45.0,
19.476348052153472
]
],
"closed": true
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "FallY",
"distance": 120.0,
"operation": "new",
"body_name": "FallY"
}
},
{
"command": "solid.combine",
"params": {
"target": "FallX",
"tools": [
"FallY"
],
"operation": "intersect"
}
},
{
"command": "solid.combine",
"params": {
"target": "Pocket",
"tools": [
"FallX"
],
"operation": "join"
}
},
{
"command": "solid.combine",
"params": {
"target": "Slab",
"tools": [
"Pocket"
],
"operation": "cut"
}
},
{
"command": "solid.shell",
"params": {
"body": "Slab",
"faces": [
[
5,
5,
50.0
]
],
"thickness": 3.0
}
}
]
}
@@ -0,0 +1,11 @@
{
"sources": [],
"what": "a trough whose floor falls 1 deg from its edges to a central drain (four faces meet at each bottom corner and at the drain), a tab joined on one end, shelled 2 mm open at the top",
"source": "analytic",
"method": "The floor below z = 0 is a pyramid, apex at the centre h = 30 tan 1 deg = 0.523652 below: two triangular prisms (a triangle on XZ swept along y, one on YZ swept along x) intersected. Trough 100 x 60 x 40 plus the pyramid 100 60 h/3, plus the tab 20^3 at x 100..120, y 20..40, z 20..40. The shell moves every face 2 in, the offset faces extended to meet (sharp inner corners, as every shell in the ladder's tier 09): the cavity is x 2..98, y 2..58 from the four facets moved 2 up (z >= max of the moved planes, which no longer meet in one point) to the open top, Int (40 - max) dA exactly over the cells where each plane is highest = 205325.031680, and the tab's 20 x 16 x 18 = 5760. V = 37962.272215",
"body_count": 1,
"volume_mm3": 37962.27221527102,
"tolerance": {
"rel": 1e-05
}
}
@@ -0,0 +1,143 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 100.0,
"width": 60.0,
"height": 40.0,
"body_name": "Trough"
}
},
{
"command": "sketch.create",
"params": {
"plane": "XZ",
"name": "FallX"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
100.0,
0
],
[
50.0,
0.5236519478465276
]
],
"closed": true
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "FallX",
"distance": 60.0,
"operation": "new",
"body_name": "FallX"
}
},
{
"command": "sketch.create",
"params": {
"plane": "YZ",
"name": "FallY"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
60.0,
0
],
[
30.0,
-0.5236519478465276
]
],
"closed": true
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "FallY",
"distance": 100.0,
"operation": "new",
"body_name": "FallY"
}
},
{
"command": "solid.combine",
"params": {
"target": "FallX",
"tools": [
"FallY"
],
"operation": "intersect"
}
},
{
"command": "solid.combine",
"params": {
"target": "Trough",
"tools": [
"FallX"
],
"operation": "join"
}
},
{
"command": "solid.box",
"params": {
"length": 20,
"width": 20,
"height": 20,
"corner": [
100.0,
20,
20
],
"operation": "join",
"targets": [
"Trough"
]
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
50,
30,
40.0
]
],
"thickness": 2.0
}
}
]
}
@@ -0,0 +1,7 @@
{
"sources": [],
"what": "four squares drawn edge to edge, three extruded 10 up and three 10 down and joined, shelled 0.346 mm open at a side wall (action matrix (apps/solidcraft-cli/tests/action_matrix.rs): typical/up-down-join, Body1/F2:side:l1 face.shell)",
"source": "invariants",
"method": "every wall is 10 x 10 or more and the shell thin: the cavity's corners where the up and down parts overlap only along an edge are the offset's own choice, so no closed form: one closed valid solid is the right answer",
"body_count": 1
}
@@ -0,0 +1,136 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": "XY",
"name": "Squares"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
0
],
"p1": [
10,
10
]
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
-10,
0
],
"p1": [
0,
10
]
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
-10
],
"p1": [
10,
0
]
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
-10,
-10
],
"p1": [
0,
0
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "solid.extrude",
"params": {
"sketch": "Squares",
"profiles": [
{
"point": [
-5,
5
]
},
{
"point": [
-5,
-5
]
},
{
"point": [
5,
-5
]
}
],
"distance": 10
}
},
{
"command": "solid.extrude",
"params": {
"sketch": "Squares",
"profiles": [
{
"point": [
5,
5
]
},
{
"point": [
5,
-5
]
},
{
"point": [
-5,
5
]
}
],
"distance": 10,
"direction": "negative",
"operation": "join"
}
},
{
"command": "solid.shell",
"params": {
"faces": [
[
6.666666666666666,
0.0,
1.6666666666666665
]
],
"thickness": 0.346
}
}
]
}