diff --git a/readme.md b/readme.md
index 17251b4..d95ff2a 100644
--- a/readme.md
+++ b/readme.md
@@ -43,13 +43,13 @@ A list of changes classified as breaking, additions or fixes is maintained in [C
Extrusion_brackets | PSUs | Terminals | Pocket_handle | Sweep | |
Extrusions | Panel_meters | Toggles | Press_fit | Thread | |
Fans | Photo_interrupters | Transformers | Printed_box | Tube | |
- Fastons | Pillars | Tubings | Printed_pulleys | | |
- Fuseholder | Pillow_blocks | Variacs | Ribbon_clamp | | |
- Gear_motors | Pin_headers | Veroboard | SSR_shroud | | |
- Geared_steppers | Potentiometers | Washers | Screw_knob | | |
- Green_terminals | Pulleys | Wire | Socket_box | | |
- Hot_ends | | Zipties | Strap_handle | | |
- Hygrometer | | | | | |
+ Fastons | Pillars | Ttracks | Printed_pulleys | | |
+ Fuseholder | Pillow_blocks | Tubings | Ribbon_clamp | | |
+ Gear_motors | Pin_headers | Variacs | SSR_shroud | | |
+ Geared_steppers | Potentiometers | Veroboard | Screw_knob | | |
+ Green_terminals | Pulleys | Washers | Socket_box | | |
+ Hot_ends | | Wire | Strap_handle | | |
+ Hygrometer | | Zipties | | | |
---
@@ -4684,6 +4684,80 @@ Iron core transformers. The grey shaded area is the keep out region where the te
| 1 | `transformer(SMALLTX)` | Transformer Small mains |
+Top
+
+---
+
+## Ttracks
+T-Tracks used in woodworking jigs
+
+[vitamins/ttracks.scad](vitamins/ttracks.scad) Object definitions.
+
+[vitamins/ttrack.scad](vitamins/ttrack.scad) Implementation.
+
+[tests/ttracks.scad](tests/ttracks.scad) Code for this example.
+
+### Properties
+| Function | Description |
+|:--- |:--- |
+| `t_insert_description(type)` | Description of this t-track insert |
+| `t_insert_height(type)` | Height of t-track insert |
+| `t_insert_thread(type)` | M thread for this the screw hole in this insert |
+| `t_insert_top_thickness(type)` | Top thickness for t-track insert |
+| `t_insert_top_width(type)` | Top Width of t-track insert |
+| `t_insert_width(type)` | Width of t-track insert |
+| `tbolt_description(type)` | Description of this t-track bolt |
+| `tbolt_head_length(type)` | Head length for t-track bolt |
+| `tbolt_head_thickness(type)` | Head thickness for t-track bolt |
+| `tbolt_head_width(type)` | Head width for t-track bolt |
+| `tbolt_thread(type)` | M thread for this bolt |
+| `ttrack_fixture(type)` | Fixture, such as T-bolt or Miter insert used with this track |
+| `ttrack_height(type)` | Height of track section |
+| `ttrack_opening(type)` | Width of the opening |
+| `ttrack_screw(type)` | Screw used to fasten track |
+| `ttrack_screw_pitch(type)` | Distance between screws |
+| `ttrack_slot_height(type)` | Height of the slot |
+| `ttrack_slot_width(type)` | Width of the slot |
+| `ttrack_top_thickness(type)` | Thickness of the top layer |
+| `ttrack_width(type)` | Width of track section |
+
+### Functions
+| Function | Description |
+|:--- |:--- |
+| `ttrack_holes(type, length)` | Number of holes in a rail given its `length` |
+
+### Modules
+| Module | Description |
+|:--- |:--- |
+| `ttrack(type, length, colour = "LightSlateGray")` | Draw the specified rail |
+| `ttrack_hole_positions(type, length)` | Position children over screw holes |
+| `ttrack_place_bolt(type, pos, bolt = undef)` | Place a T-Bolt relative to the centre of the track |
+| `ttrack_place_insert(type, pos, insert = undef)` | Place a T-Insert relative to the centre of the track |
+
+
+
+### Vitamins
+| Qty | Module call | BOM entry |
+| ---:|:--- |:---|
+| 3 | `screw(M3_cs_cap_screw, 15)` | Screw M3 cs cap x 15mm |
+| 3 | `screw(M4_cs_cap_screw, 15)` | Screw M4 cs cap x 15mm |
+| 2 | `screw(M6_hex_screw, 15)` | Screw M6 hex x 15mm |
+| 1 | `ttrack(ttrack_mitre_30mm, 120)` | T-Track ttrack_mitre_30mm x 120mm |
+| 1 | `ttrack(ttrack_mitre_30mm, 200)` | T-Track ttrack_mitre_30mm x 200mm |
+| 1 | `ttrack(ttrack_mitre_36mm, 120)` | T-Track ttrack_mitre_36mm x 120mm |
+| 1 | `ttrack(ttrack_universal_19mm, 120)` | T-Track ttrack_universal_19mm x 120mm |
+| 1 | `ttrack(ttrack_universal_19mm, 200)` | T-Track ttrack_universal_19mm x 200mm |
+| 1 | `ttrack(ttrack_universal_19mm_A, 120, colour="red")` | T-Track ttrack_universal_19mm_A x 120mm |
+| 1 | `ttrack(ttrack_universal_19mm_B, 120, colour="blue")` | T-Track ttrack_universal_19mm_B x 120mm |
+| 1 | `T-Track Bolt M6` | M6 x 30mm |
+| 1 | `T-Track Bolt M6 with small head` | M6 x 30mm |
+| 3 | `T-Track Bolt M8` | M8 x 30mm |
+| 1 | `ttrack_insert(TTrack_insert_Miter30_M6, 30, 1)` | T-Track insert, Miter track 30mm, M6 thread, M30mm, with 1 M6 |
+| 1 | `ttrack_insert(TTrack_insert_Miter30_M6, 30, 1, colour="red")` | T-Track insert, Miter track 30mm, M6 thread, M30mm, with 1 M6 |
+| 1 | `ttrack_insert(TTrack_insert_Miter30_M6, 60, 2, colour="red")` | T-Track insert, Miter track 30mm, M6 thread, M60mm, with 2 M6 |
+| 1 | `ttrack_insert(TTrack_insert_Miter30_M8, 30, 1, colour="red")` | T-Track insert, Miter track 30mm, M8 thread, M30mm, with 1 M8 |
+
+
Top
---
diff --git a/tests/png/ttracks.png b/tests/png/ttracks.png
new file mode 100644
index 0000000..0fd7f0f
Binary files /dev/null and b/tests/png/ttracks.png differ
diff --git a/tests/ttracks.scad b/tests/ttracks.scad
new file mode 100644
index 0000000..9e713d3
--- /dev/null
+++ b/tests/ttracks.scad
@@ -0,0 +1,67 @@
+//
+// NopSCADlib Copyright Chris Palmer 2018
+// nop.head@gmail.com
+// hydraraptor.blogspot.com
+//
+// This file is part of NopSCADlib.
+//
+// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with NopSCADlib.
+// If not, see .
+//
+include <../utils/core/core.scad>
+use <../utils/layout.scad>
+
+include <../vitamins/ttracks.scad>
+
+module ttracks() {
+ colours = [ "LightSlateGray", "red", "blue", "LightSlateGray", "LightSlateGray" ];
+
+ for(i = [0: len(ttracks) -1])
+ translate([(i < 4 ? 30 : 35) * i, 60])
+ ttrack(ttracks[i], 120, colours[i]);
+
+ for(i = [0: len(ttrack_bolts) -1])
+ translate([30 * i, -15])
+ ttrack_bolt(ttrack_bolts[i], 30);
+
+ for(i = [0: len(ttrack_inserts) -1]) {
+ translate([35 * (i + 3), -25])
+ rotate([0,0,90])
+ ttrack_insert(ttrack_inserts[i], 30, colour=colours[i]);
+ }
+
+ translate([-35,20,0]) {
+ ttrack_assembly(ttrack_mitre_30mm, 200);
+ ttrack_place_insert(ttrack_mitre_30mm, 50)
+ ttrack_insert(ttrack_fixture(ttrack_mitre_30mm), 30, 1, "red");
+
+ ttrack_place_insert(ttrack_mitre_30mm, -60) {
+ ttrack_insert(ttrack_fixture(ttrack_mitre_30mm), 60, 2, "red");
+ ttrack_insert_hole_positions(ttrack_fixture(ttrack_mitre_30mm), 60, 2)
+ translate_z(8)
+ screw(M6_hex_screw, 15);
+ }
+ }
+
+ translate([-70,20,0]) {
+ ttrack_assembly(ttrack_universal_19mm, 200);
+ ttrack_place_bolt(ttrack_universal_19mm, 50)
+ ttrack_bolt(ttrack_fixture(ttrack_universal_19mm), 30);
+
+ ttrack_place_bolt(ttrack_universal_19mm, -60)
+ ttrack_bolt(ttrack_fixture(ttrack_universal_19mm), 30);
+ }
+
+}
+
+if($preview)
+ let($show_threads = true)
+ ttracks();
diff --git a/vitamins/ttrack.scad b/vitamins/ttrack.scad
new file mode 100644
index 0000000..6544d3f
--- /dev/null
+++ b/vitamins/ttrack.scad
@@ -0,0 +1,209 @@
+//
+// NopSCADlib Copyright Chris Palmer 2018
+// nop.head@gmail.com
+// hydraraptor.blogspot.com
+//
+// This file is part of NopSCADlib.
+//
+// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with NopSCADlib.
+// If not, see .
+
+//
+//! T-Tracks used in woodworking jigs
+//
+include <../utils/core/core.scad>
+use <../utils/thread.scad>
+
+use
+
+function ttrack_width(type) = type[1]; //! Width of track section
+function ttrack_height(type) = type[2]; //! Height of track section
+function ttrack_opening(type) = type[3]; //! Width of the opening
+function ttrack_slot_width(type) = type[4]; //! Width of the slot
+function ttrack_slot_height(type) = type[5]; //! Height of the slot
+function ttrack_top_thickness(type) = type[6]; //! Thickness of the top layer
+function ttrack_screw_pitch(type) = type[7]; //! Distance between screws
+function ttrack_screw(type) = type[8]; //! Screw used to fasten track
+function ttrack_fixture(type) = type[9]; //! Fixture, such as T-bolt or Miter insert used with this track
+
+function tbolt_description(type) = type[1]; //! Description of this t-track bolt
+function tbolt_head_length(type) = type[2]; //! Head length for t-track bolt
+function tbolt_head_width(type) = type[3]; //! Head width for t-track bolt
+function tbolt_head_thickness(type) = type[4]; //! Head thickness for t-track bolt
+function tbolt_thread(type) = type[5]; //! M thread for this bolt
+
+function t_insert_description(type) = type[1]; //! Description of this t-track insert
+function t_insert_top_width(type) = type[2]; //! Top Width of t-track insert
+function t_insert_width(type) = type[3]; //! Width of t-track insert
+function t_insert_height(type) = type[4]; //! Height of t-track insert
+function t_insert_top_thickness(type) = type[5]; //! Top thickness for t-track insert
+function t_insert_thread(type) = type[6]; //! M thread for this the screw hole in this insert
+
+function ttrack_holes(type, length) = //! Number of holes in a rail given its `length`
+ floor((length - 2 * ttrack_screw_end(type)) / ttrack_screw_pitch(type)) + 1;
+
+
+
+module ttrack(type, length, colour = "LightSlateGray") { //! Draw the specified rail
+ W = ttrack_width(type);
+ H = ttrack_height(type);
+ SW = ttrack_slot_width(type);
+ SH = ttrack_slot_height(type);
+ T = ttrack_top_thickness(type);
+ O = ttrack_opening(type);
+ screw=ttrack_screw(type);
+
+ vit_colour = (colour == "LightSlateGray" ? "" : str(", colour=\"", colour, "\""));
+
+ vitamin(str("ttrack(", type[0], ", ", length, vit_colour, "): T-Track ", type[0], " x ", length, "mm"));
+
+ color(colour) {
+ difference() {
+ rotate([90,0,0])
+ linear_extrude(length, center=true, convexity = 3)
+ polygon([
+ [ -O/2, 0 ], // left side of the opening
+ [ -W/2, 0 ], // left top
+ [ -W/2, -H ], // left bottom
+ [ W/2, -H ], // right bottom
+ [ W/2, 0 ], // right top
+ [ O/2, 0 ], // right side of the opening
+ [ O/2, -T ], // right bottom side of the opening
+ [ SW/2, -T ], // right top of the slot
+ [ SW/2, -T - SH ], // right bottom of the slot
+ [ -SW/2,-T - SH ], // left bottom of the slot
+ [ -SW/2, -T ], // left top of the slot
+ [ -O/2, -T ] // left bottom side of the opening
+ ]);
+ ttrack_hole_positions(type, length) {
+ B = H - (SH + T);
+ screw_countersink(screw, true);
+ translate_z(-B/2)
+ cylinder(r=screw_clearance_radius(screw), h=(H-(SH+T) + 0.2), center=true);
+ }
+ }
+
+ }
+
+}
+
+module ttrack_assembly(type, length, colour = "LightSlateGray") {
+ ttrack(type, length, colour);
+ ttrack_hole_positions(type, length)
+ explode(20)
+ screw(ttrack_screw(type), 15);
+}
+module ttrack_hole_positions(type, length) { //! Position children over screw holes
+ P = ttrack_screw_pitch(type);
+ H = ttrack_height(type);
+ B = H - (ttrack_slot_height(type) + ttrack_top_thickness(type));
+
+ count = floor(length / P);
+ first = (length - count * P)/2;
+
+ c = first < P/3 ? count - 1 : count; // we don't want screws right on the edge
+ N = (length - c * P)/2;
+
+ for (y = [N:P:length-N])
+ translate([0,length/2 - y, -H + B])
+ children();
+}
+
+module ttrack_place_bolt(type, pos, bolt = undef) { //! Place a T-Bolt relative to the centre of the track
+ bolt = is_undef(bolt) ? ttrack_fixture(type) : bolt;
+
+ T = tbolt_head_thickness(bolt);
+ translate([0,pos,-(ttrack_top_thickness(type)/2) - T])
+ rotate([0,0,90])
+ children();
+}
+
+module ttrack_place_insert(type, pos, insert = undef) { //! Place a T-Insert relative to the centre of the track
+ insert = is_undef(insert) ? ttrack_fixture(type) : insert;
+ TT = t_insert_top_thickness(insert);
+ T = ttrack_top_thickness(type);
+ translate([0,pos,-T+TT])
+ rotate([0,0,90])
+ children();
+}
+
+module ttrack_bolt(type, length) {
+ L = tbolt_head_length(type);
+ W = tbolt_head_width(type);
+ T = tbolt_head_thickness(type);
+ distance = L - W;
+
+ D = tbolt_thread(type);
+ pitch = metric_coarse_pitch(D);
+
+ vitamin(str(tbolt_description(type), ":", "M", D, " x ", length, "mm"));
+
+ color(silver) {
+ hull()
+ for (x = [-1, 1])
+ translate([x * distance/2, 0, 0])
+ cylinder(d=W, h=T, center=true);
+
+ translate_z((length/2))
+ male_metric_thread(D, pitch, length - T, center = true, top = -1, bot = 0, solid = true, colour = undef);
+ }
+
+}
+
+module ttrack_insert(type, length, num_holes = 1, colour="LightSlateGray") {
+ TW = t_insert_top_width(type);
+ W = t_insert_width(type);
+ H = t_insert_height(type);
+ T = t_insert_top_thickness(type);
+ //distance = L - W;
+
+ D = t_insert_thread(type);
+ pitch = metric_coarse_pitch(D);
+
+ vit_colour = (colour == "LightSlateGray" ? "" : str(", colour=\"", colour, "\""));
+ vitamin(str("ttrack_insert(", type[0], ", ", length, ", ", num_holes, vit_colour, "):", t_insert_description(type), ", M", length, "mm, with ", num_holes, " M", D));
+
+ color(colour) {
+ union() {
+ difference() {
+ rotate([90,0,90]) {
+ linear_extrude(length, center=true, convexity=2)
+ polygon([
+ [ -TW/2, 0 ], // left top
+ [ -TW/2, -T ], // left centre, bottom of top
+ [ -W/2, -T ], // left centre
+ [ -W/2, -H ], // left bottom
+ [ W/2, -H ], // right bottom
+ [ W/2, -T ], // right centre
+ [ TW/2, -T ], // right centre, bottom of top
+ [ TW/2, 0 ] // right top
+ ]);
+ }
+ ttrack_insert_hole_positions(type, length, num_holes)
+ translate_z(-H/2)
+ cylinder(h=H+1, d=t_insert_thread(type), center=true);
+ }
+ ttrack_insert_hole_positions(type, length, num_holes)
+ translate_z(-H/2)
+ female_metric_thread(D, pitch, H, center = true);
+ }
+ }
+
+
+
+}
+
+module ttrack_insert_hole_positions(type, length, num_holes) {
+ P = length / (num_holes + 1);
+ for (x = [P:P:length-P])
+ translate([length/2 - x,0,0])
+ children();
+}
\ No newline at end of file
diff --git a/vitamins/ttracks.scad b/vitamins/ttracks.scad
new file mode 100644
index 0000000..0c75a29
--- /dev/null
+++ b/vitamins/ttracks.scad
@@ -0,0 +1,52 @@
+//
+// NopSCADlib Copyright Chris Palmer 2018
+// nop.head@gmail.com
+// hydraraptor.blogspot.com
+//
+// This file is part of NopSCADlib.
+//
+// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with NopSCADlib.
+// If not, see .
+//
+include <../core.scad>
+
+use
+
+// Bolts HL, HW, HT, Thread M
+ttrack_bolt_M6 = [ "ttrack_bolt_M6", "T-Track Bolt M6", 18, 12, 2.5, 6 ];
+ttrack_bolt_M6_small = [ "ttrack_bolt_M6_small", "T-Track Bolt M6 with small head", 18, 11, 2.5, 6 ];
+ttrack_bolt_M8 = [ "ttrack_bolt_M8", "T-Track Bolt M8", 22.5, 12.6, 3, 8 ];
+
+// Inserts
+// TW, W, H, SH, Thread M
+ttrack_insert_mitre_30_M6 = [ "TTrack_insert_Miter30_M6", "T-Track insert, Miter track 30mm, M6 thread", 19, 23, 7.8, 4.8, 6 ];
+ttrack_insert_mitre_30_M8 = [ "TTrack_insert_Miter30_M8", "T-Track insert, Miter track 30mm, M8 thread", 19, 23, 7.8, 4.8, 8 ];
+
+//
+// Tracks
+// Width, Depth, Opening, Slot width, slot height, Top thickness, Screw pitch
+// W D O SW SH TT Sp
+ttrack_universal_19mm = [ "ttrack_universal_19mm", 19, 9.5, 9.5, 14.2, 3.3, 2.4, 75, M3_cs_cap_screw, ttrack_bolt_M8 ];
+ttrack_universal_19mm_A = [ "ttrack_universal_19mm_A", 18.7, 12.5, 8.3, 12, 7.3, 3.5, 75, M3_cs_cap_screw, ttrack_bolt_M6 ];
+ttrack_universal_19mm_B = [ "ttrack_universal_19mm_B", 19, 9.5, 6.6, 11.3, 4, 2.5, 75, M3_cs_cap_screw, ttrack_bolt_M6_small ];
+
+ttrack_mitre_30mm = [ "ttrack_mitre_30mm", 30, 12.8, 19.3, 23.6, 3.1, 5.4, 75, M4_cs_cap_screw, ttrack_insert_mitre_30_M6 ];
+ttrack_mitre_36mm = [ "ttrack_mitre_36mm", 36, 13.5, 19, 23.5, 3.6, 3.6, 75, M4_cs_cap_screw ];
+
+
+
+
+ttracks = [ ttrack_universal_19mm, ttrack_universal_19mm_A, ttrack_universal_19mm_B, ttrack_mitre_30mm, ttrack_mitre_36mm];
+ttrack_bolts = [ ttrack_bolt_M6, ttrack_bolt_M6_small, ttrack_bolt_M8 ];
+ttrack_inserts = [ ttrack_insert_mitre_30_M6, ttrack_insert_mitre_30_M8 ];
+
+
+use