-
Notifications
You must be signed in to change notification settings - Fork 41
/
horn.scad
133 lines (110 loc) · 4.22 KB
/
horn.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
Creates a solid 'tube'
generate the path of the centre of the shape with function pf(t)
generate the perimeter_points at each step using function lf(t,d)
*/
function m_translate(v) = [ [1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[v.x, v.y, v.z, 1 ] ];
function m_rotate(v) = [ [1, 0, 0, 0],
[0, cos(v.x), sin(v.x), 0],
[0, -sin(v.x), cos(v.x), 0],
[0, 0, 0, 1] ]
* [ [ cos(v.y), 0, -sin(v.y), 0],
[0, 1, 0, 0],
[ sin(v.y), 0, cos(v.y), 0],
[0, 0, 0, 1] ]
* [ [ cos(v.z), sin(v.z), 0, 0],
[-sin(v.z), cos(v.z), 0, 0],
[ 0, 0, 1, 0],
[ 0, 0, 0, 1] ];
function vec3(v) = [v.x, v.y, v.z];
function transform(v, m) = vec3([v.x, v.y, v.z, 1] * m);
// matrix to orient from centre in direction normal
function orient_to(centre,normal) =
m_rotate([0, atan2(sqrt(pow(normal.x, 2) + pow(normal.y, 2)), normal.z), 0])
* m_rotate([0, 0, atan2(normal[1], normal[0])])
* m_translate(centre);
// vector product functions for point scaling
function hadamard(a,b) =
len(a)==len(b)
? [for (i=[0:len(a)-1]) a[i]*b[i]]
: [];
function hadamardv(v,s) =
[for (p = v) hadamard(p,s)];
// generate points on the circumference of the tube
// using global function pf(d,i)
// d is position along the centre line
// t is angle around perimeter
function perimeter_points(d, sides) =
[for (i=[0:sides-1]) pf(d, i * 360 /sides)];
// generate the points along the centre of the tube
// using global function cf(d)
// where d is distance along centre line
function centre_points(step,min,max,scale) =
hadamardv([for (d=[min:step:max]) cf(d)],scale);
// generate all points on the tube surface
function tube_points(loop,min,step,sides) =
[for (i=[0:len(loop)-1])
let (m = orient_to(loop[i], loop[(i + 1) % len(loop)] - loop[i]) )
let (d = min + i * step)
for (p = perimeter_points(d,sides) )
transform(p,m)
];
// generate the faces of the tube surface
function tube_faces(segs, sides, open=true) =
open
? concat(
[[for (j=[sides - 1:-1:0]) j ]],
[for (i=[0:segs-3])
for (j=[0:sides -1])
[ i * sides + j,
i * sides + (j + 1) % sides,
(i + 1) * sides + (j + 1) % sides,
(i + 1) * sides + j
]
] ,
[[for (j=[0:1:sides - 1]) (segs-2)*sides + j]]
)
: [for (i=[0:segs])
for (j=[0:sides -1])
[ i * sides + j,
i * sides + (j + 1) % sides,
((i + 1) % segs) * sides + (j + 1) % sides,
((i + 1) % segs) * sides + j
]
]
;
function sign(x) = x > 0 ? +1 : -1;
function sq(a) = a*a;
module extrude_fun(step,min,max,sides,scale=[1,1,1]) {
// points along the centre line
centre_points = centre_points(step,min,max,scale);
// echo("centre points",centre_points);
// points on the exterior of the tube
tube_points = tube_points(centre_points,min,step,sides);
// echo("tube points",tube_points);
tube_faces = tube_faces(len(centre_points),sides);
polyhedron(points = tube_points, faces = tube_faces);
};
r=10;
h=30;
sides = 50;
// a simple column
function cf(d) = [0,0,d];
// cylinder with linear diminishing radius with sinusoidal x offset
// vary amplitude and frequency
// finishes with a radius of 1
function sinf(a,t) =
(r * (1-a)+1.0 )* [1.5*sin(120*a) + cos(t), sin(t),0];
// the offset is linearly proportional to height
function linearf(a,t) =
(r * (1-a) * [ 4*a + cos(t),sin(t),0]);
// parametric teardrop curve
function teardropf(a,t) =
let (m=a*10)
r* [cos(t),sin(t) * pow(sin(t/2),m),0];
// select active function here
function pf(d,t) = linearf(d/h,t);
extrude_fun(0.2,0,h,sides);