Commit Graph
9 Commits
Author SHA1 Message Date
jyvikoandClaude Opus 5.5 2c4212c042 Thread: the chamfered tip at the start or at both ends
`tip` was none|chamfer, chamfer cutting every free end. It is now none|start|both: `start`
chamfers the end the thread starts from, refused when that end is not free (a shoulder, or a
stop inside the face), and `both` every free end as `chamfer` did. The dialog's Tip pick offers
None, Start and Both; `tip: chamfer` in a command names its replacements.

The thread's end options (runouts, tip, chamfer angle and depth) came without a format
change file; `pending/thread-ends.rs` records them and rewrites a saved `tip: chamfer` to
`both`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 13:02:32 -04:00
jyvikoandClaude Opus 5.5 a30a85698f Thread: the chamfered tip reaches ISO 724's external minor diameter
ISO 4753's chamfered end bounds the end's diameter by the minor diameter. The default took the
modelled root (the basic d1) for it, so the cone's small circle lay on the root cylinder and
the chamfer ring pinched to nothing wherever the groove reached the end. The default is now
the external minor diameter d3 = d - 1.226869 P of ISO 724, below d1: the cone crosses the
root, each end is a whole disk of d3 inside a whole conical ring. ISO 4753 is for ISO metric
threads; the other forms, whose root is already their design minor, give chamfer_depth.

Ladder 06/017's analytic volume follows (1945.354522563); its golden entry re-measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 13:02:32 -04:00
jyvikoandClaude Opus 5.5 84473f61fa kernel-ladder: tier 06 grades the threaded boss; both hands and Tr40x14(P7) added
010 passed on one valid body alone: it now checks the tier-05 part less
the M16 groove (stopped w above the boss's shoulder, run out at its free
top) and the bbox. Two new cases with closed forms: 018, an M10 cut both
hands, whose crossing grooves leave the material fraction squared
(2 pi L int r m^2 dr, exact for L a whole number of pitches); 019, a
two-start Tr40x14(P7), six pitches of the Tr40x7 section. All hold on
SMLib (worst 2e-6 relative).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:28:53 -04:00
jyvikoandClaude Opus 5.5 d433ce2c9f Thread runouts: the groove fades out instead of stopping square
Ladder 06/009 had no way to ask for one: "solid.thread has no runout (vanishing thread)
length". With SMLib's smlib_screw_sweep_radial (replay e7acea1):

- smlib: the FFI binding and Brep::screw_sweep_radial, the profile moved off the axis by a
  piecewise linear law of the turn; crate test: a tooth moved out 1 mm over three turns has
  A 2π (c turns + ∫ offset dt).
- kernel: sweep_helix_radial, sharing sweep_helix's checks (helix_profile).
- doc: `ease_in`, `ease_out` (a length, or ISO 3508's standard 2.5 P or short 1.25 P) fade the
  groove over that length, its section moving out of the material as it turns (outward for a
  shaft, inward for a nut). ease_in is at the end the thread starts from. The runout lies past
  the full-form length: beyond a square stop, before a shoulder up to its clearance; at a free
  end inside the face. Runouts longer than the thread are refused. No end gets one by default,
  so saved threads keep their geometry.

The cut is the integral over the turn of the clipped section's 2π∫ r dA: engine test (2.5 P
and 1.25 P between two collars) within the sweep's wall tolerance times the runouts' wall area
(0.029 against a 0.036 mm³ bound), ladder 06/009 (004's shaft, a 2 P runout before the
shoulder) graded in closed form (measured 1.7e-6 off).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:28:53 -04:00
jyvikoandClaude Opus 5.5 7bfc184e8e A modelled thread's chamfered tip (ISO 4753)
`tip: chamfer` cuts ISO 4753's chamfered end at each free end a modelled external thread
reaches, after the groove, so the last teeth taper into the cone instead of ending in a
ragged first turn: the material outside a cone `chamfer_angle` to the axis (default 45°)
reaching d_f = d - 2 `chamfer_depth` at the face's end (default the external minor diameter,
the largest the standard allows), a revolved ring cut by one boolean per end. Past the end the
ring keeps to the radii the groove's overrun already cuts. An internal thread is refused (its
entry takes the hole's countersink), as is a tip with no free end or on a cosmetic thread.

The cone is axisymmetric and cut after the screw-symmetric groove, so the volume is the stock's
chamfered section with the thread's material fraction: engine test (both ends 45°, and 30°
x 0.5 mm at a shaft's one free end above a collar) within 1e-4, ladder 06/017 (measured
2.4e-7 off).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:28:53 -04:00
jyvikoandClaude Opus 5.5 3287bcba9e Threads with several starts
Ladder 06/008 had no way to ask for one: "solid.thread has no start count". `starts: n` (1 to
8) cuts n grooves of lead n x P, the j-th a j/n turn round from the first (the same helix j
pitches along), in one boolean with their union. A designation that gives the lead
(M16xPh3P1.5, Tr40x14(P7)) gives the starts, and a `starts` that disagrees is refused. The
helix's self-clearance check and the turn limit use the lead.

