{"id":51670903,"url":"https://github.com/scottconverse/tq-threads","last_synced_at":"2026-07-15T00:03:45.471Z","repository":{"id":366656400,"uuid":"1277212402","full_name":"scottconverse/tq-threads","owner":"scottconverse","description":"Clean-room, MIT, printable OpenSCAD screw threads (ISO metric + Unified) with bolts, nuts, washers, tapped/clearance/countersunk holes, standoffs, couplers and more.","archived":false,"fork":false,"pushed_at":"2026-06-22T18:31:06.000Z","size":74,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T20:21:10.261Z","etag":null,"topics":["3d-printing","bolts-and-nuts","cad","clean-room","fasteners","fdm","iso-metric","library","openscad","threads"],"latest_commit_sha":null,"homepage":null,"language":"OpenSCAD","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scottconverse.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-22T17:28:10.000Z","updated_at":"2026-06-22T18:31:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/scottconverse/tq-threads","commit_stats":null,"previous_names":["scottconverse/tq-threads"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/scottconverse/tq-threads","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottconverse%2Ftq-threads","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottconverse%2Ftq-threads/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottconverse%2Ftq-threads/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottconverse%2Ftq-threads/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scottconverse","download_url":"https://codeload.github.com/scottconverse/tq-threads/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottconverse%2Ftq-threads/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35483861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d-printing","bolts-and-nuts","cad","clean-room","fasteners","fdm","iso-metric","library","openscad","threads"],"created_at":"2026-07-15T00:03:44.721Z","updated_at":"2026-07-15T00:03:45.462Z","avatar_url":"https://github.com/scottconverse.png","language":"OpenSCAD","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- SPDX-License-Identifier: MIT --\u003e\n\u003cdiv align=\"center\"\u003e\n\n# tq‑threads\n\n### Clean‑room, printable **screw threads for OpenSCAD** — ISO metric + Unified, plus the hardware built from them.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![GPL‑2.0 compatible](https://img.shields.io/badge/GPL--2.0-compatible-blue.svg)](#license--attribution)\n[![OpenSCAD](https://img.shields.io/badge/OpenSCAD-2021.01%2B-f9d72c.svg)](https://openscad.org)\n[![Version](https://img.shields.io/badge/version-0.6.0-informational.svg)](CHANGELOG.md)\n[![CI](https://github.com/scottconverse/tq-threads/actions/workflows/ci.yml/badge.svg)](https://github.com/scottconverse/tq-threads/actions/workflows/ci.yml)\n\n*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.*\n\n\u003c/div\u003e\n\n---\n\n## Why tq‑threads\n\n- **Clean‑room \u0026 standards‑based.** Written from public engineering standards only (ISO 68‑1, ISO 261/262, ISO 273, ISO 4032, ISO 4762, ISO 7089, ISO 10642, ASME B1.1). No third‑party thread library was copied or consulted — see [REFERENCES.md](REFERENCES.md).\n- **Manifold by construction.** The thread surface is a helical *height‑field* turned into one closed `polyhedron` (no boolean unions to go non‑manifold). It renders cleanly and slices.\n- **Printable‑first.** Fit clearance, internal‑oversize / external‑undersize compensation, lead‑in chamfers, rounded roots, and `$fn/$fa/$fs` resolution are all parameters.\n- **Batteries included.** **101 presets** (M1.6–M64 coarse + full ISO 261 fine + UNC/UNF #0–1″), plus bolts (hex/socket/**Phillips**), nuts, washers, countersunk \u0026 wood screws, **augers**, clearance/counterbore/countersink holes, standoffs, couplers, child‑difference wrappers (`tq_tap`/`tq_drill`/…), and a debug view. Profile control: custom flank **angle**, `side_angle`, `thread_size`, square/rectangular/groove forms, **tooth_height**, **minor_d**, **taper**, and optional **ISO 965 `fit=`** allowance.\n- **MIT licensed** → permissive *and* GPL‑2.0‑compatible, so it drops into a GPL‑2.0‑only project (e.g. TinkerQuarry) unchanged.\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"docs/architecture.svg\" alt=\"tq-threads architecture\" width=\"820\"\u003e\n\u003c/div\u003e\n\n---\n\n## Contents\n\n- [Install / use as a library](#install--use-as-a-library)\n- [Quick start](#quick-start)\n- [Integrating with other OpenSCAD packages](#integrating-with-other-openscad-packages)\n- [Capability checklist](#capability-checklist)\n- [Thread terminology](#thread-terminology)\n- [Diameter vs pitch vs TPI](#diameter-vs-pitch-vs-tpi)\n- [FDM tolerance guide](#fdm-tolerance-guide)\n- [When to use heat‑set inserts](#when-to-use-heat-set-inserts)\n- [API reference](#api-reference)\n- [Presets](#presets)\n- [Testing \u0026 render‑proof](#testing--render-proof)\n- [Limitations](#limitations)\n- [Versioning, contributing, license](#license--attribution)\n\n\u003e Looking for the deep dive? Use the polished **[web manual](https://scottconverse.github.io/tq-threads/manual.html)**. The repo also keeps **[MANUAL.md](MANUAL.md)** as the Markdown source/reference.\n\n---\n\n## Install / use as a library\n\nOpenSCAD has no central package manager; libraries are consumed by putting the\n`.scad` file where an `include`/`use` can find it. Pick whichever fits:\n\n**1. Git submodule (recommended for a project under version control)**\n```sh\ngit submodule add https://github.com/scottconverse/tq-threads libs/tq-threads\n```\n```openscad\ninclude \u003clibs/tq-threads/tq_threads.scad\u003e;\ntq_thread_preset(\"M8\", 20);\n```\n\n**2. Clone / download a release, drop on the OpenSCAD library path**\n```sh\ngit clone https://github.com/scottconverse/tq-threads\n# copy tq_threads.scad into your OpenSCAD library folder, e.g.:\n#   Windows : %USERPROFILE%\\Documents\\OpenSCAD\\libraries\\\n#   Linux   : ~/.local/share/OpenSCAD/libraries/\n#   macOS   : ~/Documents/OpenSCAD/libraries/\n```\n```openscad\ninclude \u003ctq_threads.scad\u003e;   // resolved from the library path\n```\n\n**3. Vendoring (e.g. into TinkerQuarry's `library/` folder)**\nCopy `tq_threads.scad` next to your model and `include \u003ctq_threads.scad\u003e;`.\nA release `.zip` (Releases tab) works the same way for non‑git users.\n\n\u003e Only `tq_threads.scad` is required at runtime. The `*_examples.scad`,\n\u003e `*_tests.scad`, `scripts/`, and `docs/` are for development and can be ignored\n\u003e by consumers.\n\n---\n\n## Quick start\n\n```openscad\ninclude \u003ctq_threads.scad\u003e;\n$fn = 64;\n\n// 1. An M8 × 1.25 threaded rod, 20 mm long\ntq_thread_preset(\"M8\", 20);\n\n// 2. A tapped M6 hole through a block\ndifference() {\n    cube([20, 20, 12], center = true);\n    tq_threaded_hole(d = 6, pitch = 1.0, depth = 12);\n}\n\n// 3. A socket-head cap screw and a matching nut (same clearance =\u003e they fit)\ntq_bolt(d = 8, pitch = 1.25, length = 20, head = \"socket\", shank = 4, clearance = 0.4);\ntranslate([20,0,0]) tq_nut(d = 8, pitch = 1.25, clearance = 0.4);\n\n// 4. Imperial by threads-per-inch\ntranslate([0,20,0]) tq_thread_tpi(d = tq_in(1/4), tpi = 20, length = 12);\n```\n\nOpen any `.scad` here in OpenSCAD: **F5** previews instantly, **F6** renders.\nHeadless STL:\n```sh\nopenscad -o rod.stl -D 'SHOW=\"bolt\"' tq_threads_examples.scad\n```\n\n## Choose Your Starting Point\n\n| Need | Start with | Example |\n|---|---|---|\n| A named threaded rod | `tq_thread_preset` | `tq_thread_preset(\"M8\", 20);` |\n| A custom diameter/pitch thread | `tq_thread` | `tq_thread(8, 1.25, 20);` |\n| A tapped printed hole | `tq_threaded_hole` | `difference(){ part(); tq_threaded_hole(6, 1, 12); }` |\n| A subtractive thread cutter | `tq_thread_cutter` | `difference(){ part(); tq_thread_cutter(8, 1.25, 16); }` |\n| A matching printed bolt/nut pair | same `clearance` on both | `tq_bolt(..., clearance=0.4); tq_nut(..., clearance=0.4);` |\n| A square, rectangular, or groove profile | `tq_thread` or preset/TPI wrappers | `tq_thread_preset(\"M8\", 20, profile=\"square\", thread_size=1);` |\n\n---\n\n## Integrating with other OpenSCAD packages\n\ntq‑threads is a plain library with a `tq_`‑prefixed namespace, so it coexists\nwith anything. Common combinations (full recipes in the **[web manual](https://scottconverse.github.io/tq-threads/manual.html#integration)**):\n\n| You use… | How tq‑threads fits |\n|---|---|\n| **BOSL2 / BOSL** | Use BOSL2 for attachments, rounding, and shapes; use tq‑threads for the actual threads. No symbol clashes (`tq_*` vs BOSL2's names). Subtract `tq_thread_cutter()` from BOSL2 solids; the `tq_*` parts are normal children you can `attach()` around. |\n| **Migrating from Dan Kirshner / rcolyer `threads.scad`** | `metric_thread(d,p,l)` → `tq_thread(d,p,l)`; `english_thread()` → `tq_thread_tpi()`; `ScrewThread`/`ScrewHole` → `tq_thread` / `tq_threaded_hole`; `RodStart/RodEnd` → `tq_rod_start/tq_rod_end`. See the [migration table](https://scottconverse.github.io/tq-threads/manual.html#migration). |\n| **TinkerQuarry** | MIT → GPL‑2.0 compatible; vendor `tq_threads.scad` into `library/` and `include` it from generated `.scad`. The generator can call presets by name (`tq_thread_preset(\"M8\", …)`). |\n| **Slicers (Orca/Cura/Prusa/Bambu)** | Export STL/3MF; threads are manifold so no repair step is needed. Print **axis vertical** for best flanks. |\n| **NopSCADlib / hardware libs** | Use their part catalogs for visualization; use tq‑threads when you need a *printable* thread instead of a cosmetic one. |\n\n---\n\n## Capability checklist\n\n| Capability | API |\n|---|---|\n| ISO metric external thread | `tq_thread(internal=false)` |\n| ISO metric internal cutter | `tq_thread_cutter` / `internal=true` |\n| Unified external / internal | `tq_thread_tpi`, inch presets |\n| Named presets (101: metric coarse+fine + UNC/UNF) | `tq_thread_preset`, `tq_preset`, `tq_preset_count` |\n| ISO 965 fit class (allowance) | `fit=\"6g\"`/`\"6H\"`/… |\n| Custom Ø / pitch / TPI / minor Ø | `tq_thread`, `tq_thread_tpi`, `minor_d=` |\n| Left / right hand | `hand=\"left\"\\|\"right\"` |\n| Multi‑start | `starts=N` |\n| Length / centering | `length=`, `center=` |\n| Lead‑in/out chamfers | `lead_in`, `lead_out`, `chamfer` |\n| FDM clearance + over/undersize | `clearance=`, `internal=` |\n| Flat / sharp / rounded / square / rectangular profile | `profile=`, `crest_flat`, `root_flat`, `round`, `rect_ratio=` |\n| **Custom flank angle** | `angle=` (default 60°) |\n| **Side angle convention** | `side_angle=30` gives a 60-degree included V |\n| Independent tooth width | `thread_size=` |\n| Groove channels | `groove=true` |\n| **Explicit tooth height** | `tooth_height=` |\n| **Tapered threads** (NPT‑ish, auger tips) | `taper=`, `taper_rate=`, `tq_npt_taper_rate()` |\n| Partial arc | `arc=\u003cdeg\u003e` |\n| Rod / bolt / countersunk bolt / wood screw | `tq_threaded_rod`, `tq_bolt`, `tq_countersunk_bolt`, `tq_wood_screw` |\n| **Hex *or* Phillips drive** | `drive=\"hex\"\\|\"phillips\"\\|\"none\"`; `tq_phillips_drive`, `tq_phillips_tip` |\n| **Auger / deep coarse flight** | `tq_auger`, `tq_auger_hole` |\n| Nut / standoff / coupler | `tq_nut`, `tq_standoff`, `tq_rod_coupler` |\n| Tapped / clearance / counterbore / countersink holes | `tq_threaded_hole`, `tq_clearance_hole`, `tq_recessed_clearance_hole`, `tq_countersunk_clearance_hole` |\n| **Child‑difference wrappers** | `tq_tap`, `tq_drill`, `tq_counterbore`, `tq_countersink` |\n| **Thread‑relief groove** | `tq_relief_groove` |\n| Washer | `tq_washer` |\n| Hex / drive geometry | `tq_hex`, `tq_hex_drive`, `tq_hex_across_flats/corners`, `tq_hex_key_af` |\n| Bottle / coarse thread | `tq_bottle_thread` |\n| Debug view | `tq_thread_debug` |\n\n---\n\n## Thread terminology\n\n```\n        |\u003c-- P --\u003e|              P     = pitch: axial crest-to-crest distance\n     /\\        /\\        /\\       crest = outer tip of the thread\n    /  \\      /  \\      /  \\      root  = inner valley between threads\n___/    \\____/    \\____/    \\__   flank = angled side wall (60° included angle)\n   |\u003c-------- major Ø --------\u003e|  major Ø = largest diameter (over crests)\n       |\u003c---- minor Ø ----\u003e|      minor Ø = smallest diameter (over roots)\n   lead = axial advance per turn = starts × P\n```\n\n- **External** = bolt/rod (crests outward). **Internal** = nut/tapped hole (the negative; cut with `tq_thread_cutter`).\n- **Hand**: right‑hand advances when turned clockwise (default). Left is mirrored.\n- **Starts**: multi‑start = several parallel grooves; `lead = starts × P` (faster travel, common on caps).\n\n---\n\n## Diameter vs pitch vs TPI\n\n| System | You give | Call |\n|---|---|---|\n| Metric | major Ø + **pitch (mm)** | `tq_thread(d, pitch, length)` |\n| Imperial / Unified | major Ø + **TPI** | `tq_thread_tpi(d, tpi, length)` |\n\n`pitch_mm = 25.4 / TPI`. `tq_in(x)` converts inches → mm. Pitch ≠ lead unless single‑start.\n\n---\n\n## FDM tolerance guide\n\n`clearance` is the **total diametral gap** between mating threads, split evenly\n(external shrinks `clearance/2`, internal grows `clearance/2`). Make a bolt and\nits nut with the **same** `clearance` and they fit.\n\n| Printer / fit | `clearance` |\n|---|---|\n| Tight, well‑tuned | 0.2 – 0.3 mm |\n| **Default / safe** | **0.4 mm** |\n| Loose / fast | 0.5 – 0.6 mm |\n| Coarse caps / lids | 0.5 – 0.8 mm |\n\n- Print **axis vertical**; avoid supports inside tapped holes.\n- Keep lead‑in chamfers on (default) for self‑starting threads + clean top layers.\n- Pitches **\u003c ~0.7 mm** (fine M2–M3) are at a 0.4 mm nozzle's limit — print slow or use a heat‑set insert.\n- `profile=\"rounded\"` gives stronger roots for load‑bearing parts.\n- Calibrate once with a small clearance matrix; it's the highest‑value 10 minutes you'll spend.\n\n---\n\n## When to use heat‑set inserts\n\n`fit=` is nominal ISO 965 position intent, not an FDM fit knob. For example,\nM8 `6g` shifts diameter by about 0.029 mm, below typical printed clearance and\nlayer-line effects; tune `clearance` for real printed fit.\n\nReach for **brass heat‑set inserts** instead of a printed thread when the hole is small/fine (≤ M3), the joint is assembled/disassembled often, you need high pull‑out/torque, or you're threading across layer lines (side walls). For those, print a smooth tapered pilot (a plain `cylinder()` or `tq_standoff` with a plain bore) sized to the insert spec and melt it in. Reserve `tq_threaded_hole` for printed threads ≥ M4 and coarse/cap threads. Details in the [web manual](https://scottconverse.github.io/tq-threads/manual.html#fit).\n\n---\n\n## API reference\n\nConcise list; **full signatures + every parameter are in the [web manual](https://scottconverse.github.io/tq-threads/manual.html#core-api)**.\n\n```openscad\n// core (v0.6 adds square/rectangle/groove, thread_size, side_angle, taper_rate)\ntq_thread(d, pitch, length, internal=false, starts=1, hand=\"right\",\n          clearance=0.4, fit=undef, profile=\"flat\", angle=60,\n          tooth_height=undef, minor_d=undef, crest_flat=undef, root_flat=undef,\n          round=1, lead_in=true, lead_out=true, chamfer=undef, taper=0,\n          arc=360, fn=undef, steps_per_pitch=16, center=false,\n          thread_size=undef, side_angle=undef, rect_ratio=undef,\n          groove=false, taper_rate=undef, lead_ends=undef);\n// preset introspection / table self-check\ntq_preset_count();  tq_presets_selfcheck();\n\n// presets / specs\ntq_preset(name) -\u003e [major, pitch];   tq_thread_preset(name, length, ...); // forwards profile controls\ntq_thread_tpi(d, tpi, length, ...);  tq_in(inches) -\u003e mm;                 // forwards profile controls\n\n// threaded primitives\ntq_threaded_rod(d,pitch,length,...);  tq_thread_cutter(d,pitch,length,through=true,...);\ntq_threaded_hole(d,pitch,depth,through=true,...);  tq_standoff(d,pitch,length,od,...);\ntq_nut(d,pitch,height,across_flats,chamfer=true,...);\n\n// bolts / screws (solid, fused) — drive = \"hex\" | \"phillips\" | \"none\"\ntq_bolt(d,pitch,length,head=\"socket\"|\"hex\"|\"plain\"|\"none\",shank=0,drive=\"hex\",...);\ntq_countersunk_bolt(d,pitch,length,head_d,head_angle=90,shank=0,drive=\"hex\",...);\ntq_wood_screw(d,length,pitch,head=\"countersunk\"|\"pan\",point=true,...);\n\n// drives, auger, relief (v0.3)\ntq_phillips_drive(size,depth);  tq_phillips_tip(size,shank_d,length);\ntq_ph_dims(size) -\u003e [arm_reach,wing_width];  tq_ph_size_for(d) -\u003e PH number;\ntq_auger(d,length,pitch,flight,taper=0,...);  tq_auger_hole(d,length,pitch,flight,through=true,...);\ntq_relief_groove(d,width,depth);\n\n// child-difference convenience wrappers (v0.3): cut a hole into children() at `at`\ntq_tap(d,pitch,depth,at=[0,0,0],...) \u003cchildren\u003e;\ntq_drill(size,depth,at=[0,0,0],fit=\"medium\",...) \u003cchildren\u003e;\ntq_counterbore(size,depth,at=[0,0,0],...) \u003cchildren\u003e;\ntq_countersink(size,depth,at=[0,0,0],angle=90,...) \u003cchildren\u003e;\n\n// holes / washers / rods\ntq_clearance_hole(size,depth,fit=\"medium\",through=true,...);\ntq_recessed_clearance_hole(size,depth,head_d,head_h,...);     // counterbore\ntq_countersunk_clearance_hole(size,depth,head_d,angle=90,...);\ntq_washer(size,od,id,thk,...);\ntq_rod_start(d,pitch,length,...);  tq_rod_end(...);  tq_rod_coupler(d,pitch,length,od,...);\ntq_bottle_thread(d,pitch,length,internal=false,depth_frac=0.6,...);\n\n// hardware dimension tables (functions)\ntq_clearance_dia(size,fit);  tq_washer_dims(size);  tq_nut_thickness(size);\ntq_nut_across_flats(size);   tq_shcs_head(size);    tq_hex_key_af(size);  tq_csk_head_dia(size);\n\n// hex / drive\ntq_hex(af,h);  tq_hex_drive(af,depth);  tq_hex_across_flats(ac);  tq_hex_across_corners(af);\n\n// debug\ntq_thread_debug(d,pitch,length,...);\n```\n\n---\n\n## Standards \u0026 fidelity (exact vs. approximate)\n\ntq-threads is **printable-first, not metrology-grade** — it renders one nominal\nsurface, so it cannot certify a tolerance class or replace gauges/calipers. Every\ntable/formula is classified **EXACT / DERIVED / FDM / APPROX** in\n[REFERENCES.md §0](REFERENCES.md) and the [PROVENANCE ledger](PROVENANCE.md):\n\n- **Exact nominal**: metric coarse/fine Ø+pitch (ISO 261), Unified Ø+TPI (ASME B1.1), listed ISO hardware dims (273/4032/4762/7089/10642).\n- **Derived** (exact formula): the 60° form \u0026 `H`, custom-`angle` geometry, rounded fillets, and the optional **ISO 965 `fit=`** allowance (the *position*, e.g. `es=-(15+11·P)` µm for `g`; the tolerance *grade/band* is **not** modelled). On M8 `6g`, this is about 0.029 mm diametral shift, so treat it as nominal intent and use `clearance` for FDM fit.\n- **FDM defaults**: `clearance` (0.4 mm) and resolution floors.\n- **Approx / generic** (no standard claimed): Phillips recess, `tq_auger`, `tq_bottle_thread`, `tq_wood_screw`, ratio fallbacks for unlisted sizes.\n- **Generic profile controls**: `profile=\"square\"`, `\"rectangle\"`, `thread_size`, `rect_ratio`, and `groove` are printable first-principles forms, not ACME/trapezoidal/buttress standards or fit-class guarantees.\n\n```openscad\ntq_thread(8,1.25,20);                          // printable default (FDM clearance)\ntq_thread(8,1.25,20, clearance=0);             // nominal geometry, no allowance\ntq_thread(8,1.25,20, clearance=0, fit=\"6g\");   // + ISO 965 position-g allowance\ntq_thread(10,4,20, thread_size=1, side_angle=30, profile=\"sharp\"); // narrow 60-degree V\ntq_thread(12,3,20, profile=\"square\", thread_size=1.5);             // square tooth\ntq_thread(12,6,20, profile=\"rectangle\", thread_size=4, rect_ratio=1/3);\ntq_thread(14,4,20, profile=\"square\", groove=true, lead_ends=\"both\"); // helical channel\n```\n\n### Profile recipes\n\n| Intent | Parameters | Notes |\n|---|---|---|\n| Standard ISO/UN-style V | default `profile=\"flat\"` | Basic truncated 60-degree form. |\n| Full pointed V | `profile=\"sharp\"` | Full V height; useful for visualization/self-tapping-style forms, not load-bearing FDM. |\n| Narrow widely spaced V | `thread_size \u003c pitch`, optional `side_angle=30` | Pitch controls travel; `thread_size` controls tooth width/depth. |\n| Square tooth | `profile=\"square\", thread_size=\u003cw\u003e` | Generic printable square form, no standards fit class claimed. |\n| Shallow rectangular tooth | `profile=\"rectangle\", rect_ratio=1/3` | Radial depth = `thread_size * rect_ratio`. |\n| Helical groove/channel | `groove=true` with any profile | Inverts the profile into the cylinder surface. |\n| NPT-rate taper reference | `taper_rate=tq_npt_taper_rate()` | 1:16 diameter taper only; not an NPT thread profile. |\nWhat needs **physical prints + calipers** (real fit, class compliance, SPI/GPI\ninterchange, pull-out strength) is listed in [PROVENANCE.md](PROVENANCE.md).\n\n---\n\n## Presets (101)\n\nMetric coarse (ISO 261): `M1.6 M2 M2.5 M3 M3.5 M4 M5 M6 M7 M8 M10 M12 M14 M16 M18 M20 M22 M24 M27 M30 M33 M36 M39 M42 M45 M48 M52 M56 M60 M64`\nMetric fine (ISO 261): `M3x0.35 M4x0.5 M5x0.5 M6x0.75 M8x1 M8x0.75 M10x1.25 M10x1 M10x0.75 M12x1.5 M12x1.25 M12x1 M14x1.5 M16x1.5 M16x1 M18x2 M18x1.5 M20x2 M20x1.5 M20x1 M22x1.5 M24x2 M24x1.5 M27x2 M30x3 M30x2 M30x1.5 M33x2 M36x3 M36x2 M42x3 M48x3`\nUnified numbered (ASME B1.1): `#0-80 #1-64 #1-72 #2-56 #2-64 #3-48 #3-56 #4-40 #4-48 #5-40 #5-44 #6-32 #6-40 #8-32 #8-36 #10-24 #10-32 #12-24 #12-28`\nUnified fractional: `1/4-20 1/4-28 5/16-18 5/16-24 3/8-16 3/8-24 7/16-14 7/16-20 1/2-13 1/2-20 9/16-12 9/16-18 5/8-11 5/8-18 3/4-10 3/4-16 7/8-9 7/8-14 1-8 1-12`\n\n```openscad\np = tq_preset(\"M12\");          // -\u003e [12, 1.75]\ntq_thread_preset(\"#10-32\", 16);\necho(tq_preset_count());        // 101   (assert tq_presets_selfcheck())\n```\n\n---\n\n## Testing \u0026 render‑proof\n\n```sh\n# fast smoke suite (preset assertions + small grid) — seconds\nopenscad -o selftest.stl tq_threads_selftest.scad   # standards-table asserts\nopenscad -o out.stl      tq_threads_fast_tests.scad\n\n# full visual demo grid — minutes (N-way union); F5 preview is instant\nopenscad -o demo.stl tq_threads_heavy_tests.scad\n```\nPowerShell render‑proof (auto-detects OpenSCAD, checks both stdout/stderr, runs negative asserts and independent STL edge-pairing):\n```powershell\npowershell -ExecutionPolicy Bypass -File scripts\\render_proof.ps1          # full proof: PASS/FAIL, version+timings, negative tests, exits nonzero on fail\npowershell -ExecutionPolicy Bypass -File scripts\\render_proof.ps1 -Heavy   # + heavy grid\n```\nRuns on Windows PowerShell 5.1 and pwsh 7+. (`scripts/render-tests.ps1` is a deprecated alias.) If you pass `-OpenSCAD`, that exact executable must exist; otherwise the script auto-detects one.\n\n**Running one example (Windows-robust, no fragile quoting):**\n```sh\nopenscad -o bolt.stl examples/bolt.scad                  # wrapper file — works in every shell\nopenscad -o nut.stl  -D PART=5 tq_threads_examples.scad  # shell-safe numeric index (no quotes)\n```\n\u003e The legacy `-D SHOW=\"bolt\"` form still works but needs careful PowerShell quoting (`-D 'SHOW=\\\"bolt\\\"'`); it's a fallback, not the primary path.\n\nA GitHub Actions workflow ([`.github/workflows/ci.yml`](.github/workflows/ci.yml)) runs the suites on every push.\n\n---\n\n## Limitations\n\n- Default `flat` profile uses the ISO/UN **basic** truncations (flat root, engaged height `0.5413·P`); choose `profile=\"rounded\"` for the deeper rounded root.\n- Internal threads are cut with an external‑form **cutter** sized by `clearance` — pragmatic and accurate for FDM, not metrology‑grade.\n- It's a **height‑field**, so high `$fn` × long coarse threads make large meshes; tune `$fn`/`steps_per_pitch` for big parts.\n- A single fused STL of the *whole* heavy grid is slow (N‑way CGAL union) — that's the union, not any one part. Per‑part export and F5 preview are fast.\n- `profile=\"sharp\"` makes full-height knife‑edge crests (for self‑tapping-style forms / visualization), not for load-bearing FDM.\n- `side_angle` is measured from the plane perpendicular to the axis; `side_angle=30` gives a 60-degree included V. The older `angle=60` parameter is still the included-angle convention.\n- `taper_rate=tq_npt_taper_rate()` reproduces the NPT reference rate of 1:16 diameter change per length; it does not make the thread an NPT standard profile.\n- Square, rectangular, and groove profiles are generic printable forms. ACME/trapezoidal, buttress, and full NPT standards profiles are out of scope.\n\n---\n\n## Migration from v0.2 / v0.3 / v0.5\n\nv0.6 is **backward compatible** — no public API was removed or renamed.\n\n- `include \u003ctq_threads.scad\u003e;` unchanged; default `angle=60` keeps v0.2/v0.3 geometry bit-for-bit.\n- New **optional** params through v0.6: `fit`, `minor_d`, `thread_size`, `side_angle`, `rect_ratio`, `groove`, `taper_rate`, and `lead_ends` on `tq_thread`; preset/TPI wrappers forward the same profile controls.\n- `tq_wood_screw(... taper=, core_d=, thread_depth=, point=\"gimlet\"|\"cone\"|\"flat\", shank=)` keeps old `point=true/false`; `tq_bottle_thread(... angle=, tooth_height=, profile=, lead_in=)` remains compatible.\n- Presets expanded 43 → **101** (existing names unchanged).\n- Example selection: prefer **`examples/\u003cpart\u003e.scad` wrappers** or **`-D PART=n`** over the old `-D SHOW=\"...\"` string (still supported).\n- `scripts/render-tests.ps1` → **`scripts/render_proof.ps1`** (old name kept as a deprecated alias).\n\n---\n\n## License \u0026 attribution\n\nMIT — see [LICENSE](LICENSE). The FSF lists MIT/Expat as **GPL‑compatible**, so\ntq‑threads can be included in and distributed with a GPL‑2.0‑only project.\nGeometry derives from public standards only; the clean‑room statement and the\nfull list of standards/formulae are in [REFERENCES.md](REFERENCES.md).\nContributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) and the\n[discussion seeds](docs/discussions/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottconverse%2Ftq-threads","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscottconverse%2Ftq-threads","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottconverse%2Ftq-threads/lists"}