diff --git a/ball_bearings.scad b/ball_bearings.scad new file mode 100644 index 0000000..5ad035a --- /dev/null +++ b/ball_bearings.scad @@ -0,0 +1,231 @@ +////////////////////////////////////////////////////////////////////// +// LibFile: ball_bearings.scad +// Models for standard ball bearing cartridges. +// Includes: +// include +// include +// FileGroup: Parts +// FileSummary: Models for standard ball bearing cartridges. +////////////////////////////////////////////////////////////////////// + + + +// Section: Ball Bearing Models + +// Module: ball_bearing() +// Description: +// Creates a model of a ball bearing assembly. +// Arguments: +// trade_size = String name of a standard ball bearing trade size. ie: "608", "6902ZZ", or "R8" +// id = Inner diameter of ball bearing assembly. +// od = Outer diameter of ball bearing assembly. +// width = Width of ball bearing assembly. +// 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: +// ball_bearing("608"); +// Example: +// ball_bearing("608ZZ"); +// Example: +// ball_bearing("R8"); +// Example: +// ball_bearing(id=12,od=32,width=10,shield=false); +module ball_bearing(trade_size, id, od, width, shield=true, anchor=CTR, spin=0, orient=UP) { + info = is_undef(trade_size)? [id, od, width, shield] : + ball_bearing_info(trade_size); + check = assert(all_defined(info), "Bad Input"); + id = info[0]; + od = info[1]; + width = info[2]; + shield = info[3]; + mid_d = (id+od)/2; + wall = (od-id)/2/3; + color("silver") + attachable(anchor,spin,orient, d=od, l=width) { + if (shield) { + tube(id=id, wall=wall, h=width); + tube(od=od, wall=wall, h=width); + tube(id=id+0.1, od=od-0.1, h=(wall*2+width)/2); + } else { + ball_cnt = floor(PI*mid_d*0.95 / (wall*2)); + difference() { + union() { + tube(id=id, wall=wall, h=width); + tube(od=od, wall=wall, h=width); + } + torus(r_maj=mid_d/2, r_min=wall); + } + for (i=[0:1:ball_cnt-1]) { + zrot(i*360/ball_cnt) right(mid_d/2) sphere(d=wall*2); + } + } + children(); + } +} + + + +// Section: Ball Bearing Info + + +// Function: ball_bearing_info() +// Description: +// Get dimensional info for a standard metric ball bearing cartridge. +// Returns `[SHAFT_DIAM, OUTER_DIAM, WIDTH, SHIELDED]` for the cylindrical cartridge. +// Arguments: +// size = Inner diameter of lmXuu bearing, in mm. +function ball_bearing_info(trade_size) = + assert(is_string(trade_size)) + let( + IN = 25.4, + data = [ + // trade_size, ID, OD, width, shielded + [ "R2", 1/8*IN, 3/8*IN, 5/32*IN, false], + [ "R3", 3/16*IN, 1/2*IN, 5/32*IN, false], + [ "R4", 1/4*IN, 5/8*IN, 0.196*IN, false], + [ "R6", 3/8*IN, 7/8*IN, 7/32*IN, false], + [ "R8", 1/2*IN, 9/8*IN, 1/4*IN, false], + [ "R10", 5/8*IN, 11/8*IN, 9/32*IN, false], + [ "R12", 3/4*IN, 13/8*IN, 5/16*IN, false], + [ "R14", 7/8*IN, 15/8*IN, 3/8*IN, false], + [ "R16", 8/8*IN, 16/8*IN, 3/8*IN, false], + [ "R18", 9/8*IN, 17/8*IN, 3/8*IN, false], + [ "R20", 10/8*IN, 18/8*IN, 3/8*IN, false], + [ "R22", 11/8*IN, 20/8*IN, 7/16*IN, false], + [ "R24", 12/8*IN, 21/8*IN, 7/16*IN, false], + + [ "R2ZZ", 1/8*IN, 3/8*IN, 5/32*IN, true ], + [ "R3ZZ", 3/16*IN, 1/2*IN, 5/32*IN, true ], + [ "R4ZZ", 1/4*IN, 5/8*IN, 0.196*IN, true ], + [ "R6ZZ", 3/8*IN, 7/8*IN, 7/32*IN, true ], + [ "R8ZZ", 1/2*IN, 9/8*IN, 1/4*IN, true ], + [ "R10ZZ", 5/8*IN, 11/8*IN, 9/32*IN, true ], + [ "R12ZZ", 3/4*IN, 13/8*IN, 5/16*IN, true ], + [ "R14ZZ", 7/8*IN, 15/8*IN, 3/8*IN, true ], + [ "R16ZZ", 8/8*IN, 16/8*IN, 3/8*IN, true ], + [ "R18ZZ", 9/8*IN, 17/8*IN, 3/8*IN, true ], + [ "R20ZZ", 10/8*IN, 18/8*IN, 3/8*IN, true ], + [ "R22ZZ", 11/8*IN, 20/8*IN, 7/16*IN, true ], + [ "R24ZZ", 12/8*IN, 21/8*IN, 7/16*IN, true ], + + [ "608", 8, 22, 7, false], + [ "629", 9, 26, 8, false], + [ "635", 5, 19, 6, false], + [ "6000", 10, 26, 8, false], + [ "6001", 12, 28, 8, false], + [ "6002", 15, 32, 9, false], + [ "6003", 17, 35, 10, false], + [ "6007", 35, 62, 14, false], + [ "6200", 10, 30, 9, false], + [ "6201", 12, 32, 10, false], + [ "6202", 15, 35, 11, false], + [ "6203", 17, 40, 12, false], + [ "6204", 20, 47, 14, false], + [ "6205", 25, 52, 15, false], + [ "6206", 30, 62, 16, false], + [ "6207", 35, 72, 17, false], + [ "6208", 40, 80, 18, false], + [ "6209", 45, 85, 19, false], + [ "6210", 50, 90, 20, false], + [ "6211", 55, 100, 21, false], + [ "6212", 60, 110, 22, false], + [ "6301", 12, 37, 12, false], + [ "6302", 15, 42, 13, false], + [ "6303", 17, 47, 14, false], + [ "6304", 20, 52, 15, false], + [ "6305", 25, 62, 17, false], + [ "6306", 30, 72, 19, false], + [ "6307", 35, 80, 21, false], + [ "6308", 40, 90, 23, false], + [ "6309", 45, 100, 25, false], + [ "6310", 50, 110, 27, false], + [ "6311", 55, 120, 29, false], + [ "6312", 60, 130, 31, false], + [ "6403", 17, 62, 17, false], + [ "6800", 10, 19, 5, false], + [ "6801", 12, 21, 5, false], + [ "6802", 15, 24, 5, false], + [ "6803", 17, 26, 5, false], + [ "6804", 20, 32, 7, false], + [ "6805", 25, 37, 7, false], + [ "6806", 30, 42, 7, false], + [ "6900", 10, 22, 6, false], + [ "6901", 12, 24, 6, false], + [ "6902", 15, 28, 7, false], + [ "6903", 17, 30, 7, false], + [ "6904", 20, 37, 9, false], + [ "6905", 25, 42, 9, false], + [ "6906", 30, 47, 9, false], + [ "6907", 35, 55, 10, false], + [ "6908", 40, 62, 12, false], + [ "16002", 15, 22, 8, false], + [ "16004", 20, 42, 8, false], + [ "16005", 25, 47, 8, false], + [ "16100", 10, 28, 8, false], + [ "16101", 12, 30, 8, false], + + [ "608ZZ", 8, 22, 7, true ], + [ "629ZZ", 9, 26, 8, true ], + [ "635ZZ", 5, 19, 6, true ], + [ "6000ZZ", 10, 26, 8, true ], + [ "6001ZZ", 12, 28, 8, true ], + [ "6002ZZ", 15, 32, 9, true ], + [ "6003ZZ", 17, 35, 10, true ], + [ "6007ZZ", 35, 62, 14, true ], + [ "6200ZZ", 10, 30, 9, true ], + [ "6201ZZ", 12, 32, 10, true ], + [ "6202ZZ", 15, 35, 11, true ], + [ "6203ZZ", 17, 40, 12, true ], + [ "6204ZZ", 20, 47, 14, true ], + [ "6205ZZ", 25, 52, 15, true ], + [ "6206ZZ", 30, 62, 16, true ], + [ "6207ZZ", 35, 72, 17, true ], + [ "6208ZZ", 40, 80, 18, true ], + [ "6209ZZ", 45, 85, 19, true ], + [ "6210ZZ", 50, 90, 20, true ], + [ "6211ZZ", 55, 100, 21, true ], + [ "6212ZZ", 60, 110, 22, true ], + [ "6301ZZ", 12, 37, 12, true ], + [ "6302ZZ", 15, 42, 13, true ], + [ "6303ZZ", 17, 47, 14, true ], + [ "6304ZZ", 20, 52, 15, true ], + [ "6305ZZ", 25, 62, 17, true ], + [ "6306ZZ", 30, 72, 19, true ], + [ "6307ZZ", 35, 80, 21, true ], + [ "6308ZZ", 40, 90, 23, true ], + [ "6309ZZ", 45, 100, 25, true ], + [ "6310ZZ", 50, 110, 27, true ], + [ "6311ZZ", 55, 120, 29, true ], + [ "6312ZZ", 60, 130, 31, true ], + [ "6403ZZ", 17, 62, 17, true ], + [ "6800ZZ", 10, 19, 5, true ], + [ "6801ZZ", 12, 21, 5, true ], + [ "6802ZZ", 15, 24, 5, true ], + [ "6803ZZ", 17, 26, 5, true ], + [ "6804ZZ", 20, 32, 7, true ], + [ "6805ZZ", 25, 37, 7, true ], + [ "6806ZZ", 30, 42, 7, true ], + [ "6900ZZ", 10, 22, 6, true ], + [ "6901ZZ", 12, 24, 6, true ], + [ "6902ZZ", 15, 28, 7, true ], + [ "6903ZZ", 17, 30, 7, true ], + [ "6904ZZ", 20, 37, 9, true ], + [ "6905ZZ", 25, 42, 9, true ], + [ "6906ZZ", 30, 47, 9, true ], + [ "6907ZZ", 35, 55, 10, true ], + [ "6908ZZ", 40, 62, 12, true ], + [ "16002ZZ", 15, 22, 8, true ], + [ "16004ZZ", 20, 42, 8, true ], + [ "16005ZZ", 25, 47, 8, true ], + [ "16100ZZ", 10, 28, 8, true ], + [ "16101ZZ", 12, 30, 8, true ], + ], + found = search([trade_size], data, 1)[0] + ) + assert(found!=[], str("Unsupported ball bearing trade size: ", trade_size)) + select(data[found], 1, -1); + + + +// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/linear_bearings.scad b/linear_bearings.scad index 93dc2e9..b44d9d5 100644 --- a/linear_bearings.scad +++ b/linear_bearings.scad @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////// // LibFile: linear_bearings.scad -// Mounts for LMxUU style linear bearings. +// Mounts and models for LMxUU style linear bearings. // Includes: // include // include @@ -12,58 +12,7 @@ include -// Section: Functions - - -// Function: get_lmXuu_bearing_diam() -// Description: Get outside diameter, in mm, of a standard lmXuu bearing. -// Arguments: -// size = Inner size of lmXuu bearing, in mm. -function get_lmXuu_bearing_diam(size) = lookup(size, [ - [ 4.0, 8.0], - [ 5.0, 10.0], - [ 6.0, 12.0], - [ 8.0, 15.0], - [ 10.0, 19.0], - [ 12.0, 21.0], - [ 13.0, 23.0], - [ 16.0, 28.0], - [ 20.0, 32.0], - [ 25.0, 40.0], - [ 30.0, 45.0], - [ 35.0, 52.0], - [ 40.0, 60.0], - [ 50.0, 80.0], - [ 60.0, 90.0], - [ 80.0, 120.0], - [100.0, 150.0] - ]); - - -// Function: get_lmXuu_bearing_length() -// Description: Get length, in mm, of a standard lmXuu bearing. -// Arguments: -// size = Inner size of lmXuu bearing, in mm. -function get_lmXuu_bearing_length(size) = lookup(size, [ - [ 4.0, 12.0], - [ 5.0, 15.0], - [ 6.0, 19.0], - [ 8.0, 24.0], - [ 10.0, 29.0], - [ 12.0, 30.0], - [ 13.0, 32.0], - [ 16.0, 37.0], - [ 20.0, 42.0], - [ 25.0, 59.0], - [ 30.0, 64.0], - [ 35.0, 70.0], - [ 40.0, 80.0], - [ 50.0, 100.0], - [ 60.0, 110.0], - [ 80.0, 140.0], - [100.0, 175.0] - ]); - +// Section: Generic Linear Bearings // Module: linear_bearing_housing() // Description: @@ -125,6 +74,34 @@ module linear_bearing_housing(d=15, l=24, tab=7, gap=5, wall=3, tabwall=5, screw } +// Module: linear_bearing() +// Description: +// Creates a rough model of a generic linear ball bearing cartridge. +// Arguments: +// l/length = The length of the linear bearing cartridge. +// od = The outer diameter of the linear bearing cartridge. +// id = The inner diameter of the linear bearing cartridge. +// 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: +// linear_bearing(l=24, od=15, id=8); +module linear_bearing(l, od=15, id=8, length, anchor=CTR, spin=0, orient=UP) { + l = first_defined([l, length, 24]); + attachable(anchor,spin,orient, d=od, l=l) { + color("silver") { + tube(id=id, od=od, l=l-1); + tube(id=od-1, od=od, l=l); + tube(id=id, od=id+1, l=l); + tube(id=id+2, od=od-2, l=l); + } + children(); + } +} + + +// Section: lmXuu Linear Bearings + // Module: lmXuu_housing() // Description: // Creates a model of a clamp to hold a standard sized lmXuu linear bearing cartridge. @@ -142,10 +119,65 @@ module linear_bearing_housing(d=15, l=24, tab=7, gap=5, wall=3, tabwall=5, screw // lmXuu_housing(size=10, wall=2, tab=6, screwsize=2.5); module lmXuu_housing(size=8, tab=7, gap=5, wall=3, tabwall=5, screwsize=3, anchor=BOTTOM, spin=0, orient=UP) { - d = get_lmXuu_bearing_diam(size); - l = get_lmXuu_bearing_length(size); + info = lmXuu_info(size); + d = info[0]; + l = info[1]; linear_bearing_housing(d=d, l=l, tab=tab, gap=gap, wall=wall, tabwall=tabwall, screwsize=screwsize, orient=orient, spin=spin, anchor=anchor) children(); } +// Module: lmXuu_bearing() +// Description: +// Creates a model of an lmXuu linear ball bearing cartridge. +// Arguments: +// size = Standard lmXuu inner size. +// 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: +// lmXuu_bearing(size=10); +module lmXuu_bearing(size=8, anchor=CTR, spin=0, orient=UP) { + info = lmXuu_info(size); + linear_bearing(l=info[1], id=size, od=info[0], anchor=anchor, spin=spin, orient=orient) children(); +} + + +// Section: lmXuu Linear Bearing Info + + +// Function: lmXuu_info() +// Description: +// Get dimensional info for a standard metric lmXuu linear bearing cartridge. +// Returns `[DIAM, LENGTH]` for the cylindrical cartridge. +// Arguments: +// size = Inner diameter of lmXuu bearing, in mm. +function lmXuu_info(size) = + let( + data = [ + // size, diam, length + [ 4, 8, 12], + [ 5, 10, 15], + [ 6, 12, 19], + [ 8, 15, 24], + [ 10, 19, 29], + [ 12, 21, 30], + [ 13, 23, 32], + [ 16, 28, 37], + [ 20, 32, 42], + [ 25, 40, 59], + [ 30, 45, 64], + [ 35, 52, 70], + [ 40, 60, 80], + [ 50, 80, 100], + [ 60, 90, 110], + [ 80, 120, 140], + [100, 150, 175], + ], + found = search([size], data, 1)[0] + ) + assert(found!=[], str("Unsupported lmXuu linear bearing size: ", size)) + select(data[found], 1, -1); + + + // vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/masks2d.scad b/masks2d.scad index f1fbf65..674766a 100644 --- a/masks2d.scad +++ b/masks2d.scad @@ -23,7 +23,8 @@ // See Also: corner_profile(), edge_profile(), face_profile() // Description: // Creates a 2D roundover/bead mask shape that is useful for extruding into a 3D mask for a 90° edge. -// This 2D mask is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. +// Conversely, you can use that same extruded shape to make an interior fillet between two walls at a 90º angle. +// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. // If called as a function, this just returns a 2D path of the outline of the mask shape. // Arguments: // r = Radius of the roundover. @@ -38,10 +39,18 @@ // Example(2D): 2D Bead Mask // mask2d_roundover(r=10,inset=2); // Example: Masking by Edge Attachment -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT]) // mask2d_roundover(r=10, inset=2); +// Example: Making an interior fillet +// %render() difference() { +// move(-[5,0,5]) cube(30, anchor=BOT+LEFT); +// cube(310, anchor=BOT+LEFT); +// } +// xrot(90) +// linear_extrude(height=30, center=true) +// mask2d_roundover(r=10); module mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) { path = mask2d_roundover(r=r,d=d,excess=excess,inset=inset); attachable(anchor,spin, two_d=true, path=path) { @@ -77,7 +86,8 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) = // See Also: corner_profile(), edge_profile(), face_profile() // Description: // Creates a 2D cove mask shape that is useful for extruding into a 3D mask for a 90° edge. -// This 2D mask is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. +// Conversely, you can use that same extruded shape to make an interior rounded shelf decoration between two walls at a 90º angle. +// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. // If called as a function, this just returns a 2D path of the outline of the mask shape. // Arguments: // r = Radius of the cove. @@ -92,10 +102,18 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) = // Example(2D): 2D Inset Cove Mask // mask2d_cove(r=10,inset=3); // Example: Masking by Edge Attachment -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT]) // mask2d_cove(r=10, inset=2); +// Example: Making an interior rounded shelf +// %render() difference() { +// move(-[5,0,5]) cube(30, anchor=BOT+LEFT); +// cube(310, anchor=BOT+LEFT); +// } +// xrot(90) +// linear_extrude(height=30, center=true) +// mask2d_cove(r=5, inset=5); module mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) { path = mask2d_cove(r=r,d=d,excess=excess,inset=inset); attachable(anchor,spin, two_d=true, path=path) { @@ -135,7 +153,8 @@ function mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) = // See Also: corner_profile(), edge_profile(), face_profile() // Description: // Creates a 2D chamfer mask shape that is useful for extruding into a 3D mask for a 90° edge. -// This 2D mask is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. +// Conversely, you can use that same extruded shape to make an interior chamfer between two walls at a 90º angle. +// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. // If called as a function, this just returns a 2D path of the outline of the mask shape. // The edge parameter specifies the length of the chamfer's slanted edge. Alternatively you can give x or y to // specify the width or height. Only one of x, y, or width is permitted. @@ -158,10 +177,18 @@ function mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) = // Example(2D): 2D Inset Chamfer Mask // mask2d_chamfer(x=10, inset=2); // Example: Masking by Edge Attachment -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT]) // mask2d_chamfer(x=10, inset=2); +// Example: Making an interior chamfer +// %render() difference() { +// move(-[5,0,5]) cube(30, anchor=BOT+LEFT); +// cube(310, anchor=BOT+LEFT); +// } +// xrot(90) +// linear_extrude(height=30, center=true) +// mask2d_chamfer(edge=10); module mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTER,spin=0) { path = mask2d_chamfer(x=x, y=y, edge=edge, angle=angle, excess=excess, inset=inset); attachable(anchor,spin, two_d=true, path=path, extent=true) { @@ -200,7 +227,8 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE // See Also: corner_profile(), edge_profile(), face_profile() // Description: // Creates a 2D rabbet mask shape that is useful for extruding into a 3D mask for a 90° edge. -// This 2D mask is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. +// Conversely, you can use that same extruded shape to make an interior shelf decoration between two walls at a 90º angle. +// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. // If called as a function, this just returns a 2D path of the outline of the mask shape. // Arguments: // size = The size of the rabbet, either as a scalar or an [X,Y] list. @@ -213,10 +241,18 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE // Example(2D): 2D Asymmetrical Rabbet Mask // mask2d_rabbet(size=[5,10]); // Example: Masking by Edge Attachment -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT]) // mask2d_rabbet(size=10); +// Example: Making an interior shelf +// %render() difference() { +// move(-[5,0,5]) cube(30, anchor=BOT+LEFT); +// cube(310, anchor=BOT+LEFT); +// } +// xrot(90) +// linear_extrude(height=30, center=true) +// mask2d_rabbet(size=[5,10]); module mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) { path = mask2d_rabbet(size=size, excess=excess); attachable(anchor,spin, two_d=true, path=path, extent=false) { @@ -250,7 +286,8 @@ function mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) = // See Also: corner_profile(), edge_profile(), face_profile() // Description: // Creates a 2D dovetail mask shape that is useful for extruding into a 3D mask for a 90° edge. -// This 2D mask is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. +// Conversely, you can use that same extruded shape to make an interior dovetail between two walls at a 90º angle. +// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. // If called as a function, this just returns a 2D path of the outline of the mask shape. // Arguments: // edge = The length of the edge of the dovetail. @@ -272,10 +309,18 @@ function mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) = // Example(2D): 2D Inset Dovetail Mask // mask2d_dovetail(x=10, inset=2); // Example: Masking by Edge Attachment -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile([TOP,"Z"],except=[BACK,TOP+LEFT]) // mask2d_dovetail(x=10, inset=2); +// Example: Making an interior dovetail +// %render() difference() { +// move(-[5,0,5]) cube(30, anchor=BOT+LEFT); +// cube(310, anchor=BOT+LEFT); +// } +// xrot(90) +// linear_extrude(height=30, center=true) +// mask2d_dovetail(x=10); module mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, anchor=CENTER, spin=0) { path = mask2d_dovetail(x=x, y=y, edge=edge, angle=angle, inset=inset, shelf=shelf, excess=excess); attachable(anchor,spin, two_d=true, path=path) { @@ -316,7 +361,8 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an // See Also: corner_profile(), edge_profile(), face_profile() // Description: // Creates a 2D teardrop mask shape that is useful for extruding into a 3D mask for a 90° edge. -// This 2D mask is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. +// Conversely, you can use that same extruded shape to make an interior teardrop fillet between two walls at a 90º angle. +// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. // If called as a function, this just returns a 2D path of the outline of the mask shape. // This is particularly useful to make partially rounded bottoms, that don't need support to print. // Arguments: @@ -332,10 +378,18 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an // Example(2D): Using a Custom Angle // mask2d_teardrop(r=10,angle=30); // Example: Masking by Edge Attachment -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile(BOT) // mask2d_teardrop(r=10, angle=40); +// Example: Making an interior teardrop fillet +// %render() difference() { +// move(-[5,0,5]) cube(30, anchor=BOT+LEFT); +// cube(310, anchor=BOT+LEFT); +// } +// xrot(90) +// linear_extrude(height=30, center=true) +// mask2d_teardrop(r=10); function mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) = assert(is_finite(angle)) assert(angle>0 && angle<90) @@ -371,7 +425,8 @@ module mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) { // // Description: // Creates a 2D Ogee mask shape that is useful for extruding into a 3D mask for a 90° edge. -// This 2D mask is designed to be `difference()`d away from the edge of a shape that is in the first (X+Y+) quadrant. +// Conversely, you can use that same extruded shape to make an interior ogee decoration between two walls at a 90º angle. +// As a 2D mask, this is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant. // Since there are a number of shapes that fall under the name ogee, the shape of this mask is given as a pattern. // Patterns are given as TYPE, VALUE pairs. ie: `["fillet",10, "xstep",2, "step",[5,5], ...]`. See Patterns below. // If called as a function, this just returns a 2D path of the outline of the mask shape. @@ -400,7 +455,7 @@ module mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) { // "ystep",1, "xstep",1 // Ending shoulder. // ]); // Example: Masking by Edge Attachment -// diff("mask") +// diff() // cube([50,60,70],center=true) // edge_profile(TOP) // mask2d_ogee([ @@ -408,6 +463,18 @@ module mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) { // "fillet",5, "round",5, // S-curve. // "ystep",1, "xstep",1 // Ending shoulder. // ]); +// Example: Making an interior ogee +// %render() difference() { +// move(-[5,0,5]) cube(30, anchor=BOT+LEFT); +// cube(310, anchor=BOT+LEFT); +// } +// xrot(90) +// linear_extrude(height=30, center=true) +// mask2d_ogee([ +// "xstep", 1, "round",5, +// "ystep",1, "fillet",5, +// "xstep", 1, "ystep", 1, +// ]); module mask2d_ogee(pattern, excess=0.01, anchor=CENTER,spin=0) { path = mask2d_ogee(pattern, excess=excess); attachable(anchor,spin, two_d=true, path=path) { @@ -485,3 +552,4 @@ function mask2d_ogee(pattern, excess=0.01, anchor=CENTER, spin=0) = +// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/masks3d.scad b/masks3d.scad index 243fcc7..74d4b8d 100644 --- a/masks3d.scad +++ b/masks3d.scad @@ -385,6 +385,9 @@ module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=U // rounding = Radius of the edge rounding. // --- // d = Diameter of cylinder. +// 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: // difference() { // cylinder(r=50, h=50, center=false); @@ -402,14 +405,16 @@ module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=U // #tag("remove") // rounding_cylinder_mask(d=30, rounding=5); // } -function rounding_cylinder_mask(r, rounding, d) = no_function("rounding_cylinder_mask"); -module rounding_cylinder_mask(r, rounding, d) +function rounding_cylinder_mask(r, rounding, d, anchor, spin, orient) = no_function("rounding_cylinder_mask"); +module rounding_cylinder_mask(r, rounding, d, anchor=CENTER, spin=0, orient=UP) { - no_children($children); r = get_radius(r=r, d=d, dflt=1); - difference() { - cyl(r=r+rounding, l=rounding*2, anchor=CENTER); - cyl(r=r, l=rounding*3, rounding=rounding, anchor=TOP); + attachable(anchor,spin,orient, r=r+rounding, l=rounding*2) { + difference() { + cyl(r=r+rounding, l=rounding*2, anchor=CENTER); + cyl(r=r, l=rounding*3, rounding=rounding, anchor=TOP); + } + children(); } } @@ -428,6 +433,7 @@ module rounding_cylinder_mask(r, rounding, d) // d = Diameter of hole to rounding. // rounding = Radius of the rounding. // excess = The extra thickness of the mask. Default: `0.1`. +// --- // 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` @@ -473,6 +479,10 @@ module rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, ori // d = Diameter of the mask rounding. // angle = Maximum angle from vertical. Default: 45 // excess = Excess mask size. Default: 0.1 +// --- +// 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(VPD=50,VPR=[55,0,120]): // teardrop_edge_mask(l=20, r=10, angle=40); // Example(VPD=300,VPR=[75,0,25]): @@ -483,19 +493,16 @@ module rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, ori // corner_mask(BOT) // teardrop_corner_mask(r=10, angle=40); // } -function teardrop_edge_mask(l, r, angle, excess=0.1, d) = no_function("teardrop_edge_mask"); -module teardrop_edge_mask(l, r, angle, excess=0.1, d) +function teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor, spin, orient) = no_function("teardrop_edge_mask"); +module teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor=CTR, spin=0, orient=UP) { - no_children($children); assert(is_num(l)); assert(is_num(angle)); assert(is_num(excess)); assert(angle>0 && angle<90); r = get_radius(r=r, d=d, dflt=1); - difference() { - translate(-[1,1,0]*excess) cube([r+excess,r+excess,l], anchor=FWD+LEFT); - translate([r,r,0]) teardrop(r=r, l=l+1, cap_h=r, ang=angle, orient=FWD); - } + path = mask2d_teardrop(r=r, angle=angle, excess=excess); + linear_sweep(path, height=l, center=true, atype="bbox", anchor=anchor, spin=spin, orient=orient) children(); } @@ -510,6 +517,9 @@ module teardrop_edge_mask(l, r, angle, excess=0.1, d) // excess = Excess mask size. Default: 0.1 // --- // d = Diameter of the mask rounding. +// 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: // teardrop_corner_mask(r=20, angle=40); // Example: @@ -520,17 +530,21 @@ module teardrop_edge_mask(l, r, angle, excess=0.1, d) // corner_mask(BOT) // teardrop_corner_mask(r=10, angle=40); // } -function teardrop_corner_mask(r, angle, excess=0.1, d) = no_function("teardrop_corner_mask"); -module teardrop_corner_mask(r, angle, excess=0.1, d) +function teardrop_corner_mask(r, angle, excess=0.1, d, anchor, spin, orient) = no_function("teardrop_corner_mask"); +module teardrop_corner_mask(r, angle, excess=0.1, d, anchor=CTR, spin=0, orient=UP) { - no_children($children); assert(is_num(angle)); assert(is_num(excess)); assert(angle>0 && angle<90); r = get_radius(r=r, d=d, dflt=1); - difference() { - translate(-[1,1,1]*excess) cube(r+excess, center=false); - translate([1,1,1]*r) onion(r=r, ang=angle, orient=DOWN); + size = (r+excess) * [1,1,1]; + midpt = (r-excess)/2 * [1,1,1]; + attachable(anchor,spin,orient, size=size, offset=midpt) { + difference() { + translate(-[1,1,1]*excess) cube(r+excess, center=false); + translate([1,1,1]*r) onion(r=r, ang=angle, orient=DOWN); + } + children(); } } diff --git a/shapes3d.scad b/shapes3d.scad index 9dc376b..307307b 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -4,7 +4,7 @@ // that produce a VNF. Also included are shortcuts cylinders in each orientation and extended versions of // the standard modules that provide roundovers and chamfers. The spheroid() module provides // several different ways to make a sphere, and the text modules let you write text on a path -// so you can place it on a curved object. A ruler lets you measure objects. +// so you can place it on a curved object. A ruler lets you measure objects. // Includes: // include // FileGroup: Basic Modeling @@ -319,7 +319,7 @@ module cuboid( teardrop = is_bool(teardrop)&&teardrop? 45 : teardrop; chamfer = approx(chamfer,0) ? undef : chamfer; rounding = approx(rounding,0) ? undef : rounding; - checks = + checks = assert(is_vector(size,3)) assert(all_positive(size)) assert(is_undef(chamfer) || is_finite(chamfer),"chamfer must be a finite value") @@ -574,7 +574,7 @@ function cuboid( // Creates a rectangular prismoid shape with optional roundovers and chamfering. // You can only round or chamfer the vertical(ish) edges. For those edges, you can // specify rounding and/or chamferring per-edge, and for top and bottom separately. -// If you want to round the bottom or top edges see {{rounded_prism()}}. +// If you want to round the bottom or top edges see {{rounded_prism()}}. // // Arguments: // size1 = [width, length] of the bottom end of the prism. @@ -657,7 +657,7 @@ module prismoid( eps = pow(2,-14); size1 = is_num(size1)? [size1,size1] : size1; size2 = is_num(size2)? [size2,size2] : size2; - checks2 = + checks2 = assert(all_nonnegative(size1)) assert(all_nonnegative(size2)) assert(size1.x + size2.x > 0) @@ -951,7 +951,7 @@ module rect_tube( isize2 = is_def(is2)? is2 : (is_def(wall) && is_def(s2))? (s2-2*[wall,wall]) : undef; - checks2 = + checks2 = assert(wall==undef || is_num(wall)) assert(size1!=undef, "Bad size/size1 argument.") assert(size2!=undef, "Bad size/size2 argument.") @@ -1155,10 +1155,15 @@ function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP) // cyl(l|h, r|d, rounding2=, ...); // cyl(l|h, r|d, rounding1=, rounding2=, ...); // +// Usage: Textured Cylinders +// cyl(l|h, r|d, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...); +// cyl(l|h, r1=, r2=, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...); +// cyl(l|h, d1=, d2=, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_rot=], [tex_samples=], [tex_style=], [tex_taper=], [tex_inset=], ...); +// // Topics: Cylinders, Textures, Rounding, Chamfers // // Description: -// Creates cylinders in various anchorings and orientations, with optional rounding and chamfers. +// Creates cylinders in various anchorings and orientations, with optional rounding, chamfers, or textures. // You can use `h` and `l` interchangably, and all variants allow specifying size by either `r`|`d`, // or `r1`|`d1` and `r2`|`d2`. Note: the chamfers and rounding cannot be cumulatively longer than // the cylinder's length. @@ -1522,7 +1527,8 @@ module cyl( [0,l/2] ]; - rotate_extrude(convexity=2) polygon(path); + vnf = rotate_sweep(path); + vnf_polyhedron(vnf, convexity=2); } } children(); @@ -2007,19 +2013,19 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // When called as a function, returns a [VNF](vnf.scad) for a spheroid. // The exact triangulation of this spheroid can be controlled via the `style=` // argument, where the value can be one of `"orig"`, `"aligned"`, `"stagger"`, -// `"octa"`, or `"icosa"`. +// `"octa"`, or `"icosa"`. // - `style="orig"` constructs a sphere the same way that the OpenSCAD `sphere()` built-in does. // - `style="aligned"` constructs a sphere where, if `$fn` is a multiple of 4, it has vertices at all axis maxima and minima. ie: its bounding box is exactly the sphere diameter in length on all three axes. This is the default. // - `style="stagger"` forms a sphere where all faces are triangular, but the top and bottom poles have thinner triangles. // - `style="octa"` forms a sphere by subdividing an octahedron. This makes more uniform faces over the entirety of the sphere, and guarantees the bounding box is the sphere diameter in size on all axes. The effective `$fn` value is quantized to a multiple of 4. This is used in constructing rounded corners for various other shapes. -// - `style="icosa"` forms a sphere by subdividing an icosahedron. This makes even more uniform faces over the whole sphere. The effective `$fn` value is quantized to a multiple of 5. This sphere has a guaranteed bounding box when `$fn` is a multiple of 10. +// - `style="icosa"` forms a sphere by subdividing an icosahedron. This makes even more uniform faces over the whole sphere. The effective `$fn` value is quantized to a multiple of 5. This sphere has a guaranteed bounding box when `$fn` is a multiple of 10. // . // By default the object spheroid() produces is a polyhedron whose vertices all lie on the requested sphere. This means // the approximating polyhedron is inscribed in the sphere. // The `circum` argument requests a circumscribing sphere, where the true sphere is // inside and tangent to all the faces of the approximating polyhedron. To produce // a circumscribing polyhedron, we use the dual polyhedron of the basic form. The dual of a polyhedron is -// a new polyhedron whose vertices are obtained from the faces of the parent polyhedron. +// a new polyhedron whose vertices are obtained from the faces of the parent polyhedron. // The "orig" and "align" forms are duals of each other. If you request a circumscribing polyhedron in // these styles then the polyhedron will look the same as the default inscribing form. But for the other // styles, the duals are completely different from their parents, and from each other. Generation of the circumscribed versions (duals) @@ -2030,7 +2036,7 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // but is undersized on the Z axis. With style="octa" the circumscribed sphere has faces at each axis, so // the radius on the axes is equal to the specified radius, which is the *minimum* radius of the circumscribed sphere. // The same thing is true for style="icosa" when $fn is a multiple of 10. This would enable you to create spherical -// holes with guaranteed on-axis dimensions. +// holes with guaranteed on-axis dimensions. // Arguments: // r = Radius of the spheroid. // style = The style of the spheroid's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "aligned" @@ -2052,14 +2058,14 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // spheroid(d=100, style="stagger", $fn=10); // Example: style="stagger" with circum=true // spheroid(d=100, style="stagger", circum=true, $fn=10); -// Example: style="octa", octahedral based tesselation. In this style, $fn is quantized to a multiple of 4. +// Example: style="octa", octahedral based tesselation. In this style, $fn is quantized to a multiple of 4. // spheroid(d=100, style="octa", $fn=10); // Example: style="octa", with circum=true, produces mostly very irregular hexagonal faces // spheroid(d=100, style="octa", circum=true, $fn=16); // Example: style="icosa", icosahedral based tesselation. In this style, $fn is quantized to a multiple of 5. -// spheroid(d=100, style="icosa", $fn=10); +// spheroid(d=100, style="icosa", $fn=10); // Example: style="icosa", circum=true. This style has hexagons and 12 pentagons, similar to (but not the same as) a soccer ball. -// spheroid(d=100, style="icosa", circum=true, $fn=10); +// spheroid(d=100, style="icosa", circum=true, $fn=10); // Example: Anchoring // spheroid(d=100, anchor=FRONT); // Example: Spin @@ -2071,10 +2077,10 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient= // Example: Called as Function // vnf = spheroid(d=100, style="icosa"); // vnf_polyhedron(vnf); -// Example: With "orig" the circumscribing sphere has the same form. The green sphere is a tiny bit oversized so it pokes through the low points in the circumscribed sphere with low $fn. This demonstrates that these spheres are in fact circumscribing. +// Example: With "orig" the circumscribing sphere has the same form. The green sphere is a tiny bit oversized so it pokes through the low points in the circumscribed sphere with low $fn. This demonstrates that these spheres are in fact circumscribing. // color("green")spheroid(r=10.01, $fn=256); // spheroid(r=10, style="orig", circum=true, $fn=16); -// Example: With "aligned" the same is true: the circumscribing sphere is also aligned, if $fn is divisible by 4. +// Example: With "aligned" the same is true: the circumscribing sphere is also aligned, if $fn is divisible by 4. // color("green")spheroid(r=10.01, $fn=256); // spheroid(r=10, style="aligned", circum=true, $fn=16); // Example: For the other styles, the circumscribing sphere is different, as shown here with "stagger" @@ -2118,8 +2124,8 @@ module spheroid(r, style="aligned", d, circum=false, dual=false, anchor=CENTER, // p is a list of 3 points defining a triangle in any dimension. N is the number of extra points -// to add, so output triangle has N+2 points on each side. -function _subsample_triangle(p,N) = +// to add, so output triangle has N+2 points on each side. +function _subsample_triangle(p,N) = [for(i=[0:N+1]) [for (j=[0:N+1-i]) unit(lerp(p[0],p[1],i/(N+1)) + (p[2]-p[0])*j/(N+1))]]; @@ -2165,7 +2171,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or [reorient(anchor,spin,orient, r=r, p=dualvert), faces] : style=="icosa" ? // subdivide faces of an icosahedron and project them onto a sphere - let( + let( N = icosa_steps-1, // construct an icosahedron icovert=[ for(i=[-1,1], j=[-1,1]) each [[0,i,j*PHI], [i,j*PHI,0], [j*PHI,0,i]]], @@ -2188,7 +2194,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or // Expand to full face list fullfaces = [for(i=idx(tri_list)) each [for(f=faces) f+i*size]], fullvert = flatten(flatten(tri_list)) // eliminate triangle structure - ) + ) [reorient(anchor,spin,orient, r=r, p=fullvert), fullfaces] : let( @@ -2231,10 +2237,10 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or [ for (i=idx(meridians), j=[0:1:meridians[i]-1]) spherical_to_xyz(r, j*360/meridians[i], i*180/(len(meridians)-1)) - ] + ] : assert(in_list(style,["orig","aligned","stagger","octa","icosa"])), lv = len(verts), - faces = circum && style=="stagger" ? + faces = circum && style=="stagger" ? let(ptcount=2*hsides) [ [for(i=[ptcount-2:-2:0]) i], @@ -2252,7 +2258,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or ? [(j*2+3)%ptcount, j*2+1, lv-ptcount+(2+j*2)%ptcount, lv-ptcount+(3+j*2)%ptcount, lv-ptcount+(4+j*2)%ptcount] : [(j*2+3)%ptcount, j*2+1, lv-ptcount+(1+j*2)%ptcount, lv-ptcount+(j*2)%ptcount, lv-ptcount+(3+j*2)%ptcount], [for(i=[1:2:ptcount-1]) i], - ] + ] : style=="aligned" || style=="stagger" ? // includes case of aligned with circum == true [ for (i=[0:1:hsides-1]) @@ -2270,7 +2276,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or ] : [ [base+j, base+(j+1)%hsides, base+hsides+(j+1)%hsides], [base+j, base+hsides+(j+1)%hsides, base+hsides+j], - ] + ] ) ] : style=="orig"? [ @@ -2280,7 +2286,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or each [ [(i+1)*hsides+j, i*hsides+j, i*hsides+(j+1)%hsides], [(i+1)*hsides+j, i*hsides+(j+1)%hsides, (i+1)*hsides+(j+1)%hsides], - ] + ] ] : /*style=="octa"?*/ let( @@ -2288,7 +2294,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or 0, 1, for (i = [1:1:octa_steps]) i*4, for (i = [octa_steps-1:-1:1]) i*4, - 1, + 1, ], offs = cumsum(meridians), pc = last(offs)-1, @@ -2318,7 +2324,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or [p5, p7, p8], if (k0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here? + w = i>0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here? cube([quantup(actlen,1/1024),quantup(w,1/1024),thickness], anchor=FRONT+LEFT); } mark = diff --git a/skin.scad b/skin.scad index 1296aa8..8da85fd 100644 --- a/skin.scad +++ b/skin.scad @@ -508,6 +508,8 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close // Function&Module: linear_sweep() // Usage: // linear_sweep(region, [height], [center=], [slices=], [twist=], [scale=], [style=], [convexity=]) [ATTACHMENTS]; +// Usage: With Texturing +// linear_sweep(region, [height], [center=], texture=, [tex_size=]|[tex_counts=], [tex_scale=], [style=], [tex_samples=], ...) [ATTACHMENTS]; // Description: // If called as a module, creates a polyhedron that is the linear extrusion of the given 2D region or polygon. // If called as a function, returns a VNF that can be used to generate a polyhedron of the linear extrusion @@ -541,6 +543,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close // Anchor Types: // "hull" = Anchors to the virtual convex hull of the shape. // "intersect" = Anchors to the surface of the shape. +// "bbox" = Anchors to the bounding box of the extruded shape. // Extra Anchors: // "origin" = Centers the extruded shape vertically only, but keeps the original path positions in the X and Y. Oriented UP. // "original_base" = Keeps the original path positions in the X and Y, but at the bottom of the extrusion. Oriented UP. @@ -662,9 +665,16 @@ module linear_sweep( named_anchor("original_base", [0,0,-h/2], UP) ]; cp = default(cp, "centroid"); - geom = atype=="hull"? attach_geom(cp=cp, region=region, h=h, extent=true, shift=shift, scale=scale, twist=twist, anchors=anchors) : - atype=="intersect"? attach_geom(cp=cp, region=region, h=h, extent=false, shift=shift, scale=scale, twist=twist, anchors=anchors) : - assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\""); + geom = atype=="hull"? attach_geom(cp=cp, region=region, h=h, extent=true, shift=shift, scale=scale, twist=twist, anchors=anchors) : + atype=="intersect"? attach_geom(cp=cp, region=region, h=h, extent=false, shift=shift, scale=scale, twist=twist, anchors=anchors) : + atype=="bbox"? + let( + bounds = pointlist_bounds(flatten(region)), + size = bounds[1] - bounds[0], + midpt = (bounds[0] + bounds[1])/2 + ) + attach_geom(cp=[0,0,0], size=point3d(size,h), offset=point3d(midpt), shift=shift, scale=scale, twist=twist, anchors=anchors) : + assert(in_list(atype, ["hull","intersect","bbox"]), "Anchor type must be \"hull\", \"intersect\", or \"bbox\"."); attachable(anchor,spin,orient, geom=geom) { vnf_polyhedron(vnf, convexity=convexity); children(); @@ -744,20 +754,29 @@ function linear_sweep( named_anchor("original_base", [0,0,-h/2], UP) ], cp = default(cp, "centroid"), - geom = atype=="hull"? attach_geom(cp=cp, region=region, h=h, extent=true, shift=shift, scale=scale, twist=twist, anchors=anchors) : - atype=="intersect"? attach_geom(cp=cp, region=region, h=h, extent=false, shift=shift, scale=scale, twist=twist, anchors=anchors) : - assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"") + geom = atype=="hull"? attach_geom(cp=cp, region=region, h=h, extent=true, shift=shift, scale=scale, twist=twist, anchors=anchors) : + atype=="intersect"? attach_geom(cp=cp, region=region, h=h, extent=false, shift=shift, scale=scale, twist=twist, anchors=anchors) : + atype=="bbox"? + let( + bounds = pointlist_bounds(flatten(region)), + size = bounds[1] - bounds[0], + midpt = (bounds[0] + bounds[1])/2 + ) + attach_geom(cp=[0,0,0], size=point3d(size,h), offset=point3d(midpt), shift=shift, scale=scale, twist=twist, anchors=anchors) : + assert(in_list(atype, ["hull","intersect","bbox"]), "Anchor type must be \"hull\", \"intersect\", or \"bbox\".") ) reorient(anchor,spin,orient, geom=geom, p=vnf); // Function&Module: rotate_sweep() // Usage: As Function -// vnf = rotate_sweep(shape, angle, ...); +// vnf = rotate_sweep(shape, [angle], ...); // Usage: As Module -// rotate_sweep(shape, angle, ...) [ATTACHMENTS]; +// rotate_sweep(shape, [angle], ...) [ATTACHMENTS]; +// Usage: With Texturing +// rotate_sweep(shape, texture=, [tex_size=]|[tex_counts=], [tex_scale=], [tex_samples=], [tex_rot=], [tex_inset=], ...) [ATTACHMENTS]; // Topics: Extrusion, Sweep, Revolution // Description: -// Takes a polygon or [region](regions.scad) and sweeps it in a rotation around the Z axis. +// Takes a polygon or [region](regions.scad) and sweeps it in a rotation around the Z axis, with optional texturing. // When called as a function, returns a [VNF](vnf.scad). // When called as a module, creates the sweep as geometry. // Arguments: diff --git a/tests/test_linear_bearings.scad b/tests/test_linear_bearings.scad index fb57ba5..a30d682 100644 --- a/tests/test_linear_bearings.scad +++ b/tests/test_linear_bearings.scad @@ -2,27 +2,15 @@ include <../std.scad> include <../linear_bearings.scad> -module test_get_lmXuu_bearing_diam() { - assert_equal(get_lmXuu_bearing_diam(4), 8); - assert_equal(get_lmXuu_bearing_diam(8), 15); - assert_equal(get_lmXuu_bearing_diam(10), 19); - assert_equal(get_lmXuu_bearing_diam(25), 40); - assert_equal(get_lmXuu_bearing_diam(50), 80); - assert_equal(get_lmXuu_bearing_diam(100), 150); +module test_lmXuu_info() { + assert_equal(lmXuu_info(4), [8, 12]); + assert_equal(lmXuu_info(8), [15, 24]); + assert_equal(lmXuu_info(10), [19, 29]); + assert_equal(lmXuu_info(25), [40, 59]); + assert_equal(lmXuu_info(50), [80, 100]); + assert_equal(lmXuu_info(100), [150, 175]); } -test_get_lmXuu_bearing_diam(); +test_lmXuu_info(); -module test_get_lmXuu_bearing_length() { - assert_equal(get_lmXuu_bearing_length(4), 12); - assert_equal(get_lmXuu_bearing_length(8), 24); - assert_equal(get_lmXuu_bearing_length(10), 29); - assert_equal(get_lmXuu_bearing_length(25), 59); - assert_equal(get_lmXuu_bearing_length(50), 100); - assert_equal(get_lmXuu_bearing_length(100), 175); -} -test_get_lmXuu_bearing_length(); - - - -// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap +// vim: expandtab shiftwidth=4 softtabstop=4 nowrap