1//////////////////////////////////////////////////////////////////////
  2// LibFile: hingesnaps.scad
  3//   Modules for creating snap-locking foldable hined parts.  Includes the mask to create the hinge and
  4//   modules to create the snap-locks. 
  5// Includes:
  6//   include <BOSL2/std.scad>
  7//   include <BOSL2/hingesnaps.scad>
  8// FileGroup: Parts
  9// FileSummary: Foldable, snap-locking parts.
 10//////////////////////////////////////////////////////////////////////
 11
 12// Section: Hinges and Snaps
 13
 14// Module: apply_folding_hinges_and_snaps()
 15// Usage:
 16//   apply_folding_hinges_and_snaps(thick, [foldangle=], [hinges=], [snaps=], [sockets=], [snaplen=], [snapdiam=], [hingegap=], [layerheight=], [$slop=]) CHILDREN;
 17// Description:
 18//   Adds snaplocks and create hinges in children at the given positions.
 19// Arguments:
 20//   thick = Thickness in mm of the material to make the hinge in.
 21//   foldangle = The interior angle in degrees of the joint to be created with the hinge.  Default: 90
 22//   hinges = List of [LENGTH, POSITION, SPIN] for each hinge to difference from the children.
 23//   snaps = List of [POSITION, SPIN] for each central snaplock to add to the children.
 24//   sockets = List of [POSITION, SPIN] for each outer snaplock sockets to add to the children.
 25//   snaplen = Length of locking snaps.
 26//   snapdiam = Diameter/width of locking snaps.
 27//   hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
 28//   layerheight = The expected printing layer height in mm.
 29//   ---
 30//   $slop = increase hinge gap by twice this amount
 31// Example(Med):
 32//   size=100;
 33//   apply_folding_hinges_and_snaps(
 34//       thick=3, foldangle=54.74,
 35//       hinges=[
 36//           for (a=[0,120,240], b=[-size/2,size/4]) each [
 37//               [200, polar_to_xy(b,a), a+90]
 38//           ]
 39//       ],
 40//       snaps=[
 41//           for (a=[0,120,240]) each [
 42//               [rot(a,p=[ size/4, 0        ]), a+90],
 43//               [rot(a,p=[-size/2,-size/2.33]), a-90]
 44//           ]
 45//       ],
 46//       sockets=[
 47//           for (a=[0,120,240]) each [
 48//               [rot(a,p=[ size/4, 0        ]), a+90],
 49//               [rot(a,p=[-size/2, size/2.33]), a+90]
 50//           ]
 51//       ]
 52//   ) {
 53//       $fn=3;
 54//       difference() {
 55//           cylinder(r=size-1, h=3);
 56//           down(0.01) cylinder(r=size/4.5, h=3.1, spin=180);
 57//           down(0.01) for (a=[0:120:359.9]) zrot(a) right(size/2) cylinder(r=size/4.5, h=3.1);
 58//       }
 59//   }
 60module apply_folding_hinges_and_snaps(thick, foldangle=90, hinges=[], snaps=[], sockets=[], snaplen=5, snapdiam=5, hingegap=undef, layerheight=0.2)
 61{
 62    hingegap = default(hingegap, layerheight)+2*get_slop();
 63    difference() {
 64        children();
 65        for (hinge = hinges) {
 66            translate(hinge[1]) {
 67                folding_hinge_mask(
 68                    l=hinge[0], thick=thick, layerheight=layerheight,
 69                    foldangle=foldangle, hingegap=hingegap, spin=hinge[2]
 70                );
 71            }
 72        }
 73    }
 74    for (snap = snaps) {
 75        translate(snap[0]) {
 76            snap_lock(
 77                thick=thick, snaplen=snaplen, snapdiam=snapdiam,
 78                layerheight=layerheight, foldangle=foldangle,
 79                hingegap=hingegap, spin=snap[1]
 80            );
 81        }
 82    }
 83    for (socket = sockets) {
 84        translate(socket[0]) {
 85            snap_socket(
 86                thick=thick, snaplen=snaplen, snapdiam=snapdiam,
 87                layerheight=layerheight, foldangle=foldangle,
 88                hingegap=hingegap, spin=socket[1]
 89            );
 90        }
 91    }
 92}
 93
 94
 95
 96// Module: folding_hinge_mask()
 97// Usage:
 98//   folding_hinge_mask(l, thick, [layerheight=], [foldangle=], [hingegap=], [$slop=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
 99// Description:
100//   Creates a mask to be differenced away from a plate to create a foldable hinge.
101//   Center the mask at the bottom of the plate you want to make a hinge in.
102//   The mask will leave  hinge material two `layerheight`s thick on the bottom of the hinge.
103// Arguments:
104//   l = Length of the hinge in mm.
105//   thick = Thickness in mm of the material to make the hinge in.
106//   ---
107//   layerheight = The expected printing layer height in mm.
108//   foldangle = The interior angle in degrees of the joint to be created with the hinge.  Default: 90
109//   hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
110//   $slop = Increase size of hinge gap by double this amount
111//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
112//   spin = Rotate this many degrees around the Z axis.  See [spin](attachments.scad#subsection-spin).  Default: `0`
113//   orient = Vector to rotate top towards.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
114// Example:
115//   folding_hinge_mask(l=100, thick=3, foldangle=60);
116module folding_hinge_mask(l, thick, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
117{
118    hingegap = default(hingegap, layerheight)+2*get_slop();
119    size = [l, hingegap, 2*thick];
120    size2 = [l, hingegap+2*thick*tan(foldangle/2)];
121    attachable(anchor,spin,orient, size=size, size2=size2) {
122        up(layerheight*2) prismoid([l,hingegap], [l, hingegap+2*thick/tan(foldangle/2)], h=thick, anchor=BOT);
123        children();
124    }
125}
126
127
128// Module: snap_lock()
129// Usage:
130//   snap_lock(thick, [snaplen=], [snapdiam=], [layerheight=], [foldangle=], [hingegap=], [$slop=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
131// Description:
132//   Creates the central snaplock part.
133// Arguments:
134//   thick = Thickness in mm of the material to make the hinge in.
135//   ---
136//   snaplen = Length of locking snaps.
137//   snapdiam = Diameter/width of locking snaps.
138//   layerheight = The expected printing layer height in mm.
139//   foldangle = The interior angle in degrees of the joint to be created with the hinge.  Default: 90
140//   hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
141//   $slop = increase size of hinge gap by double this amount
142//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
143//   spin = Rotate this many degrees around the Z axis.  See [spin](attachments.scad#subsection-spin).  Default: `0`
144//   orient = Vector to rotate top towards.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
145// Example:
146//   snap_lock(thick=3, foldangle=60);
147module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
148{
149    hingegap = default(hingegap, layerheight)+2*get_slop();
150    snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
151    size = [snaplen, snapdiam, 2*thick];
152    attachable(anchor,spin,orient, size=size) {
153        back(snap_x) {
154            cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
155                attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
156                attach(TOP) xcopies(snaplen-snapdiam/4/3) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12);
157            }
158        }
159        children();
160    }
161}
162
163
164// Module: snap_socket()
165// Usage:
166//   snap_socket(thick, [snaplen=], [snapdiam=], [layerheight=], [foldangle=], [hingegap=], [$slop=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
167// Description:
168//   Creates the outside snaplock socketed part.
169// Arguments:
170//   thick = Thickness in mm of the material to make the hinge in.
171//   ---
172//   snaplen = Length of locking snaps.
173//   snapdiam = Diameter/width of locking snaps.
174//   layerheight = The expected printing layer height in mm.
175//   foldangle = The interior angle in degrees of the joint to be created with the hinge.  Default: 90
176//   hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
177//   $slop = Increase size of hinge gap by double this amount
178//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
179//   spin = Rotate this many degrees around the Z axis.  See [spin](attachments.scad#subsection-spin).  Default: `0`
180//   orient = Vector to rotate top towards.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
181// Example:
182//   snap_socket(thick=3, foldangle=60);
183module snap_socket(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
184{
185    hingegap = default(hingegap, layerheight)+2*get_slop();
186    snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
187    size = [snaplen, snapdiam, 2*thick];
188    attachable(anchor,spin,orient, size=size) {
189        fwd(snap_x) {
190            zrot_copies([0,180], r=snaplen+get_slop()) {
191                diff("divot")
192                cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
193                    attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
194                    tag("divot") attach(TOP) left((snaplen+snapdiam/4/3)/2) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12);
195                }
196            }
197        }
198        children();
199    }
200}
201
202
203
204
205// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap