1//////////////////////////////////////////////////////////////////////
  2// LibFile: metric_screws.scad
  3//   Screws, Bolts, and Nuts.
  4// Includes:
  5//   include <BOSL2/std.scad>
  6//   include <BOSL2/metric_screws.scad>
  7// FileGroup: Threaded Parts
  8// FileSummary: Metric screws, nuts, and screwholes.
  9//////////////////////////////////////////////////////////////////////
 10
 11
 12include <threading.scad>
 13include <screw_drive.scad>
 14
 15
 16// Section: Functions
 17
 18
 19// Function: get_metric_bolt_head_size()
 20// Description: Returns the diameter of a typical metric bolt's head, based on the bolt `size`.
 21function get_metric_bolt_head_size(size) = lookup(size, [
 22        [ 3.0,  5.5],
 23        [ 4.0,  7.0],
 24        [ 5.0,  8.0],
 25        [ 6.0, 10.0],
 26        [ 7.0, 11.0],
 27        [ 8.0, 13.0],
 28        [10.0, 17.0],
 29        [12.0, 19.0],
 30        [14.0, 22.0],
 31        [16.0, 24.0],
 32        [18.0, 27.0],
 33        [20.0, 30.0],
 34        [24.0, 36.0],
 35        [30.0, 46.0],
 36        [36.0, 55.0],
 37        [42.0, 65.0],
 38        [48.0, 75.0],
 39        [56.0, 85.0],
 40        [64.0, 95.0]
 41    ]);
 42
 43
 44// Function: get_metric_bolt_head_height()
 45// Description: Returns the height of a typical metric bolt's head, based on the bolt `size`.
 46function get_metric_bolt_head_height(size) = lookup(size, [
 47        [ 1.6,  1.23],
 48        [ 2.0,  1.53],
 49        [ 2.5,  1.83],
 50        [ 3.0,  2.13],
 51        [ 4.0,  2.93],
 52        [ 5.0,  3.65],
 53        [ 6.0,  4.15],
 54        [ 8.0,  5.45],
 55        [10.0,  6.58],
 56        [12.0,  7.68],
 57        [14.0,  8.98],
 58        [16.0, 10.18],
 59        [20.0, 12.72],
 60        [24.0, 15.35],
 61        [30.0, 19.12],
 62        [36.0, 22.92],
 63        [42.0, 26.42],
 64        [48.0, 30.42],
 65        [56.0, 35.50],
 66        [64.0, 40.50]
 67    ]);
 68
 69
 70// Function: get_metric_socket_cap_diam()
 71// Description: Returns the diameter of a typical metric socket cap bolt's head, based on the bolt `size`.
 72function get_metric_socket_cap_diam(size) = lookup(size, [
 73        [ 1.6,  3.0],
 74        [ 2.0,  3.8],
 75        [ 2.5,  4.5],
 76        [ 3.0,  5.5],
 77        [ 4.0,  7.0],
 78        [ 5.0,  8.5],
 79        [ 6.0, 10.0],
 80        [ 8.0, 13.0],
 81        [10.0, 16.0],
 82        [12.0, 18.0],
 83        [14.0, 21.0],
 84        [16.0, 24.0],
 85        [18.0, 27.0],
 86        [20.0, 30.0],
 87        [22.0, 33.0],
 88        [24.0, 36.0],
 89        [27.0, 40.0],
 90        [30.0, 45.0],
 91        [33.0, 50.0],
 92        [36.0, 54.0],
 93        [42.0, 63.0],
 94        [48.0, 72.0],
 95        [56.0, 84.0],
 96        [64.0, 96.0]
 97    ]);
 98
 99
