mirror of
https://github.com/gittrahan/support-fins.git
synced 2026-10-19 02:10:52 -05:00
calibration: torture test -- one part with ramps, ball, thin ledge, table, mushroom, cave, sideways holes and an arch, built in Full coverage at the defaults (must-hold 95 %); coupon.py label() for its raised angle / hole sizes
This commit is contained in:
1 parent
4b353e48f4
commit
335f62a5ab
7 files changed
+137
No files matched your search
@@ -178,6 +178,21 @@ bore's axis, inside the bore, running out the open end; 0 unserved. Checks the
|
||||
2026-09-27 reversal (bores DO get supported) on a printed part.
|
||||
- **waiting on print.**
|
||||
|
||||
### torture/ -- one part with every hard shape, as the site supports it (no setting)
|
||||
Not a rung coupon: a showcase that sets nothing. A spine on the plate with, front:
|
||||
40 / 30 / 20 deg ramps rising 10 mm (angle raised on top), a 20 mm ball, a 2 mm
|
||||
ledge 18 mm out and 24 mm up; back: a table (30 mm flat bridge, 14 up), a 26 mm
|
||||
mushroom cap on a 5 mm stem, a cave (18 x 14 flat ceiling); through the spine:
|
||||
3 / 6 / 12 mm sideways holes (size raised above each); on the end: an arch tunnel.
|
||||
One build in Full coverage (mode 'full') at every other default, all supports kept.
|
||||
Every feature is big enough for real walls (10-26 mm long), so the print shows
|
||||
whether each kind snaps off clean. A point-down tip in the first draft was dropped
|
||||
(Matthew: a mess, tells us nothing).
|
||||
- **2026-10-06 build:** 32 walls (10 from the fill pass), must-hold 95 % of 2977 mm2
|
||||
(coverage scoreboard). Still bare: thin strips along the arch's curved sides and
|
||||
the 12 mm hole's sides.
|
||||
- **waiting on print.**
|
||||
|
||||
### bite/ -- RETIRED 2026-10-03 (files removed; last in git at 6ec7c16)
|
||||
Asked how far tines should reach into the part (the old Tine bite field): twelve 40 deg
|
||||
ledges, bite 0.15-0.70. **Printed twice in PLA: every rung fused and left a mark, none
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Torture test, step 2: ONE build of the whole part the way the site makes it --
|
||||
* Full coverage (mode 'full') at every other default -- and every support kept.
|
||||
* Prints what got walls and what Full coverage says no wall can reach.
|
||||
*
|
||||
* deno run -A prototype/calibration/torture/build.js
|
||||
*/
|
||||
import { loadCoupon, finsWith, supportOf, writeCoupon } from '../coupon.js';
|
||||
|
||||
const c = loadCoupon(import.meta.url);
|
||||
const built = finsWith(c, { mode: 'full' });
|
||||
const kinds = {};
|
||||
for (const f of built.fins) { const k = f.kind + (f.short ? ' (short)' : ''); kinds[k] = (kinds[k] ?? 0) + 1; }
|
||||
console.log('walls', kinds, 'fill walls', built.fill?.walls ?? built.fins.filter((f) => f.fill).length,
|
||||
'tines', built.tines, 'pad', !!built.pad);
|
||||
console.log('fill', JSON.stringify(built.fill, (k, v) => (Array.isArray(v) && v.length > 8 ? `[${v.length}]` : v)));
|
||||
await writeCoupon(c, 'torture', 'Torture test', supportOf(built));
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Torture test: one part with every overhang the tool has to handle, built by the
|
||||
site's Full coverage at its defaults. Not a rung coupon: it sets nothing. It shows
|
||||
what the site makes on each shape, in one print.
|
||||
|
||||
Along a spine block on the plate (x 0-126, y -7..7, 30 mm tall), clockwise from the
|
||||
front left:
|
||||
|
||||
front (-y) ramps at 40 / 30 / 20 deg rising 10 mm, a 20 mm ball, a 2 mm ledge 18 mm out
|
||||
back (+y) a table (30 mm flat bridge), a 26 mm mushroom cap on a 5 mm stem, a cave
|
||||
through sideways holes 3 / 6 / 12 mm across, along y
|
||||
end an arch tunnel (x 0 end)
|
||||
|
||||
Every feature is big enough that its walls are real walls (the first draft's 3-8 mm
|
||||
stubs couldn't show whether a wall snaps off clean). Ramps and holes carry their
|
||||
angle / size as raised text.
|
||||
|
||||
Everything joins the spine, so it is ONE solid piece (coupon.write checks).
|
||||
|
||||
python3 prototype/calibration/torture/gen.py && deno run -A prototype/calibration/torture/build.js
|
||||
"""
|
||||
import math
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import trimesh
|
||||
from trimesh.creation import cylinder, icosphere
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
from coupon import bx, label, write # noqa: E402
|
||||
|
||||
L, HW, H = 126.0, 7.0, 30.0
|
||||
add, cut = [], []
|
||||
|
||||
|
||||
def ramp(x0, w, angle, z0=4.0, rise=10.0, side=-1):
|
||||
"""A wedge off the spine face: underside rising `rise` at `angle` up from the plate."""
|
||||
d = rise / math.tan(math.radians(angle))
|
||||
yz = [(0, z0), (d, z0 + rise), (d, z0 + rise + 2), (0, z0 + rise + 2)]
|
||||
yz = [(side * (HW - 0.5 + y), z) for y, z in yz]
|
||||
if side < 0:
|
||||
yz = yz[::-1]
|
||||
m = trimesh.creation.extrude_polygon(trimesh.path.polygons.Polygon(yz), w)
|
||||
m.apply_transform([[0, 0, 1, x0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
|
||||
return m
|
||||
|
||||
|
||||
def along_y(m):
|
||||
"""Rotate a z-axis primitive (cylinder) to run along y."""
|
||||
m.apply_transform(trimesh.transformations.rotation_matrix(math.pi / 2, [1, 0, 0]))
|
||||
return m
|
||||
|
||||
|
||||
def at(m, x, y, z):
|
||||
m.apply_translation([x, y, z])
|
||||
return m
|
||||
|
||||
|
||||
# the spine
|
||||
add.append(bx(0, L, -HW, HW, 0, H))
|
||||
|
||||
# FRONT (-y): three ramps, a ball, a thin far ledge
|
||||
for x0, a in [(2, 40), (17, 30), (32, 20)]:
|
||||
add.append(ramp(x0, 13, a))
|
||||
d = 10 / math.tan(math.radians(a))
|
||||
add += label(f'{a}', x0 + 6.5, -HW - min(d, 14) / 2 - 0.5, 16, size=5.0) # on the ramp's top
|
||||
add.append(at(icosphere(subdivisions=3, radius=10), 56, -HW - 7, 17)) # ball, low point 7 up
|
||||
add.append(bx(70, 94, -HW - 18, -HW + 0.5, 24, 26)) # 2 mm ledge, 18 out, 24 up
|
||||
|
||||
# BACK (+y): table, mushroom, cave
|
||||
add += [bx(2, 38, HW - 0.5, HW + 16, 14, 17), # table top: 30 mm bridge
|
||||
bx(2, 6, HW + 12, HW + 16, 0, 14), bx(34, 38, HW + 12, HW + 16, 0, 14)] # its two legs
|
||||
add += [at(cylinder(radius=2.5, height=16, sections=32), 56, HW + 14, 8), # stem on the plate
|
||||
at(cylinder(radius=13, height=3, sections=64), 56, HW + 14, 17.5), # cap, 13 mm round
|
||||
bx(53.5, 58.5, HW - 0.5, HW + 12, 0, 3)] # foot strip to the spine
|
||||
add.append(bx(70, 94, HW - 0.5, HW + 14, 0, 24)) # block holding the cave
|
||||
cut.append(bx(73, 91, HW + 0.5, HW + 14.5, 3, 18)) # cave: open to +y, flat 18 x 14 ceiling
|
||||
|
||||
# THROUGH: sideways holes along y, centred high enough that each has a ceiling to hold
|
||||
# (their own stretch, x 96-124: nothing else on either face there)
|
||||
for x, d in [(99, 3.0), (106, 6.0), (117, 12.0)]:
|
||||
cut.append(at(along_y(cylinder(radius=d / 2, height=2 * HW + 2, sections=48)), x, 0, 16))
|
||||
add += label(f'{d:g}', x, 0, H, size=5.0) # its size, on the spine's top
|
||||
|
||||
# END: arch through a block on the x 0 end (along y)
|
||||
add.append(bx(-14, 0.5, -HW, HW, 0, 20))
|
||||
cut += [at(along_y(cylinder(radius=5, height=2 * HW + 2, sections=48)), -7, 0, 8),
|
||||
bx(-12, -2, -HW - 1, HW + 1, -1, 8)] # arch: 10 wide, 13 high
|
||||
|
||||
m = trimesh.boolean.difference([trimesh.boolean.union(add, engine='manifold'),
|
||||
trimesh.boolean.union(cut, engine='manifold')], engine='manifold')
|
||||
m = write(__file__, [m], [])
|
||||
print(f'torture part {m.extents.round(1)} mm, {len(m.faces)} triangles')
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
Binary file not shown.
Reference in new issue
Block a user