chiark / gitweb /
poster-tube-lid: WallMountBase wip
[reprap-play.git] / poster-tube-lid.scad
1 // -*- C -*-
2
3 // Print, for each end:
4 //
5 //   CoverPrint
6 //   StrapMount
7 //   CatchAssembly
8
9 include <funcs.scad>
10 include <utils.scad>
11
12 coarse = false;
13 enable_head_cups = false;
14
15 main_dia = 71.2 + 0.50 - 2.26;
16 top_thick_middle = 4;
17 top_thick_by_oring = 3.0;
18 top_middle_dr = 11;
19
20 main_cnr = 6.0;
21
22 min_wall = 3;
23
24 rivet_posn = 6.0 + 0.30;
25 rivet_thick = 1.67;
26 rivet_width = 4.15 + 1.0;
27 rivet_tall = 5.51 + 1.49;
28
29 over_rivet_wall = 1.0;
30 side_rivet_gap = 1.5;
31 inside_rivet_gap = 1.5;
32
33 bayo_interf = 0.30;
34 bayo_behind = 8.5;
35 bayo_interf_width = 2.0;
36 bayo_interf_slope = 0.5;
37
38 oring_thick = 5.0;
39 oring_bore = 62.0;
40
41 oring_upper_embed_angle = 80;
42 oring_compress = 0.1; // proportion
43 oring_compress_more = 0.2;
44
45 oring_rm_beside = 8;
46 oring_rm_scale = 2.0;
47 oring_rm_angle = 20;
48
49 side_taper = 1.0;
50
51 bayo_gap = 6.0;
52
53 bayo_entry = 1.167;
54 bayo_inramp = 0.9;
55
56 bayo_slice_size = coarse ? 5 : 1;
57
58 brace_hole_width = 1.0;
59 brace_above_below = 1.2;
60 brace_end_shorter = 0.3;
61
62 jig_thick = 1.4;
63 jig_hole_dia = 3.0;
64 jig_rim = 5;
65 jig_mark = 5;
66
67 strap_loop_thick = 6;
68 strap_loop_inside = 10;
69 strap_loop_strlen = 10;
70 strap_loop_elevation = 45;
71
72 sm_inner_circum = 218 - 1.90 - 1.00 - 0.50;
73 sm_main_thick = 2.0;
74 sm_main_width = 20;
75
76 sm_bolt_dia = 3.5 + 0.1;
77 sm_bolt_shaft = 21.0;
78 sm_bolt_head_dia = 6.94 + 1.0;
79 sm_bolt_head_thick = 2.14;
80 sm_bolt_nut_width = 5.89 + 0.25;
81 sm_bolt_nut_thick = 3.68;
82 sm_bolt_tighten_allow = 2.0;
83
84 sm_bolt_y_clear = 0.75;
85 sm_bolt_y_over = 0.5;
86
87 sm_closure_cnr = 3.0;
88
89 wm_thick = 5;
90 wm_screw_dia = 4.5; // XXX
91 wm_screwdriver_dia = 6.0; // XXX
92 wm_screw_around = 4.0; // XXX
93 wm_screw_slot = 3.5;
94 wm_screw_head = 7.5; // XXX
95
96 wmb_screw_dia = 5;
97 wmb_screw_head_dia = 10; // XXX
98 wmb_screw_around_x = 4; // XXX
99 wmb_screw_around_z = 6; // XXX
100 wmb_screw_depth_min = 10;
101 web_screw_len = 15 + 1; // XXX
102 wmb_nut_across = 8; // XXX
103 wmb_nut_around_min = 2; // XXX
104 wmb_nut_behind_min = 5;
105 wmb_nut_th = 4; // XXX
106 wmb_mount_wall = 4.5;
107 wmb_mount_gap_xy = 0.5;
108 wmb_mount_y_width = 10;
109 wmb_ring_gap = 1.0;
110
111 catch_stalk_h = 4.5;
112 catch_stalk_len = 50;
113 catch_tip_th = 4;
114 catch_head_th = 3;
115
116 catch_pin_slop = 0.25; // each side, and above
117 catch_pin_slop_x_extra = 0.0; // only on one side
118 catch_stalk_above_gap = 1.5;
119 catch_stalk_eff_bend_rad = catch_stalk_len * 0.75;
120
121 catch_strap_width = 12;
122 catch_stalk_base_width = 15;
123
124 catch_knob_dia = 6;
125 catch_knob_above_gap = 5;
126 catch_knob_height = 3.0;
127
128 catch_stalk_below_gap = 1.0;
129 catch_stalk_beside_gap = 2.0;
130
131 // calculated
132
133 TAU = PI*2;
134
135 bayo_entry_x = bayo_entry;
136 bayo_entry_z = bayo_entry;
137 bayo_inramp_x = bayo_inramp;
138 bayo_inramp_z = bayo_inramp;
139
140 oring_mid_dia = oring_bore + oring_thick;
141 oring_outer_dia = oring_mid_dia + oring_thick;
142
143 oring_oblate = (1 - oring_compress);
144
145 oring_y_rad = oring_thick/2 * oring_oblate;
146 oring_x_rad = oring_thick/2 / oring_oblate;
147
148 by_oring_z = oring_y_rad * (1 + cos(oring_upper_embed_angle));
149
150 side_height = rivet_posn + bayo_behind + rivet_thick/2;
151 side_thick = rivet_tall + over_rivet_wall;
152
153 top_z = top_thick_by_oring + oring_y_rad + by_oring_z;
154
155 middle_bot_z = top_z - top_thick_middle;
156
157 bayo_top_z = bayo_behind + bayo_gap;
158
159 bayo_nom_rad = main_dia/2 + side_thick;
160 bayo_real_rad = main_dia/2 + rivet_tall;
161
162 rivet_entry_width = rivet_width + side_rivet_gap;
163
164 jig_mark_rad = jig_mark + main_dia/2 + jig_thick;
165
166 handling_dia = oring_bore + oring_thick*2 + min_wall*2;
167 handling_angle = 45;
168
169 sm_inner_rad = (sm_inner_circum + sm_bolt_tighten_allow/2) / TAU;
170 sm_outer_rad = sm_inner_rad + sm_main_thick;
171
172 wm_main_width = sm_main_width;
173 wm_y_min = sqrt( pow(sm_inner_rad, 2) -
174                  pow(sm_inner_rad - (wm_thick - sm_main_thick), 2) );
175 wm_y_screw = wm_y_min + wm_screw_around + wm_screw_dia/2;
176 wm_y_max = wm_y_screw + wm_screw_dia/2 + wm_screw_around;
177 wm_y_slotc_screw = wm_y_screw + wm_screw_slot/2;
178 wm_y_slot1_screw = wm_y_screw + wm_screw_slot;
179 wm_y_slot1_max = wm_y_max + wm_screw_slot;
180 wm_z_slot0_screw = wm_main_width + wm_screwdriver_dia/2;
181 wm_z_slotc_screw = wm_z_slot0_screw + wm_screw_slot/2;
182 wm_z_slot1_screw = wm_z_slot0_screw + wm_screw_slot;
183 wm_z_max = wm_z_slot1_screw + wm_screw_around;
184
185 wmb_mount_cut_rad = sm_outer_rad + wmb_ring_gap;
186 wmb_nut_rad = wmb_nut_across / cos(30) * 0.5;
187 wmb_x_screw_plus_around_r = max(
188                                 wmb_screw_around_x + wmb_screw_dia/2,
189                                 wmb_nut_around_min + wmb_nut_across/2
190                                 );
191 wmb_x_screw = -sm_outer_rad + wmb_x_screw_plus_around_r;
192 wmb_x_outer = -sm_outer_rad + wmb_x_screw_plus_around_r * 2;
193 function wmb_screw_thing_y_min(dia) = sqrt(
194                        pow(wmb_mount_cut_rad, 2) -
195                        pow(wmb_x_screw + dia/2, 2)
196                        );
197 wmb_y_screw_end = wmb_screw_thing_y_min(wmb_screw_dia);
198 wmb_y_nut_min = wmb_screw_thing_y_min(wmb_nut_across + wmb_nut_around_min*2);
199 wmb_y_mount_max = max(
200                       wmb_y_nut_min + wmb_nut_th + wmb_nut_behind_min,
201                       wmb_y_screw_end + wmb_screw_depth_min
202                       );
203 wmb_z_screw = max(
204                   wmb_screw_around_z + wmb_screw_dia/2,
205                   wmb_nut_around_min + wmb_nut_rad
206                   );
207 wmb_z_max = wmb_z_screw * 2;
208 wmbb_y_max = wmb_y_mount_max + wmb_mount_gap_xy + wmb_mount_wall;
209 wmbb_x_outer = wmb_x_outer + (wmb_mount_gap_xy + wmb_mount_wall);
210 wmbb_z_min = -20; // XXX
211
212 smc_pos = [ 0, sm_inner_rad, 0 ];
213
214 smc_bolt_nut_dia = sm_bolt_nut_width / cos(30);
215 smc_bolt_nut_eff_thick = sm_bolt_nut_thick + sm_bolt_tighten_allow;
216
217 smc_bolt_y = sm_bolt_dia/2 + sm_bolt_y_clear;
218 smc_max_y = smc_bolt_y + sm_bolt_y_over
219   + max(sm_bolt_head_dia/2, smc_bolt_nut_dia/2);
220 smc_cnr_c_x = sm_bolt_shaft/2 - sm_closure_cnr
221   + sm_bolt_head_thick/2 + smc_bolt_nut_eff_thick/2;
222
223 catch_cr = catch_knob_dia/2 + catch_stalk_beside_gap;
224 catch_strap_thick = sm_main_thick;
225
226 echo("R ", sm_inner_rad, bayo_real_rad, bayo_nom_rad);
227
228 $fs= coarse ? 2.5 : 0.5;
229 $fa= coarse ? 5 : 1;
230
231 include <poster-tube-lid-parametric.scad>
232
233 // bayonet definition
234
235 bayo_a = [ bayo_entry_x, 0 ];
236 bayo_p = [ 0, bayo_entry_z ];
237 bayo_n = [ 0, bayo_behind-bayo_inramp_z ];
238 bayo_m = [ bayo_inramp_x, bayo_behind ];
239 bayo_l = bayo_m + bayo_interf * [ 1/bayo_interf_slope,  1 ];
240 bayo_k = bayo_l + [ bayo_interf_width, 0 ];
241 bayo_j = bayo_k + bayo_interf * [ 1/bayo_interf_slope, -1 ];
242 bayo_i = bayo_j + [ rivet_width + inside_rivet_gap, 0 ];
243 bayo_h = [ bayo_i[0], bayo_behind + bayo_gap + bayo_interf ];
244 bayo_g = [ bayo_m[0] - rivet_width, bayo_h[1] ];
245
246 bayo_e = [-bayo_p[0], bayo_p[1]] - [rivet_entry_width,0];
247 bayo_d = [-bayo_a[0], bayo_a[1]] - [rivet_entry_width,0];
248 bayo_c = bayo_d + [0,-5];
249 bayo_b = bayo_a + [0,-5];
250
251 bayo_f = [ bayo_e[0], bayo_g[1] + (bayo_e[0] - bayo_g[0]) ];
252
253 bayo_polygon = [ bayo_a,
254                  bayo_b,
255                  bayo_c,
256                  bayo_d,
257                  bayo_e,
258                  bayo_f,
259                  bayo_g,
260                  bayo_h,
261                  bayo_i,
262                  bayo_j,
263                  bayo_k,
264                  bayo_l,
265                  bayo_m,
266                  bayo_n,
267                  bayo_p ];
268
269 echo(bayo_polygon);
270
271 // CATCH
272
273 cppxC = 0.41 * sm_inner_rad * TAU;
274
275 // catch pin
276
277 cpp_adj = (bayo_n[0] - bayo_f[0]) * (1 - sm_inner_rad / bayo_nom_rad);
278 // radius scaling due to nom and actual radius difference in
279 // bayo entry construction
280
281 cppa = bayo_f + [1,-1] * catch_pin_slop + [1,0] * cpp_adj;
282 cppb = bayo_g + [1,-1] * catch_pin_slop + [1,0] * cpp_adj;
283 cppd = [ bayo_n[0]
284          - catch_pin_slop - catch_pin_slop_x_extra,
285          -catch_stalk_above_gap ];
286 cppi = [ cppa[0], cppd[1] ];
287 cppc = [ cppd[0], cppb[1] ];
288 cpph = cppd + [0,-1] * catch_stalk_h;
289 cppe = cppd + [0,-1] * (catch_knob_above_gap + catch_knob_dia/2);
290 cppf = [ cppa[0], cppe[1] ];
291 cppg = [ cppa[0], cpph[1] ];
292 cppB = 0.5 * (cppf + cppe);
293
294 echo("RR", sm_inner_rad / bayo_nom_rad);
295
296 // catch assembly depression below pin
297
298 cppy6 = cppB[1] - (catch_knob_dia/2
299                    + (cppc[1] - cppd[1])
300                    + catch_stalk_below_gap);
301 cpp7 = [ cppB[0], cppy6 + catch_cr ];
302 cpp11 = cpp7 + [1,0] * catch_cr;
303 cppy9 = cppy6 + catch_strap_width * 1/3;
304 cpp9 = [ cpp7[0] + catch_cr * 2, cppy9 ];
305 cpp8 = cpp9 + [0,-1] * catch_cr;
306 cpp10 = cpp8 + [-1,0] * catch_cr;
307 cppC = [ cppxC, cpp9[1] ];
308 cppD = cppC + [0,-1] * catch_strap_width;
309
310 // catch assembly stalk and so on
311
312 catch_cr3 = catch_cr + catch_stalk_h;
313
314 cppF = [ cppg[0] - catch_stalk_eff_bend_rad, cppd[1] ];
315 cpp4 = [ cppg[0] - catch_stalk_len, cpph[1] ] + [1,-1] * catch_cr;
316 cpp5 = [ cpp4[0], cppC[1] + catch_cr ];
317 cpp2 = cpp5 + [-1,0] * (catch_cr * 2 + catch_stalk_base_width);
318 cpp2r = cpp2 + [1,0] * catch_cr;
319 cpp2d = cpp2 + [0,-1] * catch_cr;
320 cpp3 = [ cpp2[0] + catch_cr + catch_cr3, cppd[1] - catch_cr3 ];
321 cppA = [ -cppxC, cpp9[1] ];
322 cppE = [ cppA[0], cppD[1] ];
323
324 catch_assembly_dy = -cppy9 + catch_strap_width;
325
326
327 module MainProfile(){
328   main_cnr_pos = [ side_thick, top_z ] - [1,1]*main_cnr;
329   difference(){
330     union(){
331       translate(main_cnr_pos){
332         intersection(){
333           difference(){
334             circle(r = main_cnr);
335             circle(r = main_cnr * 0.5);
336           }
337           square([10,10]);
338         }
339       }
340       polygon([[ -top_middle_dr,        middle_bot_z      ],
341                [ -top_middle_dr,        top_z             ],
342                [ main_cnr_pos[0],       top_z             ],
343                [ side_thick,            main_cnr_pos[1]   ],
344                [ side_thick,            -side_height      ],
345                [ side_taper,            -side_height      ],
346                [ 0,                     -rivet_posn       ],
347                [ 0,                     by_oring_z        ],
348                [ -oring_x_rad,          by_oring_z        ],
349                ],
350               convexity=10);
351     }
352     translate([ oring_mid_dia/2 - main_dia/2, 0 ])
353       hull(){
354       translate([ 0, oring_y_rad ])
355         scale([ 1/oring_oblate * (oring_compress_more+1) , oring_oblate ])
356         circle(oring_thick/2);
357       translate([ 0, oring_y_rad*2 - oring_thick/2 ])
358         circle(oring_thick/2);
359     }
360   }
361 }
362
363 module StrapLoopProfile(){
364   circle(r = strap_loop_thick/2);
365 }
366
367 module StrapLoop(){ ////toplevel
368   bigrad = strap_loop_inside/2 + strap_loop_thick/2;
369   extralen = strap_loop_thick * 5;
370
371   intersection(){
372     rotate([strap_loop_elevation, 0,0]){
373       for (x= [ -1, +1 ] * bigrad) {
374         translate([x, -extralen, 0])
375           rotate([-90,0,0])
376           linear_extrude(height= extralen + strap_loop_strlen + 0.1,
377                          convexity=10)
378           StrapLoopProfile();
379       }
380       translate([0, strap_loop_strlen, 0]){
381         intersection(){
382           rotate_extrude(convexity=10)
383             translate([bigrad, 0,0])
384             StrapLoopProfile();
385           translate([0,50,0])
386             cube([100,100,100], center=true);
387         }
388       }
389     }
390     translate([0, 50, 0])
391       cube(100, center=true);
392   }
393 }
394
395 module RotateProjectSlice(offset, slice_size, nom_rad, real_rad){
396   // nom_rad > real_rad
397   rotate([0,0, atan2(offset, nom_rad) ]){
398     intersection(){
399       translate([-offset, -10, 0])
400         rotate([90,0,0])
401         linear_extrude(height= nom_rad*2, convexity=50)
402         children(0);
403       translate([0,0, -25])
404         cylinder(h=50, r= real_rad);
405       translate([0,0, -25])
406         linear_extrude(height= 50, convexity=50)
407         polygon([ [ 0,0 ],
408                   [ -slice_size, -real_rad*2 ],
409                   [ +slice_size, -real_rad*2 ] ]);
410     }
411   }
412 }
413
414 module RotateProject(x_min, x_max, slice_size, nom_rad, real_rad){
415   offs = [ for (i=[ x_min :
416                     slice_size :
417                     x_max + slice_size ]) i ];
418   echo (offs);
419   for (off=offs)
420     RotateProjectSlice(off, slice_size, nom_rad, real_rad)
421     children(0);
422 }
423
424 module BayonetCutout(){
425   RotateProject(bayo_c[0], bayo_i[0], bayo_slice_size,
426                 bayo_nom_rad, 
427                 bayo_real_rad)
428     translate([-0.5 * (bayo_a[0] + bayo_d[0]), 0])
429     polygon(bayo_polygon, convexity=10);
430 }
431
432 module ProfilesDemo(){ ////toplevel
433   translate([-10,0]) MainProfile();
434   translate([+10, -side_height]) polygon(bayo_polygon, convexity=10);
435 }
436
437 module LimitForHandling(){ ////toplevel
438   hull() for (r=[0,180])
439     rotate([0,0,r]) {
440       for (rs=[-1,+1]) {
441         for (xd=[0,1]) {
442           rotate([0,0, rs * handling_angle/2]) {
443             translate([rs * xd * main_dia/2 * tan(handling_angle/2),
444                        main_dia/2 + side_thick - main_cnr,
445                        top_z - main_cnr]) {
446               mirror([0,0,1])
447                 cylinder(r= main_cnr, h=50);
448               sphere(main_cnr);
449             }
450           }
451         }
452       } 
453     }
454   hull() rotate_extrude(convexity=10){
455     translate([ handling_dia/2 - main_cnr, top_z - main_cnr ]) {
456       circle(r = main_cnr);
457       mirror([0,1]) square([ main_cnr, 50 ]);
458     }
459   }
460   //cylinder(r= handling_dia/2, h=20);
461 }
462
463 module Cover(){ ////toplevel
464   render() difference(){
465     intersection(){
466       union(){
467         rotate_extrude(convexity=10)
468           translate([main_dia/2, 0])
469           MainProfile();
470         translate([0,0, middle_bot_z])
471           cylinder(h= top_thick_middle, r = main_dia/2 - top_middle_dr + 1);
472       }
473       LimitForHandling();
474     }
475     for (r=[0,180]){
476       rotate([0,0, r])
477         translate([0,0, -side_height])
478         BayonetCutout();
479       rotate([0,0, r + asin((-oring_rm_beside) / (main_dia/2))])
480         translate([0,
481                    oring_mid_dia/2 + oring_thick/4 * oring_rm_scale,
482                    oring_y_rad * 1.5])
483         rotate([-oring_rm_angle, 0, 0])
484         mirror([0,0,1])
485         cylinder(r = oring_thick/4 * oring_rm_scale, h=20);
486     }
487     for (r=[0 : 60 : 179]) {
488       rotate([0,0, r]) {
489         height = top_thick_middle - brace_above_below*2;
490         translate([0,0, middle_bot_z + brace_above_below + height/2 ])
491         cube(center=true, [ oring_bore - brace_end_shorter,
492                             brace_hole_width, height ]);
493       }
494     }
495   }
496   if (enable_head_cups)
497     for (r=[0,180])
498       rotate([0,0,r])
499         translate([-implheadcup_large_dia * .5 - implheadcup_thick/2,
500                    -implheadcup_large_dia * .0,
501                    middle_bot_z + 0.1])
502         ImplHeadCup();
503
504 //  translate(strap_loop_thick * [-0.5, 0, +1])
505 //    translate([handling_dia/2, 0, -side_height])
506 //    rotate([0,180,0]) rotate([0,0,90])
507 //    StrapLoop();
508 }
509
510 module SavingHole(){
511   translate([0,0, -10])
512     cylinder(r= main_dia/2 - jig_rim, h=20);
513 }
514
515 module Jig(){ ////toplevel
516   difference(){
517     union(){
518       translate([0,0, -side_height]){
519         cylinder(r= main_dia/2 + jig_thick, h= side_height + jig_thick);
520       }
521       translate([-jig_mark_rad, 0, jig_thick - jig_mark])
522         cube([jig_mark_rad*2, jig_mark, jig_mark]);
523     }
524     translate([0,0, -side_height-1])
525       cylinder(r= main_dia/2, h= side_height + 1);
526     SavingHole();
527     translate([0,0, -rivet_posn])
528       rotate([90, 0,0])
529       translate([0,0, -100])
530       cylinder(r= jig_hole_dia/2, h = 200);
531   }
532 }
533
534 module CoverPrint(){ ////toplevel
535   rotate([0,180,0]) Cover();
536 }
537
538 module CoverTest2(){ ////toplevel
539   difference(){
540     Cover();
541     SavingHole();
542   }
543 }
544
545 module CoverTest1(){ ////toplevel
546   difference(){
547     CoverTest2();
548     difference(){
549       for (r= [ 40, 147 ]){
550         rotate([0,0, r]){
551           translate([0,0, -10]) {
552             cube([ main_dia*3, main_dia * .53, 18], center=true);
553           }
554         }
555       }
556 //      translate([ 50, 0, 0 ])
557 //      cube([ 100,
558 //             strap_loop_inside + strap_loop_thick*2 + 1,
559 //             100 ],
560 //           center=true);
561     }
562   }
563 }
564
565 module ImplHeadCupTest(){ ////toplevel
566   for (r=[0,180])
567     rotate([0,0,r])
568       translate([-17,0,0])
569       ImplHeadCup();
570 }
571
572 module SomeStrap(width, cut_width=0){
573   // children(0) is to add, (1) subtract
574   difference(){
575     union(){
576       cylinder(r=sm_outer_rad, h=width);
577       StrapMountProtrusion(smc_cnr_c_x + sm_closure_cnr,
578                            smc_max_y,
579                            sm_closure_cnr,
580                            width);
581       children(0);
582     }
583     translate([0,0,-1])
584       cylinder(r=sm_inner_rad, h=max(width+2, cut_width));
585     translate(smc_pos)
586       StrapMountBolt(10, width);
587     translate(smc_pos)
588       cube([ sm_bolt_tighten_allow, 40,100 ], center=true);
589     children(1);
590   }
591 }
592
593 module StrapMountBolt(l_delta, strap_width){ ///toplevel
594   // positioned relative to smc_pos
595   translate([(smc_bolt_nut_eff_thick - sm_bolt_head_thick)/2,
596              smc_bolt_y,
597              strap_width/2]){
598     translate([ -sm_bolt_shaft/2-1, 0,0 ]){
599       rotate([0,90,0]) cylinder(r= sm_bolt_dia/2, h= sm_bolt_shaft+2);
600     }
601     translate([ -sm_bolt_shaft/2, 0,0 ])
602       rotate([0,-90,0])
603       cylinder($fn=6, r=smc_bolt_nut_dia/2,
604                h=smc_bolt_nut_eff_thick + l_delta);
605     translate([ sm_bolt_shaft/2, 0,0 ])
606       rotate([0,90,0])
607       cylinder(r=sm_bolt_head_dia/2, h=sm_bolt_head_thick + l_delta);
608   }
609 }
610
611 module StrapMountProtrusion(half_x, max_y, cnr, width){
612   translate(smc_pos){
613     linear_extrude(height=width, convexity=10){
614       hull(){
615         for (m = [0,1]) mirror([m,0,0]) {
616           translate([-(half_x - cnr), max_y - cnr])
617             circle(r=cnr);
618           translate([-half_x, -sm_inner_rad])
619             square([1,1]);
620         }
621       }
622     }
623   }
624 }
625
626 module StrapMount(){ ////toplevel
627   SomeStrap(sm_main_width){
628     rotate([0,0,180]){
629       StrapMountProtrusion(strap_loop_inside/2 + strap_loop_thick,
630                            strap_loop_thick,
631                            sm_closure_cnr,
632                            sm_main_width);
633       translate(smc_pos +
634                 [0,0, sm_main_width] +
635                 strap_loop_thick * [ 0, 0.5, -1.0 ])
636         StrapLoop();
637     }
638     union(){ };
639   }
640 }
641
642 module WallScrewHoleSlot(){ ////toplevel
643   ds = [-1,+1] * wm_screw_slot/2;
644   linextr_x_yz(-(wm_thick + 1), 1) {
645     hull(){
646       for (d = ds)
647         translate([d, 0])
648           circle(r = wm_screw_dia/2);
649     }
650   }
651   hull(){
652     for (d = ds){
653       translate([0, d, 0]){
654         linextr_x_yz(0, 1)
655           circle(r = wm_screw_head/2);
656         linextr_x_yz(-(wm_screw_head - wm_screw_dia)/2, 0)
657           circle(r = wm_screw_dia/2);
658       }
659     }
660   }
661 }
662
663 module WallMountMounts(){
664   linextr(0, wm_z_max){
665     translate([ -sm_outer_rad, 0 ])
666       rectfromto([ 0, -wm_y_max ],
667                  [ wm_thick, wm_y_slot1_max ]);
668   }
669 }
670 module WallMountScrewHoles(){
671   translate([ -sm_outer_rad + wm_thick, 0, wm_z_slotc_screw]) {
672     translate([ 0, wm_y_slotc_screw, 0 ])
673       WallScrewHoleSlot();
674     translate([ 0, -wm_y_slotc_screw, 0 ])
675       rotate([90,0,0])
676       WallScrewHoleSlot();
677   }
678 }
679
680 module WallMount(){ ////toplevel
681   SomeStrap(sm_main_width, wm_z_max + 2){
682     WallMountMounts();
683     WallMountScrewHoles();
684   }
685 }
686
687 module WallMountBaseRingCut(){
688   circle(r = wmb_mount_cut_rad);
689 }
690
691 module WallMountBaseMounts(){
692   linextr(0, wmb_z_max) {
693     difference(){
694       rectfromto([ -sm_outer_rad,            -wmb_y_mount_max ],
695                  [ wmb_x_outer, +wmb_y_mount_max ]);
696       WallMountBaseRingCut();
697     }
698   }
699 }
700
701 // screws, nuts, slots for nuts to go down into
702 module WallMountBaseScrewsEtc(){ ////toplevel
703   for (my=[0,1]) {
704     mirror([0, my, 0]) {
705       translate([wmb_x_screw, 0, wmb_z_screw]) {
706         linextr_y_xz(wmb_y_screw_end,
707                      wmb_y_screw_end + 100) // XXX change 100
708           circle(r = wmb_screw_dia/2);
709         linextr_y_xz(wmb_y_screw_end + web_screw_len,
710                      wmb_y_screw_end + 100) // XXX change 100
711           circle(r = wmb_screw_head_dia/2);
712         linextr_y_xz(wmb_y_nut_min,
713                      wmb_y_nut_min + wmb_nut_th){
714           hull(){
715             rotate(30)
716               circle(r = wmb_nut_rad, $fn = 6);
717             translate([0, 100]) // XXX change 100
718               square(wmb_nut_across, center=true);
719           }
720         }
721       }
722     }
723   }
724 }
725
726 module WallMountForBase(){ ////toplevel
727   SomeStrap(sm_main_width, wm_z_max + 2){
728     union(){
729       WallMountMounts();
730       WallMountBaseMounts();
731     }
732     union(){
733       WallMountScrewHoles();
734       WallMountBaseScrewsEtc();
735     }
736   }
737 }
738
739 module WallMountBase(){ ////toplevel
740   difference(){
741     union(){
742       linextr(wmbb_z_min, wmb_z_max) {
743         difference(){
744           for (my = [0,1]) {
745             mirror([0, my]) {
746               rectfromto([ -sm_outer_rad, wmbb_y_max - wmb_mount_y_width ],
747                          [ wmbb_x_outer, wmbb_y_max ]);
748             }
749           }
750           WallMountBaseRingCut();
751         }
752       }
753     }
754   }
755 }
756
757 module WallMountForBaseDemo(){ ////toplevel
758   WallMountForBase();
759   color("blue") WallMountBase();
760   %WallMountBaseScrewsEtc();
761 }
762
763 module CatchAssemblyCoreProfile(){
764   difference(){
765     union(){
766       hull(){
767         translate(cpp3) circle(r= catch_cr3);
768         polygon([ cpp3,
769                   cpp2r,
770                   cpp5,
771                   cpph,
772                   cppd
773                   ]);
774       }
775       polygon([cppD,
776                cppC,
777                cpp9,
778                cpp10,
779                cpp11,
780                cpp4,
781                cpp2r,
782                cpp2d,
783                cppA,
784                cppE
785                ]);
786       translate(cpp8) circle(r= catch_cr);
787     }
788     hull(){
789       translate(cpp4) circle(r= catch_cr);
790       translate(cpp5) circle(r= catch_cr);
791       translate(cpp7) circle(r= catch_cr);
792       polygon([cpp4,
793                cppg,
794                cpph,
795                cpp10,
796                cpp11,
797                ]);
798     }
799     translate(cpp2) circle(r= catch_cr);
800   }
801   // if cpp11 is above cpp10, the subtracted hull above
802   // can go down too far.  Ensure we do not cut off below cppy6.
803   polygon([ cppE,
804             cppD,
805             cpp9,
806             [ cpp9[0],            cppy6 ],
807             [ cpp7[0] - catch_cr, cppy6 ],
808             cpp2d
809             ]);
810 }
811
812 module CatchTipProfile(dy){
813   ddy = [0,dy];
814   intersection(){
815     translate(cppF){
816       difference(){
817 //      circle(r = dist2d(cppF, cppd));
818         //circle(r = dist2d(cppF, cppa));
819       }
820     }
821     polygon([ cppa,
822               cppi + ddy,
823               cppd + ddy,
824               cppc,
825               cppb ]);
826   }
827 }
828
829 module CatchHeadProfile(){
830   polygon([ cppd,
831             cppd,
832             cppi,
833             cppf,
834             cppe,
835             cpph ]);
836 }
837
838
839 module CatchCore(){ /////toplevel
840   linear_extrude(height=catch_strap_thick, convexity=10)
841     CatchAssemblyCoreProfile();
842
843   hull(){
844     linear_extrude(height=catch_head_th, convexity=10)
845       CatchTipProfile(0);
846     linear_extrude(height=catch_tip_th, convexity=10)
847       CatchTipProfile(catch_tip_th - catch_head_th);
848   }
849
850   linear_extrude(height=catch_head_th, convexity=10)
851     CatchHeadProfile();
852
853   translate(concat(cppB,[0])) hull(){
854     translate([0,0, catch_knob_height + catch_head_th - catch_knob_dia/2])
855       sphere(r = catch_knob_dia/2);
856     cylinder(r = catch_knob_dia/2, h = 0.1);
857   }
858 }
859
860 module CatchPreDistort(){ /////toplevel
861   scale(100 / sm_inner_rad)
862     rotate([90,0,0])
863     CatchCore();
864 }
865
866 module CatchAssembly(){ /////toplevel
867   rotate([0,0, -(cppe[0] + cppB[0] + catch_pin_slop) / sm_inner_rad * 360/TAU])
868     translate([0,0, catch_assembly_dy])
869     scale(sm_inner_rad / 100)
870     import(str("poster-tube-lid,CatchPostDistort-fa",
871                (coarse ? 20 : 3),
872                ".stl"),
873            convexity=20);
874
875   SomeStrap(catch_strap_width){
876     union(){ }
877     union(){
878       translate([-200, -200, -200])
879         cube([400, 200, 400]);
880     }
881   }
882 }
883
884 module CatchDemo(){ /////toplevel
885   color("blue") translate([0,0,
886                            -catch_assembly_dy
887              ])
888     CatchAssembly();
889   translate([0,0,+side_height
890              ])
891     Cover();
892 }
893
894 module CatchDemoS(){ /////toplevel
895   color("blue") translate([0,0,
896              -catch_assembly_dy
897              ])
898     CatchAssembly();
899   intersection(){
900     translate([0,0,+side_height
901                ])
902       Cover();
903     mirror([0,1,0]) translate([-250,33,0]) cube([500,500,500]);
904   }
905   color("black")
906     translate([0,-33,0])
907     cube([6.15, 2,2], center=true);
908 }
909
910 module CatchPinProfileDemo(){ /////toplevel
911   translate([0, 0 * -bayo_behind,0]) {
912     echo("G ",
913          bayo_n[0] - bayo_e[0]);
914     color("blue") translate([0,0,
915                              +1,
916                ]) {
917       CatchAssemblyCoreProfile();
918       CatchHeadProfile();
919     }
920     translate([0,0,10])
921       color("red")
922       CatchTipProfile(0);
923
924     polygon(bayo_polygon, convexity=10);
925
926     // adhoc show a position
927     color("purple")
928     translate(concat(
929                      cppa,
930                      10
931                      )) difference(){ circle(2.5); circle(2.0); }
932
933  }
934 }
935
936 //ProfilesDemo();
937 //BayonetCutout();
938 //MainProfile();
939 //Cover();
940 //Jig();
941 //CoverTest();