kernel-ladder: cases.py makes every committed case again

The generator had fallen behind the tree: it no longer wrote 02/021-025,
03/010, 04/011-012 and 09/012-015, and its 07/016 lacked the second round's
tangent_chain. Each is now built in cases.py; the two reporters' scripts
(04/011, 04/012) are kept verbatim in reported.py. Regenerating reproduces
the tree exactly; the only file changes are the generator's own format
(volumes to 9 decimals, one-space indent, a final newline), all under 1e-8
relative.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-26 10:53:04 -04:00
parent 9ffd2f7839
commit 191b2f4c4f
17 changed files with 228 additions and 26 deletions
@@ -4,6 +4,6 @@
"source": "analytic",
"method": "V = 60 40 20 - 2 pi 5^2 20; faces: 6 of the box + 2 bores (top and bottom each one loop round both holes, through their common vertex twice)",
"body_count": 1,
"volume_mm3": 44858.407346410204,
"volume_mm3": 44858.40734641,
"faces": 8
}
@@ -6,5 +6,5 @@
"source": "analytic",
"method": "part 12x12x5.1 = 734.4 minus the hole pi*1.6^2*4.1 = 32.97 (hole z -4..0.1, part top z 0.1). The tool (z -3.9..3.2, the square 1.5x1.5 where r >= 1.5) overlaps solid only where r >= 1.6: area A1 = integral_0^1.5 (1.5 - min(1.5, sqrt(2.56-x^2))) dx = 0.31409, over the 4.0 mm of shared z: 1.25638 mm3 (the 0.0003 offset moves this by about 3e-3). V = 734.4 - 32.9662 - 1.2564 = 700.1695. Reduced from the report's STEP geometry (no pocket or rotation); the answer is for this geometry",
"body_count": 1,
"volume_mm3": 700.1694662079215
"volume_mm3": 700.169466214
}
@@ -6,5 +6,5 @@
"source": "analytic",
"method": "base area = 2 straight rails (2 x 20) x 2 + full annulus pi(25-9) = 80 + 16 pi, times 2 mm = 160 + 32 pi. Each lip is a half annulus pi(25-16)/2 = 4.5 pi, two lips x 18 mm = 162 pi. The lips sit above z=2, the base is below, so nothing overlaps (the crescent overhang is above z=2 too): V = 160 + 194 pi = 769.469. One body",
"body_count": 1,
"volume_mm3": 769.4689747964198
}
"volume_mm3": 769.468974796
}
@@ -282,4 +282,4 @@
}
}
]
}
}
@@ -8,5 +8,5 @@
"source": "analytic",
"method": "hub = revolve of (8,0) (30,0) (30,6) (18,6) (18,22) (8,22) about Z: V = pi [(30^2 - 8^2) 6 + (18^2 - 8^2) 16] = 28826.6. Extruding the whole annulus z = 6, r 18..30 outward (upward) 5 mm adds pi (30^2 - 18^2) 5 = 9047.8 (the new ring sits on the flange and touches the hub wall r = 18).",
"body_count": 1,
"volume_mm3": 37875.04103167855
}
"volume_mm3": 37875.041031679
}
@@ -82,4 +82,4 @@
}
}
]
}
}
@@ -8,5 +8,5 @@
"method": "the layers only meet face to face, so V is their sum: Body1 = pi 37^2 1.2 + (pi 37^2 - the four bands y -29..-24, -13..-8, 8..11, 24..27 of the disc, Int 2 sqrt(37^2 - y^2) dy) 2.4; Body2 = pi (37^2-35^2) 2; Body3 = pi 37^2 2.4. The bands run out to the rim, so the space inside r35 under Body1 opens to the outside: one shell (the reporter's 52-command script, generic dimensions)",
"body_count": 1,
"shells": 1,
"volume_mm3": 24340.9358
"volume_mm3": 24340.935804077
}
@@ -6,5 +6,5 @@
"source": "analytic",
"method": "Pappus: the half disc (the side away from the axis) has area pi 14^2 / 2 and centroid at 14 + 4 * 14 / (3 pi) from the axis: V = (270/360) 2 pi (14 + 4*14/(3 pi)) pi 14^2 / 2 = 28932.2 (the design measures 28930.7).",
"body_count": 1,
"volume_mm3": 28932.17609889229
}
"volume_mm3": 28932.176098892
}
@@ -69,4 +69,4 @@
}
}
]
}
}
@@ -1,9 +1,9 @@
{
"sources": [
"tangency-labs/solidcraft#4092"
],
"what": "the same without the top flange: the join fails with 'boolean Union: no result'",
"source": "invariants",
"method": "the pad (X -8..8, Y 18..25, Z 36..59) overlaps the body, ribs and ring, so the join is one connected solid; the join must succeed with one valid closed solid and no panic",
"body_count": 1
}
"sources": [
"tangency-labs/solidcraft#4092"
],
"what": "the same without the top flange: the join fails with 'boolean Union: no result'",
"source": "invariants",
"method": "the pad (X -8..8, Y 18..25, Z 36..59) overlaps the body, ribs and ring, so the join is one connected solid; the join must succeed with one valid closed solid and no panic",
"body_count": 1
}
@@ -4,6 +4,6 @@
"source": "analytic",
"method": "V = (2/3) pi (20^3 - 18^3); faces: outer sphere, inner sphere, base ring",
"body_count": 1,
"volume_mm3": 4540.648581988447,
"volume_mm3": 4540.648581988,
"faces": 3
}
@@ -7,4 +7,4 @@
"source": "invariants",
"method": "no closed-form volume (tilted rounds). Invariants: the shell succeeds, one closed body, and the record's geometry check holds (every edge of the four inner rounds lies on its faces; the old offset left them up to 0.02 mm off, which other STEP readers reject)",
"body_count": 1
}
}
@@ -6,5 +6,5 @@
"source": "analytic",
"method": "shell: (2/3) pi (20^3 - 18^3). The ring's prism r 18..20, z 0..10 lies inside the dome's wall where r^2 + z^2 <= 20^2 (r >= 18 keeps it outside the cavity) and pokes out elsewhere: it adds 760 pi - Int_18^20 2 pi r sqrt(400 - r^2) dr = 760 pi - (2 pi/3) 76^1.5",
"body_count": 1,
"volume_mm3": 5540.612
"volume_mm3": 5540.611995642
}
+118 -1
View File
@@ -14,6 +14,7 @@ import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from ladder_lib import * # noqa: E402,F403
from reported import LOFT_RIBS_PAD, PLEATED_SKINS # noqa: E402
def up(tier, name):
return f"../../{tier}/{name}"
@@ -144,6 +145,76 @@ case(T2, "020-part-back-wall", "the running part: a 60x10x15 back wall joined on
"an L section (6 sides) extruded along X: 8 faces; the coplanar back and end faces merge", base=B1)
C2 = up(T2, "020-part-back-wall")
V2 = VB + 9000
case(T2, "021-holes-touching-at-a-point", "two through holes r5 whose circles touch at one point (30, 20)",
[cyl([25, 20, -1], 5, 22, operation="cut"), cyl([35, 20, -1], 5, 22, operation="cut")],
{"body_count": 1, "volume_mm3": VB - 2 * PI * 25 * 20, "faces": 8},
"V = 60 40 20 - 2 pi 5^2 20; faces: 6 of the box + 2 bores (top and bottom each one loop round both holes, through their common vertex twice)", base=B1)
# The tool's square 1.5 x 1.5 outside r 1.6 (the hole wall): A1 = int_x0^1.5 (1.5 - sqrt(1.6^2 - x^2)) dx, x0 = sqrt(1.6^2 - 1.5^2).
x0 = math.sqrt(2.56 - 2.25)
Fc = lambda x: (x * math.sqrt(2.56 - x * x) + 2.56 * math.asin(x / 1.6)) / 2
A1 = 1.5 * (1.5 - x0) - (Fc(1.5) - Fc(x0))
case(T2, "022-cylinder-grazing-a-hole-edge",
"a corner piece (square column minus a quarter disc r1.5, 0.0003 off the axis) cut out of a part with a blind r1.6 hole on the same axis: the tool's r1.5 face sits 0.1 mm inside the hole wall; 'no result'",
[box([-6, -6, -5], 12, 12, 5.1, body_name="Part"), cyl([0, 0, -4], 1.6, 4.1, operation="cut"),
box([0, 0, -3.9], 1.5, 1.5, 7.1, operation="new", body_name="Tool"), cyl([0.0003, 0, -4], 1.5, 7.5, operation="cut", targets=["Tool"]),
C("solid.combine", target="Part", tools=["Tool"], operation="cut")],
{"body_count": 1, "volume_mm3": 734.4 - PI * 1.6 ** 2 * 4.1 - A1 * 4.0},
"part 12x12x5.1 = 734.4 minus the hole pi*1.6^2*4.1 = 32.97 (hole z -4..0.1, part top z 0.1). The tool (z -3.9..3.2, the square 1.5x1.5 where r >= 1.5) overlaps solid only where r >= 1.6: "
"area A1 = integral_0^1.5 (1.5 - min(1.5, sqrt(2.56-x^2))) dx = 0.31409, over the 4.0 mm of shared z: 1.25638 mm3 (the 0.0003 offset moves this by about 3e-3). "
"V = 734.4 - 32.9662 - 1.2564 = 700.1695. Reduced from the report's STEP geometry (no pocket or rotation); the answer is for this geometry",
sources=["tangency-labs/solidcraft#1279"])
def arc_c(center, start, sweep):
return C("sketch.arc.center_point", center=center, start=start, sweep=sweep)
case(T2, "023-lips-1e-4-off-the-walls-joined",
"two half-annulus lips (r 4..5, from z=2 to 20) joined onto a stadium-ring base (z 0..2, r 3..5 arcs, centres 20 apart) with their cylinder walls 0.0001 mm off the base's: "
"the lip cap touches the base top, leaving a 0.0001 mm crescent overhang. Layout is a hand-built variant of the PR's public reproduction",
[C("sketch.create", plane="XY", name="Base"),
line([[5, -10], [5, 10]]), arc_c([0, 10], [5, 10], 180), line([[-5, 10], [-5, -10]]), arc_c([0, -10], [-5, -10], 180),
line([[3, -10], [3, 10]]), arc_c([0, 10], [3, 10], 180), line([[-3, 10], [-3, -10]]), arc_c([0, -10], [-3, -10], 180),
C("sketch.finish"),
C("solid.extrude", sketch="Base", profiles=[{"point": [4, 0]}], distance=2, operation="new", body_name="Base"),
C("sketch.create", plane="XY", offset=2, name="Lips"),
arc_c([0.0001, 10], [5.0001, 10], 180), line([[-4.9999, 10], [-3.9999, 10]]), arc_c([0.0001, 10], [-3.9999, 10], -180), line([[4.0001, 10], [5.0001, 10]]),
arc_c([-0.0001, -10], [-5.0001, -10], 180), line([[4.9999, -10], [3.9999, -10]]), arc_c([-0.0001, -10], [3.9999, -10], -180), line([[-4.0001, -10], [-5.0001, -10]]),
C("sketch.finish"),
C("solid.extrude", sketch="Lips", distance=18, operation="join", profiles="all")],
{"body_count": 1, "volume_mm3": 160 + 194 * PI},
"base area = 2 straight rails (2 x 20) x 2 + full annulus pi(25-9) = 80 + 16 pi, times 2 mm = 160 + 32 pi. Each lip is a half annulus pi(25-16)/2 = 4.5 pi, two lips x 18 mm = 162 pi. "
"The lips sit above z=2, the base is below, so nothing overlaps (the crescent overhang is above z=2 too): V = 160 + 194 pi = 769.469. One body",
sources=["tangency-labs/solidcraft#2928"])
case(T2, "024-wall-halves-merged-into-a-flange",
"the flange top annulus of a freshly revolved hub (z = 6, r 18..30) picked by a point and extruded 5 mm (the pick found a third of the face: \"the selected planar face no longer exists\")",
sketch(vplane([0.0, 0.0, 0.0]), C("sketch.line", points=[[8, 0], [30, 0], [30, 6], [18, 6], [18, 22], [8, 22]], infer=False, closed=True), name="P")
+ [C("solid.revolve", axis="Z", angle="360 deg", operation="new", body_name="Hub"),
C("solid.extrude", face=[12, 12 * math.sqrt(3), 6], distance=5, operation="join")],
{"body_count": 1, "volume_mm3": PI * ((900 - 64) * 6 + (324 - 64) * 16) + PI * (900 - 324) * 5},
"hub = revolve of (8,0) (30,0) (30,6) (18,6) (18,22) (8,22) about Z: V = pi [(30^2 - 8^2) 6 + (18^2 - 8^2) 16] = 28826.6. "
"Extruding the whole annulus z = 6, r 18..30 outward (upward) 5 mm adds pi (30^2 - 18^2) 5 = 9047.8 (the new ring sits on the flange and touches the hub wall r = 18).",
sources=["tangency-labs/solidcraft#726", "tangency-labs/solidcraft#494", "tangency-labs/solidcraft#2114"])
# 18 chords across a disc r37; the layers' regions between them, four bands left out of the second layer.
CHORD_Y = [-32, -29, -24, -21, -16, -13, -8, -5, 0, 3, 8, 11, 16, 19, 24, 27, 32, 35]
BANDS = [(-29, -24), (-13, -8), (8, 11), (24, 27)]
def chords(name):
return sketch("XY", C("sketch.circle.center", center=[0, 0], radius=37),
*[line([[-math.sqrt(1369 - y * y), y], [math.sqrt(1369 - y * y), y]]) for y in CHORD_Y], name=name)
ys = [-37] + CHORD_Y + [37]
picks = [{"point": [0, (a + b) / 2]} for a, b in zip(ys, ys[1:]) if (a, b) not in BANDS]
band_area = sum(quad(lambda y: 2 * math.sqrt(1369 - y * y), a, b) for a, b in BANDS)
case(T2, "025-flush-chord-layers-joined",
"a join of flush layers: a disc r37 (z -1.2..0) carrying 15 of the 19 regions of a sketch of 18 chords (z -3.6..-1.2; four bands left out), on an annulus r35..37 (z -5.6..-3.6) "
"joined to a disc of all the chord regions (z -8..-5.6): SMLib's result came back with 'loop encloses no (u, v) area' though both operands are valid",
chords("S1") + chords("S3")
+ sketch("XY", C("sketch.circle.center", center=[0, 0], radius=37), C("sketch.circle.center", center=[0, 0], radius=35), name="Rings")
+ [C("solid.extrude", sketch="Rings", profiles="all", distance=1.2, direction="negative", body_name="Body1"),
C("solid.extrude", sketch="S1", profiles=picks, distance=2.4, direction="negative", **{"from": [0, 0, -1.2]}, operation="join"),
C("solid.extrude", sketch="Rings", profiles=[{"point": [36, 0]}], distance=2, direction="negative", **{"from": [36, 0, -3.6]}, operation="new", body_name="Body2"),
C("solid.extrude", sketch="S3", profiles="all", distance=2.4, direction="negative", **{"from": [36, 0, -5.6]}, operation="new", body_name="Body3"),
C("solid.combine", target="Body2", tools=["Body3"], operation="join"),
C("solid.combine", target="Body1", tools=["Body2"], operation="join")],
{"body_count": 1, "shells": 1, "volume_mm3": PI * 1369 * 1.2 + (PI * 1369 - band_area) * 2.4 + PI * (1369 - 1225) * 2 + PI * 1369 * 2.4},
"the layers only meet face to face, so V is their sum: Body1 = pi 37^2 1.2 + (pi 37^2 - the four bands y -29..-24, -13..-8, 8..11, 24..27 of the disc, Int 2 sqrt(37^2 - y^2) dy) 2.4; "
"Body2 = pi (37^2-35^2) 2; Body3 = pi 37^2 2.4. The bands run out to the rim, so the space inside r35 under Body1 opens to the outside: one shell (the reporter's 52-command script, generic dimensions)",
sources=["tangency-labs/solidcraft#5197", "tangency-labs/solidcraft#3396"])
# ---------------------------------------------------------------- 03 analytic profiles
A = 2400 + PI * 400 / 2
@@ -189,6 +260,15 @@ case(T3, "009-part-boss-and-slot", "the running part: a revolved boss r8 h10 joi
"back-wall part (57000) + pi 8^2 10 - 20 (15*8 + pi 4^2); faces 8 + boss side and top + slot's 2 planes and 2 half cylinders", base=C2)
C3 = up(T3, "009-part-boss-and-slot")
V3 = V2 + Vboss - 20 * Aslot
case(T3, "010-revolve-horn-torus-270",
"the half disc of radius 14 on the far side of a diameter 14 mm from the axis (the full circle would touch the axis: a horn torus) revolved 270 degrees",
sketch(vplane([0.0, 0.0, 0.0]), C("sketch.arc.center_point", center=[14, 0], start=[14, -14], end=[14, 14]),
C("sketch.line", points=[[14, 14], [14, -14]], infer=False), name="P")
+ [C("solid.revolve", axis="Z", angle="270 deg", operation="new")],
{"body_count": 1, "volume_mm3": 270 / 360 * 2 * PI * (14 + 4 * 14 / (3 * PI)) * PI * 196 / 2},
"Pappus: the half disc (the side away from the axis) has area pi 14^2 / 2 and centroid at 14 + 4 * 14 / (3 pi) from the axis: "
"V = (270/360) 2 pi (14 + 4*14/(3 pi)) pi 14^2 / 2 = 28932.2 (the design measures 28930.7).",
sources=["tangency-labs/solidcraft#4007"])
# ---------------------------------------------------------------- 04 spline profiles
P = [[40, 10], [30, 30], [10, 30], [0, 10]]
@@ -254,6 +334,16 @@ case(T4, "010-part-bezier-window", "the running part: a Bezier-arched window cut
"the arch over z=22 from x=20 to 40 rises to z = 22 + 0.75*12 = 31, under the wall top (35): removed 10 * %.9f; + window floor and arch faces" % Awin, base=C3)
C4 = up(T4, "010-part-bezier-window")
V4 = V3 - 10 * Awin
case(T4, "011-crossing-pleated-loft-skins-joined",
"a join of two pleated skins (lofts between 24-pleat star outlines, less the same loft moved in 1.1 mm) that cross along a ring near their bottoms: "
"truck panicked ('tolerance must be no less than 1e-6') or gave no result",
PLEATED_SKINS, {"body_count": 1},
"the narrowing cone skin and the flaring lip skin cross at z = -0.3, so their union is one connected solid: one valid closed body, no panic. The reporter's own script (pleated_union.py, 24 pleats)",
source="invariants", sources=["tangency-labs/solidcraft#4623", "tangency-labs/solidcraft#4180", "tangency-labs/solidcraft#4881"])
case(T4, "012-loft-ribs-joined-to-a-rounded-pad", "the same without the top flange: the join fails with 'boolean Union: no result'",
LOFT_RIBS_PAD, {"body_count": 1},
"the pad (X -8..8, Y 18..25, Z 36..59) overlaps the body, ribs and ring, so the join is one connected solid; the join must succeed with one valid closed solid and no panic",
source="invariants", sources=["tangency-labs/solidcraft#4092"])
# ---------------------------------------------------------------- 05 holes and taps
def H(**p):
@@ -529,7 +619,7 @@ case(T7, "010-corner-unequal-r7-r3", "an r7 vertical round at a corner, then r3
[F([corner[2]], 7), F([[60, 15, 20]], 3)], {"body_count": 1},
"two radii meeting at a corner over a tangent chain; one valid body", base=B1, source="invariants")
case(T7, "016-corner-three-sequential-r5-r3-r7", "rounds r5 and r3 on the two top edges at a corner, then r7 on the vertical edge under them",
[F([corner[0]], 5), F([corner[1]], 3), F([[60, 40, 8]], 7)], {"body_count": 1},
[F([corner[0]], 5), F([corner[1]], 3, tangent_chain=False), F([[60, 40, 8]], 7)], {"body_count": 1},
"three unequal radii at one corner, one after another; the vertical edge stays sharp below the two top rounds (x=60, y=40, z from 0 to 15), so it can be picked at z=8; one valid body", base=B1, source="invariants")
case(T7, "011-chain-ending-at-corner", "r5 rounds on two top edges meeting at a corner whose vertical edge stays sharp",
[F([corner[0], corner[1]], 5)], {"body_count": 1},
@@ -617,6 +707,33 @@ case(T9, "011-part-shell", "the running part shelled 1.5 mm open at the bottom",
[S([[30, 20, 0]], 1.5)], {"body_count": 1},
"a shell around holes, a slot, a window, rounds and chamfers; one valid body", base=C8, source="invariants")
C9 = up(T9, "011-part-shell")
case(T9, "012-closed-shell-sealed-void", "the stock shelled 2 mm with no face open: a closed body with a sealed void", [S([], 2)],
{"body_count": 1, "shells": 2, "volume_mm3": VB - 56 * 36 * 16, "faces": 12},
"void 56x36x16: V = 48000 - 32256; faces 6 outer + 6 inner; one body, an outer and an inner shell", base=B1)
DOME = sketch(vplane([0, 0, 0]), line([[0, 0], [20, 0]]), C("sketch.arc.center_point", center=[0, 0], start=[20, 0], end=[0, 20]), line([[0, 20], [0, 0]]))
case(T9, "013-dome-shelled-from-base", "a dome r20 shelled 2 mm, open at its flat base: the rim is the circle r18 where the inner sphere meets the base plane",
DOME + [C("solid.revolve", axis="Z", angle="360 deg", operation="new"), S([[10, 0, 0]], 2)],
{"body_count": 1, "volume_mm3": 2 / 3 * PI * (20 ** 3 - 18 ** 3), "faces": 3},
"V = (2/3) pi (20^3 - 18^3); faces: outer sphere, inner sphere, base ring")
dr5 = 20 * math.tan(math.radians(5))
case(T9, "014-drafted-box-with-rounds-shelled",
"a 120x80x40 box drafted 5 degrees with 4 mm rounds on the sloping corners, shelled 2 mm open at the top: the inner rounds' edges must lie on their faces (#3573 reports the same design)",
sketch("XY", C("sketch.rectangle.center", center=[0, 0], corner=[60, 40]))
+ [C("solid.extrude", distance=40, taper="-5 deg", operation="new"),
F([[sx * (60 - dr5), sy * (40 - dr5), 20] for sx, sy in [(1, 1), (1, -1), (-1, 1), (-1, -1)]], 4), S([[0, 0, 40]], 2)],
{"body_count": 1},
"no closed-form volume (tilted rounds). Invariants: the shell succeeds, one closed body, and the record's geometry check holds "
"(every edge of the four inner rounds lies on its faces; the old offset left them up to 0.02 mm off, which other STEP readers reject)",
source="invariants", sources=["tangency-labs/solidcraft#3576", "tangency-labs/solidcraft#3573"])
case(T9, "015-shelled-dome-ring-joined-back",
"a dome (a quarter disc r20 revolved) shelled 2 mm from its flat base, then the base ring (r 18..20) face-extruded 10 mm back into the dome as a join: ~120 s, then 'boolean Union: no result'",
sketch(vplane([0, 0, 0]), line([[0, 0], [20, 0]]), C("sketch.arc.three_point", start=[20, 0], through=[14.142136, 14.142136], end=[0, 20]), line([[0, 20], [0, 0]]), name="Quarter")
+ [C("solid.revolve", sketch="Quarter", axis="y", body_name="Dome"), S([[0, 0, 0]], 2),
C("solid.extrude", face=[19, 0, 0], face_body="Dome", distance=10, direction="negative", operation="join")],
{"body_count": 1, "volume_mm3": 2 / 3 * PI * (20 ** 3 - 18 ** 3) + 760 * PI - 2 * PI / 3 * 76 ** 1.5},
"shell: (2/3) pi (20^3 - 18^3). The ring's prism r 18..20, z 0..10 lies inside the dome's wall where r^2 + z^2 <= 20^2 (r >= 18 keeps it outside the cavity) and pokes out elsewhere: "
"it adds 760 pi - Int_18^20 2 pi r sqrt(400 - r^2) dr = 760 pi - (2 pi/3) 76^1.5",
sources=["tangency-labs/solidcraft#4847"])
# ---------------------------------------------------------------- 10 patterns and mirrors
case(T10, "001-rect-pattern-holes", "a d5 hole patterned 3 x 2 at 20 mm in a 60x40x10 plate",
+85
View File
@@ -0,0 +1,85 @@
"""Reported recipes the ladder keeps verbatim: the reporters' own scripts, whose numbers (rounded
outline points, a modeller's sketch coordinates) are the case and have no generator here. cases.py
writes them unchanged. Plain Python 3, standard library only."""
import json
# tangency-labs/solidcraft#4623: pleated_union.py (24 pleats), two pleated skins (a loft between
# star outlines less the same loft moved in 1.1 mm) joined where they cross.
PLEATED_SKINS = json.loads(r"""[
{"command": "sketch.create", "params": {"plane": "XY", "offset": "-1", "name": "ConeLo"}},
{"command": "sketch.line", "params": {"points": [[115.7949, 0.0], [112.5082, 14.812], [111.8493, 29.9699], [104.8409, 43.4265], [100.2813, 57.8974], [90.0289, 69.0816], [81.8793, 81.8793], [69.0816, 90.0289], [57.8974, 100.2813], [43.4265, 104.8409], [29.9699, 111.8493], [14.812, 112.5082], [0.0, 115.7949], [-14.812, 112.5082], [-29.9699, 111.8493], [-43.4265, 104.8409], [-57.8974, 100.2813], [-69.0816, 90.0289], [-81.8793, 81.8793], [-90.0289, 69.0816], [-100.2813, 57.8974], [-104.8409, 43.4265], [-111.8493, 29.9699], [-112.5082, 14.812], [-115.7949, 0.0], [-112.5082, -14.812], [-111.8493, -29.9699], [-104.8409, -43.4265], [-100.2813, -57.8974], [-90.0289, -69.0816], [-81.8793, -81.8793], [-69.0816, -90.0289], [-57.8974, -100.2813], [-43.4265, -104.8409], [-29.9699, -111.8493], [-14.812, -112.5082], [-0.0, -115.7949], [14.812, -112.5082], [29.9699, -111.8493], [43.4265, -104.8409], [57.8974, -100.2813], [69.0816, -90.0289], [81.8793, -81.8793], [90.0289, -69.0816], [100.2813, -57.8974], [104.8409, -43.4265], [111.8493, -29.9699], [112.5082, -14.812]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "sketch.create", "params": {"plane": "XY", "offset": "88.3", "name": "ConeHi"}},
{"command": "sketch.line", "params": {"points": [[14.39, 0.0], [13.9816, 1.8407], [13.8997, 3.7244], [13.0287, 5.3967], [12.4621, 7.195], [11.188, 8.5849], [10.1753, 10.1753], [8.5849, 11.188], [7.195, 12.4621], [5.3967, 13.0287], [3.7244, 13.8997], [1.8407, 13.9816], [0.0, 14.39], [-1.8407, 13.9816], [-3.7244, 13.8997], [-5.3967, 13.0287], [-7.195, 12.4621], [-8.5849, 11.188], [-10.1753, 10.1753], [-11.188, 8.5849], [-12.4621, 7.195], [-13.0287, 5.3967], [-13.8997, 3.7244], [-13.9816, 1.8407], [-14.39, 0.0], [-13.9816, -1.8407], [-13.8997, -3.7244], [-13.0287, -5.3967], [-12.4621, -7.195], [-11.188, -8.5849], [-10.1753, -10.1753], [-8.5849, -11.188], [-7.195, -12.4621], [-5.3967, -13.0287], [-3.7244, -13.8997], [-1.8407, -13.9816], [-0.0, -14.39], [1.8407, -13.9816], [3.7244, -13.8997], [5.3967, -13.0287], [7.195, -12.4621], [8.5849, -11.188], [10.1753, -10.1753], [11.188, -8.5849], [12.4621, -7.195], [13.0287, -5.3967], [13.8997, -3.7244], [13.9816, -1.8407]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.loft", "params": {"sections": [{"sketch": "ConeLo"}, {"sketch": "ConeHi"}], "operation": "new", "body_name": "Cone", "name": "Cone"}},
{"command": "sketch.create", "params": {"plane": "XY", "offset": "-2", "name": "ConeInLo"}},
{"command": "sketch.line", "params": {"points": [[115.8304, 0.0], [112.5209, 14.8137], [111.8836, 29.9791], [104.8528, 43.4314], [100.3121, 57.9152], [90.0391, 69.0894], [81.9045, 81.9045], [69.0894, 90.0391], [57.9152, 100.3121], [43.4314, 104.8528], [29.9791, 111.8836], [14.8137, 112.5209], [0.0, 115.8304], [-14.8137, 112.5209], [-29.9791, 111.8836], [-43.4314, 104.8528], [-57.9152, 100.3121], [-69.0894, 90.0391], [-81.9045, 81.9045], [-90.0391, 69.0894], [-100.3121, 57.9152], [-104.8528, 43.4314], [-111.8836, 29.9791], [-112.5209, 14.8137], [-115.8304, 0.0], [-112.5209, -14.8137], [-111.8836, -29.9791], [-104.8528, -43.4314], [-100.3121, -57.9152], [-90.0391, -69.0894], [-81.9045, -81.9045], [-69.0894, -90.0391], [-57.9152, -100.3121], [-43.4314, -104.8528], [-29.9791, -111.8836], [-14.8137, -112.5209], [-0.0, -115.8304], [14.8137, -112.5209], [29.9791, -111.8836], [43.4314, -104.8528], [57.9152, -100.3121], [69.0894, -90.0391], [81.9045, -81.9045], [90.0391, -69.0894], [100.3121, -57.9152], [104.8528, -43.4314], [111.8836, -29.9791], [112.5209, -14.8137]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "sketch.create", "params": {"plane": "XY", "offset": "89.3", "name": "ConeInHi"}},
{"command": "sketch.line", "params": {"points": [[12.1544, 0.0], [11.7876, 1.5519], [11.7403, 3.1458], [10.9843, 4.5499], [10.5261, 6.0772], [9.4325, 7.2378], [8.5945, 8.5945], [7.2378, 9.4325], [6.0772, 10.5261], [4.5499, 10.9843], [3.1458, 11.7403], [1.5519, 11.7876], [0.0, 12.1544], [-1.5519, 11.7876], [-3.1458, 11.7403], [-4.5499, 10.9843], [-6.0772, 10.5261], [-7.2378, 9.4325], [-8.5945, 8.5945], [-9.4325, 7.2378], [-10.5261, 6.0772], [-10.9843, 4.5499], [-11.7403, 3.1458], [-11.7876, 1.5519], [-12.1544, 0.0], [-11.7876, -1.5519], [-11.7403, -3.1458], [-10.9843, -4.5499], [-10.5261, -6.0772], [-9.4325, -7.2378], [-8.5945, -8.5945], [-7.2378, -9.4325], [-6.0772, -10.5261], [-4.5499, -10.9843], [-3.1458, -11.7403], [-1.5519, -11.7876], [-0.0, -12.1544], [1.5519, -11.7876], [3.1458, -11.7403], [4.5499, -10.9843], [6.0772, -10.5261], [7.2378, -9.4325], [8.5945, -8.5945], [9.4325, -7.2378], [10.5261, -6.0772], [10.9843, -4.5499], [11.7403, -3.1458], [11.7876, -1.5519]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.loft", "params": {"sections": [{"sketch": "ConeInLo"}, {"sketch": "ConeInHi"}], "operation": "new", "body_name": "ConeIn", "name": "ConeIn"}},
{"command": "solid.combine", "params": {"target": "Cone", "tools": ["ConeIn"], "operation": "cut"}},
{"command": "sketch.create", "params": {"plane": "XY", "offset": "-1", "name": "LipLo"}},
{"command": "sketch.line", "params": {"points": [[114.4444, 0.0], [111.196, 14.6392], [110.5448, 29.6204], [103.6182, 42.9201], [99.1118, 57.2222], [88.979, 68.276], [80.9244, 80.9244], [68.276, 88.979], [57.2222, 99.1118], [42.9201, 103.6182], [29.6204, 110.5448], [14.6392, 111.196], [0.0, 114.4444], [-14.6392, 111.196], [-29.6204, 110.5448], [-42.9201, 103.6182], [-57.2222, 99.1118], [-68.276, 88.979], [-80.9244, 80.9244], [-88.979, 68.276], [-99.1118, 57.2222], [-103.6182, 42.9201], [-110.5448, 29.6204], [-111.196, 14.6392], [-114.4444, 0.0], [-111.196, -14.6392], [-110.5448, -29.6204], [-103.6182, -42.9201], [-99.1118, -57.2222], [-88.979, -68.276], [-80.9244, -80.9244], [-68.276, -88.979], [-57.2222, -99.1118], [-42.9201, -103.6182], [-29.6204, -110.5448], [-14.6392, -111.196], [-0.0, -114.4444], [14.6392, -111.196], [29.6204, -110.5448], [42.9201, -103.6182], [57.2222, -99.1118], [68.276, -88.979], [80.9244, -80.9244], [88.979, -68.276], [99.1118, -57.2222], [103.6182, -42.9201], [110.5448, -29.6204], [111.196, -14.6392]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "sketch.create", "params": {"plane": "XY", "offset": "6", "name": "LipHi"}},
{"command": "sketch.line", "params": {"points": [[120.0, 0.0], [116.5939, 15.3499], [115.9111, 31.0583], [108.6482, 45.0036], [103.923, 60.0], [93.2984, 71.5903], [84.8528, 84.8528], [71.5903, 93.2984], [60.0, 103.923], [45.0036, 108.6482], [31.0583, 115.9111], [15.3499, 116.5939], [0.0, 120.0], [-15.3499, 116.5939], [-31.0583, 115.9111], [-45.0036, 108.6482], [-60.0, 103.923], [-71.5903, 93.2984], [-84.8528, 84.8528], [-93.2984, 71.5903], [-103.923, 60.0], [-108.6482, 45.0036], [-115.9111, 31.0583], [-116.5939, 15.3499], [-120.0, 0.0], [-116.5939, -15.3499], [-115.9111, -31.0583], [-108.6482, -45.0036], [-103.923, -60.0], [-93.2984, -71.5903], [-84.8528, -84.8528], [-71.5903, -93.2984], [-60.0, -103.923], [-45.0036, -108.6482], [-31.0583, -115.9111], [-15.3499, -116.5939], [-0.0, -120.0], [15.3499, -116.5939], [31.0583, -115.9111], [45.0036, -108.6482], [60.0, -103.923], [71.5903, -93.2984], [84.8528, -84.8528], [93.2984, -71.5903], [103.923, -60.0], [108.6482, -45.0036], [115.9111, -31.0583], [116.5939, -15.3499]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.loft", "params": {"sections": [{"sketch": "LipLo"}, {"sketch": "LipHi"}], "operation": "new", "body_name": "Lip", "name": "Lip"}},
{"command": "sketch.create", "params": {"plane": "XY", "offset": "-2", "name": "LipInLo"}},
{"command": "sketch.line", "params": {"points": [[112.5508, 0.0], [109.3343, 14.3941], [108.7157, 29.1303], [101.8834, 42.2015], [97.4718, 56.2754], [87.4892, 67.1329], [79.5854, 79.5854], [67.1329, 87.4892], [56.2754, 97.4718], [42.2015, 101.8834], [29.1303, 108.7157], [14.3941, 109.3343], [0.0, 112.5508], [-14.3941, 109.3343], [-29.1303, 108.7157], [-42.2015, 101.8834], [-56.2754, 97.4718], [-67.1329, 87.4892], [-79.5854, 79.5854], [-87.4892, 67.1329], [-97.4718, 56.2754], [-101.8834, 42.2015], [-108.7157, 29.1303], [-109.3343, 14.3941], [-112.5508, 0.0], [-109.3343, -14.3941], [-108.7157, -29.1303], [-101.8834, -42.2015], [-97.4718, -56.2754], [-87.4892, -67.1329], [-79.5854, -79.5854], [-67.1329, -87.4892], [-56.2754, -97.4718], [-42.2015, -101.8834], [-29.1303, -108.7157], [-14.3941, -109.3343], [-0.0, -112.5508], [14.3941, -109.3343], [29.1303, -108.7157], [42.2015, -101.8834], [56.2754, -97.4718], [67.1329, -87.4892], [79.5854, -79.5854], [87.4892, -67.1329], [97.4718, -56.2754], [101.8834, -42.2015], [108.7157, -29.1303], [109.3343, -14.3941]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "sketch.create", "params": {"plane": "XY", "offset": "7", "name": "LipInHi"}},
{"command": "sketch.line", "params": {"points": [[119.6937, 0.0], [116.2745, 15.3078], [115.6152, 30.979], [108.3505, 44.8803], [103.6577, 59.8468], [93.0427, 71.3942], [84.6362, 84.6362], [71.3942, 93.0427], [59.8468, 103.6577], [44.8803, 108.3505], [30.979, 115.6152], [15.3078, 116.2745], [0.0, 119.6937], [-15.3078, 116.2745], [-30.979, 115.6152], [-44.8803, 108.3505], [-59.8468, 103.6577], [-71.3942, 93.0427], [-84.6362, 84.6362], [-93.0427, 71.3942], [-103.6577, 59.8468], [-108.3505, 44.8803], [-115.6152, 30.979], [-116.2745, 15.3078], [-119.6937, 0.0], [-116.2745, -15.3078], [-115.6152, -30.979], [-108.3505, -44.8803], [-103.6577, -59.8468], [-93.0427, -71.3942], [-84.6362, -84.6362], [-71.3942, -93.0427], [-59.8468, -103.6577], [-44.8803, -108.3505], [-30.979, -115.6152], [-15.3078, -116.2745], [-0.0, -119.6937], [15.3078, -116.2745], [30.979, -115.6152], [44.8803, -108.3505], [59.8468, -103.6577], [71.3942, -93.0427], [84.6362, -84.6362], [93.0427, -71.3942], [103.6577, -59.8468], [108.3505, -44.8803], [115.6152, -30.979], [116.2745, -15.3078]], "closed": true, "infer": false}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.loft", "params": {"sections": [{"sketch": "LipInLo"}, {"sketch": "LipInHi"}], "operation": "new", "body_name": "LipIn", "name": "LipIn"}},
{"command": "solid.combine", "params": {"target": "Lip", "tools": ["LipIn"], "operation": "cut"}},
{"command": "solid.combine", "params": {"target": "Cone", "tools": ["Lip"], "operation": "join"}}
]""")
# tangency-labs/solidcraft#4092, reduced: a cap's neck, oval transition loft and chamber, a handle
# ring, two ribs and a rounded pad joined onto them (without the report's top flange).
LOFT_RIBS_PAD = json.loads(r"""[
{"command": "file.new", "params": {"name": "Native_loft_pad_union_repro"}},
{"command": "document.units", "params": {"units": "mm"}},
{"command": "solid.cylinder", "params": {"diameter": "36 mm", "height": "21 mm", "base": [0, 0, 0], "operation": "new", "name": "01_Neck_outer_D36_H21", "body_name": "NATIVE_CAP_BODY"}},
{"command": "sketch.create", "params": {"name": "02_Outer_transition_round", "plane": "XY", "offset": "21 mm"}},
{"command": "sketch.circle.center", "params": {"center": [0, 0], "diameter": 36}},
{"command": "sketch.finish", "params": {}},
{"command": "sketch.create", "params": {"name": "03_Outer_transition_ellipse", "plane": "XY", "offset": "38 mm"}},
{"command": "sketch.ellipse", "params": {"center": [0, 0], "major": [30.0, 0], "minor_radius": 20.0}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.loft", "params": {"sections": [{"sketch": "02_Outer_transition_round"}, {"sketch": "03_Outer_transition_ellipse"}], "operation": "join", "targets": ["NATIVE_CAP_BODY"], "name": "04_Outer_round_to_oval_transition"}},
{"command": "sketch.create", "params": {"name": "05_Upper_chamber_60x40", "plane": "XY", "offset": "38 mm"}},
{"command": "sketch.ellipse", "params": {"center": [0, 0], "major": [30.0, 0], "minor_radius": 20.0}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.extrude", "params": {"sketch": "05_Upper_chamber_60x40", "distance": 26, "operation": "join", "targets": ["NATIVE_CAP_BODY"], "name": "06_Upper_chamber_blank"}},
{"command": "sketch.create", "params": {"name": "Handle_outer_D24", "plane": {"origin": [-5, 0, 0], "x_dir": [0, 1, 0], "y_dir": [0, 0, 1]}}},
{"command": "sketch.circle.center", "params": {"center": [30, 47], "diameter": 24}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.extrude", "params": {"sketch": "Handle_outer_D24", "distance": 10, "operation": "join", "targets": ["NATIVE_CAP_BODY"], "name": "Handle_outer_D24_thickness10"}},
{"command": "sketch.create", "params": {"name": "Handle_lower_rib_X-8", "plane": {"origin": [-8, 0, 0], "x_dir": [0, 1, 0], "y_dir": [0, 0, 1]}}},
{"command": "sketch.arc.three_point", "params": {"start": [18.0, 37.5], "end": [19.5, 36.0], "through": [18.439339828220177, 36.43933982822018]}},
{"command": "sketch.line", "params": {"points": [[19.5, 36.0], [24.4516191451179, 36.0]]}},
{"command": "sketch.arc.three_point", "params": {"start": [24.4516191451179, 36.0], "end": [25.20742568340403, 38.79566835134765], "through": [25.89963546529897, 37.10853003117829]}},
{"command": "sketch.line", "params": {"points": [[25.20742568340403, 38.79566835134765], [20.25580653828613, 41.68411285266642]]}},
{"command": "sketch.arc.three_point", "params": {"start": [20.25580653828613, 41.68411285266642], "end": [18.0, 40.38844450131877], "through": [18.75290891031588, 41.68915773017231]}},
{"command": "sketch.line", "params": {"points": [[18.0, 40.38844450131877], [18.0, 37.5]]}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.extrude", "params": {"sketch": "Handle_lower_rib_X-8", "distance": 4, "operation": "join", "targets": ["NATIVE_CAP_BODY"], "name": "Handle_lower_rib_X-8_R1p5_thickness4"}},
{"command": "sketch.create", "params": {"name": "Handle_lower_rib_X4", "plane": {"origin": [4, 0, 0], "x_dir": [0, 1, 0], "y_dir": [0, 0, 1]}}},
{"command": "sketch.arc.three_point", "params": {"start": [18.0, 37.5], "end": [19.5, 36.0], "through": [18.439339828220177, 36.43933982822018]}},
{"command": "sketch.line", "params": {"points": [[19.5, 36.0], [24.4516191451179, 36.0]]}},
{"command": "sketch.arc.three_point", "params": {"start": [24.4516191451179, 36.0], "end": [25.20742568340403, 38.79566835134765], "through": [25.89963546529897, 37.10853003117829]}},
{"command": "sketch.line", "params": {"points": [[25.20742568340403, 38.79566835134765], [20.25580653828613, 41.68411285266642]]}},
{"command": "sketch.arc.three_point", "params": {"start": [20.25580653828613, 41.68411285266642], "end": [18.0, 40.38844450131877], "through": [18.75290891031588, 41.68915773017231]}},
{"command": "sketch.line", "params": {"points": [[18.0, 40.38844450131877], [18.0, 37.5]]}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.extrude", "params": {"sketch": "Handle_lower_rib_X4", "distance": 4, "operation": "join", "targets": ["NATIVE_CAP_BODY"], "name": "Handle_lower_rib_X4_R1p5_thickness4"}},
{"command": "sketch.create", "params": {"name": "Handle_root_pad_R3", "plane": {"origin": [0, 18, 0], "x_dir": [1, 0, 0], "y_dir": [0, 0, 1]}}},
{"command": "sketch.rectangle.rounded", "params": {"p0": [-8, 36], "p1": [8, 59], "radius": 3}},
{"command": "sketch.finish", "params": {}},
{"command": "solid.extrude", "params": {"sketch": "Handle_root_pad_R3", "distance": 7, "direction": "negative", "operation": "join", "targets": ["NATIVE_CAP_BODY"], "name": "Native_root_pad_R3"}}
]""")