-
Notifications
You must be signed in to change notification settings - Fork 41
/
mobius_trefoil.scad
129 lines (100 loc) · 4.16 KB
/
mobius_trefoil.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
// generates Mobius strips
// based on code by nop head,
// requires openscad snapshot with concat enabled
// function parameters moved to global for generality
// a trefoil-knot with a rectangular cross-section
// for generality, cross-section is parameterised by the angle but in this case that parameter isn't used
// which is rotated by Half_twists * 180 degrees over the circle
// allowance is required when connecting up the two ends of the tube for the 180 degree
// rotation if an odd number of Half_twists
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);
function loop_points(step, t = 0) =
t < 360
? concat([f(t)], loop_points(step, t + step))
: [] ;
function transform_points(list, matrix, i = 0) =
i < len(list) ? concat([ transform(list[i], matrix) ], transform_points(list, matrix, i + 1)) : [];
function tube_points(loop, i = 0) =
(i < len(loop) - 1)
? concat(
transform_points(
cross_section_points(i * Step),
orientate(loop[i], (loop[i + 1] - loop[i])/ 2, i *Step )
),
tube_points(loop, i + 1)
)
: transform_points(
cross_section_points(i * Step),
orientate(loop[i], (loop[0] - loop[i])/ 2, i * Step)
)
;
// functions for a specific tube
function orientate(p0, p, i) = // matrix to orientate the cross-section
m_rotate([0,0,Initial_angle + i/2 * Half_twists])
* m_rotate([0, atan2(sqrt(pow(p[0], 2) + pow(p[1], 2)), p[2]), 0])
* m_rotate([0, 0, atan2(p[1], p[0])])
* m_translate(p0 + p)
;
function tube_faces(segs, facets, s, i = 0) =
i < facets
? s == segs - 1 && Half_twists % 2 ==1 // last segment if half twist
? concat([[s * facets + i,
s * facets + (i + 1) % facets,
(i + 3) % facets,
(i + 2 )% facets]
],
tube_faces(segs, facets, s, i + 1))
: concat([[s * facets + i,
s * facets + (i + 1) % facets,
((s + 1) % segs) * facets + (i + 1) % facets,
((s + 1) % segs) * facets + i]
],
tube_faces(segs, facets, s, i + 1))
: [];
function loop_faces(segs, facets, i = 0) =
i < segs
? concat(tube_faces(segs, facets, i), loop_faces(segs, facets, i + 1 ))
: [];
Half_twists = 1;
Radius=20;
Width=1;
Thickness=0.2;
Initial_angle = 0;
facets=4; // 4 sides to the rectangle cross-section
Scale = 5;
Step = 1;
function rectangle (Width, Thickness)=
[
[Width/2 , Thickness/2,0],
[-Width/2 , Thickness/2,0],
[-Width/2 , -Thickness/2,0],
[Width/2 , -Thickness/2,0]
];
function cross_section_points(t) =
rectangle( Width, Thickness);
function f(t) =
[ sin(t) + 2 * sin (2 * t),
cos(t) - 2 * cos ( 2 * t),
- sin (3 * t)
];
loop_points = loop_points(Step);
tube_points = tube_points(loop_points);
loop_faces = loop_faces(len(loop_points),facets);
scale(Scale) polyhedron(points = tube_points, faces = loop_faces);