100// Function: get_metric_socket_cap_height()
101// Description: Returns the height of a typical metric socket cap bolt's head, based on the bolt `size`.
102function get_metric_socket_cap_height(size) = lookup(size, [
103        [ 1.6,  1.7],
104        [ 2.0,  2.0],
105        [ 2.5,  2.5],
106        [ 3.0,  3.0],
107        [ 4.0,  4.0],
108        [ 5.0,  5.0],
109        [ 6.0,  6.0],
110        [ 8.0,  8.0],
111        [10.0, 10.0],
112        [12.0, 12.0],
113        [14.0, 14.0],
114        [16.0, 16.0],
115        [18.0, 18.0],
116        [20.0, 20.0],
117        [22.0, 22.0],
118        [24.0, 24.0],
119        [27.0, 27.0],
120        [30.0, 30.0],
121        [33.0, 33.0],
122        [36.0, 36.0],
123        [42.0, 42.0],
124        [48.0, 48.0],
125        [56.0, 56.0],
126        [64.0, 64.0]
127    ]);
128
129
130// Function: get_metric_socket_cap_socket_size()
131// Description: Returns the diameter of a typical metric socket cap bolt's hex drive socket, based on the bolt `size`.
132function get_metric_socket_cap_socket_size(size) = lookup(size, [
133        [ 1.6,  1.5],
134        [ 2.0,  1.5],
135        [ 2.5,  2.0],
136        [ 3.0,  2.5],
137        [ 4.0,  3.0],
138        [ 5.0,  4.0],
139        [ 6.0,  5.0],
140        [ 8.0,  6.0],
141        [10.0,  8.0],
142        [12.0, 10.0],
143        [14.0, 12.0],
144        [16.0, 14.0],
145        [18.0, 14.0],
146        [20.0, 17.0],
147        [22.0, 17.0],
148        [24.0, 19.0],
149        [27.0, 19.0],
150        [30.0, 22.0],
151        [33.0, 24.0],
152        [36.0, 27.0],
153        [42.0, 32.0],
154        [48.0, 36.0],
155        [56.0, 41.0],
156        [64.0, 46.0]
157    ]);
158
159
160// Function: get_metric_socket_cap_socket_depth()
161// Description: Returns the depth of a typical metric socket cap bolt's hex drive socket, based on the bolt `size`.
162function get_metric_socket_cap_socket_depth(size) = lookup(size, [
163        [ 1.6,  0.7],
164        [ 2.0,  1.0],
165        [ 2.5,  1.1],
166        [ 3.0,  1.3],
167        [ 4.0,  2.0],
168        [ 5.0,  2.5],
169        [ 6.0,  3.0],
170        [ 8.0,  4.0],
171        [10.0,  5.0],
172        [12.0,  6.0],
173        [14.0,  7.0],
174        [16.0,  8.0],
175        [18.0,  9.0],
176        [20.0, 10.0],
177        [22.0, 11.0],
178        [24.0, 12.0],
179        [27.0, 13.5],
180        [30.0, 15.5],
181        [33.0, 18.0],
182        [36.0, 19.0],
183        [42.0, 24.0],
184        [48.0, 28.0],
185        [56.0, 34.0],
186        [64.0, 38.0]
187    ]);
188
189
190// Function: get_metric_iso_coarse_thread_pitch()
191// Description: Returns the ISO metric standard coarse threading pitch for a given bolt `size`.
192function get_metric_iso_coarse_thread_pitch(size) = lookup(size, [
193        [ 1.6, 0.35],
194        [ 2.0, 0.40],
195        [ 2.5, 0.45],
196        [ 3.0, 0.50],
197        [ 4.0, 0.70],
198        [ 5.0, 0.80],
199        [ 6.0, 1.00],
200        [ 7.0, 1.00],
201        [ 8.0, 1.25],
202        [10.0, 1.50],
203        [12.0, 1.75],
204        [14.0, 2.00],
205        [16.0, 2.00],
206        [18.0, 2.50],
207        [20.0, 2.50],
208        [22.0, 2.50],
209        [24.0, 3.00],
210        [27.0, 3.00],
211        [30.0, 3.50],
212        [33.0, 3.50],
213        [36.0, 4.00],
214        [39.0, 4.00],
215        [42.0, 4.50],
216        [45.0, 4.50],
217        [48.0, 5.00],
218        [56.0, 5.50],
219        [64.0, 6.00]
220    ]);
221
222
223// Function: get_metric_iso_fine_thread_pitch()
224// Description: Returns the ISO metric standard fine threading pitch for a given bolt `size`.
225function get_metric_iso_fine_thread_pitch(size) = lookup(size, [
226        [ 1.6, 0.35],
227        [ 2.0, 0.40],
228        [ 2.5, 0.45],
229        [ 3.0, 0.50],
230        [ 4.0, 0.70],
231        [ 5.0, 0.80],
232        [ 6.0, 1.00],
233        [ 7.0, 1.00],
234        [ 8.0, 1.00],
235        [10.0, 1.25],
236        [12.0, 1.50],
237        [14.0, 1.50],
238        [16.0, 2.00],
239        [18.0, 2.50],
240        [20.0, 2.50],
241        [22.0, 2.50],
242        [24.0, 3.00],
243        [27.0, 3.00],
244        [30.0, 3.50],
245        [33.0, 3.50],
246        [36.0, 4.00],
247        [39.0, 4.00],
248        [42.0, 4.50],
249        [45.0, 4.50],
250        [48.0, 5.00],
251        [56.0, 5.50],
252        [64.0, 6.00]
253    ]);
254
255
256// Function: get_metric_iso_superfine_thread_pitch()
257// Description: Returns the ISO metric standard superfine threading pitch for a given bolt `size`.
258function get_metric_iso_superfine_thread_pitch(size) = lookup(size, [
259        [ 1.6, 0.35],
260        [ 2.0, 0.40],
261        [ 2.5, 0.45],
262        [ 3.0, 0.50],
263        [ 4.0, 0.70],
264        [ 5.0, 0.80],
265        [ 6.0, 1.00],
266        [ 7.0, 1.00],
267        [ 8.0, 1.00],
268        [10.0, 1.00],
269        [12.0, 1.25],
270        [14.0, 1.50],
271        [16.0, 2.00],
272        [18.0, 2.50],
273        [20.0, 2.50],
274        [22.0, 2.50],
275        [24.0, 3.00],
276        [27.0, 3.00],
277        [30.0, 3.50],
278        [33.0, 3.50],
279        [36.0, 4.00],
280        [39.0, 4.00],
281        [42.0, 4.50],
282        [45.0, 4.50],
283        [48.0, 5.00],
284        [56.0, 5.50],
285        [64.0, 6.00]
286    ]);
287
288
289// Function: get_metric_jis_thread_pitch()
290// Description: Returns the JIS metric standard threading pitch for a given bolt `size`.
291function get_metric_jis_thread_pitch(size) = lookup(size, [
292        [ 2.0, 0.40],
293        [ 2.5, 0.45],
294        [ 3.0, 0.50],
295        [ 4.0, 0.70],
296        [ 5.0, 0.80],
297        [ 6.0, 1.00],
298        [ 7.0, 1.00],
299        [ 8.0, 1.25],
300        [10.0, 1.25],
301        [12.0, 1.25],
302        [14.0, 1.50],
303        [16.0, 1.50],
304        [18.0, 1.50],
305        [20.0, 1.50]
306    ]);
307
308
309// Function: get_metric_nut_size()
310// Description: Returns the typical metric nut flat-to-flat diameter for a given bolt `size`.
311function get_metric_nut_size(size) = lookup(size, [
312        [ 2.0,  4.0],
313        [ 2.5,  5.0],
314        [ 3.0,  5.5],
315        [ 4.0,  7.0],
316        [ 5.0,  8.0],
317        [ 6.0, 10.0],
318        [ 7.0, 11.0],
319        [ 8.0, 13.0],
320        [10.0, 17.0],
321        [12.0, 19.0],
322        [14.0, 22.0],
323        [16.0, 24.0],
324        [18.0, 27.0],
325        [20.0, 30.0]
326    ]);
327
328
329// Function: get_metric_nut_thickness()
330// Description: Returns the typical metric nut thickness for a given bolt `size`.
331function get_metric_nut_thickness(size) = lookup(size, [
332        [ 1.6,  1.3],
333        [ 2.0,  1.6],
334        [ 2.5,  2.0],
335        [ 3.0,  2.4],
336        [ 4.0,  3.2],
337        [ 5.0,  4.0],
338        [ 6.0,  5.0],
339        [ 7.0,  5.5],
340        [ 8.0,  6.5],
341        [10.0,  8.0],
342        [12.0, 10.0],
343        [14.0, 11.0],
344        [16.0, 13.0],
345        [18.0, 15.0],
346        [20.0, 16.0],
347        [24.0, 21.5],
348        [30.0, 25.6],
349        [36.0, 31.0],
350        [42.0, 34.0],
351        [48.0, 38.0],
352        [56.0, 45.0],
353        [64.0, 51.0]
354    ]);
355
356
357
358// Section: Modules
359
360
361// Module: generic_screw()
362// Description:
363//   Makes a very simple screw model, useful for making screwholes.
364// Usage:
365//   generic_screw(screwsize, screwlen, headsize, headlen)
366// Arguments:
367//   screwsize = diameter of threaded part of screw.
368//   screwlen = length of threaded part of screw.
369//   headsize = diameter of the screw head.
370//   headlen = length of the screw head.
371//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
372//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
373//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
374// Extra Anchors:
375//   "base" = At the base of the head.
376//   "countersunk" = At the head height that would be just barely exposed when countersunk.
377// Examples:
378//   generic_screw(screwsize=3,screwlen=10,headsize=6,headlen=3, anchor="countersunk");
379//   generic_screw(screwsize=3,screwlen=10,headsize=6,headlen=3, anchor="base");
380// Example(FlatSpin,VPD=75): Standard Anchors
381//   generic_screw(screwsize=3,screwlen=10,headsize=6,headlen=3)
382//       show_anchors(5, custom=false);
383// Example(FlatSpin,VPD=55): Custom Named Anchors
384//   expose_anchors()
385//     generic_screw(screwsize=3,screwlen=10,headsize=6,headlen=3)
386//       show_anchors(5, std=false);
387module generic_screw(
388    screwsize=3,
389    screwlen=10,
390    headsize=6,
391    headlen=3,
392    pitch=undef,
393    anchor="base",
394    spin=0,
395    orient=UP
396) {
397    sides = max(12, segs(screwsize/2));
398    anchors = [
399        named_anchor("countersunk", [0,0,(headlen+screwlen)/2-0.01]),
400        named_anchor("base", [0,0,-headlen/2+screwlen/2])
401    ];
402    attachable(anchor,spin,orient, d=screwsize, l=headlen+screwlen, anchors=anchors) {
403        down(headlen/2-screwlen/2) {
404            down(screwlen/2) {
405                if (pitch == undef) {
406                    cylinder(r=screwsize/2, h=screwlen+0.05, center=true, $fn=sides);
407                } else {
408                    threaded_rod(d=screwsize, l=screwlen+0.05, pitch=pitch, $fn=sides);
409                }
410            }
411            cylinder(r=headsize/2, h=headlen, center=false, $fn=sides*2);
412        }
413        children();
414    }
415}
416
417
418// Module: metric_bolt()
419// Description:
420//   Makes a standard metric screw model.
421// Arguments:
422//   size = Diameter of threaded part of screw.
423//   headtype = One of `"hex"`, `"pan"`, `"button"`, `"round"`, `"countersunk"`, `"oval"`, `"socket`".  Default: `"socket"`
424//   l = Length of screw, except for the head.
425//   shank = Length of unthreaded portion of the shaft.
426//   pitch = If given, render threads of the given pitch.  If 0, then no threads.  Overrides coarse argument.
427//   details = If true model should be rendered with extra details.  (Default: false)
428//   coarse = If true, make coarse threads instead of fine threads.  Default = true
429//   flange = Radius of flange beyond the head.  Default = 0 (no flange)
430//   phillips = If given, the size of the phillips drive hole to add.  (ie: "#1", "#2", or "#3")
431//   torx = If given, the size of the torx drive hole to add.  (ie: 10, 20, 30, etc.)
432//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
433//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
434//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
435// Extra Anchors:
436//   "base" = At the base of the head.
437//   "countersunk" = At the head height that would be just barely exposed when countersunk.
438//   "shank" = At the bottom start of the unthreaded shank.
439// Example: Bolt Head Types
440//   ydistribute(40) {
441//       xdistribute(30) {
442//           // Front Row, Left to Right
443//           metric_bolt(headtype="pan", size=10, l=15, details=true, phillips="#2");
444//           metric_bolt(headtype="button", size=10, l=15, details=true, phillips="#2");
445//           metric_bolt(headtype="round", size=10, l=15, details=true, phillips="#2");
446//       }
447//       xdistribute(30) {
448//           // Back Row, Left to Right
449//           metric_bolt(headtype="socket", size=10, l=15, details=true);
450//           metric_bolt(headtype="hex", size=10, l=15, details=true, phillips="#2");
451//           metric_bolt(headtype="countersunk", size=10, l=15, details=true, phillips="#2");
452//           metric_bolt(headtype="oval", size=10, l=15, details=true, phillips="#2");
453//       }
454//   }
455// Example: Details
456//   metric_bolt(size=10, l=15, details=true, $fn=32);
457// Example: No Details Except Threads
458//   metric_bolt(size=10, l=15);
459// Example: No Details, No Threads
460//   metric_bolt(size=10, l=15, pitch=0);
461// Example: Fine Threads
462//   metric_bolt(size=10, l=15, coarse=false);
463// Example: Flange
464//   metric_bolt(size=10, l=15, flange=5);
465// Example: Shank
466//   metric_bolt(size=10, l=25, shank=10);
467// Example: Hex Head with Phillips
468//   metric_bolt(headtype="hex", size=10, l=15, phillips="#2");
469// Example: Hex Head with Torx
470//   metric_bolt(headtype="hex", size=10, l=15, torx=50);
471// Example(FlatSpin,VPD=100): Standard Anchors
472//   metric_bolt(headtype="oval", size=10, l=15, shank=5, details=true, phillips="#2")
473//       show_anchors(5, custom=false);
474// Example(FlatSpin,VPD=100): Custom Named Anchors
475//   expose_anchors(0.125)
476//     metric_bolt(headtype="oval", size=10, l=15, shank=5, details=true, phillips="#2")
477//       show_anchors(5, std=false);
478module metric_bolt(
479    headtype="socket",
480    size=3,
481    l=12,
482    shank=0,
483    pitch=undef,
484    details=false,
485    coarse=true,
486    phillips=undef,
487    torx=undef,
488    flange=0,
489    anchor="base",
490    spin=0,
491    orient=UP
492) {
493    D = headtype != "hex"?
494        get_metric_socket_cap_diam(size) :
495        get_metric_bolt_head_size(size);
496    H = headtype == "socket"?
497        get_metric_socket_cap_height(size) :
498        get_metric_bolt_head_height(size);
499    P = coarse?
500        (pitch==undef? get_metric_iso_coarse_thread_pitch(size) : pitch) :
501        (pitch==undef? get_metric_iso_fine_thread_pitch(size) : pitch);
502    tlen = l - min(l, shank);
503    sides = max(12, segs(size/2));
504    tcirc = D/cos(30);
505    bevtop = (tcirc-D)/2;
506    bevbot = P/2;
507
508    headlen = (
509        (headtype == "pan" || headtype == "round" || headtype == "button")? H*0.75 :
510        (headtype == "countersunk")? (D-size)/2 :
511        (headtype == "oval")? ((D-size)/2 + D/2/3) :
512        H
513    );
514    base = l/2 - headlen/2;
515    sunklen = (
516        (headtype == "oval")? (D-size)/2 :
517        headlen-0.001
518    );
519
520    anchors = [
521        named_anchor("countersunk", [0,0,base+sunklen]),
522        named_anchor("base",   [0,0,base]),
523        named_anchor("shank",  [0,0,base-shank])
524    ];
525
526    //color("silver")
527    attachable(anchor,spin,orient, d=size, l=headlen+l, anchors=anchors) {
528        up(base) {
529            difference() {
530                union() {
531                    // Head
532                    if (headtype == "hex") {
533                        difference() {
534                            cylinder(d=tcirc, h=H, $fn=6);
535
536                            // Bevel hex nut top
537                            if (details) {
538                                up(H-bevtop) {
539                                    difference() {
540                                        cube([tcirc+1, tcirc+1, bevtop+0.5], anchor=BOTTOM);
541                                        down(0.01) cylinder(d1=tcirc, d2=tcirc-bevtop*2, h=bevtop+0.02, center=false);
542                                    }
543                                }
544                            }
545                        }
546                    } else if (headtype == "socket") {
547                        sockw = get_metric_socket_cap_socket_size(size);
548                        sockd = get_metric_socket_cap_socket_depth(size);
549                        difference() {
550                            cylinder(d=D, h=H);
551                            up(H-sockd) cylinder(h=sockd+0.1, d=sockw/cos(30), $fn=6);
552                            if (details) {
553                                kcnt = 36;
554                                zrot_copies(n=kcnt, r=D/2) up(H/3) cube([PI*D/kcnt/2, PI*D/kcnt/2, H], anchor=BOTTOM);
555                            }
556                        }
557                    } else if (headtype == "pan") {
558                        cyl(l=H*0.75, d=D, rounding2=H*0.75/2, anchor=DOWN);
559                    } else if (headtype == "round") {
560                        top_half(D) zscale(H*0.75/D*2) sphere(d=D);
561                    } else if (headtype == "button") {
562                        up(H*0.75/3) top_half(D) zscale(H*0.75*2/3/D*2) sphere(d=D);
563                        cylinder(d=D, h=H*0.75/3+0.01, center=false);
564                    } else if (headtype == "countersunk") {
565                        cylinder(h=(D-size)/2, d1=size, d2=D);
566                    } else if (headtype == "oval") {
567                        up((D-size)/2) top_half(D) zscale(0.333) sphere(d=D);
568                        cylinder(h=(D-size)/2, d1=size, d2=D);
569                    }
570
571                    // Flange
572                    if (flange>0) {
573                        up(headtype == "countersunk" || headtype == "oval"? (D-size)/2 : 0) {
574                            cylinder(d=D+flange, h=H/8, center=false);
575                            up(H/8) cylinder(d1=D+flange, d2=D, h=H/8, center=false);
576                        }
577                    }
578
579                    // Unthreaded Shank
580                    if (tlen < l) {
581                        down(l-tlen) cylinder(d=size, h=l-tlen+0.05, center=false, $fn=sides);
582                    }
583
584                    // Threads
585                    down(l) {
586                        difference() {
587                            up(tlen/2+0.05) {
588                                if (tlen > 0) {
589                                    if (P > 0) {
590                                        threaded_rod(d=size, l=tlen+0.05, pitch=P, $fn=sides);
591                                    } else {
592                                        cylinder(d=size, h=tlen+0.05, $fn=sides, center=true);
593                                    }
594                                }
595                            }
596
597                            // Bevel bottom end of threads
598                            if (details) {
599                                difference() {
600                                    down(0.5) cube([size+1, size+1, bevbot+0.5], anchor=BOTTOM);
601                                    cylinder(d1=size-bevbot*2, d2=size, h=bevbot+0.01, center=false);
602                                }
603                            }
604                        }
605                    }
606                }
607
608                // Phillips drive hole
609                if (headtype != "socket" && phillips != undef) {
610                    down(headtype != "hex"? H/6 : 0) {
611                        phillips_mask(size=phillips); //, shaft=D);
612                    }
613                }
614
615                // Torx drive hole
616                if (headtype != "socket" && torx != undef) {
617                    up(1) torx_mask(size=torx, l=H+0.1, center=false);
618                }
619            }
620        }
621        children();
622    }
623}
624
625
626// Module: metric_nut()
627// Description:
628//   Makes a model of a standard nut for a standard metric screw.
629// Arguments:
630//   size = standard metric screw size in mm. (Default: 3)
631//   hole = include the hole in the nut.  (Default: true)
632//   pitch = pitch of threads in the hole.  No threads if not given.
633//   flange = radius of flange beyond the head.  Default = 0 (no flange)
634//   details = true if model should be rendered with extra details.  (Default: false)
635//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
636//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
637//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
638//   center = If true, centers the nut at the origin.  If false, sits on top of XY plane.  Overrides `anchor` if given.
639// Example: No details, No Hole.  Useful for a mask.
640//   metric_nut(size=10, hole=false);
641// Example:  Hole, with No Threads
642//   metric_nut(size=10, hole=true);
643// Example:  Threads
644//   metric_nut(size=10, hole=true, pitch=1.5);
645// Example:  Details
646//   metric_nut(size=10, hole=true, pitch=1.5, details=true);
647// Example:  Centered
648//   metric_nut(size=10, hole=true, pitch=1.5, details=true, center=true);
649// Example:  Flange
650//   metric_nut(size=10, hole=true, pitch=1.5, flange=3, details=true);
651module metric_nut(
652    size=3,
653    hole=true,
654    pitch=undef,
655    details=false,
656    flange=0,
657    center,
658    anchor,
659    spin=0,
660    orient=UP
661) {
662    H = get_metric_nut_thickness(size);
663    D = get_metric_nut_size(size);
664    boltfn = max(12, segs(size/2));
665    nutfn = max(12, segs(D/2));
666    dcirc = D/cos(30);
667    bevtop = (dcirc - D)/2;
668
669    //color("silver")
670    anchor = get_anchor(anchor,center,BOT,CENTER);
671    attachable(anchor,spin,orient, d=dcirc+flange, l=H) {
672        difference() {
673            union() {
674                difference() {
675                    cylinder(d=dcirc, h=H, center=true, $fn=6);
676                    if (details) {
677                        up(H/2-bevtop) {
678                            difference() {
679                                cube([dcirc+1, dcirc+1, bevtop+0.5], anchor=BOTTOM);
680                                down(0.01) cylinder(d1=dcirc, d2=dcirc-bevtop*2, h=bevtop+0.02, center=false, $fn=nutfn);
681                            }
682                        }
683                        if (flange == 0) {
684                            down(H/2) {
685                                difference() {
686                                    down(0.5) cube([dcirc+1, dcirc+1, bevtop+0.5], anchor=BOTTOM);
687                                    down(0.01) cylinder(d1=dcirc-bevtop*2, d2=dcirc, h=bevtop+0.02, center=false, $fn=nutfn);
688                                }
689                            }
690                        }
691                    }
692                }
693                if (flange>0) {
694                    down(H/2) {
695                        cylinder(d=D+flange, h=H/8, center=false);
696                        up(H/8) cylinder(d1=D+flange, d2=D, h=H/8, center=false);
697                    }
698                }
699            }
700            if (hole == true) {
701                if (pitch == undef) {
702                    cylinder(r=size/2, h=H+0.5, center=true, $fn=boltfn);
703                } else {
704                    threaded_rod(d=size, l=H+0.5, pitch=pitch, $fn=boltfn);
705                }
706            }
707        }
708        children();
709    }
710}
711
712
713// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap