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