1//////////////////////////////////////////////////////////////////////
  2// LibFile: walls.scad
  3//   Walls and structural elements that 3D print without support.
  4// Includes:
  5//   include <BOSL2/std.scad>
  6//   include <BOSL2/walls.scad>
  7// FileGroup: Parts
  8// FileSummary: Walls and structural elements that 3D print without support.
  9//////////////////////////////////////////////////////////////////////
 10
 11
 12// Section: Walls
 13
 14
 15// Module: sparse_wall()
 16// Synopsis: Makes an open cross-braced rectangular wall.
 17// SynTags: Geom
 18// Topics: FDM Optimized, Walls
 19// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
 20//
 21// Usage:
 22//   sparse_wall(h, l, thick, [maxang=], [strut=], [max_bridge=]) [ATTACHMENTS];
 23//
 24// Description:
 25//   Makes an open rectangular strut with X-shaped cross-bracing, designed to reduce
 26//   the need for support material in 3D printing.
 27//
 28// Arguments:
 29//   h = height of strut wall.
 30//   l = length of strut wall.
 31//   thick = thickness of strut wall.
 32//   ---
 33//   maxang = maximum overhang angle of cross-braces.
 34//   strut = the width of the cross-braces.
 35//   max_bridge = maximum bridging distance between cross-braces.
 36//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
 37//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
 38//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
 39//
 40// See Also: corrugated_wall(), thinning_wall()
 41//
 42// Example: Typical Shape
 43//   sparse_wall(h=40, l=100, thick=3);
 44// Example: Thinner Strut
 45//   sparse_wall(h=40, l=100, thick=3, strut=2);
 46// Example: Larger maxang
 47//   sparse_wall(h=40, l=100, thick=3, strut=2, maxang=45);
 48// Example: Longer max_bridge
 49//   sparse_wall(h=40, l=100, thick=3, strut=2, maxang=45, max_bridge=30);
 50module sparse_wall(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anchor=CENTER, spin=0, orient=UP)
 51{
 52    zoff = h/2 - strut/2;
 53    yoff = l/2 - strut/2;
 54
 55    maxhyp = 1.5 * (max_bridge+strut)/2 / sin(maxang);
 56    maxz = 2 * maxhyp * cos(maxang);
 57
 58    zreps = ceil(2*zoff/maxz);
 59    zstep = 2*zoff / zreps;
 60
 61    hyp = zstep/2 / cos(maxang);
 62    maxy = min(2 * hyp * sin(maxang), max_bridge+strut);
 63
 64    yreps = ceil(2*yoff/maxy);
 65    ystep = 2*yoff / yreps;
 66
 67    ang = atan(ystep/zstep);
 68    len = zstep / cos(ang);
 69
 70    size = [thick, l, h];
 71    attachable(anchor,spin,orient, size=size) {
 72        yrot(90)
 73        linear_extrude(height=thick, convexity=4*yreps, center=true) {
 74            difference() {
 75                square([h, l], center=true);
 76                square([h-2*strut, l-2*strut], center=true);
 77            }
 78            ycopies(ystep, n=yreps) {
 79                xcopies(zstep, n=zreps) {
 80                    skew(syx=tan(-ang)) square([(h-strut)/zreps, strut], center=true);
 81                    skew(syx=tan( ang)) square([(h-strut)/zreps, strut], center=true);
 82                }
 83            }
 84        }
 85        children();
 86    }
 87}
 88
 89
 90// Module: corrugated_wall()
 91// Synopsis: Makes a corrugated rectangular wall.
 92// SynTags: Geom
 93// Topics: FDM Optimized, Walls
 94// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
 95//
 96// Usage:
 97//   corrugated_wall(h, l, thick, [strut=], [wall=]) [ATTACHMENTS];
 98//
 99// Description:
