omdl  v0.9.8
OpenSCAD Mechanical Design Library
hinges.scad
Go to the documentation of this file.
1 //! Print-in-place hinge generators.
2 /***************************************************************************//**
3  \file
4  \author Roy Allen Sutton
5  \date 2025
6 
7  \copyright
8 
9  This file is part of [omdl] (https://github.com/royasutton/omdl),
10  an OpenSCAD mechanical design library.
11 
12  The \em omdl is free software; you can redistribute it and/or modify
13  it under the terms of the [GNU Lesser General Public License]
14  (http://www.gnu.org/licenses/lgpl.html) as published by the Free
15  Software Foundation; either version 2.1 of the License, or (at
16  your option) any later version.
17 
18  The \em omdl is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with the \em omdl; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301, USA; or see <http://www.gnu.org/licenses/>.
27 
28  \details
29 
30  \amu_define group_name (Hinges)
31  \amu_define group_brief (Print-in-place hinge generators.)
32 
33  \amu_include (include/amu/pgid_path_pstem_pg.amu)
34 *******************************************************************************/
35 
36 //----------------------------------------------------------------------------//
37 // group and macros.
38 //----------------------------------------------------------------------------//
39 
40 /***************************************************************************//**
41  \amu_include (include/amu/group_in_parent_start.amu)
42  \amu_define includes_required_add
43  (
44  models/3d/fastener/screws.scad
45  )
46  \amu_include (include/amu/includes_required.amu)
47 *******************************************************************************/
48 
49 //----------------------------------------------------------------------------//
50 
51 //! A print-in-place single-fold hinge generator.
52 /***************************************************************************//**
53 
54  \param wth <decimal> wall thickness.
55 
56  \param size <datastruct | decimal> pivot and plate sizes; a list
57  [l, w], the lengths and widths or a single decimal to
58  set the lengths. The parameter \p l is a <decimal
59  list-3 | decimal> [lh, lpl, lpr], the hinge, left,
60  and right plate lengths or a single decimal to set
61  (lh=lpl=lpr). Parameter \p w is a <decimal-list-2 |
62  decimal> [wpl, wpr], the left and right plate widths
63  or a single decimal to set (wpl=wpr). Any unspecified
64  parameters are assigned the last specified value.
65 
66  \param vr <datastruct | decimal> plate rounding radii; a list
67  [vrl, vrr], the left and right rounding radii or a
68  single decimal to set (vrl=vrr). The parameters \p
69  vrl and \p vrr are <decimal-list-4 | decimal>, the
70  corner rounding radii for the left and right plates
71  or a single decimal to round all corners the same.
72 
73  \param vrm <datastruct | integer> plate rounding mode; a list
74  [vrml, vrmr], the left and right rounding modes or a
75  single integer to set (vrml=vrmr). The parameters \p
76  vrml and \p vrmr are <integer-list-4 | integer>, the
77  corner rounding modes for the left and right plates
78  or a single integer to round all corners the same.
79 
80  \param knuckle <datastruct> knuckles (see below).
81 
82  \param offset <decimal-list-2 | dcimal> pivot-to-plate offset; a
83  list [oz, oy], the z-offset and y-offset between the
84  pivot and plates or a single decimal to set \p oz.
85  The default offset value is [-wth/2, 0] for a
86  backflap hinge configuration.
87 
88 
89  \param pbore <datastruct> the knuckle pivot bore (see below).
90 
91  \param mbore <datastruct> mount plate bore (see below).
92 
93  \param mbores <datastruct> mount plate bore instance list (see
94  below).
95 
96  \param support <boolean> add print support for knuckles.
97 
98  \param mode <integer> part mode (see below).
99 
100  \param pivot <decimal-list-2 | decimal> the pivot; a list [pl,
101  pr], the left and right mount plate pivots or a
102  single decimal to set (pl=pr).
103 
104  \param align <integer-list-3 | integer> the part alignment; a
105  list [x, y, z], or a single integer to set \p z
106  (default = [0, 0, 0]).
107 
108  \param verb <integer> console output verbosity {0=quiet, 1=info}.
109 
110  \details
111 
112  This module constructs custom single-fold hinges; such as a butt,
113  backflap, strap, gate, offset, continuous, or a knuckle hinge. Most
114  aspects of the hinge can be controlled via a parameter and the base
115  configuration is for a version that can be printed in-place on a 3d
116  printer. Alternatively, the pivot bore can be specified for use
117  with metal pins. The plate size and mount holes are configurable
118  and the bores are generated by screw_bore().
119 
120  ## Multi-value and structured parameters
121 
122  ### knuckle
123 
124  #### Data structure fields: knuckle
125 
126  e | data type | default value | parameter description
127  ---:|:-----------------:|:-----------------:|:------------------------------------
128  0 | <decimal> | wth | \p kd: diameter
129  1 | <integer> | 2 | count
130  2 | <decimal> | 1/2 | gap
131  3 | <integer> | 0 | mode
132  4 | <datastruct> | 4 | pin
133 
134 
135  ##### Data structure fields: knuckle[3]: mode
136 
137  v | description
138  ---:|:---------------------------------------
139  0 | cylinder with no gap
140  1 | male pin
141  2 | female pin
142  3 | gaped cylinders
143  4 | hole for external pin
144  5 | print support projection (for internal use)
145 
146  ##### Data structure fields: knuckle[4]: pin
147 
148  e | data type | default value | parameter description
149  ---:|:-----------------:|:-----------------:|:------------------------------------
150  0 | <decimal> | kd*3/4 | \p pd: cone base diameter
151  1 | <decimal> | pd/2 | cone height
152  2 | <decimal> | pd/3 | point rounding radius
153 
154  ### pbore, mbore
155 
156  The hinge pivot and the mount plate bores use a common
157  specification and are performed using screw_bore(). The data
158  structure is detailed in the following section.
159 
160  #### Data structure fields: pbore, mbore
161 
162  e | data type | default value | parameter description
163  ---:|:-----------------:|:-----------------:|:------------------------------------
164  0 | <decimal> | 0 | \p bd: bore diameter
165  1 | <datastruct> | undef | \p bh: bore head
166  2 | <datastruct> | undef | \p bn: bore nut
167  3 | <datastruct> | 1 | \p bf: bore scale factor
168 
169  The documentation of the bore parameters \p bh, \p bn and \p bf
170  can be found in the screw_bore().
171 
172  ### mbores
173 
174  #### Data structure schema:
175 
176  name | schema
177  ---------------:|:----------------------------------------------
178  mbores | [ instances ]
179  instances | [ instance, instance, ..., instance ]
180 
181  ##### mbores[0]: instances
182 
183  e | data type | default value | parameter description
184  ---:|:-----------------:|:-----------------:|:------------------------------------
185  0 | <datastruct-list> | undef | instance list
186 
187  ##### Data structure fields: mbores[0]: instance
188 
189  e | data type | default value | parameter description
190  ---:|:-----------------:|:-----------------:|:------------------------------------
191  0 | <decimal-list-2 \| decimal> | required | bore center offset [x, y]
192 
193  For an instance with a single decimal, the supplied value
194  controls the bore instance \p x-offset (with y=0).
195 
196  ### part mode
197 
198  A binary encoded integer value.
199 
200  b | description
201  ---:|:---------------------------------------
202  0 | generate left mount plate
203  1 | generate right mount plate
204 
205  \amu_define scope_id (example_sf_backflap)
206  \amu_define title (Backflap hinge example)
207  \amu_define image_views (top bottom right diag)
208  \amu_define image_columns (4)
209  \amu_define image_size (sxga)
210 
211  \amu_include (include/amu/scope_diagrams_3d.amu)
212 
213  \amu_define scope_id (example_sf_custom)
214  \amu_define title (Custom hinge example)
215  \amu_define image_views (top bottom right diag)
216  \amu_define image_columns (4)
217  \amu_define image_size (sxga)
218 
219  \amu_include (include/amu/scope_diagrams_3d.amu)
220 *******************************************************************************/
221 module hinge_sf
222 (
223  wth = 1,
224  size,
225  vr,
226  vrm,
227  knuckle,
228  offset,
229  pbore,
230  mbore,
231  mbores,
232  support = true,
233  mode = 3,
234  pivot,
235  align,
236  verb = 0
237 )
238 {
239  // construct knuckle section
240  module construct_knuckle
241  (
242  m, // modes [l, r]: (see below)
243  d, // diameter
244  l, // length
245  p, // pip-pin [diameter, height, vr];
246  w, // shadow width
247  g = 0 // gap
248  )
249  {
250  // modes:
251  // 0: un-gaped-cylinder
252  // 1: male, 2=female
253  // 3: gaped cylinder
254  // 4: hole for external pin
255  // 5: shadow
256 
257  // side modes [l, r]
258  ml = defined_eon_or(m, 0, 0);
259  mr = defined_e_or (m, 1, ml);
260 
261  // side gaps [l, r]
262  gl = (ml != 0) ? g/2 : 0;
263  gr = (mr != 0) ? g/2 : 0;
264 
265  // section length
266  sl = l - gl - gr;
267 
268  // shaddow: m={[5,*]|[*,5}}
269  if ((ml == 5) || (mr == 5))
270  {
271  translate([-l/2 + gl, eps/2, -w/2])
272  cube([sl, eps, w], center=false);
273  }
274  else
275  // others: m={0|1|2|3|4}
276  {
277  // pin
278  pd = defined_eon_or(p, 0, d*3/4);
279  ph = defined_e_or(p, 1, pd/2);
280  pvr = defined_e_or(p, 2, ph/3);
281 
282  // male and female cone transforms, m*={1|2}: [side, mirror, offset]
283  mc_l = [ if (ml == 1) [+1, 1, +(gl + eps*4)], if (mr == 1) [-1, 0, -(gr + eps*4)] ];
284  fc_l = [ if (ml == 2) [+1, 0, +(gl - eps*4)], if (mr == 2) [-1, 1, -(gr - eps*4)] ];
285 
286  difference()
287  {
288  // cylinder section
289  translate([0, 0, -l/2 + gl])
290  cylinder(d=d, h=sl, center=false);
291 
292  // female cone
293  for ( i = fc_l )
294  translate([0, 0, -l/2 * first(i) + third(i)])
295  mirror([0, 0, second(i)])
296  cone(d=pd, h=ph, vr=[0, pvr]);
297 
298  // pin thru-hole
299  if ((ml == 4) || (mr == 4))
300  cylinder(d=pd, h=l + eps*8, center=true);
301  }
302 
303  // male cone
304  for ( i = mc_l )
305  translate([0, 0, -l/2 * first(i) + third(i)])
306  mirror([0, 0, second(i)])
307  cone(d=pd, h=ph, vr=[0, pvr]);
308  }
309  }
310 
311  // assemble enabled hinge-half sides
312  module assemble_ehhs()
313  {
314  // generate transform list of enabled hinge-half sides
315  hht_ls = [[0, -1, 1], [1, 1, 0]];
316  hht_lse = [
317  for ( s = [0: len(hht_ls)-1] )
318  if ( binary_bit_is(mode, s, 1) )
319  hht_ls[ s ]
320  ];
321 
322  // hinge-half transforms: [hn, hs, hm]
323  for ( hht_l = hht_lse )
324  {
325  ns = first( hht_l ); // number
326  hs = second( hht_l ); // sign
327  hm = third( hht_l ); // mirror
328 
329  // current side width, vr, vrm, and bores
330  p_l = defined_e_or(l_plr, ns, undef);
331  p_w = defined_e_or(w_plr, ns, undef);
332 
333  p_vr = defined_eon_or(vr, ns, undef);
334  p_vrm = defined_eon_or(vrm, ns, 0);
335 
336  pbo_l = defined_e_or(mbores, ns, undef);
337 
338  if (verb > 0)
339  echo(strl([ "side=", ns, ", w=", p_w, ", vr=", p_vr,
340  ", vrm=", p_vrm, ", bores=", pbo_l ]));
341 
342  // hinge-half
343  rotate([defined_eon_or(pivot, ns, 0) * hs, 0, 0])
344  union()
345  {
346  // cylinder section length and x-offset
347  cs_len = l_h/(k_spc*2+1);
348  cs_xos = -(l_h - cs_len)/2;
349 
350  // cylinder section half list and flatten-list
351  // right(+1)=even, left(-1)=odd
352  cs_hl = (hs == +1) ? [0:2:k_spc*2] : [1:2:k_spc*2];
353  cs_hf = [for ( x=cs_hl ) x];
354 
355  // hinge-half: knuckle sections
356  for (s = cs_hf)
357  translate([(cs_xos + cs_len * s) * hs, 0, 0])
358  union()
359  {
360  is_fst = (s == first(cs_hf));
361  is_lst = (s == last(cs_hf));
362  is_eve = is_even( s );
363 
364  // cylinders
365  mc = is_fst ? is_eve ? [0, 3] : 3
366  : is_lst ? is_eve ? [3, 0] : 3
367  : 3;
368 
369  // shadows
370  ms = is_fst ? is_eve ? [0, 5] : 5
371  : is_lst ? is_eve ? [5, 0] : 5
372  : 5;
373 
374  // pin mode (selection based on k_mps)
375  mp = (k_mps == 0) ?
376  ( // fingers: even=male, odd=female
377  is_fst ? is_eve ? [0, 1] : 2
378  : is_lst ? is_eve ? [1, 0] : 2
379  : is_eve ? 1 : 2
380  )
381  : (k_mps == 1) ?
382  ( // fingers: even=female, odd=male
383  is_fst ? is_eve ? [0, 2] : 1
384  : is_lst ? is_eve ? [2, 0] : 1
385  : is_eve ? 2 : 1
386  )
387  : (k_mps == 2) ?
388  ( // hole for external pin
389  is_fst ? is_eve ? [0, 4] : 4
390  : is_lst ? is_eve ? [4, 0] : 4
391  : 4
392  )
393  : mc;
394 
395  difference()
396  {
397  hull()
398  {
399  // knuckle section cylinder-only (reduce diameter)
400  rotate([0, 90, 0])
401  construct_knuckle(m=mc, d=k_dia - eps*4, l=cs_len, g=k_gap, p=k_pin);
402 
403  // plate wall interface
404  translate([0, (k_dia/2 + k_yo) * hs, k_zo])
405  construct_knuckle(m=ms, l=cs_len, w=wth, g=k_gap, p=k_pin);
406 
407  // print-in-place 45% angle build-up
408  if ( support )
409  translate([0, k_dia/2 * hs, -wth/2 + k_zo])
410  rotate([90, 0, 0])
411  construct_knuckle(m=ms, l=cs_len, w=k_dia/2, g=k_gap, p=k_pin);
412  }
413 
414  // remove knuckle section cylinder-only (increase length)
415  rotate([0, 90, 0])
416  construct_knuckle(m=mc, d=k_dia, l=cs_len+eps*4, g=k_gap, p=k_pin);
417  }
418 
419  // add knuckle section (with selected pin mode)
420  rotate([0, 90, 0])
421  construct_knuckle(m=mp, d=k_dia, l=cs_len, g=k_gap, p=k_pin);
422  }
423 
424  // hinge-half: plate
425  translate([0, (p_w/2 + k_dia/2 + k_yo) * hs, k_zo])
426  mirror([0, hm, 0])
427  difference()
428  {
429  // plate
430  extrude_linear_uss(wth, center=true)
431  pg_rectangle([p_l, p_w], vr=p_vr, vrm=p_vrm, center=true);
432 
433  // remove mount plate bores
434  if ( is_defined(mbore) && is_defined(pbo_l) )
435  {
436  pb_d = defined_eon_or(mbore, 0, 0);
437  pb_h = defined_e_or(mbore, 1, undef);
438  pb_n = defined_e_or(mbore, 2, undef);
439  pb_f = defined_e_or(mbore, 3, 1);
440 
441  pb_l = wth + eps*8;
442 
443  for ( pb = pbo_l )
444  {
445  xo = defined_eon_or(pb, 0, 0);
446  yo = defined_e_or(pb, 1, 0);
447 
448  translate([xo, yo, 0])
449  screw_bore(d=pb_d, l=pb_l, h=pb_h, n=pb_n, f=pb_f);
450 
451  if (verb > 0)
452  echo(strl([ "bore=[", xo, ", ", yo, "]" ]));
453  }
454  }
455  }
456  }
457  }
458  }
459 
460  // assemble
461  module assemble()
462  {
463  difference()
464  {
465  assemble_ehhs();
466 
467  // remove pivot pin bore
468  if ( is_defined(pbore) )
469  {
470  pb_d = defined_eon_or(pbore, 0, 0);
471  pb_h = defined_e_or(pbore, 1, undef);
472  pb_n = defined_e_or(pbore, 2, undef);
473  pb_f = defined_e_or(pbore, 3, 1);
474 
475  pb_l = l_h + eps*8;
476 
477  rotate([0, -90, 0])
478  screw_bore(d=pb_d, l=pb_l, h=pb_h, n=pb_n, f=pb_f);
479  }
480  }
481  }
482 
483  //
484  // global parameters
485  //
486 
487  // size: length and width
488  l = defined_eon_or(size, 0, undef);
489  w = defined_e_or(size, 1, undef);
490 
491  // length: hinge and plates
492  l_h = defined_eon_or(l, 0, wth);
493  l_pl = defined_e_or(l, 1, l_h);
494  l_pr = defined_e_or(l, 2, l_pl);
495 
496  l_plr = [l_pl, l_pr];
497 
498  // widths: plates
499  w_pl = defined_eon_or(w, 0, wth);
500  w_pr = defined_e_or(w, 1, w_pl);
501 
502  w_plr = [w_pl, w_pr];
503 
504  // knuckle: diameter, count, gap, pin-mode, pin
505  // when pbore is specified always set k_mps, pin-mode, to 3
506  k_dia = defined_eon_or(knuckle, 0, wth);
507  k_spc = ceil(defined_e_or(knuckle, 1, 2));
508  k_gap = defined_e_or(knuckle, 2, 1/2);
509  k_mps = is_defined(pbore) ? 3
510  : defined_e_or(knuckle, 3, 0);
511  k_pin = defined_e_or(knuckle, 4, k_dia*3/5);
512 
513  // hinge offsets: open z-offset (closed y-offset) and open y-offset
514  k_zo = defined_eon_or(offset, 0, -wth/2);
515  k_yo = defined_e_or(offset, 1, 0);
516 
517  //
518  // global variables
519  //
520 
521  if (verb > 0)
522  {
523  echo(strl([ "size: l=", l, ", w=", w ]));
524  echo(strl([ "size: hinge=", l_h,
525  ", left-plate=[", w_pl, ", ", l_pl, "]",
526  ", right-plate=[", w_pr, ", ", l_pr, "]"]));
527  echo(strl([ "knuckle: mode=", k_mps, ", diameter=", k_dia,
528  ", count=", k_spc, ", gap=", k_gap, ", pin=", k_pin ]));
529  echo(strl([ "offset: zo=", k_zo, ", yo=", k_yo ]));
530  }
531 
532  //
533  // object assembly
534  //
535 
536  alignments =
537  let
538  (
539  ey = k_yo + k_dia/2,
540  ez = k_zo + wth/2
541  )
542  [
543  [0, -l_h, -l_pl, -l_pr, +l_pr, +l_pl, +l_h]/2,
544  [0, -ey, -ey-w_pr/2, -ey-w_pr, +ey, +ey+w_pl/2, +ey+w_pl ],
545  [0, -ez, -ez+wth/2, -ez+wth]
546  ];
547 
548  // when 'align' is scalar assign to 'align_z'
549  align_x = select_ci ( alignments.x, defined_e_or(align, 0, 0), false );
550  align_y = select_ci ( alignments.y, defined_e_or(align, 1, 0), false );
551  align_z = select_ci ( alignments.z, defined_eon_or(align, 2, 0), false );
552 
553  translate([align_x, align_y, align_z])
554  assemble();
555 }
556 
557 //! A print-in-place bi-fold hinge generator.
558 /***************************************************************************//**
559 
560  \param wth <decimal> wall thickness.
561 
562  \param size <datastruct | decimal> pivot and plate sizes; a list
563  [l, w], the lengths and widths or a single decimal to
564  set the lengths. The parameter \p l is a <decimal
565  list-5 | decimal> [lh, lpl, lpr, lpml, lpmr], the
566  hinge, left plate, right plate, left-middle plate,
567  and right-middle plage lengths or a single decimal to
568  set (lh=lpl=lpr=lpml=lpmr). Parameter \p w is a
569  <decimal-list-4 | decimal> [wpl, wpr, wpml, wpmr],
570  the left, right, left-middle, and right-middle plate
571  widths or a single decimal to set
572  (wpl=wpr=wpml=wpmr). Any unspecified parameters are
573  assigned the last specified value.
574 
575  \param vr <datastruct | decimal> plate rounding radii; a list
576  [vrl, vrr, vrml, vrmr], the left, right, left-middle,
577  and right-middle rounding radii or a single decimal
578  to set (vrl=vrr=vrml=vrmr). The parameters are
579  <decimal-list-4 | decimal>, the individual corner
580  rounding radii or a single decimal to round all
581  corners the same.
582 
583  \param vrm <datastruct | integer> plate rounding mode; a list
584  [vrml, vrmr, vrmml, vrmmr], the left, right,
585  left-middle, and right-middle rounding mode or a
586  single integer to set (vrml=vrmr=vrmml=vrmmr). The
587  parameters are <integer-list-4 | integer>, the
588  individual corner rounding modes or a single integer
589  to round all corners the same.
590 
591  \param knuckle <datastruct> knuckles (see below).
592 
593  \param offset <decimal-list-3 | dcimal> pivot-to-plate offsets; a
594  list [oz, oyl, oyr], the z-offset, left, and right
595  y-offset between the pivots and plates or a single
596  decimal to set \p oz (default = [0, 0, 0]).
597 
598 
599  \param pbore <datastruct> the knuckle pivot bore (see below).
600 
601  \param mbore <datastruct> mount plate bore (see below).
602 
603  \param mbores <datastruct> mount plate bore instance list (see
604  below).
605 
606  \param support <boolean> add print support for knuckles.
607 
608  \param mode <integer> part mode (see below).
609 
610  \param pivot <decimal-list-2 | decimal> the pivot; a list [pl,
611  pr], the left and right mount plate pivots or a
612  single decimal to set (pl=pr).
613 
614  \param align <integer-list-3 | integer> the part alignment; a
615  list [x, y, z], or a single integer to set \p z
616  (default = [0, 0, 0]).
617 
618  \param verb <integer> console output verbosity {0=quiet, 1=info,
619  2=details}.
620 
621  \details
622 
623  This module constructs custom bi-fold hinges with print-in-place
624  pivot pins. This type of hinge allows for full folding in both
625  directions. Most aspects of the hinge can be controlled via a
626  parameter. Alternatively, the pivot bore can be specified for use
627  with externally supplied pins. The plate size and mount holes are
628  configurable and the bores are generated by screw_bore().
629 
630  ## Multi-value and structured parameters
631 
632  ### knuckle
633 
634  #### Data structure fields: knuckle
635 
636  e | data type | default value | parameter description
637  ---:|:-----------------:|:-----------------:|:------------------------------------
638  0 | <decimal> | wth | \p kd: diameter
639  1 | <integer> | 2 | count
640  2 | <decimal> | 1/4 | gap
641  3 | <integer> | 0 | mode
642  4 | <datastruct> | 4 | pin
643 
644 
645  ##### Data structure fields: knuckle[3]: mode
646 
647  v | description
648  ---:|:---------------------------------------
649  0 | cylinder with no gap
650  1 | male pin
651  2 | female pin
652  3 | gaped cylinders
653  4 | hole for external pin
654  5 | print support projection (for internal use)
655 
656  ##### Data structure fields: knuckle[4]: pin
657 
658  e | data type | default value | parameter description
659  ---:|:-----------------:|:-----------------:|:------------------------------------
660  0 | <decimal> | kd*3/4 | \p pd: cone base diameter
661  1 | <decimal> | pd/2 | cone height
662  2 | <decimal> | pd/3 | point rounding radius
663 
664  ### pbore, mbore
665 
666  The hinge pivot and the mount plate bores use a common
667  specification and are performed using screw_bore(). The data
668  structure is detailed in the following section.
669 
670  #### Data structure fields: pbore, mbore
671 
672  e | data type | default value | parameter description
673  ---:|:-----------------:|:-----------------:|:------------------------------------
674  0 | <decimal> | 0 | \p bd: bore diameter
675  1 | <datastruct> | undef | \p bh: bore head
676  2 | <datastruct> | undef | \p bn: bore nut
677  3 | <datastruct> | 1 | \p bf: bore scale factor
678 
679  The documentation of the bore parameters \p bh, \p bn and \p bf
680  can be found in the screw_bore().
681 
682  ### mbores
683 
684  #### Data structure schema:
685 
686  name | schema
687  ---------------:|:----------------------------------------------
688  mbores | [ instances-l, instances-r, instances-lm, instances-rm ]
689  instances-* | [ instance, instance, ..., instance ]
690 
691  #### Data structure fields: mbores
692 
693  e | data type | default value | parameter description
694  ---:|:-----------------:|:-----------------:|:------------------------------------
695  0 | <datastruct-list> | undef | instance list left plate
696  1 | <datastruct-list> | undef | instance list right plate
697  2 | <datastruct-list> | undef | instance list left-middle plate
698  3 | <datastruct-list> | undef | instance list right-middle plate
699 
700  The left- and right-middle plate bores can be specified together
701  or separately as configured by a mode bit described below.
702 
703  ##### Data structure fields: mbores[0-3]: instance-*
704 
705  e | data type | default value | parameter description
706  ---:|:-----------------:|:-----------------:|:------------------------------------
707  0 | <decimal-list-2 \| decimal> | required | bore center offset [x, y]
708 
709  For an instance with a single decimal, the supplied value
710  controls the bore instance \p x-offset (with y=0).
711 
712  ### part mode
713 
714  A binary encoded integer value.
715 
716  b | description
717  ---:|:---------------------------------------
718  0 | generate left mount plate
719  1 | generate right mount plate
720  2 | generate middle mount plate
721  3 | specification of left and right middle-plate bores are separate
722 
723  When mode bit-3 is set to one, the specification of the
724  left-middle and right-middle plate bores are independent and
725  specified by \p mbores[2] and \p mbores[3], respectively. When
726  mode bit-3 is set to zero, both the left and right are specified
727  together using by \p mbores[2].
728 
729  \amu_define scope_id (example_bf)
730  \amu_define title (Bi-fold hinge example)
731  \amu_define image_views (top bottom right diag)
732  \amu_define image_columns (4)
733  \amu_define image_size (sxga)
734 
735  \amu_include (include/amu/scope_diagrams_3d.amu)
736 *******************************************************************************/
737 module hinge_bf
738 (
739  wth = 1,
740  size,
741  vr,
742  vrm,
743  knuckle,
744  offset,
745  pbore,
746  mbore,
747  mbores,
748  support = true,
749  mode = 7,
750  pivot,
751  align,
752  verb = 0
753 )
754 {
755  // assemble
756  module assemble()
757  {
758  // assemble left (n=0) and right (n=1) sides
759  for ( n=[0, 1] )
760  mirror([0, n, 0])
761  hinge_sf
762  (
763  // common and fixed
764  wth = wth,
765  knuckle = knuckle,
766  pbore = pbore,
767  mbore = mbore,
768  support = support,
769  verb = verb-1,
770  align = [0, 3, 0],
771 
772  // side-dependent adjustments
773  size = size_df[n],
774  vr = vr_df[n],
775  vrm = vrm_df[n],
776  offset = offset_df[n],
777  mbores = mbores_df[n],
778  mode = mode_df[n],
779  pivot = pivot_df[n]
780  );
781  }
782 
783  //
784  // global parameters
785  //
786 
787  // size: length and width
788  l = defined_eon_or(size, 0, undef);
789  w = defined_e_or(size, 1, undef);
790 
791  // length: hinge and plates
792  l_h = defined_eon_or(l, 0, wth);
793  l_pl = defined_e_or(l, 1, l_h);
794  l_pr = defined_e_or(l, 2, l_pl);
795  l_pml = defined_e_or(l, 3, l_h);
796  l_pmr = defined_e_or(l, 4, l_pml);
797 
798  // widths: plates
799  w_pl = defined_eon_or(w, 0, wth);
800  w_pr = defined_e_or(w, 1, w_pl);
801  w_pml = defined_e_or(w, 2, wth/2);
802  w_pmr = defined_e_or(w, 3, w_pml);
803 
804  // middle rounding radius and modes
805  vr_ml = defined_eon_or(vr, 2, undef);
806  vr_mr = defined_eon_or(vr, 3, vr_ml);
807 
808  vrm_ml = defined_eon_or(vrm, 2, 0);
809  vrm_mr = defined_eon_or(vrm, 3, vrm_ml);
810 
811  // hinge offsets
812  k_zo = defined_eon_or(offset, 0, 0);
813  kl_yo = defined_e_or(offset, 1, 0);
814  kr_yo = defined_e_or(offset, 2, kl_yo);
815 
816  // hinge bores: middle handling; mode bit b3;
817  // 0 = right bores same as left
818  // 1 = right bores separate at mbores[3]
819  mbores_l = defined_e_or(mbores, 0, undef);
820  mbores_r = defined_e_or(mbores, 1, undef);
821  mbores_ml = defined_e_or(mbores, 2, undef);
822  mbores_mr = binary_bit_is(mode, 3, 0)
823  ? mbores_ml
824  : defined_e_or(mbores, 3, undef);
825 
826  // part mode: b0=left, b1=right, b2=middle
827  mode_dm = binary_ishr(binary_and(mode, 4));
828  mode_dl = binary_and(mode, 1) + mode_dm;
829  mode_dr = binary_ishr(binary_and(mode, 2)) + mode_dm;
830 
831  // pivots
832  pivot_l = defined_eon_or(pivot, 0, 0);
833  pivot_r = defined_e_or(pivot, 1, pivot_l);
834 
835  //
836  // global variables
837  //
838 
839  size_df = [ [[l_h, l_pl, l_pml], [w_pl, w_pml]],
840  [[l_h, l_pr, l_pmr], [w_pr, w_pmr]] ];
841 
842  vr_df = [ [defined_eon_or(vr, 0, undef), vr_ml],
843  [defined_eon_or(vr, 1, undef), vr_mr] ];
844 
845  vrm_df = [ [defined_eon_or(vrm, 0, 0), vrm_ml],
846  [defined_eon_or(vrm, 1, 0), vrm_mr] ];
847 
848  offset_df = [ [k_zo, kl_yo],
849  [k_zo, kr_yo] ];
850 
851  mbores_df = [ [mbores_l, mbores_ml],
852  [mbores_r, mbores_mr] ];
853 
854  mode_df = [ mode_dl, mode_dr ];
855 
856  pivot_df = [ [pivot_l, 0], [pivot_r, 0] ];
857 
858  if (verb > 0)
859  {
860  echo(strl([ "size: l=", l, ", w=", w ]));
861 
862  echo(strl([
863  "size: hinge=", l_h,
864  ", left-plate=[", w_pl, ", ", l_pl, "]",
865  ", right-plate=[", w_pr, ", ", l_pr, "]",
866  ", middle-left-plate=[", w_pml, ", ", l_pml, "]",
867  ", middle-right-plate=[", w_pmr, ", ", l_pmr, "]"
868  ]));
869 
870  echo(strl([ "offset: zo=", k_zo, ", left-yo=", kl_yo, ", right-yo=", kr_yo ]));
871 
872  echo(strl([
873  "bores: left-plate=", mbores_l, ", right-plate=", mbores_r,
874  ", middle-left-plate=", mbores_ml, ", middle-right-plate=", mbores_mr
875  ]));
876  }
877 
878  //
879  // object assembly
880  //
881 
882  alignments =
883  let
884  ( // decode knuckle radius (diameter/2)
885  kr = defined_eon_or(knuckle, 0, wth)/2,
886 
887  // x alignments
888  xap = [l_h, l_pl, l_pr, l_pml, l_pmr]/2,
889 
890  // y-left alignments
891  eyl = kl_yo + kr,
892  yapl = [w_pml, w_pml+eyl, w_pml+eyl*2, w_pml+eyl*2+w_pl/2, w_pml+eyl*2+w_pl],
893 
894  // y-right alignments
895  eyr = kr_yo + kr,
896  yapr = [w_pmr, w_pmr+eyr, w_pmr+eyr*2, w_pmr+eyr*2+w_pr/2, w_pmr+eyr*2+w_pr],
897 
898  // z alignments
899  ez = k_zo + wth/2,
900  zap = [-kr, kr, ez-wth, ez-wth/2, ez]
901  )
902  [
903  concat(0, -xap, 0, +xap),
904  concat(0, -yapr, 0, +yapl),
905  concat(0, -zap)
906  ];
907 
908  // when 'align' is scalar assign to 'align_z'
909  align_x = select_ci ( alignments.x, defined_e_or(align, 0, 0), false );
910  align_y = select_ci ( alignments.y, defined_e_or(align, 1, 0), false );
911  align_z = select_ci ( alignments.z, defined_eon_or(align, 2, 0), false );
912 
913  // assemble left and right sides and align
914  translate([align_x, align_y, align_z])
915  assemble();
916 }
917 
918 //! @}
919 //! @}
920 
921 
922 //----------------------------------------------------------------------------//
923 // openscad-amu auxiliary scripts
924 //----------------------------------------------------------------------------//
925 
926 /*
927 BEGIN_SCOPE example_sf_backflap;
928  BEGIN_OPENSCAD;
929  include <omdl-base.scad>;
930  include <models/3d/fastener/screws.scad>;
931  include <parts/3d/fastener/hinges.scad>;
932 
933  $fn = 36;
934 
935  for (y = [[1, -2], [2, +2]])
936  translate([0, second(y), 0])
937  hinge_sf
938  (
939  wth=3,
940  size=[[28,30], 10],
941  vr=1,vrm=1,
942  pivot=45/2,
943  mode=first(y)
944  );
945 
946  // end_include
947  END_OPENSCAD;
948 
949  BEGIN_MFSCRIPT;
950  include --path "${INCLUDE_PATH}" {var_init,var_gen_png2eps}.mfs;
951  table_unset_all sizes;
952 
953  images name "sizes" types "sxga";
954  views name "views" views "top bottom right diag";
955 
956  variables set_opts_combine "sizes views";
957  variables add_opts "--viewall --autocenter --view=axes";
958 
959  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
960  END_MFSCRIPT;
961 END_SCOPE;
962 
963 BEGIN_SCOPE example_sf_custom;
964  BEGIN_OPENSCAD;
965  include <omdl-base.scad>;
966  include <models/3d/fastener/screws.scad>;
967  include <parts/3d/fastener/hinges.scad>;
968 
969  $fn = 36;
970 
971  for (y = [[1, -3], [2, +3]])
972  translate([0, second(y), 0])
973  hinge_sf
974  (
975  wth=3,
976  size=[[18, 20, 35], [4, 6]],
977  vr=1,
978  vrm=[[4,3,1,1],[10,9,5,5]],
979 
980  knuckle=[5, 2, 1/2],
981 
982  mbore=[1, [2, 1, 1/2], [2, 1]],
983  mbores=[[-7, 0, 7], [-14, -7, 0, 7, 14]],
984 
985  offset=[undef, 2],
986  mode=first(y)
987  );
988 
989  // end_include
990  END_OPENSCAD;
991 
992  BEGIN_MFSCRIPT;
993  include --path "${INCLUDE_PATH}" {var_init,var_gen_png2eps}.mfs;
994  table_unset_all sizes;
995 
996  images name "sizes" types "sxga";
997  views name "views" views "top bottom right diag";
998 
999  variables set_opts_combine "sizes views";
1000  variables add_opts "--viewall --autocenter --view=axes";
1001 
1002  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
1003  END_MFSCRIPT;
1004 END_SCOPE;
1005 
1006 BEGIN_SCOPE example_bf;
1007  BEGIN_OPENSCAD;
1008  include <omdl-base.scad>;
1009  include <models/3d/fastener/screws.scad>;
1010  include <parts/3d/fastener/hinges.scad>;
1011 
1012  $fn = 36;
1013 
1014  l = 150; w = 75; h = 8;
1015 
1016  b = [for (x=[-1,0,1], y=[-1,1]) [l/3*x, w/4*y]];
1017 
1018  hinge_bf
1019  (
1020  wth=h,
1021  size=[[l*9/10, l], [w, w, h]],
1022  vr=[w, w]/10,
1023  vrm=5,
1024  knuckle=[h, 4, 1/2],
1025  mbore=[6, [12,2,1]],
1026  mbores=[b, b],
1027  offset=[0, h/2],
1028  pivot=30
1029  );
1030 
1031  // end_include
1032  END_OPENSCAD;
1033 
1034  BEGIN_MFSCRIPT;
1035  include --path "${INCLUDE_PATH}" {var_init,var_gen_png2eps}.mfs;
1036  table_unset_all sizes;
1037 
1038  images name "sizes" types "sxga";
1039  views name "views" views "top bottom right diag";
1040 
1041  variables set_opts_combine "sizes views";
1042  variables add_opts "--viewall --autocenter --view=axes";
1043 
1044  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
1045  END_MFSCRIPT;
1046 END_SCOPE;
1047 */
1048 
1049 //----------------------------------------------------------------------------//
1050 // end of file
1051 //----------------------------------------------------------------------------//
1052 
eps
<decimal> Epsilon, small distance to deal with overlapping shapes.
Definition: constants.scad:195
function binary_and(v1, v2, bv=1)
Base-2 binary AND operation for integers.
function binary_bit_is(v, b, t=1)
Test if a binary bit position of an integer value equals a test bit.
function binary_ishr(v, s=1)
Base-2 binary right-shift operation for an integer.
function defined_e_or(v, i, d)
Return an element of an iterable when it exists or a default value otherwise.
function third(v)
Return the third element of an iterable value.
function last(v)
Return the last element of an iterable value.
function second(v)
Return the second element of an iterable value.
function defined_eon_or(v, i, d)
Return the list element or scalar numeric value, if either is defined, otherwise the default value.
function first(v)
Return the first element of an iterable value.
function select_ci(v, i, l=true)
Select specified element from list or return a default.
function strl(v)
Convert a list of values to a concatenated string.
function is_defined(v)
Test if a value is defined.
function is_even(v)
Test if a numerical value is even.
module screw_bore(d=1, l=1, h, n, t, s, f, a)
Flat and beveled-head fastener bore with nut, nut slot, and bore tolerance.
Definition: screws.scad:358
module hinge_bf(wth=1, size, vr, vrm, knuckle, offset, pbore, mbore, mbores, support=true, mode=7, pivot, align, verb=0)
A print-in-place bi-fold hinge generator.
Definition: hinges.scad:1306
module hinge_sf(wth=1, size, vr, vrm, knuckle, offset, pbore, mbore, mbores, support=true, mode=3, pivot, align, verb=0)
A print-in-place single-fold hinge generator.
Definition: hinges.scad:636
module cone(r=1, h, d, vr)
A cone.
Definition: basic_3d.scad:461
module pg_rectangle(size=1, o, vr, vrm=1, vfn, center=false)
A polygon rectangle with vertex rounding.
Definition: polygon.scad:765
module extrude_linear_uss(h, center=false, c=true, ha=0)
Linearly extrude a 2d shape with uniformly-spaced profile scaling.
Definition: extrude.scad:666