Skip to content

Commit 57264cc

Browse files
scottconverseclaude
andcommitted
v0.3.0 — augers, Phillips drives, custom angle/tooth_height/taper, child wrappers
- tq_thread: angle (custom flank angle), tooth_height (explicit depth), taper - tq_auger / tq_auger_hole: deep coarse helical flight + negative - Phillips drive: tq_phillips_drive, tq_phillips_tip, drive="phillips" on bolts - child-difference wrappers: tq_tap, tq_drill, tq_counterbore, tq_countersink - tq_relief_groove (thread runout) - minor-radius assert now accounts for taper; _TQ_H made private earlier - render-tests.ps1: Windows PowerShell 5.1 compatible (no ternary) + openscad.com - examples/fast+heavy tests/README/MANUAL/REFERENCES/CHANGELOG + landing page Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 73aa7c0 commit 57264cc

10 files changed

Lines changed: 368 additions & 27 deletions

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,37 @@
44
All notable changes to tq-threads. Format loosely follows
55
[Keep a Changelog](https://keepachangelog.com); versions are git tags.
66

7+
## [0.3.0] — 2026-06-22
8+
9+
Stronger-than-baseline release: adds the remaining helper categories users
10+
expect from a general thread library, plus more profile control — all clean-room.
11+
12+
### Added
13+
- **Custom flank angle** `angle=60` on `tq_thread` (e.g. 55° Whitworth-ish, 45°);
14+
thread height is derived from the angle (or set explicitly, below).
15+
- **Explicit `tooth_height`** override on `tq_thread` (sets the radial flight
16+
depth directly instead of deriving it from the flats/angle).
17+
- **Tapered threads** `taper=` on `tq_thread` (total diameter reduction over the
18+
length — NPT-ish tapers, auger tips, etc.).
19+
- **`tq_auger` / `tq_auger_hole`** — deep coarse helical flight + matching
20+
negative (screw conveyor / drill / feed-screw style; generic, not a standard).
21+
- **Phillips (cross) drive**: `tq_phillips_drive` (cruciform cutter/tip),
22+
`tq_phillips_tip` (driver bit), and `drive="phillips"` on `tq_bolt` /
23+
`tq_countersunk_bolt`; helpers `tq_ph_dims`, `tq_ph_size_for`.
24+
- **Child-difference convenience wrappers** (ScrewHole/ClearanceHole in spirit,
25+
`tq_*` naming): `tq_tap`, `tq_drill`, `tq_counterbore`, `tq_countersink`.
26+
- **`tq_relief_groove`** — thread-relief / runout groove cutter.
27+
28+
### Changed
29+
- `tq_bolt` / `tq_countersunk_bolt` `drive` now selects `hex` | `phillips` |
30+
`none` via a shared `_tq_drive_recess` selector (was hex-only).
31+
- The minor-radius safety assert now also accounts for `taper` (top of a tapered
32+
thread) in addition to the rounded-root depth.
33+
- `_TQ_H` is no longer used for the flank-height calc (generalized to `angle`);
34+
default `angle=60` is bit-for-bit backward compatible with v0.2.
35+
- Examples, fast/heavy test grids, README, MANUAL, and REFERENCES updated for
36+
every new helper.
37+
738
## [0.2.0] — 2026-06-22
839

940
Feature-parity release: brings tq-threads to practical parity with common

MANUAL.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ default (or an oversize internal **cutter** with `internal=true`).
7777
| `hand` | `"right"` | `"right"` or `"left"`. |
7878
| `clearance` | `0.4` | **Total diametral** fit gap (mm); external shrinks `clearance/2`, internal grows `clearance/2`. |
7979
| `profile` | `"flat"` | `"flat"` (ISO/UN basic), `"sharp"` (full V), `"rounded"` (filleted root/crest). |
80+
| `angle` | `60` | Included flank angle (degrees). 60 = ISO/UN; e.g. 55 ≈ Whitworth. Thread height derives from it. |
81+
| `tooth_height` | `undef` | Explicit radial flight depth (mm). Overrides the angle-derived height. |
82+
| `taper` | `0` | Total **diameter** reduction over the length (mm), applied linearly (base full, top reduced) — NPT-ish tapers / auger tips. |
8083
| `crest_flat` | `pitch/8` | Axial crest-flat width (mm) for `flat`. |
8184
| `root_flat` | `pitch/4` | Axial root-flat width (mm) for `flat`. |
8285
| `round` | `1` | Fillet scale for `profile="rounded"` (1 = standard ISO radii). |
@@ -214,6 +217,57 @@ tq_washer(8); // ISO 7089 M8
214217

215218
---
216219

220+
## Augers, drives, child wrappers & relief (v0.3)
221+
222+
### Custom profile controls
223+
```openscad
224+
tq_thread(12, 2, 14, angle=55); // 55° flank (Whitworth-ish)
225+
tq_thread(10, 2, 14, tooth_height=1.2); // set the radial flight depth directly
226+
tq_thread(12, 1.75, 16, taper=3); // cone: 3 mm dia reduction over the length
227+
```
228+
`angle` (default 60) sets the included flank angle; the thread height derives
229+
from it. `tooth_height` overrides that height explicitly. `taper` shifts the
230+
whole profile inward linearly along Z (NPT-ish tapers, auger tips). The
231+
minor-radius safety assert accounts for both rounded roots and `taper`.
232+
233+
### Auger / deep coarse flight
234+
```openscad
235+
tq_auger(d, length, pitch=d, flight=0.28·d, profile="rounded", starts=1, taper=0);
236+
tq_auger_hole(d, length, pitch, flight, through=true); // negative for a channel
237+
```
238+
A generic deep, large-pitch helical flight (screw-conveyor / drill / feed-screw
239+
style) — `tq_thread` driven with a big pitch + explicit `tooth_height`. Not a
240+
specific auger standard.
241+
242+
### Phillips (cross) drive
243+
```openscad
244+
tq_bolt(6, 1.0, 14, drive="phillips"); // bolt with a Phillips recess
245+
tq_countersunk_bolt(6, 1.0, 14, drive="phillips");
246+
tq_phillips_drive(size=2, depth); // cruciform cutter / tip shape
247+
tq_phillips_tip(size=2, shank_d, length); // driver-bit
248+
```
249+
`drive` selects the head recess: `"hex"` (default), `"phillips"`, or `"none"`.
250+
The Phillips form is a clean-room printable approximation (see REFERENCES),
251+
sized by PH number; `tq_ph_size_for(d)` maps a diameter to a PH number.
252+
253+
### Child-difference convenience wrappers
254+
Apply to `children()`; each cuts its hole at position `at` (default origin, axis +Z):
255+
```openscad
256+
tq_tap(8, 1.25, 12) cube([20,20,12]); // threaded hole
257+
tq_drill(5, 8, at=[6,6,0]) cube([20,20,8]); // clearance hole
258+
tq_counterbore(5, 12) translate([-9,-9,0]) cube([18,18,12]);
259+
tq_countersink(5, 8) translate([-9,-9,0]) cube([18,18,8]);
260+
```
261+
These are the ScrewHole/ClearanceHole idea expressed as original `tq_*` modules.
262+
263+
### Thread-relief groove
264+
```openscad
265+
difference() { tq_thread(10,1.5,16); translate([0,0,5]) tq_relief_groove(10); }
266+
```
267+
A shallow runout groove so a mating nut can seat fully.
268+
269+
---
270+
217271
## Hardware dimension tables
218272

219273
Public lookup **functions** (return nominal ISO values; ratio fallback for

README.md

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
99
[![GPL‑2.0 compatible](https://img.shields.io/badge/GPL--2.0-compatible-blue.svg)](#license--attribution)
1010
[![OpenSCAD](https://img.shields.io/badge/OpenSCAD-2021.01%2B-f9d72c.svg)](https://openscad.org)
11-
[![Version](https://img.shields.io/badge/version-0.2.0-informational.svg)](CHANGELOG.md)
11+
[![Version](https://img.shields.io/badge/version-0.3.0-informational.svg)](CHANGELOG.md)
1212
[![CI](https://github.com/scottconverse/tq-threads/actions/workflows/ci.yml/badge.svg)](https://github.com/scottconverse/tq-threads/actions/workflows/ci.yml)
1313

1414
*Threaded rods, bolts, nuts, tapped holes, countersinks, washers, standoffs, couplers and caps — every thread is a single watertight `polyhedron`, so models stay manifold and export straight to STL.*
@@ -148,10 +148,17 @@ with anything. Common combinations (full recipes in **[MANUAL.md](MANUAL.md#inte
148148
| Lead‑in/out chamfers | `lead_in`, `lead_out`, `chamfer` |
149149
| FDM clearance + over/undersize | `clearance=`, `internal=` |
150150
| Flat / sharp / rounded profile | `profile=`, `crest_flat`, `root_flat`, `round` |
151+
| **Custom flank angle** | `angle=` (default 60°) |
152+
| **Explicit tooth height** | `tooth_height=` |
153+
| **Tapered threads** (NPT‑ish, auger tips) | `taper=` |
151154
| Partial arc | `arc=<deg>` |
152155
| Rod / bolt / countersunk bolt / wood screw | `tq_threaded_rod`, `tq_bolt`, `tq_countersunk_bolt`, `tq_wood_screw` |
156+
| **Hex *or* Phillips drive** | `drive="hex"\|"phillips"\|"none"`; `tq_phillips_drive`, `tq_phillips_tip` |
157+
| **Auger / deep coarse flight** | `tq_auger`, `tq_auger_hole` |
153158
| Nut / standoff / coupler | `tq_nut`, `tq_standoff`, `tq_rod_coupler` |
154159
| Tapped / clearance / counterbore / countersink holes | `tq_threaded_hole`, `tq_clearance_hole`, `tq_recessed_clearance_hole`, `tq_countersunk_clearance_hole` |
160+
| **Child‑difference wrappers** | `tq_tap`, `tq_drill`, `tq_counterbore`, `tq_countersink` |
161+
| **Thread‑relief groove** | `tq_relief_groove` |
155162
| Washer | `tq_washer` |
156163
| Hex / drive geometry | `tq_hex`, `tq_hex_drive`, `tq_hex_across_flats/corners`, `tq_hex_key_af` |
157164
| Bottle / coarse thread | `tq_bottle_thread` |
@@ -220,10 +227,11 @@ Reach for **brass heat‑set inserts** instead of a printed thread when the hole
220227
Concise list; **full signatures + every parameter are in [MANUAL.md](MANUAL.md#api)**.
221228

222229
```openscad
223-
// core
230+
// core (v0.3 adds angle, tooth_height, taper)
224231
tq_thread(d, pitch, length, internal=false, starts=1, hand="right",
225-
clearance=0.4, profile="flat", crest_flat, root_flat, round=1,
226-
lead_in=true, lead_out=true, chamfer, arc=360, fn, steps_per_pitch=16, center=false);
232+
clearance=0.4, profile="flat", angle=60, tooth_height, crest_flat, root_flat,
233+
round=1, lead_in=true, lead_out=true, chamfer, taper=0,
234+
arc=360, fn, steps_per_pitch=16, center=false);
227235
228236
// presets / specs
229237
tq_preset(name) -> [major, pitch]; tq_thread_preset(name, length, ...);
@@ -234,11 +242,22 @@ tq_threaded_rod(d,pitch,length,...); tq_thread_cutter(d,pitch,length,through=tr
234242
tq_threaded_hole(d,pitch,depth,through=true,...); tq_standoff(d,pitch,length,od,...);
235243
tq_nut(d,pitch,height,across_flats,chamfer=true,...);
236244
237-
// bolts / screws (solid, fused)
245+
// bolts / screws (solid, fused) — drive = "hex" | "phillips" | "none"
238246
tq_bolt(d,pitch,length,head="socket"|"hex"|"plain"|"none",shank=0,drive="hex",...);
239-
tq_countersunk_bolt(d,pitch,length,head_d,head_angle=90,shank=0,...);
247+
tq_countersunk_bolt(d,pitch,length,head_d,head_angle=90,shank=0,drive="hex",...);
240248
tq_wood_screw(d,length,pitch,head="countersunk"|"pan",point=true,...);
241249
250+
// drives, auger, relief (v0.3)
251+
tq_phillips_drive(size,depth); tq_phillips_tip(size,shank_d,length);
252+
tq_auger(d,length,pitch,flight,taper=0,...); tq_auger_hole(d,length,pitch,flight,through=true,...);
253+
tq_relief_groove(d,width,depth);
254+
255+
// child-difference convenience wrappers (v0.3): cut a hole into children() at `at`
256+
tq_tap(d,pitch,depth,at=[0,0,0],...) <children>;
257+
tq_drill(size,depth,at=[0,0,0],fit="medium",...) <children>;
258+
tq_counterbore(size,depth,at=[0,0,0],...) <children>;
259+
tq_countersink(size,depth,at=[0,0,0],angle=90,...) <children>;
260+
242261
// holes / washers / rods
243262
tq_clearance_hole(size,depth,fit="medium",through=true,...);
244263
tq_recessed_clearance_hole(size,depth,head_d,head_h,...); // counterbore

REFERENCES.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,38 @@ for sizes outside its table.
9494
> formulae** only. Values were transcribed/derived from the published series;
9595
> no third-party library's data tables, code, or parameter choices were used.
9696
97+
### v0.3 additions — profile controls, drives, auger, taper
98+
99+
- **Custom flank angle** (`angle`, default 60°). The sharp-V height for a
100+
symmetric included angle α follows from the right triangle of half-angle α/2
101+
over an axial half-pitch: `H = (P/2)/tan(α/2)`, and the flank radial height is
102+
`h = (P − crest_flat − root_flat)/(2·tan(α/2))`. For α=60° this reduces to the
103+
ISO/UN `h = (P−cf−rf)·(√3/2)` used in v0.2 (bit-for-bit compatible). This is
104+
pure trigonometry, not taken from any library. Non-60° angles are useful for
105+
Whitworth-style (55°) or shallow printable threads.
106+
- **Explicit tooth height** (`tooth_height`). A direct override of the radial
107+
flight depth `h`; geometry then interpolates the flanks between the flats and
108+
the given depth. No external source — it is just exposing `h` as an input.
109+
- **Tapered threads** (`taper`). The whole profile is shifted radially inward by
110+
`(taper/2)·(z/L)` along the length — a linear cone applied to the height-field.
111+
For reference, real tapered pipe threads (e.g. **ANSI/ASME B1.20.1 NPT**) use a
112+
1:16 taper (≈1.79° per side); `taper` lets you reproduce any linear taper, but
113+
this library does not implement NPT's specific truncated profile.
114+
- **Phillips (cross) recess** (`tq_phillips_drive`, `drive="phillips"`). The
115+
cruciform recess concept (a central point plus four 90°-spaced wings that taper
116+
toward the tip) is described by **ISO 4757** (cross recesses for screws) and
117+
the ANSI Type I Phillips standard. tq-threads builds an **approximate, clean-room**
118+
cruciform from OpenSCAD primitives (a tapered core + two crossed hulled wings)
119+
sized by PH number; it is a printable approximation, not a gauge-accurate
120+
Phillips form, and no third-party recess code was used.
121+
- **Auger / deep coarse flight** (`tq_auger`). A generic deep, large-pitch single
122+
/multi-start helical flight (screw-conveyor / drill / feed-screw style). No
123+
specific standard; it is the core `tq_thread` driven with a large pitch and an
124+
explicit `tooth_height`, optionally tapered.
125+
- **Child-difference wrappers** (`tq_tap`, `tq_drill`, `tq_counterbore`,
126+
`tq_countersink`) and `tq_relief_groove` are pure OpenSCAD `difference()`
127+
conveniences over the existing primitives — original code, `tq_*` named.
128+
97129
The coarse "bottle/jar" thread (`tq_bottle_thread`) is a **generic** printable
98130
rounded coarse thread, **not** a specific consumer-packaging finish. If you need
99131
a real finish, public references include the **SPI/GPI "400-series"** finish

docs/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ <h1>tq-threads</h1>
7171
<a href="https://github.com/scottconverse/tq-threads/blob/main/LICENSE"><img alt="MIT" src="https://img.shields.io/badge/License-MIT-green.svg"></a>
7272
<img alt="GPL-2.0 compatible" src="https://img.shields.io/badge/GPL--2.0-compatible-blue.svg">
7373
<img alt="OpenSCAD" src="https://img.shields.io/badge/OpenSCAD-2021.01%2B-f9d72c.svg">
74-
<img alt="version" src="https://img.shields.io/badge/version-0.2.0-informational.svg">
74+
<img alt="version" src="https://img.shields.io/badge/version-0.3.0-informational.svg">
7575
<a href="https://github.com/scottconverse/tq-threads/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/scottconverse/tq-threads/actions/workflows/ci.yml/badge.svg"></a>
7676
</div>
7777
<div class="cta">
7878
<a class="btn primary" href="https://github.com/scottconverse/tq-threads">View on GitHub</a>
79-
<a class="btn ghost" href="https://github.com/scottconverse/tq-threads/releases/tag/v0.2.0">Download v0.2.0</a>
79+
<a class="btn ghost" href="https://github.com/scottconverse/tq-threads/releases/tag/v0.3.0">Download v0.3.0</a>
8080
<a class="btn ghost" href="https://github.com/scottconverse/tq-threads/blob/main/MANUAL.md">Manual</a>
8181
<a class="btn ghost" href="https://github.com/scottconverse/tq-threads/discussions">Discussions</a>
8282
</div>
@@ -90,7 +90,7 @@ <h2>Why tq-threads</h2>
9090
<div class="card"><h3>🧩 Manifold by construction</h3><p>The thread surface is a helical height-field turned into one closed <code>polyhedron</code> — no boolean unions to go non-manifold. It renders cleanly and slices.</p></div>
9191
<div class="card"><h3>📐 Standards-based, clean-room</h3><p>Built only from public standards (ISO 68-1/261/262/273/4032/4762/7089/10642, ASME&nbsp;B1.1). No third-party thread library was copied or consulted.</p></div>
9292
<div class="card"><h3>🖨️ Printable-first</h3><p>Fit clearance, internal-oversize / external-undersize compensation, lead-in chamfers, rounded roots, and real <code>$fn/$fa/$fs</code> are all parameters.</p></div>
93-
<div class="card"><h3>🔩 Batteries included</h3><p>Presets <strong>M2–M64</strong> + fine + UNC/UNF, plus bolts, nuts, washers, countersunk &amp; wood screws, clearance/counterbore/countersink holes, standoffs, couplers.</p></div>
93+
<div class="card"><h3>🔩 Batteries included</h3><p>Presets <strong>M2–M64</strong> + fine + UNC/UNF, plus bolts, nuts, washers, countersunk &amp; wood screws, clearance/counterbore/countersink holes, standoffs, couplers — and v0.3 adds <strong>augers, Phillips drives, tapered &amp; custom‑angle threads,</strong> and child‑difference <code>tq_tap</code>/<code>tq_drill</code> wrappers.</p></div>
9494
<div class="card"><h3>⚖️ MIT licensed</h3><p>Permissive <em>and</em> GPL-2.0-compatible, so it drops into a GPL-2.0-only project (e.g.&nbsp;TinkerQuarry) unchanged.</p></div>
9595
<div class="card"><h3>✅ Tested &amp; CI</h3><p>Compile-time preset assertions, split fast/heavy suites, a PowerShell render-proof, and GitHub Actions rendering on every push.</p></div>
9696
</div>

scripts/render-tests.ps1

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
pwsh scripts/render-tests.ps1 -OpenSCAD "C:\Program Files\OpenSCAD\openscad.exe" -Heavy
2323
2424
.NOTES
25+
Runs on BOTH Windows PowerShell 5.1 and PowerShell 7+ (pwsh). No PS7-only
26+
syntax is used.
27+
28+
On Windows, prefer the console build "openscad.com" (returns exit codes and
29+
stderr to the console correctly); "openscad.exe" is the GUI build and may not
30+
surface console output. This script auto-detects ".com" first, then ".exe".
31+
2532
Expected render times (typical desktop):
2633
fast suite (tq_threads_fast_tests.scad) : ~2-8 seconds
2734
examples (SHOW=all) : ~30-90 seconds
@@ -40,10 +47,16 @@ $root = Split-Path -Parent $PSScriptRoot # repo root (scripts/..)
4047
function Resolve-OpenSCAD([string]$hint) {
4148
$cands = @()
4249
if ($hint) { $cands += $hint }
50+
# Prefer the Windows console build (.com) -- it returns exit codes/stderr to
51+
# the console; the GUI build (.exe) may not.
4352
$cands += @(
53+
"C:\Program Files\OpenSCAD\openscad.com",
4454
"C:\Program Files\OpenSCAD\openscad.exe",
55+
"C:\Program Files\OpenSCAD (Nightly)\openscad.com",
4556
"C:\Program Files\OpenSCAD (Nightly)\openscad.exe",
57+
"C:\Users\Scott\Desktop\CODE\_tools\openscad\openscad-2021.01\openscad.com",
4658
"C:\Users\Scott\Desktop\CODE\_tools\openscad\openscad-2021.01\openscad.exe",
59+
"openscad.com",
4760
"openscad"
4861
)
4962
foreach ($c in $cands) {
@@ -75,7 +88,7 @@ foreach ($name in $jobs.Keys) {
7588
-NoNewWindow -Wait -PassThru -RedirectStandardError $err
7689
$sw.Stop()
7790
$secs = [math]::Round($sw.Elapsed.TotalSeconds, 1)
78-
$stderr = (Test-Path $err) ? (Get-Content $err -Raw) : ""
91+
$stderr = if (Test-Path $err) { Get-Content $err -Raw } else { "" } # PS 5.1-safe (no ternary)
7992
$warn = $stderr -match "WARNING|ERROR|not a valid 2-manifold"
8093
$facets = if ($stderr -match "Facets:\s*(\d+)") { $Matches[1] } else { "?" }
8194
$okExit = ($p.ExitCode -eq 0)

0 commit comments

Comments
 (0)