100//   Makes a corrugated wall which relieves contraction stress while still
101//   providing support strength.  Designed with 3D printing in mind.
102//
103// Arguments:
104//   h = height of strut wall.
105//   l = length of strut wall.
106//   thick = thickness of strut wall.
107//   ---
108//   strut = the width of the cross-braces.
109//   wall = thickness of corrugations.
110//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
111//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
112//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
113//
114// See Also: sparse_wall(), thinning_wall()
115//
116// Example: Typical Shape
117//   corrugated_wall(h=50, l=100);
118// Example: Wider Strut
119//   corrugated_wall(h=50, l=100, strut=8);
120// Example: Thicker Wall
121//   corrugated_wall(h=50, l=100, strut=8, wall=3);
122module corrugated_wall(h=50, l=100, thick=5, strut=5, wall=2, anchor=CENTER, spin=0, orient=UP)
123{
124    amplitude = (thick - wall) / 2;
125    period = min(15, thick * 2);
126    steps = quantup(segs(thick/2),4);
127    step = period/steps;
128    il = l - 2*strut + 2*step;
129    size = [thick, l, h];
130    attachable(anchor,spin,orient, size=size) {
131        union() {
132            linear_extrude(height=h-2*strut+0.1, slices=2, convexity=ceil(2*il/period), center=true) {
133                polygon(
134                    points=concat(
135                        [for (y=[-il/2:step:il/2]) [amplitude*sin(y/period*360)-wall/2, y] ],
136                        [for (y=[il/2:-step:-il/2]) [amplitude*sin(y/period*360)+wall/2, y] ]
137                    )
138                );
139            }
140            difference() {
141                cube([thick, l, h], center=true);
142                cube([thick+0.5, l-2*strut, h-2*strut], center=true);
143            }
144        }
145        children();
146    }
147}
148
149
150// Module: thinning_wall()
151// Synopsis: Makes a rectangular wall with a thin middle.
152// SynTags: Geom
153// Topics: FDM Optimized, Walls
154// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
155//
156// Usage:
157//   thinning_wall(h, l, thick, [ang=], [braces=], [strut=], [wall=]) [ATTACHMENTS];
158//
159// Description:
160//   Makes a rectangular wall which thins to a smaller width in the center,
161//   with angled supports to prevent critical overhangs.
162//
163// Arguments:
164//   h = Height of wall.
165//   l = Length of wall.  If given as a vector of two numbers, specifies bottom and top lengths, respectively.
166//   thick = Thickness of wall.
167//   ---
168//   ang = Maximum overhang angle of diagonal brace.
169//   braces = If true, adds diagonal crossbraces for strength.
170//   strut = The width of the borders and diagonal braces.  Default: `thick/2`
171//   wall = The thickness of the thinned portion of the wall.  Default: `thick/2`
172//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
173//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
174//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
175//
176// See Also: sparse_wall(), corrugated_wall(), thinning_triangle()
177//
178// Example: Typical Shape
179//   thinning_wall(h=50, l=80, thick=4);
180// Example: Trapezoidal
181//   thinning_wall(h=50, l=[80,50], thick=4);
182// Example: Trapezoidal with Braces
183//   thinning_wall(h=50, l=[80,50], thick=4, strut=4, wall=2, braces=true);
184module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut, wall, anchor=CENTER, spin=0, orient=UP)
185{
186    l1 = (l[0] == undef)? l : l[0];
187    l2 = (l[1] == undef)? l : l[1];
188    strut = is_num(strut)? strut : min(h,l1,l2,thick)/2;
189    wall = is_num(wall)? wall : thick/2;
190
191    bevel_h = strut + (thick-wall)/2/tan(ang);
192    cp1 = circle_2tangents(strut, [0,0,+h/2], [l2/2,0,+h/2], [l1/2,0,-h/2])[0];
193    cp2 = circle_2tangents(bevel_h, [0,0,+h/2], [l2/2,0,+h/2], [l1/2,0,-h/2])[0];
194    cp3 = circle_2tangents(bevel_h, [0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,+h/2])[0];
195    cp4 = circle_2tangents(strut, [0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,+h/2])[0];
196
197    z1 = h/2;
198    z2 = cp1.z;
199    z3 = cp2.z;
200
201    x1 = l2/2;
202    x2 = cp1.x;
203    x3 = cp2.x;
204    x4 = l1/2;
205    x5 = cp4.x;
206    x6 = cp3.x;
207
208    y1 = thick/2;
209    y2 = wall/2;
210
211    corner1 = [ x2, 0,  z2];
212    corner2 = [-x5, 0, -z2];
213    brace_len = norm(corner1-corner2);
214
215    size = [l1, thick, h];
216    attachable(anchor,spin,orient, size=size, size2=[l2,thick]) {
217        zrot(90) {
218            polyhedron(
219                points=[
220                    [-x4, -y1, -z1],
221                    [ x4, -y1, -z1],
222                    [ x1, -y1,  z1],
223                    [-x1, -y1,  z1],
224
225                    [-x5, -y1, -z2],
226                    [ x5, -y1, -z2],
227                    [ x2, -y1,  z2],
228                    [-x2, -y1,  z2],
229
230                    [-x6, -y2, -z3],
231                    [ x6, -y2, -z3],
232                    [ x3, -y2,  z3],
233                    [-x3, -y2,  z3],
234
235                    [-x4,  y1, -z1],
236                    [ x4,  y1, -z1],
237                    [ x1,  y1,  z1],
238                    [-x1,  y1,  z1],
239
240                    [-x5,  y1, -z2],
241                    [ x5,  y1, -z2],
242                    [ x2,  y1,  z2],
243                    [-x2,  y1,  z2],
244
245                    [-x6,  y2, -z3],
246                    [ x6,  y2, -z3],
247                    [ x3,  y2,  z3],
248                    [-x3,  y2,  z3],
249                ],
250                faces=[
251                    [ 4,  5,  1],
252                    [ 5,  6,  2],
253                    [ 6,  7,  3],
254                    [ 7,  4,  0],
255
256                    [ 4,  1,  0],
257                    [ 5,  2,  1],
258                    [ 6,  3,  2],
259                    [ 7,  0,  3],
260
261                    [ 8,  9,  5],
262                    [ 9, 10,  6],
263                    [10, 11,  7],
264                    [11,  8,  4],
265
266                    [ 8,  5,  4],
267                    [ 9,  6,  5],
268                    [10,  7,  6],
269                    [11,  4,  7],
270
271                    [11, 10,  9],
272                    [20, 21, 22],
273
274                    [11,  9,  8],
275                    [20, 22, 23],
276
277                    [16, 17, 21],
278                    [17, 18, 22],
279                    [18, 19, 23],
280                    [19, 16, 20],
281
282                    [16, 21, 20],
283                    [17, 22, 21],
284                    [18, 23, 22],
285                    [19, 20, 23],
286
287                    [12, 13, 17],
288                    [13, 14, 18],
289                    [14, 15, 19],
290                    [15, 12, 16],
291
292                    [12, 17, 16],
293                    [13, 18, 17],
294                    [14, 19, 18],
295                    [15, 16, 19],
296
297                    [ 0,  1, 13],
298                    [ 1,  2, 14],
299                    [ 2,  3, 15],
300                    [ 3,  0, 12],
301
302                    [ 0, 13, 12],
303                    [ 1, 14, 13],
304                    [ 2, 15, 14],
305                    [ 3, 12, 15],
306                ],
307                convexity=6
308            );
309            if(braces) {
310                bracepath = [
311                    [-strut*0.33,thick/2],
312                    [ strut*0.33,thick/2],
313                    [ strut*0.33+(thick-wall)/2/tan(ang), wall/2],
314                    [ strut*0.33+(thick-wall)/2/tan(ang),-wall/2],
315                    [ strut*0.33,-thick/2],
316                    [-strut*0.33,-thick/2],
317                    [-strut*0.33-(thick-wall)/2/tan(ang),-wall/2],
318                    [-strut*0.33-(thick-wall)/2/tan(ang), wall/2]
319                ];
320                xflip_copy() {
321                    intersection() {
322                        extrude_from_to(corner1,corner2) {
323                            polygon(bracepath);
324                        }
325                        prismoid([l1,thick],[l2,thick],h=h,anchor=CENTER);
326                    }
327                }
328            }
329        }
330        children();
331    }
332}
333
334
335// Module: thinning_triangle()
336// Synopsis: Makes a triangular wall with a thin middle.
337// SynTags: Geom
338// Topics: FDM Optimized, Walls
339// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
340//
341// Usage:
342//   thinning_triangle(h, l, thick, [ang=], [strut=], [wall=], [diagonly=], [center=]) [ATTACHMENTS];
343//
344// Description:
345//   Makes a triangular wall with thick edges, which thins to a smaller width in
346//   the center, with angled supports to prevent critical overhangs.
347//
348// Arguments:
349//   h = height of wall.
350//   l = length of wall.
351//   thick = thickness of wall.
352//   ---
353//   ang = maximum overhang angle of diagonal brace.
354//   strut = the width of the diagonal brace.
355//   wall = the thickness of the thinned portion of the wall.
356//   diagonly = boolean, which denotes only the diagonal side (hypotenuse) should be thick.
357//   center = If true, centers shape.  If false, overrides `anchor` with `UP+BACK`.
358//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
359//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
360//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
361//
362// See Also: thinning_wall()
363//
364// Example: Centered
365//   thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, center=true);
366// Example: All Braces
367//   thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, center=false);
368// Example: Diagonal Brace Only
369//   thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, diagonly=true, center=false);
370module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly=false, center, anchor, spin=0, orient=UP)
371{
372    dang = atan(h/l);
373    dlen = h/sin(dang);
374    size = [thick, l, h];
375    anchor = get_anchor(anchor, center, BOT+FRONT, CENTER);
376    attachable(anchor,spin,orient, size=size) {
377        difference() {
378            union() {
379                if (!diagonly) {
380                    translate([0, 0, -h/2])
381                        narrowing_strut(w=thick, l=l, wall=strut, ang=ang);
382                    translate([0, -l/2, 0])
383                        xrot(-90) narrowing_strut(w=thick, l=h-0.1, wall=strut, ang=ang);
384                }
385                intersection() {
386                    cube(size=[thick, l, h], center=true);
387                    xrot(-dang) yrot(180) {
388                        narrowing_strut(w=thick, l=dlen*1.2, wall=strut, ang=ang);
389                    }
390                }
391                cube(size=[wall, l-0.1, h-0.1], center=true);
392            }
393            xrot(-dang) {
394                translate([0, 0, h/2]) {
395                    cube(size=[thick+0.1, l*2, h], center=true);
396                }
397            }
398        }
399        children();
400    }
401}
402
403
404// Module: narrowing_strut()
405// Synopsis: Makes a strut like an extruded baseball home plate.
406// SynTags: Geom
407// Topics: FDM Optimized
408// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
409//
410// Usage:
411//   narrowing_strut(w, l, wall, [ang=]) [ATTACHMENTS];
412//
413// Description:
414//   Makes a rectangular strut with the top side narrowing in a triangle.
415//   The shape created may be likened to an extruded home plate from baseball.
416//   This is useful for constructing parts that minimize the need to support
417//   overhangs.
418//
419// Arguments:
420//   w = Width (thickness) of the strut.
421//   l = Length of the strut.
422//   wall = height of rectangular portion of the strut.
423//   ---
424//   ang = angle that the trianglar side will converge at.
425//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
426//   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
427//   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
428//
429// Example:
430//   narrowing_strut(w=10, l=100, wall=5, ang=30);
431module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orient=UP)
432{
433    h = wall + w/2/tan(ang);
434    size = [w, l, h];
435    attachable(anchor,spin,orient, size=size) {
436        xrot(90)
437        fwd(h/2) {
438            linear_extrude(height=l, center=true, slices=2) {
439                back(wall/2) square([w, wall], center=true);
440                back(wall-0.001) {
441                    yscale(1/tan(ang)) {
442                        difference() {
443                            zrot(45) square(w/sqrt(2), center=true);
444                            fwd(w/2) square(w, center=true);
445                        }
446                    }
447                }
448            }
449        }
450        children();
451    }
452}
453
454
455
456// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap