From aeed8e9f30e843c41e249d1e3f6da9073fdb3ee7 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 19 Sep 2022 16:49:43 -0700 Subject: [PATCH 1/9] Added model for lmXuu linear ball bearing cartridge. --- linear_bearings.scad | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/linear_bearings.scad b/linear_bearings.scad index 93dc2e9..e1cfc1d 100644 --- a/linear_bearings.scad +++ b/linear_bearings.scad @@ -148,4 +148,27 @@ module lmXuu_housing(size=8, tab=7, gap=5, wall=3, tabwall=5, screwsize=3, ancho } +// 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) { + d = get_lmXuu_bearing_diam(size); + l = get_lmXuu_bearing_length(size); + color("silver") { + tube(id=size, od=d, l=l-1); + tube(id=d-1, od=d, l=l); + tube(id=size, od=size+1, l=l); + tube(id=size+2, od=d-2, l=l); + } +} + + + // vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap From 75dfe87c51b43a7a2f8efd810a845c9420b09f33 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 19 Sep 2022 20:18:25 -0700 Subject: [PATCH 2/9] Added ball_bearings.scad --- ball_bearings.scad | 231 +++++++++++++++++++++++++++++++++++++++++++ linear_bearings.scad | 138 +++++++++++++------------- 2 files changed, 303 insertions(+), 66 deletions(-) create mode 100644 ball_bearings.scad diff --git a/ball_bearings.scad b/ball_bearings.scad new file mode 100644 index 0000000..df9cf34 --- /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("603"); +// Example: +// ball_bearing("603ZZ"); +// 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 e1cfc1d..2ea7dc5 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 @@ -9,61 +9,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 +71,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,8 +116,9 @@ 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(); } @@ -159,16 +134,47 @@ module lmXuu_housing(size=8, tab=7, gap=5, wall=3, tabwall=5, screwsize=3, ancho // Example: // lmXuu_bearing(size=10); module lmXuu_bearing(size=8, anchor=CTR, spin=0, orient=UP) { - d = get_lmXuu_bearing_diam(size); - l = get_lmXuu_bearing_length(size); - color("silver") { - tube(id=size, od=d, l=l-1); - tube(id=d-1, od=d, l=l); - tube(id=size, od=size+1, l=l); - tube(id=size+2, od=d-2, l=l); - } + 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.0, 8.0, 12.0], + [ 5.0, 10.0, 15.0], + [ 6.0, 12.0, 19.0], + [ 8.0, 15.0, 24.0], + [ 10.0, 19.0, 29.0], + [ 12.0, 21.0, 30.0], + [ 13.0, 23.0, 32.0], + [ 16.0, 28.0, 37.0], + [ 20.0, 32.0, 42.0], + [ 25.0, 40.0, 59.0], + [ 30.0, 45.0, 64.0], + [ 35.0, 52.0, 70.0], + [ 40.0, 60.0, 80.0], + [ 50.0, 80.0, 100.0], + [ 60.0, 90.0, 110.0], + [ 80.0, 120.0, 140.0], + [100.0, 150.0, 175.0], + ], + 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 From 0a1abb78ef4586b9d6b9d4c8169bca699e4733f7 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Tue, 20 Sep 2022 00:48:34 -0700 Subject: [PATCH 3/9] lmXuu_info() bugfix. ball_bearing_info() bugfix. --- ball_bearings.scad | 2 +- linear_bearings.scad | 39 ++++++++++++++++++--------------- tests/test_linear_bearings.scad | 30 ++++++++----------------- 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/ball_bearings.scad b/ball_bearings.scad index df9cf34..b1dae05 100644 --- a/ball_bearings.scad +++ b/ball_bearings.scad @@ -223,7 +223,7 @@ function ball_bearing_info(trade_size) = ], found = search([trade_size], data, 1)[0] ) - assert(found, str("Unsupported ball bearing trade size: ", trade_size)) + assert(found!=[], str("Unsupported ball bearing trade size: ", trade_size)) select(data[found], 1, -1); diff --git a/linear_bearings.scad b/linear_bearings.scad index 2ea7dc5..b44d9d5 100644 --- a/linear_bearings.scad +++ b/linear_bearings.scad @@ -9,6 +9,9 @@ ////////////////////////////////////////////////////////////////////// +include + + // Section: Generic Linear Bearings // Module: linear_bearing_housing() @@ -152,27 +155,27 @@ function lmXuu_info(size) = let( data = [ // size, diam, length - [ 4.0, 8.0, 12.0], - [ 5.0, 10.0, 15.0], - [ 6.0, 12.0, 19.0], - [ 8.0, 15.0, 24.0], - [ 10.0, 19.0, 29.0], - [ 12.0, 21.0, 30.0], - [ 13.0, 23.0, 32.0], - [ 16.0, 28.0, 37.0], - [ 20.0, 32.0, 42.0], - [ 25.0, 40.0, 59.0], - [ 30.0, 45.0, 64.0], - [ 35.0, 52.0, 70.0], - [ 40.0, 60.0, 80.0], - [ 50.0, 80.0, 100.0], - [ 60.0, 90.0, 110.0], - [ 80.0, 120.0, 140.0], - [100.0, 150.0, 175.0], + [ 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)) + assert(found!=[], str("Unsupported lmXuu linear bearing size: ", size)) select(data[found], 1, -1); 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 From b9b0841044d3f1c467c8608dbf15f51914fb4739 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Tue, 20 Sep 2022 01:29:41 -0700 Subject: [PATCH 4/9] Fixed ball_bearing examples. --- ball_bearings.scad | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ball_bearings.scad b/ball_bearings.scad index b1dae05..5ad035a 100644 --- a/ball_bearings.scad +++ b/ball_bearings.scad @@ -24,9 +24,9 @@ // 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("603"); +// ball_bearing("608"); // Example: -// ball_bearing("603ZZ"); +// ball_bearing("608ZZ"); // Example: // ball_bearing("R8"); // Example: From 314442afefcee17a5cdc0160bcdeb85b89e22235 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Sat, 24 Sep 2022 01:12:31 -0700 Subject: [PATCH 5/9] Fix mask2d attachment examples. --- masks2d.scad | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/masks2d.scad b/masks2d.scad index f1fbf65..d24ebbc 100644 --- a/masks2d.scad +++ b/masks2d.scad @@ -38,7 +38,7 @@ // 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); @@ -92,7 +92,7 @@ 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); @@ -158,7 +158,7 @@ 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); @@ -213,7 +213,7 @@ 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); @@ -272,7 +272,7 @@ 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); @@ -332,7 +332,7 @@ 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); @@ -400,7 +400,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([ From e33d4e692b5f9286509a47e3d48d8618d42d5083 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Sat, 24 Sep 2022 18:27:12 -0700 Subject: [PATCH 6/9] Documented usage of 2D masks to make interior angle decorations. --- masks2d.scad | 82 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/masks2d.scad b/masks2d.scad index d24ebbc..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. @@ -42,6 +43,14 @@ // 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. @@ -96,6 +106,14 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) = // 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. @@ -162,6 +181,14 @@ function mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) = // 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. @@ -217,6 +245,14 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE // 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. @@ -276,6 +313,14 @@ function mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) = // 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: @@ -336,6 +382,14 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an // 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. @@ -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 From ee248ec74dc873836060e056bb61948b68b72de9 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Sun, 25 Sep 2022 20:56:04 -0700 Subject: [PATCH 7/9] Made various masks3d.scad shapes attachable. Added bbox atype to linear_sweep() --- masks3d.scad | 52 +++++++++++++++++++++++++++++++++------------------- skin.scad | 27 +++++++++++++++++++++------ 2 files changed, 54 insertions(+), 25 deletions(-) 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/skin.scad b/skin.scad index 01095e7..b38781a 100644 --- a/skin.scad +++ b/skin.scad @@ -541,6 +541,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 +663,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,9 +752,16 @@ 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); From 21692e6704544331a1d1dc662a423165e90dfd62 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 3 Oct 2022 18:40:37 -0700 Subject: [PATCH 8/9] Fix chamfered cyl() orientation for odd $fn --- shapes3d.scad | 93 ++++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index 5afa3e0..45a74ac 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.") @@ -1522,7 +1522,8 @@ module cyl( [0,l/2] ]; - rotate_extrude(convexity=2) polygon(path); + vnf = rotate_sweep(path); + vnf_polyhedron(vnf, convexity=2); } } children(); @@ -2007,19 +2008,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 +2031,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 +2053,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 +2072,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 +2119,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 +2166,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 +2189,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 +2232,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 +2253,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 +2271,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 +2281,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 +2289,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 +2319,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 = From 0e34b6799be479a5876e9ac5a1a75b768a2ab1b6 Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Thu, 13 Oct 2022 00:15:50 -0700 Subject: [PATCH 9/9] Cleaning up textures docs. --- shapes3d.scad | 7 ++++++- skin.scad | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/shapes3d.scad b/shapes3d.scad index 45a74ac..13d2efc 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -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. diff --git a/skin.scad b/skin.scad index b38781a..f6f6090 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 @@ -767,12 +769,14 @@ function linear_sweep( // 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: