Snap fits and compliant features
cadagent.mechanical.compliant sizes and checks snap-fit joints so an agent does not re-derive the equations, guess a
permissible strain or forget layer lines. It is the calculator half of the compliant-mechanism work (#94); the method,
sources and open questions are in research/compliant-mechanisms.md.
Why it is built, not adopted. The survey of 2026-10-31 (research/agent-toolkits-2026-10.md) found agent skills for snap fits (static74/3dp-compliant-mechanisms, the AgentCAD snap-fits skill) but they are prompts only: no calculator and no tests against the design guides' worked examples, and static74's printed strain limits are about twice those the filament datasheets support. This module is tested against the guide's own examples, and every material value names its source.
What it does
- Cantilever, torsion and annular snaps by the closed-form method of the Covestro (formerly Bayer) guide Snap-Fit Joints for Plastics – A Design Guide: permissible deflection from strain, thickness for a target deflection, deflection force from the secant modulus, mating and separation force from friction and the lead and return angles, the torsion-bar and annular-joint relations. Rectangular and ring-segment sections (the guide's Example II section is computed exactly).
- Deterministic pass/fail rows for a declared snap: root strain against the allowable, root radius (at least 0.38 mm; R/h below 0.6 concentrates strain), mating force against a limit, retention force against a minimum.
- Allowable strain with its source: moulded resins from the Covestro Table 2 and DuPont Table 10.06; 11 printed
filaments (13 entries: two have dry and wet values) from their manufacturers' data sheets by print direction
(
allowables.py). - Along the insertion:
engagement()gives the root strain and the push to mate as the mating edge rides the hook's lead, slides along its land and drops off (a snap engaging). - Figures:
tools/snapfit_figures.pydraws the cantilever with its dimensions, andtools/readme_anim.pyanimates one engaging (docs/img/compliant/).
Example I of the Covestro guide (polycarbonate, tapered hook), drawn by tools/snapfit_figures.py from the
module's own result: the arm length, root thickness and undercut are the guide's inputs; the 2.00 % root strain and
the forces are computed by the module, not typed in.
Declaring snaps
# snaps.yaml: cad-agent snapfit snaps.yaml --output exports/snap-checks.json
snaps:
- name: lid-latch
material: copa-polymaker-dry # a printed filament: orientation decides the allowable
orientation: along # bending stress along the layers (arm lies in XY); 'across' = arm built along Z
repeated: true # opened and closed often: 60 % of the single-joining strain
length_mm: 14
undercut_mm: 0.5
design: 1 # 1 constant section, 2 thickness tapered to h/2, 3 width tapered to b/4
section: {rect: {width_mm: 6, thickness_mm: 1.6}}
root_radius_mm: 0.8
lead_deg: 30
return_deg: 45
max_mating_n: 30
- name: example-I # the guide's Example I, moulded polycarbonate
material: pc
process: moulding
length_mm: 19
undercut_mm: 2.4
design: 2
section: {rect: {width_mm: 9.5, thickness_mm: 3.28}}
lead_deg: 30
return_deg: 90
root_radius_mm: 1.0
cad-agent snapfit FILE prints one PASS/FAIL line per snap with the root strain, the allowable and the forces, and
any warnings. It exits 0 if every check passes, 1 if any fails and 2 for an unreadable or out-of-range file (the
message names the snap and the field). --output writes every row, the material derivation and the limits as JSON.
Fields:
- Required:
name,material(a name below, or{name, strain, source, secant_mpa, friction}withstraina fraction: 0.03 = 3 %),length_mm,undercut_mm,section(rect: {width_mm, thickness_mm}orring: {r_inner_mm, r_outer_mm, arc_deg, tension}),root_radius_mm, andprocess(moulding,fdm,sla,slsormjf; a printed filament impliesfdm). - Optional:
design(default 1),repeated,share(0.5 when both parts flex equally),secant_mpa,friction,same_material,lead_deg,return_deg,max_mating_n,min_retention_n. - Layered processes: a printed filament needs
orientation(alongoracrossthe layers). Any other material in a layered process needsorientation,process_factor(0–1: a derating) andprocess_source.
Nothing passes unchecked. A missing process, orientation, derating or root radius is a failing row. A declared
max_mating_n or min_retention_n that cannot be computed fails and names what is missing: no secant modulus (only
pc has guide points; give secant_mpa otherwise), no friction (PLA and PETG are not in the guide's table) or no
angle. A self-locking hook (μ·tan α ≥ 1, e.g. a 90° return) cannot be pulled apart, so its retention is the hook's
own strength, which this method does not compute: a declared retention minimum fails there. Where the guide gives
secant-modulus points, the modulus is interpolated at the arm's actual root strain.
Materials
Moulded (permissible strain for one joining; frequent use in brackets): Covestro Table 2 — pc 4 % (2.4),
pc-high-heat 4 %, pc-abs 2.5 % (1.5), pc-blend 3.5 %, pc-gf10 2.2 %, pc-gf20 2.0 %. DuPont Table 10.06 —
pom-delrin-100 8 % (2), pom-delrin-500 6 % (2), pa66-dry 4 % (2), pa66-50rh 6 % (3), pa66-gf-dry 0.8 %
(0.5), pa66-gf-50rh 1.5 % (1.0), pet-gf 1 % (0.5), pbt-gf 1.2 % (0.6), tpc-hytrel 20 % (10). Where DuPont gives
a range the lower end is used.
Printed, single joining, along / across the layers (derived from the datasheet; ×0.6 for frequent use):
| Name | Along | Across | Name | Along | Across |
|---|---|---|---|---|---|
pla-polymaker |
1.1 % | 0.9 % | asa-polymaker |
1.3 % | 0.8 % |
pla-bambu-basic |
0.95 % | 0.95 % | asa-bambu |
1.06 % | 1.02 % |
pla-bambu-matte |
1.07 % | 0.92 % | copa-polymaker-dry |
2.0 % | 0.65 % |
petg-polymaker |
1.7 % | 1.6 % | copa-polymaker-wet |
3.3 % | 0.85 % |
petg-bambu-basic |
1.28 % | 0.96 % | pa6-cf20-polymaker-dry |
0.8 % | 0.8 % |
petg-bambu-hf |
1.3 % | 1.0 % | pa6-cf20-polymaker-wet |
1.5 % | 1.5 % |
petg-cf-bambu |
1.0 % | 1.0 % |
The rule, per direction: min(0.7 × UTS / E, 0.5 × elongation at break) — the guide's 70 %-of-yield rule for
amorphous resin with UTS/E as a lower bound on the yield strain, and its half-the-elongation rule for materials without
a yield point. Across the layers the smaller of the Z and XY values is used. Nylon is capped at the moulded value of
its family: CoPA at PA66 (the cap never binds), carbon-filled PA6 at DuPont's glass-filled PA66 (0.8 % dry, 1.5 % at
50 % RH; both bind, from derived 0.89 % and 1.53 %). The "wet" rows are water-saturated datasheet specimens.
The direction matters more than strength suggests: across the layers the PLA, PETG, ASA and CoPA datasheets keep
40–89 % of the in-plane strength but only 10–61 % of the elongation at break, and snap fits are limited by strain.
(Polymaker's carbon-filled PA6 keeps 90–96 % of its elongation: the fibre already limits it in-plane.)
Which data-sheet edition each value comes from (#156)
Makers reissue their sheets. Bambu's current V3.0 sheets, served from its store, give lower strengths than the V2.0 copies resellers still serve: PETG-CF's tensile strength falls from 59 / 38 MPa to 35 / 29 MPa, so its allowable falls from 1.7 % to 1.0 %. V3.0 PETG Basic is a reformulated filament sold under the same name, and a spool does not say which it is. So every edition read is kept, each as a complete set of values, and the cautious one is taken per quantity:
- allowable strain: the lowest any edition gives;
- mating force: from the highest modulus any edition gives, so it stays an upper bound;
- retention force: from the lowest, since a softer arm holds less. It is still optimistic: the secant modulus at the design strain is below every sheet's tensile modulus.
The root strain at a given deflection does not depend on E. petg-bambu-basic takes its allowable and its mating
modulus from V3.0 (1.28 / 0.96 % and 2780 / 2550 MPa; V2.0 would allow 2.3 %) and its retention modulus from V2.0
(1460 / 1120 MPa). pla-bambu-basic takes its allowable and retention modulus from V3.0 and its mating modulus from
V2.0 (2680 / 2160 MPa, 4–5 % above V3.0's). The --output JSON names the edition behind each number (xy.sheet,
z.sheet, modulus.mating.sheet, modulus.retention.sheet), and
research/compliant-mechanisms.md §5 and §10 list every sheet with its date and
link.
What this costs in allowable strain depends on which limit governs. Across the layers the allowable is 75–100 % of the in-plane value for PLA and PETG, 97 % for Bambu ASA, 64 % for Polymaker ASA and 26–32 % for CoPA, where half the elongation at break governs: 2.0 % with the arm lying in the bed plane against 0.65 % built upright. Layer lines also act as notches, which no tensile test shows, so lay flexing arms in the bed plane whatever the numbers say.
Try it: the snap-arm explorer
Size a rectangular cantilever arm and see where it fails. The arm bends along its computed curve, coloured by strain. The panel shows the root strain, the force at the hook and pass or fail against the filament's allowable strain for the print direction you choose. The default arm is CoPA laid flat on the bed, and it passes at 44 % of its allowable. Print the same arm upright and it fails at 138 %.
The numbers come from cadagent.formulas.snap_arm, which uses the Covestro method exactly as cad-agent snapfit
does. The browser runs a port of it that is tested against the Python on shared vectors (see
Engineering formulas). The curve is the exact small-deflection shape for the section you choose.
- Force. It uses the datasheet modulus, which is higher than the secant modulus at the design strain, so the force shown is an upper bound.
- Small deflection. When the deflection passes a tenth of the length, the verdict says so: the arm is then outside small deflection.
- Root radius. The explorer does not check the root radius.
cad-agent snapfitdoes.
Try it: the torsion-snap explorer
A torsion snap is a lever on a bar that twists instead of bending, like the guide's rocker on two bars (its Fig. 21). The bar's peak shear strain is in the middle of its long sides. The default is a PLA rocker on two 15 mm bars: pressed 8°, it uses 86 % of its allowable, and it fails past 9.3°.
Try these: one bar halves the force (1.73 N) at the same strain; a 30 mm bar halves both; opened often it fails at 144 %; PETG (Polymaker) passes at 52 %, and CoPA fails at 126 %, since its strain across the layers is low.
The numbers come from cadagent.formulas.torsion_snap_bar: Saint-Venant torsion of a rectangle (Roark, Table 10.1)
and the guide's allowable shear strain, (1 + ν) ε with ν = 0.35 (Section C).
- Across the layers, always. However the bar lies, it shears its layer interfaces at 74 to 100 % of the peak (lying flat, its short sides do), so the check uses the filament's allowable across the layers.
- Force. From the highest datasheet modulus, so at small twist it is an upper bound. The lever is taken as rigid.
- Small twist. Twisted far, a wide thin bar's edges stretch along it (the trapeze effect), which stiffens it and strains its edges. The explorer warns when that would add more than a tenth to the torque: a 30 × 12 × 0.6 mm bar at 30° gains 41 %, with 0.37 % strain along its edges, which the check leaves out.
- Short bars. The ends are taken as free to warp. A short bar held at both ends is stiffer and more strained near them than this says.
A snap engaging, computed
One printed arm, laid flat on the bed, in two filaments. As the mating part's edge rides the hook's lead, the arm bends and its root strain rises. The same strain passes in one filament and fails in the other.
The toolkit's closed-form calculator (cadagent.mechanical.compliant.snapfit, the Covestro method) on the stated
arm, animated by tools/readme_anim.py: not a measurement. Allowables from the data sheets Polymaker PolyMide CoPA
V5.4 and Bambu Lab PETG-CF V3.0. Printed snaps need a test print.
- Strain is geometry. At a given deflection the root strain depends only on the arm (ε = y h / 0.67 L²). The filament sets the allowable. PETG-CF's V3.0 sheet allows 1.00 % (its V2.0 sheet, 1.7 %): this arm goes over it 1.63 mm up the 2.25 mm lead, before the hook clears.
- The push.
snapfit.engagement()gives it along the travel. Up the lead it rises to the guide's W = P (μ + tan α) / (1 − μ tan α), 10.1 N for CoPA. That μ, 0.525, is the guide's PA value for the plastic on itself (same_material, the default), so the mating part is CoPA too; against steel (same_material: false) it is 0.35. On the land only friction resists (μ P), and then the hook drops. PETG is not in the guide's friction table, so PETG-CF gets no push force; declarefrictionto get one. - The drawing. It is at true scale, the arm bent along its computed curve. It turns the hook with the arm's tip, as a real hook turns; the closed form, like the guide, does not. So the drawn edge tops the lead after 1.95 mm of travel, not 2.25 mm, and there it rides a face turned 7.4°: at 37.4°, not 30°. On that face the guide's formula gives CoPA a push of 13.7 N, not 10.1 N. Near the top of a steep lead, or on a short arm, the closed form under-states the push: check those with FEA or a push test.
The figure's spec, tools/anim/snap-engagement.yaml, is a snap declaration too: cad-agent snapfit tools/anim/snap-engagement.yaml prints the same two verdicts. tests/test_anim_snapfit.py runs the calculator
again and checks the figure against it (animated figures).
Limits
- A pass has no extra margin. It means the root strain is within the allowable; the guide's own examples design to half the permissible strain.
- Closed-form, small-deflection beam theory with one part rigid: no large deflection, contact, creep, fatigue or wall deflection at the root. A warning is given when the deflection exceeds a tenth of the arm length (the guide's Example I is at 0.13). Large-deflection force-travel curves need FEA (CalculiX is the planned external solver).
- Printed allowables are hypotheses until a coupon is measured: the datasheets are for 100 % infill on one printer and profile. Forces for printed snaps use the datasheet tensile modulus, which is higher than the secant modulus at the design strain, so mating forces are conservative and retention forces optimistic; the force rows say so. Where a filament has several editions, mating takes the highest modulus and retention the lowest.
- Hook-face geometry and mould release are not checked. CAD and calculation do not prove a joint: print it and measure.
Tests that keep it honest
tests/test_snapfit.py reproduces the guide's worked examples — Example I (h 3.28 mm, P 32.5 N, W 58.5 N), Example II
(ring-segment hook, y 2.11 mm) and the annular lamp cover (P 748 N, W 1346 N) — checks that every printed row matches
the derived table in the research note, that direction changes the verdict for the same geometry, that uncomputable
limits, out-of-range inputs and unstated processes fail, the ring section against numerical integration (arcs up to
360°), the torsion relations from first principles, and that this page's YAML example and printed table match the
code. tests/test_torsion_snap_boss.py checks the torsion bar against Saint-Venant's series solution and this page's
explorer numbers against the Python. The stated elongation and strength ranges are checked against the datasheet rows too.