Over the same length n grooves of lead nP take the volume of one start of pitch P: engine test
(2 and 3 starts, M10xPh3P1.5) within 1e-4 of the closed form, ladder 06/008 graded as 001
(measured 3.5e-7 off).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:28:53 -04:00
jyvikoandClaude Opus 5.5 b4549d2700 Threads in the standard forms, right- or left-handed or both
Only the ISO metric 60° thread existed. Forms now (crates/doc/src/thread_forms.rs, values and
sources in docs/threads.md): ISO metric (ISO 68-1), trapezoidal (ISO 2904 design profile, ISO
2902 sizes), general purpose Acme (ASME B1.5), metric buttress 3°/30° (DIN 513), buttress inch
7°/45° (ASME B1.9 basic profile). Each has its groove as a straight-flanked polygon, its standard
sizes (none for ASME buttress), its designations (M10, M16xPh3P1.5, Tr40x14(P7), S20x4,
1/2-10 ACME, 2.5-8 BUTT) and the size that fits a face. The square thread is refused: no current
standard defines it.

`hand: right | left | both`: a left-handed groove is the screw motion about the reversed axis
rising along it; both cuts the two grooves, crossing, in one boolean. `steep_flank` turns a
buttress. The design diameters are checked against the published tables (ISO 2904/DIN 103,
DIN 513 via IS 4696-3); every form's cut against 2π∫ r w(r) dr per turn to 1e-4 in engine tests
and to 1e-4 in ladder 06/011 to 016 (they measure within 5e-7).

FeatureKind::Thread holds every option the command has (form, hand, starts, ease_in, ease_out,
tip, chamfer_angle, chamfer_depth, steep_flank, all defaulted so saved threads load unchanged);
starts, runouts and the chamfered tip are refused as not built yet. suggested_thread_in takes the
form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:28:52 -04:00
jyvikoandClaude Opus 5.5 366b90597f Threads start at the end meant and stop clear of a shoulder
A thread of some length ran from "the end of the face nearest the pick", a coin toss for a
pick in the middle (rig 602's 4 mm thread meant for the free bottom end ran at the head end,
cutting 1.17 mm into the hex), and every thread end at a face end got a one-pitch overrun,
which at a shoulder gouged the material past it (ladder 06/004 cut 0.9% of its volume out of
the collar).

- kernel: material_in_ring, the exact intersection of a body with a ring about a cylinder
  face's axis, by an SMLib boolean.
- doc: a face end is free when no material lies past it, over the span the groove's one-pitch
  overrun reaches beyond its first pitch, within the radii the groove cuts (a cap, a chamfer
  the groove runs out through, a counterbore). At a free end the groove runs out as before; at
  a closed one (a shoulder, a head, a blind hole's bottom) it stops with its widest part clear
  of it; inside the face it stops square.
- doc: a thread of some length starts at the end nearest `from`, else at the face's only free
  end, else at the end the pick lies within a third of the face of; a pick in the middle of a
  face whose ends are alike is refused, naming `from`. A length as long as the face runs the
  whole face. `up_to` a plane or a point's place along the axis. New fields `from`, `up_to`
  default to none, so saved threads keep their meaning where it was not a coin toss.
- engine: solid.thread takes extent (full|length|up_to), from and up_to.
- ladder 06/003 (now with `from`), 004 and 007 are graded by volume and centre of mass in
  closed form (a square stop inside material removes exactly length/P turns, the section being
  symmetric); rig 602's method says why the thread is at the bottom, tolerance 0.02%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:28:52 -04:00
jyvikoandClaude Opus 5.5 b249100eae ladder: 116 cases in 11 tiers, from primitives to a threaded, shelled housing
Tiers: primitives; booleans in the degeneracy classes (coincident and coplanar faces, edge-on-edge,
vertex-on-face, tangent along a line and a circle, near-tangent gaps and overlaps of 1e-3 and
1e-6 mm, seam and pole crossings) and cuts that end in a single line (a knife-edge wedge, a V
groove and a cylinder that pinch the part in two, a hole tangent to a face, a notch flush with an
end); line-and-arc extrudes and revolves (partial, touching the axis); spline profiles, sweeps
and lofts; holes and tapped holes (blind, drilled, counterbore, countersink, M5-M8 taps, into a
curved face, near and tangent to an edge, crossing); modelled threads (external, fine, partial,
to a shoulder, internal, into a chamfer, at a filleted shoulder); fillets (constant, tangent
chains, convex and concave, variable down to 1e-3 and to 0 at a vertex, corners with equal and
unequal radii, g2 corners); chamfers (two distances, angle, three- and two-edge corners, curved);
shells and offsets; patterns and mirrors (overlapping instances that cut a core free); and
cumulative parts.

A running part grows one tier at a time through `base` (back wall, revolved boss and slot,
spline window, tapped holes, rounds, chamfers, shell, vents), and the last case adds its thread:
it carries every tier. Answers are analytic wherever the geometry has them (Pappus, Steinmetz,
ISO 68-1 basic thread profiles, exact Gauss quadrature of Bezier profiles, inclusion-exclusion
for chamfered corners), otherwise invariants; each `method` gives the derivation, and
tools/kernel-ladder/cases.py (standard-library Python, like tools/oracle-analytic) writes them.
Capabilities SolidCraft lacks are `missing` cases: multi-start threads, thread runout lengths,
fillet corner setbacks.

The golden is the first recording on truck, each tier sorted by its time. SMLib booleans are
not on this branch yet, so the smlib column records "not supported yet" for every case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWhMwdqJYQKQq8RCLSL1LT
2026-10-27 02:28:46 -04:00