diff --git a/walls.scad b/walls.scad index 333f21d..a177942 100644 --- a/walls.scad +++ b/walls.scad @@ -12,44 +12,71 @@ // 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. +// Module: sparse_wall() // // Usage: -// narrowing_strut(w, l, wall, [ang]); +// sparse_wall(h, l, thick, [maxang=], [strut=], [max_bridge=]) [ATTACHMENTS]; +// +// Topics: FDM Optimized, Walls +// +// Description: +// Makes an open rectangular strut with X-shaped cross-bracing, designed to reduce +// the need for support material in 3D printing. // // 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. +// h = height of strut wall. +// l = length of strut wall. +// thick = thickness of strut wall. +// --- +// maxang = maximum overhang angle of cross-braces. +// strut = the width of the cross-braces. +// max_bridge = maximum bridging distance between cross-braces. // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` // -// Example: -// narrowing_strut(w=10, l=100, wall=5, ang=30); -module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orient=UP) +// See Also: corrugated_wall(), thinning_wall() +// +// Example: Typical Shape +// sparse_wall(h=40, l=100, thick=3); +// Example: Thinner Strut +// sparse_wall(h=40, l=100, thick=3, strut=2); +// Example: Larger maxang +// sparse_wall(h=40, l=100, thick=3, strut=2, maxang=45); +// Example: Longer max_bridge +// sparse_wall(h=40, l=100, thick=3, strut=2, maxang=45, max_bridge=30); +module sparse_wall(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anchor=CENTER, spin=0, orient=UP) { - h = wall + w/2/tan(ang); - size = [w, l, h]; + zoff = h/2 - strut/2; + yoff = l/2 - strut/2; + + 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]; attachable(anchor,spin,orient, size=size) { - xrot(90) - 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); - } - } + 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); + } + ycopies(ystep, n=yreps) { + xcopies(zstep, n=zreps) { + skew(syx=tan(-ang)) square([(h-strut)/zreps, strut], center=true); + skew(syx=tan( ang)) square([(h-strut)/zreps, strut], center=true); } } } @@ -58,27 +85,90 @@ module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orien } +// Module: corrugated_wall() +// +// Usage: +// corrugated_wall(h, l, thick, [strut=], [wall=]) [ATTACHMENTS]; +// +// Topics: FDM Optimized, Walls +// +// Description: +// Makes a corrugated wall which relieves contraction stress while still +// providing support strength. Designed with 3D printing in mind. +// +// 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. +// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` +// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` +// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` +// +// See Also: sparse_wall(), thinning_wall() +// +// 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, anchor=CENTER, spin=0, orient=UP) +{ + 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]; + attachable(anchor,spin,orient, size=size) { + 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(); + } +} + + // Module: thinning_wall() // +// Usage: +// thinning_wall(h, l, thick, [ang=], [braces=], [strut=], [wall=]) [ATTACHMENTS]; +// +// Topics: FDM Optimized, Walls +// // 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]); -// // 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. -// wall = The thickness of the thinned portion of the wall. Default: `thick/2` +// --- // ang = Maximum overhang angle of diagonal brace. // braces = If true, adds diagonal crossbraces for strength. // strut = The width of the borders and diagonal braces. Default: `thick/2` +// wall = The thickness of the thinned portion of the wall. Default: `thick/2` // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` // +// See Also: sparse_wall(), corrugated_wall(), thinning_triangle() +// // Example: Typical Shape // thinning_wall(h=50, l=80, thick=4); // Example: Trapezoidal @@ -238,17 +328,20 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut, wall, an // Module: thinning_triangle() // +// Usage: +// thinning_triangle(h, l, thick, [ang=], [strut=], [wall=], [diagonly=], [center=]) [ATTACHMENTS]; +// +// Topics: FDM Optimized, Walls +// // 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], [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. @@ -258,6 +351,8 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut, wall, an // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` // +// See Also: thinning_wall() +// // Example: Centered // thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, center=true); // Example: All Braces @@ -298,220 +393,49 @@ module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly } -// 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. +// Module: narrowing_strut() // // Usage: -// sparse_strut(h, l, thick, [strut], [maxang], [max_bridge]) +// narrowing_strut(w, l, wall, [ang=]) [ATTACHMENTS]; +// +// Topics: FDM Optimized +// +// 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. // // 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. +// 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. // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` // -// 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, anchor=CENTER, spin=0, orient=UP) +// Example: +// narrowing_strut(w=10, l=100, wall=5, ang=30); +module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orient=UP) { - zoff = h/2 - strut/2; - yoff = l/2 - strut/2; - - 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]; - attachable(anchor,spin,orient, size=size) { - 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); - } - ycopies(ystep, n=yreps) { - xcopies(zstep, n=zreps) { - skew(syx=tan(-ang)) square([(h-strut)/zreps, strut], center=true); - skew(syx=tan( ang)) square([(h-strut)/zreps, strut], center=true); - } - } - } - children(); - } -} - - -// Module: sparse_strut3d() -// -// Usage: -// sparse_strut3d(h, w, l, [thick], [maxang], [max_bridge], [strut]); -// -// 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. -// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` -// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` -// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// -// Example(Med): Typical Shape -// sparse_strut3d(h=30, w=30, l=100); -// Example(Med): Thinner strut -// sparse_strut3d(h=30, w=30, l=100, strut=2); -// Example(Med): Larger maxang -// sparse_strut3d(h=30, w=30, l=100, strut=2, maxang=50); -// Example(Med): 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, anchor=CENTER, spin=0, orient=UP) -{ - - 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; - + h = wall + w/2/tan(ang); size = [w, l, h]; attachable(anchor,spin,orient, size=size) { - intersection() { - union() { - ybridge = (l - (yreps+1) * strut) / yreps; - xcopies(xoff) sparse_strut(h=h, l=l, thick=thick, maxang=maxang, strut=strut, max_bridge=ybridge/ceil(ybridge/max_bridge)); - ycopies(yoff) zrot(90) sparse_strut(h=h, l=w, thick=thick, maxang=maxang, strut=strut, max_bridge=max_bridge); - for(zs = [0:1:zreps-1]) { - for(xs = [0:1:xreps-1]) { - for(ys = [0:1: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:1:supp_reps-1] ) { - yflip_copy() { - back(soff*supp_step) { - skew(syz=tan(supp_ang)) { - cube([strut, strut, zstep], anchor=BOTTOM); - } - } - } - } - } - } - } - } + xrot(90) + 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); } } } } - 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]); -// -// 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. -// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` -// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` -// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` -// -// 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, anchor=CENTER, spin=0, orient=UP) -{ - 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]; - attachable(anchor,spin,orient, size=size) { - 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(); } diff --git a/wiring.scad b/wiring.scad index ae3f12b..d3be7a1 100644 --- a/wiring.scad +++ b/wiring.scad @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////// // LibFile: wiring.scad -// Rendering for wiring bundles +// Rendering for wire bundles // Includes: // include // include @@ -10,51 +10,42 @@ include -// Section: Functions + +/// Function: _hex_offset_ring() +/// Usage: +/// _hex_offset_ring(d, lev) +/// Description: +/// Returns a hexagonal ring of points, with a spacing of `d`. +/// If `lev=0`, returns a single point at `[0,0]`. All greater +/// levels return `6 * lev` points. +/// Arguments: +/// d = Base unit diameter to build rings upon. +/// lev = How many rings to produce. +/// Example: +/// _hex_offset_ring(d=1, lev=3); // Returns a hex ring of 18 points. +function _hex_offset_ring(d, lev=0) = + (lev == 0)? [[0,0]] : + subdivide_path(reverse(hexagon(r=lev*d)), refine=lev); -// Function: hex_offset_ring() -// Description: -// Returns a hexagonal ring of points, with a spacing of `d`. -// If `lev=0`, returns a single point at `[0,0]`. All greater -// levels return 6 times `lev` points. -// Usage: -// hex_offset_ring(d, lev) -// Arguments: -// d = Base unit diameter to build rings upon. -// lev = How many rings to produce. -// Example: -// hex_offset_ring(d=1, lev=3); // Returns a hex ring of 18 points. -function hex_offset_ring(d, lev=0) = - (lev == 0)? [[0,0]] : [ - for ( - sideang = [0:60:359.999], - sidenum = [1:1:lev] - ) [ - lev*d*cos(sideang)+sidenum*d*cos(sideang+120), - lev*d*sin(sideang)+sidenum*d*sin(sideang+120) - ] - ]; - - -// Function: hex_offsets() -// Description: -// Returns the centerpoints for the optimal hexagonal packing -// of at least `n` circular items, of diameter `d`. Will return -// enough points to fill out the last ring, even if that is more -// than `n` points. -// Usage: -// hex_offsets(n, d) -// Arguments: -// n = Number of items to bundle. -// d = How far to space each point away from others. -function hex_offsets(n, d, lev=0, arr=[]) = +/// Function: _hex_offsets() +/// Usage: +/// _hex_offsets(n, d) +/// Description: +/// Returns the centerpoints for the optimal hexagonal packing +/// of at least `n` circular items, of diameter `d`. Will return +/// enough points to fill out the last ring, even if that is more +/// than `n` points. +/// Arguments: +/// n = Number of items to bundle. +/// d = How far to space each point away from others. +function _hex_offsets(n, d, lev=0, arr=[]) = (len(arr) >= n)? arr : - hex_offsets( + _hex_offsets( n=n, d=d, lev=lev+1, - arr=concat(arr, hex_offset_ring(d, lev=lev)) + arr=concat(arr, _hex_offset_ring(d, lev=lev)) ); @@ -62,23 +53,25 @@ function hex_offsets(n, d, lev=0, arr=[]) = // Section: Modules -// Module: wiring() +// Module: wire_bundle() +// Usage: +// wire_bundle(path, wires, [wirediam], [rounding], [wirenum=], [corner_steps=]); // Description: // Returns a 3D object representing a bundle of wires that follow a given path, // with the corners rounded to a given radius. There are 17 base wire colors. // If you have more than 17 wires, colors will get re-used. -// Usage: -// wiring(path, wires, [wirediam], [rounding], [wirenum], [bezsteps]); // Arguments: // path = The 3D path that the wire bundle should follow. -// wires = The number of wires in the wiring bundle. +// wires = The number of wires in the wire bundle. // wirediam = The diameter of each wire in the bundle. // rounding = The radius that the path corners will be rounded to. +// --- // wirenum = The first wire's offset into the color table. // corner_steps = The corner roundings in the path will be converted into this number of segments. // Example: -// wiring([[50,0,-50], [50,50,-50], [0,50,-50], [0,0,-50], [0,0,0]], rounding=10, wires=13); -module wiring(path, wires, wirediam=2, rounding=10, wirenum=0, corner_steps=12) { +// wire_bundle([[50,0,-50], [50,50,-50], [0,50,-50], [0,0,-50], [0,0,0]], rounding=10, wires=13); +module wire_bundle(path, wires, wirediam=2, rounding=10, wirenum=0, corner_steps=15) { + no_children($children); colors = [ [0.2, 0.2, 0.2], [1.0, 0.2, 0.2], [0.0, 0.8, 0.0], [1.0, 1.0, 0.2], [0.3, 0.3, 1.0], [1.0, 1.0, 1.0], [0.7, 0.5, 0.0], [0.5, 0.5, 0.5], @@ -86,12 +79,11 @@ module wiring(path, wires, wirediam=2, rounding=10, wirenum=0, corner_steps=12) [1.0, 0.5, 1.0], [0.5, 0.6, 0.0], [1.0, 0.7, 0.0], [0.7, 1.0, 0.5], [0.6, 0.6, 1.0], ]; - offsets = hex_offsets(wires, wirediam); - rounded_path = round_corners(path, radius=rounding,$fn=(corner_steps+1)*4,closed=false); - n = max(segs(wirediam), 8); - r = wirediam/2; + sides = max(segs(wirediam/2), 8); + offsets = _hex_offsets(wires, wirediam); + rounded_path = round_corners(path, radius=rounding, $fn=(corner_steps+1)*4, closed=false); for (i = [0:1:wires-1]) { - extpath = [for (j = [0:1:n-1]) let(a=j*360/n) [r*cos(a)+offsets[i][0], r*sin(a)+offsets[i][1]]]; + extpath = move(offsets[i], p=circle(d=wirediam, $fn=sides)); color(colors[(i+wirenum)%len(colors)]) { path_sweep(extpath, rounded_path); }