BOSL2/walls.scad
2019-04-26 02:15:53 -07:00

561 lines
17 KiB
OpenSCAD

//////////////////////////////////////////////////////////////////////
// LibFile: walls.scad
// Various wall constructions.
// To use, add the following lines to the beginning of your file:
// ```
// include <BOSL2/std.scad>
// include <BOSL2/walls.scad>
// ```
//////////////////////////////////////////////////////////////////////
/*
BSD 2-Clause License
Copyright (c) 2017-2019, Revar Desmera
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Section: Walls
// Module: narrowing_strut()
//
// Description:
// Makes a rectangular strut with the top side narrowing in a triangle.
// The shape created may be likened to an extruded home plate from baseball.
// This is useful for constructing parts that minimize the need to support
// overhangs.
//
// Usage:
// narrowing_strut(w, l, wall, [ang], [orient], [anchor]);
//
// Arguments:
// w = Width (thickness) of the strut.
// l = Length of the strut.
// wall = height of rectangular portion of the strut.
// ang = angle that the trianglar side will converge at.
// orient = Orientation of the length axis of the shape. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Y`.
// anchor = Alignment of the shape. Use the constants from `constants.scad`. Default: `FRONT`.
//
// Example:
// narrowing_strut(w=10, l=100, wall=5, ang=30);
module narrowing_strut(w=10, l=100, wall=5, ang=30, orient=ORIENT_Y, anchor=FRONT)
{
h = wall + w/2/tan(ang);
size = [w, h, l];
orient_and_anchor(size, orient, anchor, chain=true) {
fwd(h/2) {
linear_extrude(height=l, center=true, slices=2) {
back(wall/2) square([w, wall], center=true);
back(wall-0.001) {
yscale(1/tan(ang)) {
difference() {
zrot(45) square(w/sqrt(2), center=true);
fwd(w/2) square(w, center=true);
}
}
}
}
}
children();
}
}
// Module: thinning_wall()
//
// Description:
// Makes a rectangular wall which thins to a smaller width in the center,
// with angled supports to prevent critical overhangs.
//
// Usage:
// thinning_wall(h, l, thick, [ang], [strut], [wall], [orient], [anchor]);
//
// Arguments:
// h = height of wall.
// l = length of wall. If given as a vector of two numbers, specifies bottom and top lengths, respectively.
// thick = thickness of wall.
// ang = maximum overhang angle of diagonal brace.
// strut = the width of the diagonal brace.
// wall = the thickness of the thinned portion of the wall.
// orient = Orientation of the length axis of the wall. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_X`.
// anchor = Alignment of the shape. Use the constants from `constants.scad`. Default: `CENTER`.
//
// Example: Typical Shape
// thinning_wall(h=50, l=80, thick=4);
// Example: Trapezoidal
// thinning_wall(h=50, l=[80,50], thick=4);
module thinning_wall(h=50, l=100, thick=5, ang=30, strut=5, wall=2, orient=ORIENT_Z, anchor=CENTER)
{
l1 = (l[0] == undef)? l : l[0];
l2 = (l[1] == undef)? l : l[1];
trap_ang = atan2((l2-l1)/2, h);
corr1 = 1 + sin(trap_ang);
corr2 = 1 - sin(trap_ang);
z1 = h/2;
z2 = max(0.1, z1 - strut);
z3 = max(0.05, z2 - (thick-wall)/2*sin(90-ang)/sin(ang));
x1 = l2/2;
x2 = max(0.1, x1 - strut*corr1);
x3 = max(0.05, x2 - (thick-wall)/2*sin(90-ang)/sin(ang)*corr1);
x4 = l1/2;
x5 = max(0.1, x4 - strut*corr2);
x6 = max(0.05, x5 - (thick-wall)/2*sin(90-ang)/sin(ang)*corr2);
y1 = thick/2;
y2 = y1 - min(z2-z3, x2-x3) * sin(ang);
size = [l1, thick, h];
orient_and_anchor(size, orient, anchor, size2=[l2,thick], chain=true) {
polyhedron(
points=[
[-x4, -y1, -z1],
[ x4, -y1, -z1],
[ x1, -y1, z1],
[-x1, -y1, z1],
[-x5, -y1, -z2],
[ x5, -y1, -z2],
[ x2, -y1, z2],
[-x2, -y1, z2],
[-x6, -y2, -z3],
[ x6, -y2, -z3],
[ x3, -y2, z3],
[-x3, -y2, z3],
[-x4, y1, -z1],
[ x4, y1, -z1],
[ x1, y1, z1],
[-x1, y1, z1],
[-x5, y1, -z2],
[ x5, y1, -z2],
[ x2, y1, z2],
[-x2, y1, z2],
[-x6, y2, -z3],
[ x6, y2, -z3],
[ x3, y2, z3],
[-x3, y2, z3],
],
faces=[
[ 4, 5, 1],
[ 5, 6, 2],
[ 6, 7, 3],
[ 7, 4, 0],
[ 4, 1, 0],
[ 5, 2, 1],
[ 6, 3, 2],
[ 7, 0, 3],
[ 8, 9, 5],
[ 9, 10, 6],
[10, 11, 7],
[11, 8, 4],
[ 8, 5, 4],
[ 9, 6, 5],
[10, 7, 6],
[11, 4, 7],
[11, 10, 9],
[20, 21, 22],
[11, 9, 8],
[20, 22, 23],
[16, 17, 21],
[17, 18, 22],
[18, 19, 23],
[19, 16, 20],
[16, 21, 20],
[17, 22, 21],
[18, 23, 22],
[19, 20, 23],
[12, 13, 17],
[13, 14, 18],
[14, 15, 19],
[15, 12, 16],
[12, 17, 16],
[13, 18, 17],
[14, 19, 18],
[15, 16, 19],
[ 0, 1, 13],
[ 1, 2, 14],
[ 2, 3, 15],
[ 3, 0, 12],
[ 0, 13, 12],
[ 1, 14, 13],
[ 2, 15, 14],
[ 3, 12, 15],
],
convexity=6
);
children();
}
}
// Module: braced_thinning_wall()
//
// Description:
// Makes a rectangular wall with cross-bracing, which thins to a smaller width in the center,
// with angled supports to prevent critical overhangs.
//
// Usage:
// braced_thinning_wall(h, l, thick, [ang], [strut], [wall], [orient], [anchor]);
//
// Arguments:
// h = height of wall.
// l = length of wall.
// thick = thickness of wall.
// ang = maximum overhang angle of diagonal brace.
// strut = the width of the diagonal brace.
// wall = the thickness of the thinned portion of the wall.
// orient = Orientation of the length axis of the wall. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Y`.
// anchor = Alignment of the shape. Use the constants from `constants.scad`. Default: `CENTER`.
//
// Example: Typical Shape
// braced_thinning_wall(h=50, l=100, thick=5);
module braced_thinning_wall(h=50, l=100, thick=5, ang=30, strut=5, wall=2, orient=ORIENT_Y, anchor=CENTER)
{
dang = atan((h-2*strut)/(l-2*strut));
dlen = (h-2*strut)/sin(dang);
size = [l, thick, h];
orient_and_anchor(size, orient, anchor, orig_orient=ORIENT_Y, chain=true) {
union() {
xrot_copies([0, 180]) {
down(h/2) narrowing_strut(w=thick, l=l, wall=strut, ang=ang);
fwd(l/2) xrot(-90) narrowing_strut(w=thick, l=h-0.1, wall=strut, ang=ang);
intersection() {
cube(size=[thick, l, h], center=true);
xrot_copies([-dang,dang]) {
zspread(strut/2) {
scale([1,1,1.5]) yrot(45) {
cube(size=[thick/sqrt(2), dlen, thick/sqrt(2)], center=true);
}
}
cube(size=[thick, dlen, strut/2], center=true);
}
}
}
cube(size=[wall, l-0.1, h-0.1], center=true);
}
children();
}
}
// Module: thinning_triangle()
//
// Description:
// Makes a triangular wall with thick edges, which thins to a smaller width in
// the center, with angled supports to prevent critical overhangs.
//
// Usage:
// thinning_triangle(h, l, thick, [ang], [strut], [wall], [diagonly], [orient], [anchor|center]);
//
// Arguments:
// h = height of wall.
// l = length of wall.
// thick = thickness of wall.
// ang = maximum overhang angle of diagonal brace.
// strut = the width of the diagonal brace.
// wall = the thickness of the thinned portion of the wall.
// diagonly = boolean, which denotes only the diagonal side (hypotenuse) should be thick.
// orient = Orientation of the length axis of the shape. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Y`.
// anchor = Alignment of the shape. Use the constants from `constants.scad`. Default: `CENTER`.
// center = If true, centers shape. If false, overrides `anchor` with `UP+BACK`.
//
// Example: Centered
// thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, center=true);
// Example: All Braces
// thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, center=false);
// Example: Diagonal Brace Only
// thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, diagonly=true, center=false);
module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly=false, center=undef, orient=ORIENT_Y, anchor=CENTER)
{
dang = atan(h/l);
dlen = h/sin(dang);
size = [thick, h, l];
orient_and_anchor(size, orient, anchor, center=center, noncentered=BOTTOM+FRONT, orig_orient=ORIENT_Y, chain=true) {
difference() {
union() {
if (!diagonly) {
translate([0, 0, -h/2])
narrowing_strut(w=thick, l=l, wall=strut, ang=ang);
translate([0, -l/2, 0])
xrot(-90) narrowing_strut(w=thick, l=h-0.1, wall=strut, ang=ang);
}
intersection() {
cube(size=[thick, l, h], center=true);
xrot(-dang) yrot(180) {
narrowing_strut(w=thick, l=dlen*1.2, wall=strut, ang=ang);
}
}
cube(size=[wall, l-0.1, h-0.1], center=true);
}
xrot(-dang) {
translate([0, 0, h/2]) {
cube(size=[thick+0.1, l*2, h], center=true);
}
}
}
children();
}
}
// Module: sparse_strut()
//
// Description:
// Makes an open rectangular strut with X-shaped cross-bracing, designed to reduce
// the need for support material in 3D printing.
//
// Usage:
// sparse_strut(h, l, thick, [strut], [maxang], [max_bridge], [orient], [anchor])
//
// Arguments:
// h = height of strut wall.
// l = length of strut wall.
// thick = thickness of strut wall.
// maxang = maximum overhang angle of cross-braces.
// max_bridge = maximum bridging distance between cross-braces.
// strut = the width of the cross-braces.
// orient = Orientation of the length axis of the shape. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Y`.
// anchor = Alignment of the shape. Use the constants from `constants.scad`. Default: `CENTER`.
//
// Example: Typical Shape
// sparse_strut(h=40, l=100, thick=3);
// Example: Thinner Strut
// sparse_strut(h=40, l=100, thick=3, strut=2);
// Example: Larger maxang
// sparse_strut(h=40, l=100, thick=3, strut=2, maxang=45);
// Example: Longer max_bridge
// sparse_strut(h=40, l=100, thick=3, strut=2, maxang=45, max_bridge=30);
module sparse_strut(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, orient=ORIENT_Y, anchor=CENTER)
{
zoff = h/2 - strut/2;
yoff = l/2 - strut;
maxhyp = 1.5 * (max_bridge+strut)/2 / sin(maxang);
maxz = 2 * maxhyp * cos(maxang);
zreps = ceil(2*zoff/maxz);
zstep = 2*zoff / zreps;
hyp = zstep/2 / cos(maxang);
maxy = min(2 * hyp * sin(maxang), max_bridge+strut);
yreps = ceil(2*yoff/maxy);
ystep = 2*yoff / yreps;
ang = atan(ystep/zstep);
len = zstep / cos(ang);
size = [thick, l, h];
orient_and_anchor(size, orient, anchor, orig_orient=ORIENT_Y, chain=true) {
yrot(90)
linear_extrude(height=thick, convexity=4*yreps, center=true) {
difference() {
square([h, l], center=true);
square([h-2*strut, l-2*strut], center=true);
}
yspread(ystep, n=yreps) {
xspread(zstep, n=zreps) {
skew_xy(planar=true, ya=-ang) square([h-1.99*strut, strut], center=true);
skew_xy(planar=true, ya= ang) square([h-1.99*strut, strut], center=true);
}
}
}
children();
}
}
// Module: sparse_strut3d()
//
// Usage:
// sparse_strut3d(h, w, l, [thick], [maxang], [max_bridge], [strut], [orient], [anchor]);
//
// Description:
// Makes an open rectangular strut with X-shaped cross-bracing, designed to reduce the
// need for support material in 3D printing.
//
// Arguments:
// h = Z size of strut.
// w = X size of strut.
// l = Y size of strut.
// thick = thickness of strut walls.
// maxang = maximum overhang angle of cross-braces.
// max_bridge = maximum bridging distance between cross-braces.
// strut = the width of the cross-braces.
// orient = Orientation of the length axis of the shape. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Y`.
// anchor = Alignment of the shape. Use the constants from `constants.scad`. Default: `CENTER`.
//
// Example: Typical Shape
// sparse_strut3d(h=30, w=30, l=100);
// Example: Thinner strut
// sparse_strut3d(h=30, w=30, l=100, strut=2);
// Example: Larger maxang
// sparse_strut3d(h=30, w=30, l=100, strut=2, maxang=50);
// Example: Smaller max_bridge
// sparse_strut3d(h=30, w=30, l=100, strut=2, maxang=50, max_bridge=20);
module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge=30, orient=ORIENT_Y, anchor=CENTER)
{
xoff = w - thick;
yoff = l - thick;
zoff = h - thick;
xreps = ceil(xoff/yoff);
yreps = ceil(yoff/xoff);
zreps = ceil(zoff/min(xoff, yoff));
xstep = xoff / xreps;
ystep = yoff / yreps;
zstep = zoff / zreps;
cross_ang = atan2(xstep, ystep);
cross_len = hypot(xstep, ystep);
supp_ang = min(maxang, min(atan2(max_bridge, zstep), atan2(cross_len/2, zstep)));
supp_reps = floor(cross_len/2/(zstep*sin(supp_ang)));
supp_step = cross_len/2/supp_reps;
size = [w, l, h];
orient_and_anchor(size, orient, anchor, orig_orient=ORIENT_Y, chain=true) {
intersection() {
union() {
ybridge = (l - (yreps+1) * strut) / yreps;
xspread(xoff) sparse_strut(h=h, l=l, thick=thick, maxang=maxang, strut=strut, max_bridge=ybridge/ceil(ybridge/max_bridge));
yspread(yoff) zrot(90) sparse_strut(h=h, l=w, thick=thick, maxang=maxang, strut=strut, max_bridge=max_bridge);
for(zs = [0:zreps-1]) {
for(xs = [0:xreps-1]) {
for(ys = [0:yreps-1]) {
translate([(xs+0.5)*xstep-xoff/2, (ys+0.5)*ystep-yoff/2, (zs+0.5)*zstep-zoff/2]) {
zflip_copy(offset=-(zstep-strut)/2) {
xflip_copy() {
zrot(cross_ang) {
down(strut/2) {
cube([strut, cross_len, strut], center=true);
}
if (zreps>1) {
back(cross_len/2) {
zrot(-cross_ang) {
down(strut) cube([strut, strut, zstep+strut], anchor=BOTTOM);
}
}
}
for (soff = [0 : supp_reps-1] ) {
yflip_copy() {
back(soff*supp_step) {
skew_xy(ya=supp_ang) {
cube([strut, strut, zstep], anchor=BOTTOM);
}
}
}
}
}
}
}
}
}
}
}
}
cube([w,l,h], center=true);
}
children();
}
}
// Module: corrugated_wall()
//
// Description:
// Makes a corrugated wall which relieves contraction stress while still
// providing support strength. Designed with 3D printing in mind.
//
// Usage:
// corrugated_wall(h, l, thick, [strut], [wall], [orient], [anchor]);
//
// Arguments:
// h = height of strut wall.
// l = length of strut wall.
// thick = thickness of strut wall.
// strut = the width of the cross-braces.
// wall = thickness of corrugations.
// orient = Orientation of the length axis of the shape. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Y`.
// anchor = Alignment of the shape. Use the constants from `constants.scad`. Default: `CENTER`.
//
// Example: Typical Shape
// corrugated_wall(h=50, l=100);
// Example: Wider Strut
// corrugated_wall(h=50, l=100, strut=8);
// Example: Thicker Wall
// corrugated_wall(h=50, l=100, strut=8, wall=3);
module corrugated_wall(h=50, l=100, thick=5, strut=5, wall=2, orient=ORIENT_Y, anchor=CENTER)
{
amplitude = (thick - wall) / 2;
period = min(15, thick * 2);
steps = quantup(segs(thick/2),4);
step = period/steps;
il = l - 2*strut + 2*step;
size = [thick, l, h];
orient_and_anchor(size, orient, anchor, orig_orient=ORIENT_Y, chain=true) {
union() {
linear_extrude(height=h-2*strut+0.1, slices=2, convexity=ceil(2*il/period), center=true) {
polygon(
points=concat(
[for (y=[-il/2:step:il/2]) [amplitude*sin(y/period*360)-wall/2, y] ],
[for (y=[il/2:-step:-il/2]) [amplitude*sin(y/period*360)+wall/2, y] ]
)
);
}
difference() {
cube([thick, l, h], center=true);
cube([thick+0.5, l-2*strut, h-2*strut], center=true);
}
}
children();
}
}
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap