-
Notifications
You must be signed in to change notification settings - Fork 171
/
Copy pathwiring.scad
103 lines (88 loc) · 3.34 KB
/
wiring.scad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use <GDMUtils.scad>
// Generate bezier curve to fillet 2 line segments between 3 points.
// Returns two path points with surrounding cubic bezier control points.
function fillet3pts(p0, p1, p2, r) = let(
v0 = normalize(p0-p1),
v1 = normalize(p2-p1),
a = vector3d_angle(v0,v1),
mr = min(distance(p0,p1), distance(p2,p1))*0.9,
tr = min(r/tan(a/2), mr),
tp0 = p1+v0*tr,
tp1 = p1+v1*tr,
w=-2.7e-5*a*a + 8.5e-3*a - 3e-3,
nw=max(0, w),
cp0 = tp0+nw*(p1-tp0),
cp1 = tp1+nw*(p1-tp1)
) [tp0, tp0, cp0, cp1, tp1, tp1];
// Takes a 3D polyline path and fillets it into a 3d cubic bezier path.
function fillet_path(pts, fillet) = concat(
[pts[0], pts[0]],
(len(pts) < 3)? [] : [
for (
p = [1 : len(pts)-2],
pt = fillet3pts(pts[p-1], pts[p], pts[p+1], fillet)
) pt
],
[pts[len(pts)-1], pts[len(pts)-1]]
);
// Returns an array of 1 or 6 points that form a ring, based on wire diam and ring level.
// Level 0 returns a single point at 0,0. All greater levels return 6 points.
function hex_offset_ring(wirediam, lev=0) =
(lev == 0)? [[0,0]] : [
for (
sideang = [0:60:359.999],
sidewire = [1:lev]
) [
lev*wirediam*cos(sideang)+sidewire*wirediam*cos(sideang+120),
lev*wirediam*sin(sideang)+sidewire*wirediam*sin(sideang+120)
]
];
// Returns an array of 2D centerpoints for each of a bundle of wires of given diameter.
// The lev and arr variables are used for internal recursion.
function hex_offsets(wires, wirediam, lev=0, arr=[]) =
(len(arr) >= wires)? arr :
hex_offsets(
wires=wires,
wirediam=wirediam,
lev=lev+1,
arr=concat(arr, hex_offset_ring(wirediam, lev=lev))
);
// Returns a 3D object representing a bundle of wires that follow a given path,
// with the corners filleted to a given radius. There are 17 base wire colors.
// If you have more than 17 wires, colors will get re-used.
// Arguments:
// path: The 3D polyline path that the wire bundle should follow.
// wires: The number of wires in the wiring bundle.
// wirediam: The diameter of each wire in the bundle.
// fillet: The radius that the path corners will be filleted to.
// wirenum: The first wire's offset into the color table.
// bezsteps: The corner fillets in the path will be converted into this number of segments.
// Usage:
// wiring([[50,0,-50], [50,50,-50], [0,50,-50], [0,0,-50], [0,0,0]], fillet=10, wires=13);
module wiring(path, wires, wirediam=2, fillet=10, wirenum=0, bezsteps=3) {
vect = path[1]-path[0];
theta = atan2(vect[1], vect[0]);
xydist = hypot(vect[1], vect[0]);
phi = atan2(vect[2],xydist);
colors = [
[0.2, 0.2, 0.2], [1.0, 0.2, 0.2], [0.0, 0.8, 0.0], [1.0, 1.0, 0.2],
[0.3, 0.3, 1.0], [1.0, 1.0, 1.0], [0.7, 0.5, 0.0], [0.5, 0.5, 0.5],
[0.2, 0.9, 0.9], [0.8, 0.0, 0.8], [0.0, 0.6, 0.6], [1.0, 0.7, 0.7],
[1.0, 0.5, 1.0], [0.5, 0.6, 0.0], [1.0, 0.7, 0.0], [0.7, 1.0, 0.5],
[0.6, 0.6, 1.0],
];
offsets = hex_offsets(wires, wirediam);
bezpath = fillet_path(path, fillet);
poly = simplify3d_path(path3d(bezier_polyline(bezpath, bezsteps)));
n = max(segs(wirediam), 8);
r = wirediam/2;
for (i = [0:wires-1]) {
extpath = [for (a = [0:(360.0/n):360]) [r*cos(a), r*sin(a)] + offsets[i]];
roty = matrix3_yrot(90-phi);
rotz = matrix3_zrot(theta);
color(colors[(i+wirenum)%len(colors)]) {
extrude_2dpath_along_3dpath(extpath, poly);
}
}
}
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap