4 커밋

작성자 SHA1 메시지 날짜
  Thomas Buck 6ada55dd8e added grow lamp mount 3 년 전
  Thomas Buck 6d93a16621 optimizing rail-laser (v2) 3 년 전
  Thomas Buck 7b354a68ec finished rail-laser 4 년 전
  Thomas Buck 0468dd7eaa added first rail laser test 4 년 전
4개의 변경된 파일13531개의 추가작업 그리고 0개의 파일을 삭제
  1. 140
    0
      grow_lamp_mount/lamp_mount.scad
  2. 12938
    0
      grow_lamp_mount/lamp_mount.stl
  3. 392
    0
      rail-laser/rail-laser.scad
  4. 61
    0
      rail-laser/roundedcube.scad

+ 140
- 0
grow_lamp_mount/lamp_mount.scad 파일 보기

@@ -0,0 +1,140 @@
1
+plate = 250;
2
+mount_dist = 58;
3
+trans_width = 45;
4
+trans_depth = 30;
5
+trans_height = 20;
6
+hole = 5.0;
7
+hole_dist = 2;
8
+arm_len = 70 + (hole / 2) + hole_dist;
9
+height = 3;
10
+width = 9;
11
+arm_height = 25;
12
+top_arm_len = 35.1;
13
+
14
+hook_width_add = 3;
15
+hook_dia = 15;
16
+hook_height = width;
17
+hook_size = 2;
18
+hook_off = 15;
19
+
20
+print_dist = 10;
21
+print = true;
22
+
23
+$fn = 42;
24
+
25
+module mount(layer) {
26
+    difference() {
27
+        cube([width, arm_len, height]);
28
+        
29
+        translate([width / 2, hole / 2 + hole_dist, -1])
30
+        cylinder(d = hole, h = height + 2);
31
+    }
32
+    
33
+    difference() {
34
+        translate([0, arm_len - height, 0]) {
35
+            cube([width, height, arm_height + (layer * height)]);
36
+            
37
+            translate([0, 0, arm_height + (layer * height)])
38
+            cube([width, top_arm_len, height]);
39
+        }
40
+    
41
+        translate([0, arm_len - height, 0])
42
+        translate([0, 0, arm_height + (layer * height)])
43
+        translate([width / 2, top_arm_len - 4.5, -4 * height + 2])
44
+        cylinder(d = hole, h = (height * 4) + 2);
45
+    }
46
+}
47
+
48
+module circles() {
49
+    translate([-hook_dia / 2 + hook_size, hook_height, 0])
50
+    rotate([90, 0, -0])
51
+    difference() {
52
+        cylinder(d = hook_dia, h = hook_height);
53
+        translate([0, 0, -1])
54
+        cylinder(d = hook_dia - hook_size * 2, h = hook_height + 2);
55
+        
56
+        translate([-hook_dia / 2 - 1, -hook_dia, -1])
57
+        cube([hook_dia + 2, hook_dia, hook_height + 2]);
58
+    }
59
+}
60
+
61
+module hook() {
62
+    difference() {
63
+        cube([width + hook_size + hook_width_add, width, height]);
64
+        
65
+        translate([width / 2, width / 2, -1])
66
+        cylinder(d = hole, h = height + 2);
67
+    }
68
+    
69
+    translate([width + hook_width_add, width - hook_height, height])
70
+    cube([hook_size, hook_height, hook_off]);
71
+    
72
+    translate([width + hook_width_add, width - hook_height, height + hook_off])
73
+    circles();
74
+}
75
+
76
+module print_arrangement() {
77
+    rotate([0, -90, 0])
78
+    mount(0);
79
+    
80
+    translate([print_dist, 10, 0])
81
+    rotate([0, -90, 0])
82
+    mount(1);
83
+    
84
+    translate([print_dist * 2, 20, 0])
85
+    rotate([0, -90, 0])
86
+    mount(2);
87
+    
88
+    translate([print_dist * 3, 30, 0])
89
+    rotate([0, -90, 0])
90
+    mount(3);
91
+    
92
+    translate([25, 0, width])
93
+    rotate([-90, 0, 0])
94
+    hook();
95
+}
96
+
97
+module preview_arrangement() {
98
+    // plate
99
+    translate([-plate / 2, -plate / 2, 0])
100
+    union() {
101
+        color("purple")
102
+        cube([plate, plate, 1]);
103
+        
104
+        color("green")
105
+        translate([mount_dist, mount_dist, 1])
106
+        cylinder(d = hole, h = height * 2);
107
+        
108
+        color("green")
109
+        translate([plate - mount_dist, mount_dist, 1])
110
+        cylinder(d = hole, h = height * 2);
111
+        
112
+        color("green")
113
+        translate([mount_dist, plate - mount_dist, 1])
114
+        cylinder(d = hole, h = height * 2);
115
+        
116
+        color("green")
117
+        translate([plate - mount_dist, plate - mount_dist, 1])
118
+        cylinder(d = hole, h = height * 2);
119
+        
120
+        color("orange")
121
+    translate([(plate - trans_width) / 2, (plate - trans_depth) / 2, 0])
122
+        cube([trans_width, trans_depth, trans_height]);
123
+    }
124
+
125
+    // arms
126
+    for (i = [0 : 3]) {
127
+        rotate([0, 0, 45 + (90 * i)])
128
+        translate([-width / 2, -arm_len - 27.6, 0])
129
+        mount(i);
130
+    }
131
+    
132
+    translate([-4.5, -4.5, 37])
133
+    hook();
134
+}
135
+
136
+if (print) {
137
+    print_arrangement();
138
+} else {
139
+    preview_arrangement();
140
+}

+ 12938
- 0
grow_lamp_mount/lamp_mount.stl
파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
파일 보기


+ 392
- 0
rail-laser/rail-laser.scad 파일 보기

@@ -0,0 +1,392 @@
1
+include <roundedcube.scad>
2
+
3
+$fn = 50;
4
+
5
+bodies_gap = 0.05;
6
+
7
+laser_dia = 6.5 + 0.2;
8
+laser_len = 14.0;
9
+
10
+bat_width = 18.0;
11
+bat_length = 30.0;
12
+bat_height = 9.0;
13
+bat_case_add = 1.0;
14
+
15
+switch_hole_dia = 2.2;
16
+switch_hole_dist = 15.0;
17
+switch_length = 19.6;
18
+switch_length_body = 10.6;
19
+switch_width = 5.7;
20
+switch_height = 12.0 + 2.0;
21
+switch_nub = 3.0;
22
+
23
+body_width = 25.0;
24
+body_length = 50.0;
25
+body_height = 42.0;
26
+body_frame_offset = 2.5;
27
+body_frame_gap = 0.2;
28
+body_cube_rounding = 1.0;
29
+body_bat_off = 5.5;
30
+body_switch_off_x = bat_height + 6.0;
31
+body_switch_off_y = 4.0;
32
+body_switch_add = 0.5;
33
+body_hole_dia_left = 2.5;
34
+body_hole_dia_right = 2.2;
35
+body_hole_off_x = 2.2;
36
+body_hole_off_z = body_hole_off_x;
37
+body_rail_lock_off_x = 10.0;
38
+body_rail_lock_off_z = 4.0;
39
+
40
+rail_width = 21.2;
41
+rail_height = 8.2;
42
+rail_lip_width_small = 1.3;
43
+rail_lip_width_big = 3.3;
44
+rail_lip_height = 1.0;
45
+
46
+rail_lock_width = 20.0;
47
+rail_lock_depth = 10.0;
48
+rail_lock_base_height = 3.0;
49
+rail_lock_pin_size = 5.23 - 0.1;
50
+rail_lock_pin_width = 12.0;
51
+rail_lock_pin_height = 5.0;
52
+rail_lock_tab_len = 0.5;
53
+rail_lock_tab_depth = 2.0;
54
+rail_lock_whole_width = body_width + (2 * rail_lock_tab_len);
55
+rail_lock_tab_width = (rail_lock_whole_width - rail_lock_width) / 2;
56
+rail_lock_travel = 5.0;
57
+rail_lock_spring_dia = 7.0;
58
+rail_lock_spring_hole = 1.0;
59
+
60
+frame_gap = 0.25;
61
+frame_sphere = 20;
62
+frame_add_touch = 3.0;
63
+frame_wall = 1.5;
64
+frame_mount_hole = 2.85;
65
+frame_mount_hole_off_1 = 3.0;
66
+frame_mount_hole_off_2 = 8.0;
67
+frame_mid_len = (frame_mount_hole / 4) + (2 * frame_wall);
68
+frame_mid_dia = 8; //laser_dia + (2 * frame_wall);
69
+frame_tail_len = 8.0;
70
+frame_tail_len_add = 1.0;
71
+frame_tail_width = 5.5; //frame_mid_dia + 0.5;
72
+frame_negative_width = frame_sphere * 2 / 3 + 7;
73
+frame_hole_dia = 2.85;
74
+frame_hole_dia_arch = 3.0 + 0.1;
75
+frame_hole_off = 1.8;
76
+frame_hole_neg_off = 10;
77
+frame_hole_neg_len = 15;
78
+frame_hole_neg_deg_a = 9;
79
+frame_hole_neg_deg_b = frame_hole_neg_deg_a;
80
+
81
+frame_brim_height = 0.5;
82
+frame_brim_width = 20.0;
83
+
84
+frame_hole_neg_rad_small = frame_mid_len + ((frame_sphere + frame_tail_len) / 2) - frame_hole_off;
85
+frame_hole_neg_rad_large = frame_mid_len + ((frame_sphere + frame_tail_len) / 2) + frame_hole_off;
86
+frame_len = frame_sphere + frame_mid_len + frame_tail_len;
87
+
88
+//body_frame_off = body_height - rail_height - (frame_sphere / 2) - body_frame_offset;
89
+body_frame_off = (frame_sphere / 2) + body_frame_offset;
90
+
91
+laser_preview_angle_x = -10 + (20 * $t);
92
+laser_preview_angle_y = -10 + (20 * $t);
93
+
94
+module rail_lip(l) {
95
+    hull() {
96
+        translate([-1, -0.01, 0])
97
+        cube([l + 2, 0.2, rail_lip_width_big]);
98
+        translate([-1, rail_lip_height - 0.01, (rail_lip_width_big - rail_lip_width_small) / 2])
99
+        cube([l + 2, 0.01, rail_lip_width_small]);
100
+    }
101
+}
102
+
103
+module rail(l) {
104
+    difference() {
105
+        cube([l, rail_width, rail_height]);
106
+        
107
+        translate([0, 0, rail_height - rail_lip_width_big]) {
108
+            rail_lip(l);
109
+            
110
+            translate([l, rail_width, 0])
111
+            rotate([0, 0, 180])
112
+            rail_lip(l);
113
+        }
114
+    }
115
+}
116
+
117
+module rail_lock_internal(add = 0.0) {
118
+    if (add == 0) {
119
+        cube([rail_lock_width + add, rail_lock_depth + add, rail_lock_base_height + add], center = true);
120
+    
121
+        translate([(rail_lock_width + add + rail_lock_tab_width + add) / 2, 0, 0])
122
+        cube([rail_lock_tab_width + add, rail_lock_tab_depth + add, rail_lock_base_height + add], center = true);
123
+        
124
+        translate([-(rail_lock_width + add + rail_lock_tab_width + add) / 2, 0, 0])
125
+        cube([rail_lock_tab_width + add, rail_lock_tab_depth + add, rail_lock_base_height + add], center = true);
126
+    } else {
127
+        translate([0, 0, -rail_lock_travel / 2]) {
128
+            cube([rail_lock_width + add + 0.01, rail_lock_depth + add, rail_lock_base_height + add + rail_lock_travel + 0.01], center = true);
129
+        
130
+            translate([(rail_lock_width + add + rail_lock_tab_width + add) / 2, 0, 0])
131
+            cube([rail_lock_tab_width + add, rail_lock_tab_depth + add, rail_lock_base_height + add + rail_lock_travel], center = true);
132
+            
133
+            translate([-(rail_lock_width + add + rail_lock_tab_width + add) / 2, 0, 0])
134
+            cube([rail_lock_tab_width + add, rail_lock_tab_depth + add, rail_lock_base_height + add + rail_lock_travel], center = true);
135
+        }
136
+    }
137
+    
138
+    translate([0, 0, (rail_lock_base_height + add + rail_lock_pin_height + add) / 2])
139
+    cube([rail_lock_pin_width + add, rail_lock_pin_size + add, rail_lock_pin_height + add], center = true);
140
+}
141
+
142
+module rail_lock(add = 0.0) {
143
+    if (add == 0) {
144
+        difference() {
145
+            rail_lock_internal(add);
146
+            
147
+            translate([0, 0, -rail_lock_spring_hole - rail_lock_base_height / 2])
148
+            cylinder(d = rail_lock_spring_dia, h = rail_lock_spring_hole + 1);
149
+            
150
+            translate([0, -rail_lock_pin_size / 2, (rail_lock_base_height + add + rail_lock_pin_height + add) / 2 - -rail_lock_pin_size / 2])
151
+            rotate([45, 0, 0])
152
+            cube([rail_lock_pin_width + 2, rail_lock_pin_size, rail_lock_pin_height], center = true);
153
+        }
154
+    } else {
155
+        rail_lock_internal(add);
156
+    
157
+        translate([0, 0, -rail_lock_spring_hole - (rail_lock_base_height + add) / 2 - rail_lock_travel])
158
+        cylinder(d = rail_lock_spring_dia, h = rail_lock_spring_hole);
159
+    }
160
+}
161
+
162
+module laser() {
163
+    cylinder(d = laser_dia, h = laser_len);
164
+}
165
+
166
+module laser_frame_screw_arc(radius, deg) {
167
+    for (r = [-deg : 1 : deg])
168
+    translate([radius, 0, 0])
169
+    rotate([0, 0, r])
170
+    translate([-radius, 0, 0])
171
+    cylinder(d = frame_hole_dia_arch, h = frame_negative_width + frame_hole_neg_len);
172
+}
173
+
174
+module laser_frame(added_gap = 0, negative = 0) {
175
+    difference() {
176
+        union() {
177
+            // top sphere
178
+            translate([0, 0, (frame_sphere / 2) + (frame_len - frame_sphere)])
179
+            sphere(d = frame_sphere + added_gap);
180
+            
181
+            if (negative == 0) {
182
+                %translate([0, 0, frame_len - frame_sphere / 2])
183
+                cylinder(d = 0.5, h = 50);
184
+                
185
+                // mid section
186
+                translate([0, 0, frame_len - frame_sphere - frame_mid_len - 0.5])
187
+                hull() {
188
+                    translate([-(frame_tail_width + added_gap) / 2, -(frame_tail_width + added_gap) / 2, 0])
189
+                    cube([frame_tail_width + added_gap, frame_tail_width + added_gap, frame_tail_len]);
190
+                    
191
+                    translate([0, 0, frame_mid_len + frame_add_touch])
192
+                    cylinder(d = frame_mid_dia + added_gap, h = 1.0);
193
+                }
194
+                
195
+                // bottom cube
196
+                translate([-(frame_tail_width + added_gap) / 2, -(frame_tail_width + added_gap) / 2, frame_len - frame_sphere - frame_mid_len - frame_tail_len - frame_tail_len_add]) {
197
+                    cube([frame_tail_width + added_gap, frame_tail_width + added_gap, frame_tail_len + frame_tail_len_add]);
198
+                    //roundedcube([frame_tail_width + added_gap, frame_tail_width + added_gap, frame_tail_len]);
199
+                }
200
+            } else {
201
+                translate([0, 0, frame_len - frame_add_touch])
202
+                cylinder(d = laser_dia + added_gap, h = frame_mid_len + frame_add_touch);
203
+                
204
+                translate([-frame_negative_width / 2, -frame_negative_width / 2, frame_len - frame_sphere - frame_mid_len - frame_tail_len - (added_gap * 3) - 1])
205
+                cube([frame_negative_width, frame_negative_width, frame_len - frame_sphere + frame_add_touch + (added_gap * 3) + 1]);
206
+            
207
+                translate([-frame_hole_neg_off + frame_negative_width + frame_hole_neg_len, 0, frame_len - frame_sphere - frame_mid_len - frame_tail_len + (frame_tail_len / 2) - frame_hole_off])
208
+                rotate([0, -90, 0])
209
+                laser_frame_screw_arc(frame_hole_neg_rad_large, frame_hole_neg_deg_a);
210
+            
211
+                translate([0, -frame_hole_neg_off, frame_len - frame_sphere - frame_mid_len - frame_tail_len + (frame_tail_len / 2) + frame_hole_off])
212
+                rotate([-90, -90, 0])
213
+                laser_frame_screw_arc(frame_hole_neg_rad_small, frame_hole_neg_deg_b);
214
+            }
215
+        }
216
+        
217
+        if (negative == 0) {
218
+            // cutout for laser itself
219
+            translate([0, 0, frame_len - frame_sphere + 1])
220
+            cylinder(d = laser_dia + (2 * frame_gap), h = frame_sphere);
221
+        
222
+            // holding screws for laser
223
+            translate([0, 0, frame_len - (frame_mount_hole / 2) - frame_mount_hole_off_1])
224
+            rotate([0, 90, 45]) {
225
+                cylinder(d = frame_mount_hole, h = frame_sphere);
226
+            
227
+                rotate([-90, 0, 0])
228
+                cylinder(d = frame_mount_hole, h = frame_sphere);
229
+            }
230
+            translate([0, 0, frame_len - (frame_mount_hole / 2) - frame_mount_hole_off_2])
231
+            rotate([0, 90, 45]) {
232
+                cylinder(d = frame_mount_hole, h = frame_sphere);
233
+            
234
+                rotate([-90, 0, 0])
235
+                cylinder(d = frame_mount_hole, h = frame_sphere);
236
+            }
237
+            
238
+            // cable cutout for laser
239
+            //rotate([0, 0, -90])
240
+            translate([0, 5, 6.5])
241
+            rotate([30, 0, 0])
242
+            cylinder(d = 2.5, h = 10);
243
+            
244
+            // x-axis holes
245
+            translate([-frame_tail_width / 2 - 1, 0, frame_len - frame_sphere - frame_mid_len - frame_tail_len + (frame_tail_len / 2) - frame_hole_off])
246
+            rotate([0, 90, 0])
247
+            cylinder(d = frame_hole_dia, h = frame_tail_width + 2);
248
+            
249
+            // y-axis holes
250
+            translate([0, -frame_tail_width / 2 - 1, frame_len - frame_sphere - frame_mid_len - frame_tail_len + (frame_tail_len / 2) + frame_hole_off])
251
+            rotate([-90, 0, 0])
252
+            cylinder(d = frame_hole_dia, h = frame_tail_width + 2);
253
+        }
254
+    }
255
+}
256
+
257
+module battery(add = 0.0) {
258
+    translate([-add / 2, -add / 2, -add / 2])
259
+    cube([bat_height + add, bat_width + add, bat_length + add]);
260
+}
261
+
262
+module switch(add = 0.0) {
263
+    translate([(switch_length - (switch_length_body + add * 2)) / 2, -add, 0])
264
+    cube([(switch_length_body + add * 2), switch_width + add * 2, switch_height]);
265
+    
266
+    translate([(switch_length - switch_nub) / 2, (switch_width - switch_nub) / 2, switch_height])
267
+    cube([switch_nub, switch_nub, switch_nub]);
268
+    
269
+    translate([(switch_length - switch_length_body) / 4, switch_width / 2, 0]) {
270
+        cylinder(d = switch_hole_dia, h = switch_height + 1);
271
+        translate([switch_hole_dist, 0, 0])
272
+        cylinder(d = switch_hole_dia, h = switch_height + 1);
273
+    }
274
+}
275
+
276
+module body(hole_dia) {
277
+    difference() {
278
+        // main body part
279
+        cube([body_length, body_width, body_height]);
280
+        //roundedcube([body_length, body_width, body_height], false, body_cube_rounding);
281
+        
282
+        // cutout for rail
283
+        translate([-1, (body_width - rail_width) / 2, body_height - rail_height + 0.01])
284
+        rail(body_length + 2);
285
+        
286
+        // cutout and preview for laser frame
287
+        translate([body_length - frame_len, body_width / 2, body_frame_off])
288
+        rotate([0, 90, 0]) {
289
+            laser_frame(body_frame_gap, 1);
290
+            
291
+            translate([0, 0, frame_len - frame_sphere / 2])
292
+            rotate([laser_preview_angle_x, laser_preview_angle_y, 180])
293
+            translate([0, 0, -(frame_len - frame_sphere / 2)])
294
+            %laser_frame();
295
+        }
296
+        
297
+        // cutout and preview for battery
298
+        translate([body_bat_off, (body_width - bat_width) / 2, (body_height - rail_height - bat_length) / 2]) {
299
+            battery(bat_case_add);
300
+            %battery();
301
+        }
302
+        
303
+        // cutout and preview for switch
304
+        translate([body_switch_off_x, body_width - switch_height + 0.01, body_height - rail_height - body_switch_off_y])
305
+        rotate([-90, 0, 0]) {
306
+            switch(body_switch_add);
307
+            %switch(0);
308
+            
309
+            // cutout for cabling
310
+            // TODO not very nice,
311
+            // with hardcoded values
312
+            translate([-0.01, -2.5, -8])
313
+            cube([18.5, 30, 9.5]);
314
+        }
315
+        
316
+        // cutout and preview for rail locking mechanism
317
+        translate([body_length - body_rail_lock_off_x, body_width / 2, rail_lock_base_height / 2 + body_height - rail_height - body_rail_lock_off_z])
318
+        rotate([0, 0, -90]) {
319
+            rail_lock(0.5);
320
+            
321
+            translate([0, 0, -(rail_lock_travel * $t)])
322
+            %rail_lock();
323
+        }
324
+        
325
+        // outside screw holes
326
+        translate([body_hole_off_x, -1, body_hole_off_z])
327
+        rotate([-90, 0, 0])
328
+        cylinder(d = hole_dia, h = body_width + 2);
329
+        translate([body_length - body_hole_off_x, -1, body_hole_off_z])
330
+        rotate([-90, 0, 0])
331
+        cylinder(d = hole_dia, h = body_width + 2);
332
+        translate([body_hole_off_x, -1, body_height - rail_height - body_hole_off_z])
333
+        rotate([-90, 0, 0])
334
+        cylinder(d = hole_dia, h = body_width + 2);
335
+        translate([body_length - body_hole_off_x, -1, body_height - rail_height - body_hole_off_z])
336
+        rotate([-90, 0, 0])
337
+        cylinder(d = hole_dia, h = body_width + 2);
338
+    }
339
+}
340
+
341
+module body_half(half) {
342
+    difference() {
343
+        if (half == 0) {
344
+            body(body_hole_dia_left);
345
+        } else {
346
+            body(body_hole_dia_right);
347
+        }
348
+        
349
+        if (half == 0) {
350
+            translate([-1, (bodies_gap - body_width) / 2, -1])
351
+            cube([body_length + 2, body_width, body_height + 2]);
352
+        } else {
353
+            translate([-1, (body_width - bodies_gap) / 2, -1])
354
+            cube([body_length + 2, body_width, body_height + 2]);
355
+            
356
+        }
357
+    }
358
+}
359
+
360
+module print() {
361
+    translate([0, 0, body_width])
362
+    rotate([-90, 0, 0])
363
+    body_half(0);
364
+    
365
+    translate([0, body_height * 2 + 5, 0])
366
+    rotate([90, 0, 0])
367
+    body_half(1);
368
+    
369
+    translate([body_length + (frame_brim_width / 2) + 5, body_height + (frame_brim_width / 2) + 5, 0]) {
370
+        translate([0, 0, frame_tail_len_add])
371
+        laser_frame(0, 0);
372
+        
373
+        translate([0, 0, frame_brim_height / 2])
374
+        cube([frame_brim_width, frame_brim_width, frame_brim_height], center = true);
375
+    }
376
+    
377
+    translate([body_length + 10, 20, rail_lock_base_height / 2])
378
+    rotate([0, 0, 90])
379
+    rail_lock(0);
380
+    
381
+    // simple brim
382
+    //translate([-10, -10, 0])
383
+    //cube([80, 95, 0.2]);
384
+}
385
+
386
+//laser_frame();
387
+//rail_lock();
388
+
389
+//body_half(0);
390
+//body_half(1);
391
+
392
+print();

+ 61
- 0
rail-laser/roundedcube.scad 파일 보기

@@ -0,0 +1,61 @@
1
+// Higher definition curves
2
+$fs = 0.01;
3
+
4
+module roundedcube(size = [1, 1, 1], center = false, radius = 0.5, apply_to = "all") {
5
+	// If single value, convert to [x, y, z] vector
6
+	size = (size[0] == undef) ? [size, size, size] : size;
7
+
8
+	translate_min = radius;
9
+	translate_xmax = size[0] - radius;
10
+	translate_ymax = size[1] - radius;
11
+	translate_zmax = size[2] - radius;
12
+
13
+	diameter = radius * 2;
14
+
15
+	module build_point(type = "sphere", rotate = [0, 0, 0]) {
16
+		if (type == "sphere") {
17
+			sphere(r = radius);
18
+		} else if (type == "cylinder") {
19
+			rotate(a = rotate)
20
+			cylinder(h = diameter, r = radius, center = true);
21
+		}
22
+	}
23
+
24
+	obj_translate = (center == false) ?
25
+		[0, 0, 0] : [
26
+			-(size[0] / 2),
27
+			-(size[1] / 2),
28
+			-(size[2] / 2)
29
+		];
30
+
31
+	translate(v = obj_translate) {
32
+		hull() {
33
+			for (translate_x = [translate_min, translate_xmax]) {
34
+				x_at = (translate_x == translate_min) ? "min" : "max";
35
+				for (translate_y = [translate_min, translate_ymax]) {
36
+					y_at = (translate_y == translate_min) ? "min" : "max";
37
+					for (translate_z = [translate_min, translate_zmax]) {
38
+						z_at = (translate_z == translate_min) ? "min" : "max";
39
+
40
+						translate(v = [translate_x, translate_y, translate_z])
41
+						if (
42
+							(apply_to == "all") ||
43
+							(apply_to == "xmin" && x_at == "min") || (apply_to == "xmax" && x_at == "max") ||
44
+							(apply_to == "ymin" && y_at == "min") || (apply_to == "ymax" && y_at == "max") ||
45
+							(apply_to == "zmin" && z_at == "min") || (apply_to == "zmax" && z_at == "max")
46
+						) {
47
+							build_point("sphere");
48
+						} else {
49
+							rotate = 
50
+								(apply_to == "xmin" || apply_to == "xmax" || apply_to == "x") ? [0, 90, 0] : (
51
+								(apply_to == "ymin" || apply_to == "ymax" || apply_to == "y") ? [90, 90, 0] :
52
+								[0, 0, 0]
53
+							);
54
+							build_point("cylinder", rotate);
55
+						}
56
+					}
57
+				}
58
+			}
59
+		}
60
+	}
61
+}

Loading…
취소
저장