diff --git a/readme.md b/readme.md
index de813ea..b22c8d1 100644
--- a/readme.md
+++ b/readme.md
@@ -4382,7 +4382,7 @@ If a washer is given a child, usually a screw or a nut, then it is placed on its
---
## Wire
-Just a BOM entry at the moment and cable bundle size functions for holes, plus cable ties.
+Utilities for adding wires to the BOM and optionally drawing them and cable bundle size functions for holes, plus cable ties.
[vitamins/wire.scad](vitamins/wire.scad) Implementation.
@@ -4391,21 +4391,25 @@ Just a BOM entry at the moment and cable bundle size functions for holes, plus c
### Functions
| Function | Description |
|:--- |:--- |
-| `cable(wires, size, colours, ribbon = false)` | Cable constructor |
-| `cable_bundle(cable)` | Arrangement of a bundle in a flat cable clip |
+| `cable(wires, size, colours, ribbon = false, tlen = 25)` | Cable constructor |
+| `cable_bundle(cable)` | Dimensions of the bounding rectangle of a bundle of wires in a flat cable clip |
| `cable_bundle_positions(cable)` | Positions of wires in a bundle to go through a cable strip |
| `cable_height(cable)` | Height in flat clip |
| `cable_is_ribbon(cable)` | Is a ribbon cable? |
| `cable_radius(cable)` | Radius of a bundle of wires, see . |
+| `cable_tlen(cable)` | Twisted cable twist length |
+| `cable_twisted_radius(cable)` | Approximate radius of a cable when twisted |
| `cable_width(cable)` | Width in flat clip |
| `cable_wire_colours(cable)` | Individual wire colours |
| `cable_wire_size(cable)` | Size of each wire in a bundle |
| `cable_wires(cable)` | Number of wires in a bundle |
+| `twisted_cable(cable, path, irot = 0, frot = 0)` | Return the paths for a twisted cable, `irot` is the initial rotation and frot the final rotation |
| `wire_hole_radius(cable)` | Radius of a hole to accept a bundle of wires, rounded up to standard metric drill size |
### Modules
| Module | Description |
|:--- |:--- |
+| `cable(cable, paths)` | Draw a cable, given a list of paths |
| `cable_tie(cable_r, thickness)` | A ziptie threaded around cable radius `cable_r` and through a panel with specified `thickness`. |
| `cable_tie_holes(cable_r, h = 100)` | Holes to thread a ziptie through a panel to make a cable tie. |
| `mouse_hole(cable, h = 100, teardrop = false)` | A mouse hole to allow a panel to go over a wire bundle. |
@@ -4417,13 +4421,13 @@ Just a BOM entry at the moment and cable bundle size functions for holes, plus c
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
-| 1 | | Wire black 7/0.2mm strands, length 90mm |
-| 1 | | Wire blue 7/0.2mm strands, length 90mm |
-| 1 | | Wire brown 7/0.2mm strands, length 90mm |
-| 1 | | Wire green 7/0.2mm strands, length 90mm |
-| 1 | | Wire orange 7/0.2mm strands, length 90mm |
-| 1 | | Wire red 7/0.2mm strands, length 90mm |
-| 1 | | Wire yellow 7/0.2mm strands, length 90mm |
+| 1 | | Wire black 7/0.2mm strands, length 60mm |
+| 1 | | Wire blue 7/0.2mm strands, length 60mm |
+| 1 | | Wire brown 7/0.2mm strands, length 60mm |
+| 1 | | Wire green 7/0.2mm strands, length 60mm |
+| 1 | | Wire orange 7/0.2mm strands, length 60mm |
+| 1 | | Wire red 7/0.2mm strands, length 60mm |
+| 1 | | Wire yellow 7/0.2mm strands, length 60mm |
| 1 | `ziptie(small_ziptie)` | Ziptie 2.5mm x 100mm min length |
diff --git a/tests/png/cable_clip.png b/tests/png/cable_clip.png
index 4d6dc67..2f3b6db 100644
Binary files a/tests/png/cable_clip.png and b/tests/png/cable_clip.png differ
diff --git a/tests/png/wire.png b/tests/png/wire.png
index a5ba39c..901235a 100644
Binary files a/tests/png/wire.png and b/tests/png/wire.png differ
diff --git a/tests/wire.scad b/tests/wire.scad
index f50ea34..1057518 100644
--- a/tests/wire.scad
+++ b/tests/wire.scad
@@ -17,18 +17,25 @@
// If not, see .
//
include <../utils/core/core.scad>
+use <../utils/sweep.scad>
+use <../utils/bezier.scad>
use <../vitamins/wire.scad>
-bundle = [7, 1.4];
+twist_len = 25; // [5 : 50]
+wires = 7; // [1 : 7]
+irot = -60; // [-90 : 0]
+/* [Hidden] */
+wire_d = 1.4;
+bundle = cable(wires, wire_d);
bundle_r = cable_radius(bundle);
thickness = 2;
w = 60;
d = 20;
-h = 40;
-wire_l = 90;
+h = 10;
+wire_l = 60;
mouse_y = 10;
cable_pitch = 7;
@@ -49,6 +56,7 @@ module wires() {
translate([bundle_r - d / 2, 0]) {
colour = ["black", "brown", "red", "orange", "yellow", "blue", "purple"][i];
wire(colour, 7, wire_l);
+
color(colour)
cylinder(d = d, h = wire_l, center = true);
}
@@ -66,7 +74,7 @@ module wires() {
mouse_hole(bundle, 0, true);
for(i = [1 : 6])
- let(cable = [i, 1.4], bundle = cable_bundle(cable))
+ let(cable = cable(i, wire_d), bundle = cable_bundle(cable))
translate([mouse_y + cable_pitch * i - bundle.x / 2, -eps])
square([bundle.x, bundle.y]);
}
@@ -81,18 +89,28 @@ module wires() {
cable_tie_holes(bundle_r, 0);
}
}
+
translate([-15, mouse_y])
cable_tie(bundle_r, thickness);
- for(i = [1 : 6]) let(cable = [i, 1.4])
- translate([0, mouse_y + cable_pitch * i])
- let(positions = cable_bundle_positions(cable))
- for(i = [0 : len(positions) - 1])
- let(p = positions[i])
- translate([0, p.x, p.y])
- rotate([0, 90, 0])
- color([grey(10), "blue", "red", "orange", "yellow", "green"][i])
- cylinder(d = cable_wire_size(cable), h = 60, center = true);
+ for(i = [1 : 6]) let(cable = cable(i, wire_d, [grey(10), "blue", "red", "orange", "yellow", "green"], tlen = twist_len))
+ translate([0, mouse_y + cable_pitch * i]) {
+ tr = cable_twisted_radius(cable);
+ bend_r = 5;
+ x = -d + thickness - bend_r;
+ path = [
+ [-5, 0, tr],
+ [x, 0, tr],
+ bend_r, [x, 0, -25]
+ ];
+ rpath = rounded_path(path);
+ tpaths = twisted_cable(cable, rpath, irot = irot, frot = -irot);
+ positions = cable_bundle_positions(cable);
+
+ ends = [for(p = positions) [[30, p.x, p.y], [0, p.x, p.y]]];
+ paths = [for(i = [0 : len(tpaths) - 1]) bezier_join(ends[i], tpaths[i], 1.3, 3)];
+ cable(cable, paths, $fn = 32);
+ }
}
if($preview)
diff --git a/vitamins/wire.scad b/vitamins/wire.scad
index d14126d..b413f3d 100644
--- a/vitamins/wire.scad
+++ b/vitamins/wire.scad
@@ -18,9 +18,11 @@
//
//
-//! Just a BOM entry at the moment and cable bundle size functions for holes, plus cable ties.
+//! Utilities for adding wires to the BOM and optionally drawing them and cable bundle size functions for holes, plus cable ties.
//
include <../utils/core/core.scad>
+use <../utils/sweep.scad>
+use <../utils/maths.scad>
include
module wire(colour, strands, length, strand = 0.2) //! Add stranded wire to the BOM
@@ -35,15 +37,16 @@ module ribbon_cable(ways, length) //! Add ribbon cable to the
function cable_wires(cable) = cable[0]; //! Number of wires in a bundle
function cable_wire_size(cable) = cable[1]; //! Size of each wire in a bundle
function cable_is_ribbon(cable) = len(cable) > 2 && cable[2]; //! Is a ribbon cable?
-function cable_wire_colours(cable) = assert(len(cable[3]) == cable_wires(cable)) cable[3]; //! Individual wire colours
-function cable(wires, size, colours, ribbon = false) = [wires, size, ribbon, colours]; //! Cable constructor
+function cable_wire_colours(cable) = assert(len(cable[3]) >= cable_wires(cable)) cable[3]; //! Individual wire colours
+function cable_tlen(cable) = cable[4]; //! Twisted cable twist length
+function cable(wires, size, colours, ribbon = false, tlen = 25) = [wires, size, ribbon, colours, tlen]; //! Cable constructor
// numbers from http://mathworld.wolfram.com/CirclePacking.html
function cable_radius(cable) = [0, 1, 2, 2.15, 2.41, 2.7, 3, 3, 3.3][cable_wires(cable)] * cable_wire_size(cable) / 2; //! Radius of a bundle of wires, see .
function wire_hole_radius(cable) = ceil(4 * cable_radius(cable) + 1) / 4; //! Radius of a hole to accept a bundle of wires, rounded up to standard metric drill size
-function cable_bundle(cable) = //! Arrangement of a bundle in a flat cable clip
+function cable_bundle(cable) = //! Dimensions of the bounding rectangle of a bundle of wires in a flat cable clip
(cable_is_ribbon(cable) ? [cable_wires(cable), 1] :
[[0,0], [1,1], [2,1], [2, 1 + sin(60)], [2,2], [3, 1 + sin(60)], [3,2]][cable_wires(cable)]) * cable_wire_size(cable);
@@ -53,12 +56,42 @@ function cable_bundle_positions(cable) = let( //! Positions of wires in a bundle
top = wires - bottom
)
[for(i = [0 : 1 : bottom - 1]) [i - (bottom - 1) / 2, 0.5],
- for(i = [0 : 1 : top - 1]) [i - (top - 1) / 2, top == bottom ? 1.5 : 0.5 + sin(60)]
+ for(i = [top - 1 : -1 : 0]) [i - (top - 1) / 2, top == bottom ? 1.5 : 0.5 + sin(60)]
] * cable_wire_size(cable);
function cable_width(cable) = cable_bundle(cable).x; //! Width in flat clip
function cable_height(cable) = cable_bundle(cable).y; //! Height in flat clip
+function cable_twisted_radius(cable) = let( //! Approximate radius of a cable when twisted
+ tlen = cable_tlen(cable), // Twist length
+ a = cable_wire_size(cable) / 2, // Ellipse minor axis
+ R = cable_radius(cable) - a, // Radius of wire centres when not twisted
+ angle = atan2(tlen, 2 * PI * R), // Slope angle of the spiral
+ b = a / sin(angle), // Ellipse major axis
+ grad = tan(180 / cable_wires(cable)), // Gradient at contact point between elipses
+ x = a^2 / sqrt(a^2 + (b / grad)^2), // Contact point of the ellipse tangent
+ y = b * sqrt(1 - x^2 / a^2)
+ ) R ? x + y / grad + a : a; // Where the tangent meets the X axis plus radius
+
+function twisted_cable(cable, path, irot = 0, frot = 0) = let( //! Return the paths for a twisted cable, `irot` is the initial rotation and frot the final rotation
+ tlen = cable_tlen(cable), // Twist length
+ r = cable_wire_size(cable) / 2,
+ pitch = cable_twisted_radius(cable) - r,
+ wires = cable_wires(cable),
+ bottom = wires > 4 ? 3 : 2,
+ irot = irot + 90 - 180 * (bottom - 1) / wires
+ )
+ spiral_paths(path, wires, pitch, round(path_length(path) / tlen) - frot / 360, irot);
+
+module cable(cable, paths) { //! Draw a cable, given a list of paths
+ wires = cable_wires(cable);
+ assert(len(paths) == wires);
+ r = cable_wire_size(cable) / 2;
+ for(i = [0 : wires - 1])
+ color(cable_wire_colours(cable)[i])
+ sweep(paths[i], circle_points(r), convexity = 5);
+}
+
module mouse_hole(cable, h = 100, teardrop = false) { //! A mouse hole to allow a panel to go over a wire bundle.
r = wire_hole_radius(cable);