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