From fa51cd0e7e9f8e09b526f3ee6bd1037a52713b08 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sat, 5 Oct 2024 14:05:19 -0400 Subject: [PATCH 1/9] Updated sweep_rounded to match parameters of other functions. Also added additional assertions. --- gridfinity-rebuilt-baseplate.scad | 2 +- src/core/gridfinity-rebuilt-utility.scad | 4 ++-- src/helpers/generic-helpers.scad | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/gridfinity-rebuilt-baseplate.scad b/gridfinity-rebuilt-baseplate.scad index b06496a..bd3885c 100644 --- a/gridfinity-rebuilt-baseplate.scad +++ b/gridfinity-rebuilt-baseplate.scad @@ -321,7 +321,7 @@ module baseplate_lip(height=0, width=l_grid, length=l_grid) { additional_height = height + BASEPLATE_CLEARANCE_HEIGHT; - sweep_rounded(width-2*BASEPLATE_OUTSIDE_RADIUS, length-2*BASEPLATE_OUTSIDE_RADIUS) + sweep_rounded([width-2*BASEPLATE_OUTSIDE_RADIUS, length-2*BASEPLATE_OUTSIDE_RADIUS]) translate([translation_x, additional_height, 0]) polygon(concat(BASEPLATE_LIP, [ [0, -additional_height], diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index 9084fb3..0f0c38a 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -324,7 +324,7 @@ module block_base(hole_options, off=0, size=[BASE_SIZE, BASE_SIZE], thumbscrew=f render(convexity = 2) difference() { union() { - sweep_rounded(base_profile_size.x, base_profile_size.y) + sweep_rounded(base_profile_size) translate([translation_x, 0, 0]) polygon(BASE_PROFILE); @@ -448,7 +448,7 @@ module profile_wall2(height_mm) { module block_wall(gx, gy, l) { translate([0,0,h_base]) - sweep_rounded(gx*l-2*r_base-0.5-0.001, gy*l-2*r_base-0.5-0.001) + sweep_rounded([gx*l-2*r_base-0.5-0.001, gy*l-2*r_base-0.5-0.001]) children(); } diff --git a/src/helpers/generic-helpers.scad b/src/helpers/generic-helpers.scad index d8e3a25..3c1a96e 100644 --- a/src/helpers/generic-helpers.scad +++ b/src/helpers/generic-helpers.scad @@ -175,11 +175,21 @@ function affine_scale(vector) = [ /** * @brief Create a rectangle with rounded corners by sweeping a 2d object along a path. - * Centered on origin. + * @Details Centered on origin. + * Result is on the X,Y plane. + * Expects children to be a 2D shape in Quardrant 1 of the X,Y plane. + * @param size Dimensions of the resulting object. + * Either a single number or [width, length] */ -module sweep_rounded(width=10, length=10) { - assert(width > 0 && length > 0); +module sweep_rounded(size) { + assert((is_num(size) && size > 0) || ( + is_list(size) && len(size) == 2 && + is_num(size.x) && size.x > 0 && is_num(size.y) && size.y > 0 + ) + ); + width = is_num(size) ? size : size.x; + length = is_num(size) ? size : size.y; half_width = width/2; half_length = length/2; path_points = [ From 1ee99f9c6f716d9516c2e5f7e1a3f8899712b1cc Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sat, 5 Oct 2024 14:49:06 -0400 Subject: [PATCH 2/9] Add a foreach_add helper function --- src/helpers/generic-helpers.scad | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/helpers/generic-helpers.scad b/src/helpers/generic-helpers.scad index 3c1a96e..59562ff 100644 --- a/src/helpers/generic-helpers.scad +++ b/src/helpers/generic-helpers.scad @@ -173,6 +173,17 @@ function affine_scale(vector) = [ [0, 0, 0, 1] ]; +/** + * @brief Add something to each element in a list. + * @param list The list whos elements will be modified. + * @param to_add + * @returns a list with `to_add` added to each element in the list. + */ +function foreach_add(list, to_add) = + assert(is_list(list)) + assert(!is_undef(to_add)) + [for (item = list) item + to_add]; + /** * @brief Create a rectangle with rounded corners by sweeping a 2d object along a path. * @Details Centered on origin. From d47043fa51d06e908d0683b68a43d3da9a93d236 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Tue, 22 Oct 2024 18:48:14 -0400 Subject: [PATCH 3/9] Updated solid base creation logic * Simplified. * More readable. * Prevents gaps that could be left by old logic. (rounded_square) --- gridfinity-rebuilt-baseplate.scad | 2 +- gridfinity-spiral-vase.scad | 6 +- src/core/gridfinity-rebuilt-utility.scad | 87 ++++++++++++------------ src/core/standard.scad | 69 ++++++++++++++----- 4 files changed, 102 insertions(+), 62 deletions(-) diff --git a/gridfinity-rebuilt-baseplate.scad b/gridfinity-rebuilt-baseplate.scad index bd3885c..ce9380c 100644 --- a/gridfinity-rebuilt-baseplate.scad +++ b/gridfinity-rebuilt-baseplate.scad @@ -341,7 +341,7 @@ module square_baseplate_lip(height=0, size = l_grid) { corner_center_distance = size/2 - BASEPLATE_OUTSIDE_RADIUS; - render(convexity = 2) // Fixes ghosting in preview + //render(convexity = 2) // Fixes ghosting in preview union() { baseplate_lip(height, size, size); pattern_circular(4) diff --git a/gridfinity-spiral-vase.scad b/gridfinity-spiral-vase.scad index b616c99..b8f1625 100644 --- a/gridfinity-spiral-vase.scad +++ b/gridfinity-spiral-vase.scad @@ -88,7 +88,7 @@ x_l = l_grid/2; dht = (gridz_define==0)?gridz*7 : (gridz_define==1)?h_bot+gridz+h_base : gridz-(enable_lip?3.8:0); d_height = (enable_zsnap?((abs(dht)%7==0)?dht:dht+7-abs(dht)%7):dht)-h_base; -d_fo1 = 2*+BASE_OUTSIDE_RADIUS; +d_fo1 = 2*+BASE_TOP_RADIUS; f2c = sqrt(2)*(sqrt(2)-1); // fillet to chamfer ratio me = ((gridx*l_grid-0.5)/n_divx)-nozzle*4-d_fo1-12.7-4; @@ -171,7 +171,7 @@ module gridfinityBaseVase() { intersection() { block_base_blank(0); translate([0,0,-h_base-1]) - rounded_square([l_grid-0.5-0.005, l_grid-0.5-0.005, h_base*10], BASE_OUTSIDE_RADIUS+0.001, center=true); + rounded_square([l_grid-0.5-0.005, l_grid-0.5-0.005, h_base*10], BASE_TOP_RADIUS+0.001, center=true); } translate([0,0,0.01]) difference() { @@ -239,7 +239,7 @@ module block_base_blank(o = 0) { rounded_square(l_grid-o-0.05-2*r_c2, r_fo2, center=true); mirror([0,0,1]) linear_extrude(d_bottom) - rounded_square(l_grid-o-0.05, BASE_OUTSIDE_RADIUS, center=true); + rounded_square(l_grid-o-0.05, BASE_TOP_RADIUS, center=true); } } } diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index 0f0c38a..4de939c 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -217,12 +217,12 @@ module cut_move(x, y, w, h) { // ===== Modules ===== // /** - *@summary Create the base of a gridfinity bin, or use it for a custom object. + * @brief Create the base of a gridfinity bin, or use it for a custom object. * @param grid_size Number of bases in each dimension. [x, y] * @param grid_dimensions [length, width] of a single Gridfinity base. * @param thumbscrew Enable "gridfinity-refined" thumbscrew hole in the center of each base unit. This is a ISO Metric Profile, 15.0mm size, M15x1.5 designation. */ -module gridfinityBase(grid_size, grid_dimensions=[l_grid, l_grid], hole_options=bundle_hole_options(), off=0, final_cut=true, only_corners=false, thumbscrew=false) { +module gridfinityBase(grid_size, grid_dimensions=GRID_DIMENSIONS_MM, hole_options=bundle_hole_options(), off=0, final_cut=true, only_corners=false, thumbscrew=false) { assert(is_list(grid_dimensions) && len(grid_dimensions) == 2 && grid_dimensions.x > 0 && grid_dimensions.y > 0); assert(is_list(grid_size) && len(grid_size) == 2 && @@ -235,7 +235,7 @@ module gridfinityBase(grid_size, grid_dimensions=[l_grid, l_grid], hole_options= // Per spec, there's a 0.5mm gap between each base. // This must be kept constant or half bins may not work correctly. - gap_mm = l_grid - BASE_SIZE; + gap_mm = GRID_DIMENSIONS_MM - BASE_TOP_DIMENSIONS; // Divisions per grid // Normal, half, or quarter grid sizes supported. @@ -249,22 +249,26 @@ module gridfinityBase(grid_size, grid_dimensions=[l_grid, l_grid], hole_options= final_grid_size = [grid_size.x * divisions_per_grid.x, grid_size.y * divisions_per_grid.y]; base_center_distance_mm = [grid_dimensions.x / divisions_per_grid.x, grid_dimensions.y / divisions_per_grid.y]; - individual_base_size_mm = [base_center_distance_mm.x - gap_mm, base_center_distance_mm.y - gap_mm]; + individual_base_size_mm = [base_center_distance_mm.x, base_center_distance_mm.y] - gap_mm; // Final size of the base top. In mm. // subtracting gap_mm here to remove an outer lip along the peremiter. grid_size_mm = [ - base_center_distance_mm.x * final_grid_size.x - gap_mm, - base_center_distance_mm.y * final_grid_size.y - gap_mm - ]; + base_center_distance_mm.x * final_grid_size.x, + base_center_distance_mm.y * final_grid_size.y + ] - gap_mm; // Top which ties all bases together if (final_cut) { translate([0, 0, h_base-TOLLERANCE]) - rounded_square([grid_size_mm.x, grid_size_mm.y, h_bot], BASE_OUTSIDE_RADIUS, center=true); + rounded_square([grid_size_mm.x, grid_size_mm.y, h_bot], BASE_TOP_RADIUS, center=true); } if(only_corners) { + hole_position = foreach_add( + grid_size_mm/2, + - HOLE_DISTANCE_FROM_BOTTOM_EDGE - BASE_PROFILE_MAX.x + ); difference(){ pattern_linear(final_grid_size.x, final_grid_size.y, base_center_distance_mm.x, base_center_distance_mm.y) block_base(bundle_hole_options(), 0, individual_base_size_mm, thumbscrew=thumbscrew); @@ -272,8 +276,8 @@ module gridfinityBase(grid_size, grid_dimensions=[l_grid, l_grid], hole_options= copy_mirror([0, 1, 0]) { copy_mirror([1, 0, 0]) { translate([ - grid_size_mm.x/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE - BASE_PROFILE_MAX.x, - grid_size_mm.y/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE - BASE_PROFILE_MAX.x, + hole_position.x, + hole_position.y, 0 ]) block_base_hole(hole_options, off); @@ -287,31 +291,38 @@ module gridfinityBase(grid_size, grid_dimensions=[l_grid, l_grid], hole_options= } } +/** + * @brief Solid polygon of a gridfinity base. + * @details Ready for use with `sweep_rounded(...)`. + */ +module base_polygon() { + translated_line = foreach_add(BASE_PROFILE, [BASE_BOTTOM_RADIUS, 0]); + solid_profile = concat(translated_line, + [ + [0, BASE_PROFILE_MAX.y], // Go in to form a solid polygon + [0, 0], // Needed since start has been translated. + ] + ); + polygon(solid_profile); +} + /** * @brief A single Gridfinity base. With holes (if set). * @param hole_options @see block_base_hole.hole_options * @param off - * @param size [x, y] size of a single base. Only set if deviating from the standard! + * @param top_dimensions [x, y] size of a single base. Only set if deviating from the standard! * @param thumbscrew Enable "gridfinity-refined" thumbscrew hole in the center of each base unit. This is a ISO Metric Profile, 15.0mm size, M15x1.5 designation. */ -module block_base(hole_options, off=0, size=[BASE_SIZE, BASE_SIZE], thumbscrew=false) { - assert( - is_list(size) && - len(size) == 2 && - is_bool(thumbscrew) - ); +module block_base(hole_options, off=0, top_dimensions=BASE_TOP_DIMENSIONS, thumbscrew=false) { + assert(is_list(top_dimensions) && len(top_dimensions) == 2); + assert(is_bool(thumbscrew)); - // How far, in the +x direction, - // the profile needs to be from it's [0, 0] point - // such that when swept by 90 degrees to produce a corner, - // the outside edge has the desired radius. - translation_x = BASE_OUTSIDE_RADIUS - BASE_PROFILE_MAX.x; + base_bottom = base_bottom_dimensions(top_dimensions); + sweep_inner = foreach_add(base_bottom, -2*BASE_BOTTOM_RADIUS); + cube_size = foreach_add(base_bottom, -BASE_BOTTOM_RADIUS); - outer_diameter = [2*BASE_OUTSIDE_RADIUS, 2*BASE_OUTSIDE_RADIUS]; - base_profile_size = size - outer_diameter; - base_bottom_size = base_profile_size + [2*translation_x, 2*translation_x]; - assert(base_profile_size.x > 0 && base_profile_size.y > 0, - str("Minimum size of a single base must be greater than ", outer_diameter) + assert(sweep_inner.x > 0 && sweep_inner.y > 0, + str("Minimum size of a single base must be greater than ", 2*BASE_TOP_RADIUS) ); thumbscrew_outerdiam = 15; @@ -323,20 +334,12 @@ module block_base(hole_options, off=0, size=[BASE_SIZE, BASE_SIZE], thumbscrew=f render(convexity = 2) difference() { - union() { - sweep_rounded(base_profile_size) - translate([translation_x, 0, 0]) - polygon(BASE_PROFILE); + union(){ + sweep_rounded(sweep_inner) + base_polygon(); - rounded_square( - [ - base_bottom_size.x + TOLLERANCE, - base_bottom_size.y + TOLLERANCE, - BASE_PROFILE_MAX.y - ], - translation_x, - center=true - ); + translate([0, 0, BASE_PROFILE_MAX.y/2]) + cube([cube_size.x, cube_size.y, BASE_PROFILE_MAX.y], center=true); } if (thumbscrew) { @@ -357,8 +360,8 @@ module block_base(hole_options, off=0, size=[BASE_SIZE, BASE_SIZE], thumbscrew=f j = sign(sin(a+1)); i = sign(cos(a+1)); translate([ - i * (base_bottom_size.x/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE), - j * (base_bottom_size.y/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE), + i * (base_bottom.x/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE), + j * (base_bottom.y/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE), 0]) rotate([0, 0, a]) block_base_hole(hole_options, off); diff --git a/src/core/standard.scad b/src/core/standard.scad index c294098..372fec9 100644 --- a/src/core/standard.scad +++ b/src/core/standard.scad @@ -3,9 +3,16 @@ r_c1 = 0.8; // bottom thiccness of bin h_bot = 2.2; -// length of a grid unit -l_grid = 42; +/** + * @brief Size of a single gridfinity unit. [Length, Width] In millimeters. + */ +GRID_DIMENSIONS_MM = [42, 42]; + +/** + * @deprecated Use GRID_DIMENSIONS_MM instead. + */ +l_grid = GRID_DIMENSIONS_MM.x; // Outside rounded radius of bin // Per spec, matches radius of upper base section. @@ -96,8 +103,9 @@ STACKING_LIP_SUPPORT_HEIGHT = 1.2; /** * @Summary Stacking lip as defined in the spec. No support. + * @Details This is just a line, and will not create a solid polygon. */ -RAW_STACKING_LIP = [ +STACKING_LIP_LINE = [ [0, 0], // Inner tip [0.7, 0.7], // Go out 45 degrees [0.7, (0.7+1.8)], // Vertical increase @@ -110,7 +118,7 @@ RAW_STACKING_LIP = [ * Including wall thickness. * "y": The height of the stacking lip. */ -STACKING_LIP_SIZE = RAW_STACKING_LIP[3]; +STACKING_LIP_SIZE = STACKING_LIP_LINE[3]; _stacking_lip_support_angle = 45; @@ -123,40 +131,69 @@ _stacking_lip_support_height_mm = + tan(90 - _stacking_lip_support_angle) * STACKING_LIP_SIZE.x; /** - * @Summary Stacking lip with a support. + * @Summary Stacking lip with a support. Used to create a polygon. * @Details Support is so the stacking lip is not floating in mid air when wall width is less than stacking lip depth. */ -STACKING_LIP = concat(RAW_STACKING_LIP, [ +STACKING_LIP = concat(STACKING_LIP_LINE, [ [STACKING_LIP_SIZE.x, -_stacking_lip_support_height_mm], // Down to support bottom [0, -STACKING_LIP_SUPPORT_HEIGHT], // Up and in (to bottom inner support) - [0, 0] // Close the shape. Technically not needed. + //[0, 0] // Implicit back to start ]); // **************************************** // Base constants // Based on https://gridfinity.xyz/specification/ // **************************************** -BASE_OUTSIDE_RADIUS = r_base; +/** + * @Summary Profile of a Gridfinity base as described in the spec. + * @Details This is just a line, and will not create a solid polygon. + */ BASE_PROFILE = [ [0, 0], // Innermost bottom point [0.8, 0.8], // Up and out at a 45 degree angle [0.8, (0.8+1.8)], // Straight up - [(0.8+2.15), (0.8+1.8+2.15)], // Up and out at a 45 degree angle - [0, (0.8+1.8+2.15)], // Go in to form a solid polygon - [0, 0] //Back to start + [(0.8+2.15), (0.8+1.8+2.15)] // Up and out at a 45 degree angle ]; -// Maximum [x,y] values/size of the base. +/** + * @Summary Corner radius of the top of the base. + */ +BASE_TOP_RADIUS = r_base; + +/** + * @Summary Size of the top of the base. [Length, Width] + * @Details Each unit's base is 41.5mm x 41.5mm + * Leaving 0.5mm gap with an l_grid of 42 + */ +BASE_TOP_DIMENSIONS = [41.5, 41.5]; + +/** + * @Summary Maximum [x,y] values/size of the base. + */ BASE_PROFILE_MAX = BASE_PROFILE[3]; -// Each unit's base is 41.5mm x 41.5mm -// Leaving 0.5mm gap with an l_grid of 42 -BASE_SIZE = 41.5; +/** + * @Summary Corner radius of the bottom of the base. + * @Details This is also how much BASE_PROFILE needs to be translated + * to use `sweep_rounded(...)`. + */ +BASE_BOTTOM_RADIUS = BASE_TOP_RADIUS - BASE_PROFILE_MAX.x; +/** + * @Summary Dimensions of the bottom of the base. [Length, Width] + * @Details Supports arbitrary top sizes. + * @param top_dimensions [Length, Width] of the top of the base. + */ +function base_bottom_dimensions(top_dimensions = BASE_TOP_DIMENSIONS) = + assert(is_list(top_dimensions) && len(top_dimensions) == 2 + && is_num(top_dimensions.x) && is_num(top_dimensions.y)) + [top_dimensions.x - 2*BASE_PROFILE_MAX.x, + top_dimensions.y - 2*BASE_PROFILE_MAX.x]; /** * @summary Height of the raw base + * @Deprecated */ h_base = BASE_PROFILE_MAX.y; @@ -174,7 +211,7 @@ BASEPLATE_LIP = [ [0.7, (0.7+1.8)], // Straight up [(0.7+2.15), (0.7+1.8+2.15)], // Up and out at a 45 degree angle [(0.7+2.15), 0], // Straight down - [0, 0] //Back to start + //[0, 0] // Implicit back to start ]; // Height of the baseplate lip. From bf7bbed27a382ee4ba492723397cf4fa869726b2 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Tue, 22 Oct 2024 19:18:38 -0400 Subject: [PATCH 4/9] Rename h_base to BASE_HEIGHT --- gridfinity-rebuilt-baseplate.scad | 4 +-- gridfinity-rebuilt-lite.scad | 12 ++++----- gridfinity-spiral-vase.scad | 32 ++++++++++++------------ src/core/gridfinity-rebuilt-holes.scad | 2 +- src/core/gridfinity-rebuilt-utility.scad | 22 ++++++++-------- src/core/standard.scad | 11 ++++---- 6 files changed, 41 insertions(+), 42 deletions(-) diff --git a/gridfinity-rebuilt-baseplate.scad b/gridfinity-rebuilt-baseplate.scad index ce9380c..ba2c150 100644 --- a/gridfinity-rebuilt-baseplate.scad +++ b/gridfinity-rebuilt-baseplate.scad @@ -266,7 +266,7 @@ module hole_pattern(){ } module cutter_countersink(){ - screw_hole(SCREW_HOLE_RADIUS + d_clear, 2*h_base, + screw_hole(SCREW_HOLE_RADIUS + d_clear, 2*BASE_HEIGHT, false, BASEPLATE_SCREW_COUNTERSINK_ADDITIONAL_RADIUS); } @@ -274,7 +274,7 @@ module cutter_counterbore(){ screw_radius = SCREW_HOLE_RADIUS + d_clear; counterbore_height = BASEPLATE_SCREW_COUNTERBORE_HEIGHT + 2*LAYER_HEIGHT; union(){ - cylinder(h=2*h_base, r=screw_radius); + cylinder(h=2*BASE_HEIGHT, r=screw_radius); difference() { cylinder(h = counterbore_height, r=BASEPLATE_SCREW_COUNTERBORE_RADIUS); make_hole_printable(screw_radius, BASEPLATE_SCREW_COUNTERBORE_RADIUS, counterbore_height); diff --git a/gridfinity-rebuilt-lite.scad b/gridfinity-rebuilt-lite.scad index 1414640..2d8cf2b 100644 --- a/gridfinity-rebuilt-lite.scad +++ b/gridfinity-rebuilt-lite.scad @@ -90,7 +90,7 @@ module gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap intersection() { difference() { gridfinityBase([gridx, gridy], [length, length], hole_options=style_hole, -d_wall*2, false, only_corners=only_corners); - translate([-gridx*length/2,-gridy*length/2,2*h_base]) + translate([-gridx*length/2,-gridy*length/2,2*BASE_HEIGHT]) cube([gridx*length,gridy*length,1000]); } translate([0,0,-1]) @@ -98,11 +98,11 @@ module gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap translate([0,0,bottom_layer]) rounded_rectangle(gridx*1000, gridy*1000, 1000, r_f2); } - translate([0,0,h_base+d_clear]) - rounded_rectangle(gridx*length-0.5005-d_wall*2, gridy*length-0.5005-d_wall*2, h_base, r_f2); + translate([0,0,BASE_HEIGHT+d_clear]) + rounded_rectangle(gridx*length-0.5005-d_wall*2, gridy*length-0.5005-d_wall*2, BASE_HEIGHT, r_f2); } - translate([0,0,-4*h_base]) + translate([0,0,-4*BASE_HEIGHT]) gridfinityInit(gridx, gridy, height(20,0), 0, length, sl=style_lip) children(); } @@ -120,7 +120,7 @@ module gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap intersection() { difference() { gridfinityBase([gridx, gridy], [length, length], hole_options=style_hole, -d_wall*2, false, only_corners=only_corners); - translate([-gridx*length/2,-gridy*length/2,2*h_base]) + translate([-gridx*length/2,-gridy*length/2,2*BASE_HEIGHT]) cube([gridx*length,gridy*length,1000]); } translate([0,0,-1]) @@ -129,7 +129,7 @@ module gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap rounded_rectangle(gridx*1000, gridy*1000, 1000, r_f2); } - translate([0,0,-4*h_base]) + translate([0,0,-4*BASE_HEIGHT]) gridfinityInit(gridx, gridy, height(20,0), 0, length, sl=style_lip) children(); } diff --git a/gridfinity-spiral-vase.scad b/gridfinity-spiral-vase.scad index b8f1625..e5c636f 100644 --- a/gridfinity-spiral-vase.scad +++ b/gridfinity-spiral-vase.scad @@ -85,8 +85,8 @@ d_hole = 26; // center-to-center distance between holes d_bottom = layer*(max(bottom_layer,1)); x_l = l_grid/2; -dht = (gridz_define==0)?gridz*7 : (gridz_define==1)?h_bot+gridz+h_base : gridz-(enable_lip?3.8:0); -d_height = (enable_zsnap?((abs(dht)%7==0)?dht:dht+7-abs(dht)%7):dht)-h_base; +dht = (gridz_define==0)?gridz*7 : (gridz_define==1)?h_bot+gridz+BASE_HEIGHT : gridz-(enable_lip?3.8:0); +d_height = (enable_zsnap?((abs(dht)%7==0)?dht:dht+7-abs(dht)%7):dht)-BASE_HEIGHT; d_fo1 = 2*+BASE_TOP_RADIUS; @@ -170,18 +170,18 @@ module gridfinityBaseVase() { difference() { intersection() { block_base_blank(0); - translate([0,0,-h_base-1]) - rounded_square([l_grid-0.5-0.005, l_grid-0.5-0.005, h_base*10], BASE_TOP_RADIUS+0.001, center=true); + translate([0,0,-BASE_HEIGHT-1]) + rounded_square([l_grid-0.5-0.005, l_grid-0.5-0.005, BASE_HEIGHT*10], BASE_TOP_RADIUS+0.001, center=true); } translate([0,0,0.01]) difference() { block_base_blank(nozzle*4); - translate([0,0,-h_base]) + translate([0,0,-BASE_HEIGHT]) cube([l_grid*2,l_grid*2,d_bottom*2],center=true); } // magic slice rotate([0,0,90]) - translate([0,0,-h_base+d_bottom+0.01]) + translate([0,0,-BASE_HEIGHT+d_bottom+0.01]) cube([0.001,l_grid*gridx,d_height+d_bottom*2]); } @@ -189,7 +189,7 @@ module gridfinityBaseVase() { pattern_circular(4) intersection() { rotate([0,0,45]) - translate([-nozzle,3,-h_base+d_bottom+0.01]) + translate([-nozzle,3,-BASE_HEIGHT+d_bottom+0.01]) cube([nozzle*2,l_grid*gridx,d_height+d_bottom*2]); block_base_blank(nozzle*4-0.1); @@ -202,8 +202,8 @@ module gridfinityBaseVase() { pattern_circular(4) block_magnet_blank(0, false); - translate([0,0,h_base/2]) - cube([l_grid*2, l_grid*2, h_base], center = true); + translate([0,0,BASE_HEIGHT/2]) + cube([l_grid*2, l_grid*2, BASE_HEIGHT], center = true); } if (style_base != 4) @@ -214,24 +214,24 @@ module gridfinityBaseVase() { module block_magnet_blank(o = 0, half = true) { magnet_radius = MAGNET_HOLE_RADIUS + o; - translate([d_hole/2,d_hole/2,-h_base+0.1]) + translate([d_hole/2,d_hole/2,-BASE_HEIGHT+0.1]) difference() { hull() { cylinder(r = magnet_radius, h = MAGNET_HOLE_DEPTH*2, center = true); - cylinder(r = magnet_radius-(h_base+0.1-MAGNET_HOLE_DEPTH), h = (h_base+0.1)*2, center = true); + cylinder(r = magnet_radius-(BASE_HEIGHT+0.1-MAGNET_HOLE_DEPTH), h = (BASE_HEIGHT+0.1)*2, center = true); } if (half) mirror([0,0,1]) - cylinder(r=magnet_radius*2, h = (h_base+0.1)*4); + cylinder(r=magnet_radius*2, h = (BASE_HEIGHT+0.1)*4); } } module block_base_blank(o = 0) { mirror([0,0,1]) { hull() { - linear_extrude(h_base) + linear_extrude(BASE_HEIGHT) rounded_square(l_grid-o-0.05-2*r_c2-2*r_c1, r_fo3, center=true); - linear_extrude(h_base-r_c1) + linear_extrude(BASE_HEIGHT-r_c1) rounded_square(l_grid-o-0.05-2*r_c2, r_fo2, center=true); } hull() { @@ -247,7 +247,7 @@ module block_base_blank(o = 0) { module block_pinch(height_mm) { assert(is_num(height_mm)); - translate([0, 0, -h_base]) + translate([0, 0, -BASE_HEIGHT]) block_wall(gridx, gridy, l_grid) { translate([d_wall2-nozzle*2-d_clear*2,0,0]) profile_wall(height_mm); @@ -360,7 +360,7 @@ module block_funnel_outside() { module block_vase_base() { difference() { // base - translate([0,0,-h_base]) { + translate([0,0,-BASE_HEIGHT]) { translate([0,0,-0.1]) color("firebrick") block_bottom(d_bottom, gridx, gridy, l_grid); diff --git a/src/core/gridfinity-rebuilt-holes.scad b/src/core/gridfinity-rebuilt-holes.scad index 7e40729..5b35c54 100644 --- a/src/core/gridfinity-rebuilt-holes.scad +++ b/src/core/gridfinity-rebuilt-holes.scad @@ -280,7 +280,7 @@ module block_base_hole(hole_options, o=0) { screw_radius = SCREW_HOLE_RADIUS - (o/2); magnet_radius = MAGNET_HOLE_RADIUS - (o/2); magnet_inner_radius = MAGNET_HOLE_CRUSH_RIB_INNER_RADIUS - (o/2); - screw_depth = h_base-o; + screw_depth = BASE_HEIGHT - o; // If using supportless / printable mode, need to add additional layers, so they can be removed later. supportless_additional_layers = screw_hole ? 2 : 3; magnet_depth = MAGNET_HOLE_DEPTH - o + diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index 4de939c..7634c33 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -31,7 +31,7 @@ function fromGridfinityUnits(gridfinityUnit, includeLipHeight = false) = * @returns The final value in mm. */ function includingFixedHeights(mmHeight, includeLipHeight = false) = - mmHeight + h_bot + h_base + (includeLipHeight ? STACKING_LIP_SIZE.y : 0); + mmHeight + h_bot + BASE_HEIGHT + (includeLipHeight ? STACKING_LIP_SIZE.y : 0); /** * @brief Three Functions in One. For height calculations. @@ -63,7 +63,7 @@ function height (z,d=0,l=0,enable_zsnap=true) = hf(z,d,l)+7-abs(hf(z,d,l))%7 ) :hf(z,d,l) - ) -h_base; + ) - BASE_HEIGHT; // Creates equally divided cutters for the bin // @@ -169,7 +169,7 @@ module gridfinityInit(gx, gy, h, h0 = 0, l = l_grid, sl = 0) { // s: toggle the rounded back corner that allows for easy removal module cut(x=0, y=0, w=1, h=1, t=1, s=1, tab_width=d_tabw, tab_height=d_tabh) { - translate([0,0,-$dh-h_base]) + translate([0, 0, -$dh - BASE_HEIGHT]) cut_move(x,y,w,h) block_cutter(clp(x,0,$gxx), clp(y,0,$gyy), clp(w,0,$gxx-x), clp(h,0,$gyy-y), t, s, tab_width, tab_height); } @@ -209,7 +209,7 @@ module cutEqualBins(bins_x=1, bins_y=1, len_x=1, len_y=1, pos_x=0, pos_y=0, styl // Translates an object from the origin point to the center of the requested compartment block, can be used to add custom cuts in the bin // See cut() module for parameter descriptions module cut_move(x, y, w, h) { - translate([0,0,$dh0==0?$dh+h_base:$dh0+h_base]) + translate([0, 0, ($dh0==0 ? $dh : $dh0) + BASE_HEIGHT]) cut_move_unsafe(clp(x,0,$gxx), clp(y,0,$gyy), clp(w,0,$gxx-x), clp(h,0,$gyy-y)) children(); } @@ -260,7 +260,7 @@ module gridfinityBase(grid_size, grid_dimensions=GRID_DIMENSIONS_MM, hole_option // Top which ties all bases together if (final_cut) { - translate([0, 0, h_base-TOLLERANCE]) + translate([0, 0, BASE_HEIGHT]) rounded_square([grid_size_mm.x, grid_size_mm.y, h_bot], BASE_TOP_RADIUS, center=true); } @@ -338,8 +338,8 @@ module block_base(hole_options, off=0, top_dimensions=BASE_TOP_DIMENSIONS, thumb sweep_rounded(sweep_inner) base_polygon(); - translate([0, 0, BASE_PROFILE_MAX.y/2]) - cube([cube_size.x, cube_size.y, BASE_PROFILE_MAX.y], center=true); + translate([0, 0, BASE_HEIGHT/2]) + cube([cube_size.x, cube_size.y, BASE_HEIGHT], center=true); } if (thumbscrew) { @@ -450,13 +450,13 @@ module profile_wall2(height_mm) { } module block_wall(gx, gy, l) { - translate([0,0,h_base]) + translate([0, 0, BASE_HEIGHT]) sweep_rounded([gx*l-2*r_base-0.5-0.001, gy*l-2*r_base-0.5-0.001]) children(); } module block_bottom( h = 2.2, gx, gy, l ) { - translate([0,0,h_base+0.1]) + translate([0, 0, BASE_HEIGHT + 0.1]) rounded_rectangle(gx*l-0.5-d_wall/4, gy*l-0.5-d_wall/4, h, r_base+0.01); } @@ -482,7 +482,7 @@ module block_cutter(x,y,w,h,t,s,tab_width=d_tabw,tab_height=d_tabh) { ycutlast = abs(y+h-$gyy)<0.001 && $style_lip == 0; xcutfirst = x == 0 && $style_lip == 0; xcutlast = abs(x+w-$gxx)<0.001 && $style_lip == 0; - zsmall = ($dh+h_base)/7 < 3; + zsmall = ($dh+BASE_HEIGHT)/7 < 3; ylen = h*($gyy*l_grid+d_magic)/$gyy-d_div; xlen = w*($gxx*l_grid+d_magic)/$gxx-d_div; @@ -494,7 +494,7 @@ module block_cutter(x,y,w,h,t,s,tab_width=d_tabw,tab_height=d_tabh) { cut = (zsmall || t == 5) ? (ycutlast?v_cut_lip:0) : v_cut_tab; style = (t > 1 && t < 5) ? t-3 : (x == 0 ? -1 : xcutlast ? 1 : 0); - translate([0,ylen/2,h_base+h_bot]) + translate([0, ylen/2, BASE_HEIGHT+h_bot]) rotate([90,0,-90]) { if (!zsmall && xlen - tab_width > 4*r_f2 && (t != 0 && t != 5)) { diff --git a/src/core/standard.scad b/src/core/standard.scad index 372fec9..a3554b5 100644 --- a/src/core/standard.scad +++ b/src/core/standard.scad @@ -173,6 +173,11 @@ BASE_TOP_DIMENSIONS = [41.5, 41.5]; */ BASE_PROFILE_MAX = BASE_PROFILE[3]; +/** + * @Summary Height of the base. + */ +BASE_HEIGHT = BASE_PROFILE_MAX.y; + /** * @Summary Corner radius of the bottom of the base. * @Details This is also how much BASE_PROFILE needs to be translated @@ -191,12 +196,6 @@ function base_bottom_dimensions(top_dimensions = BASE_TOP_DIMENSIONS) = [top_dimensions.x - 2*BASE_PROFILE_MAX.x, top_dimensions.y - 2*BASE_PROFILE_MAX.x]; -/** - * @summary Height of the raw base - * @Deprecated - */ -h_base = BASE_PROFILE_MAX.y; - // **************************************** // Baseplate constants // Based on https://gridfinity.xyz/specification/ From fa942bf5f53eb7a145373c4b6d4464a8383be1c5 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sun, 27 Oct 2024 09:56:21 -0400 Subject: [PATCH 5/9] Break Gridfinity Refined thumbscrew out to a separate function Also move constants to standard.scad. --- src/core/gridfinity-rebuilt-utility.scad | 28 +++++++++++------------- src/core/standard.scad | 8 +++++++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index 7634c33..3c18378 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -306,6 +306,18 @@ module base_polygon() { polygon(solid_profile); } +/** + * @brief Internal function to create the negative for a Gridfinity Refined thumbscrew hole. + * @details Magic constants are what the threads.ScrewHole function does. + */ +module _base_thumbscrew() { + ScrewThread( + 1.01 * BASE_THUMBSCREW_OUTER_DIAMETER + 1.25 * 0.4, + BASE_HEIGHT, + BASE_THUMBSCREW_PITCH + ); +} + /** * @brief A single Gridfinity base. With holes (if set). * @param hole_options @see block_base_hole.hole_options @@ -325,13 +337,6 @@ module block_base(hole_options, off=0, top_dimensions=BASE_TOP_DIMENSIONS, thumb str("Minimum size of a single base must be greater than ", 2*BASE_TOP_RADIUS) ); - thumbscrew_outerdiam = 15; - thumbscrew_height = 5; - thumbscrew_tolerance = 0.4; - thumbscrew_tooth_angle = 30; - thumbscrew_pitch = 1.5; - - render(convexity = 2) difference() { union(){ @@ -343,14 +348,7 @@ module block_base(hole_options, off=0, top_dimensions=BASE_TOP_DIMENSIONS, thumb } if (thumbscrew) { - ScrewThread( - 1.01 * thumbscrew_outerdiam + 1.25 * thumbscrew_tolerance, - thumbscrew_height, - thumbscrew_pitch, - thumbscrew_tooth_angle, - thumbscrew_tolerance, - tooth_height=0 - ); + _base_thumbscrew(); } // 4 holes // Need this fancy code to support refined holes and non-square bases. diff --git a/src/core/standard.scad b/src/core/standard.scad index a3554b5..38a756d 100644 --- a/src/core/standard.scad +++ b/src/core/standard.scad @@ -196,6 +196,14 @@ function base_bottom_dimensions(top_dimensions = BASE_TOP_DIMENSIONS) = [top_dimensions.x - 2*BASE_PROFILE_MAX.x, top_dimensions.y - 2*BASE_PROFILE_MAX.x]; +// *************** +// Gridfinity Refined Thumbscrew +// See https://www.printables.com/model/413761-gridfinity-refined +// *************** + +BASE_THUMBSCREW_OUTER_DIAMETER=15; +BASE_THUMBSCREW_PITCH=1.5; + // **************************************** // Baseplate constants // Based on https://gridfinity.xyz/specification/ From dc13ebc107cdeeb25455cf5ba145de78fb995c10 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sun, 27 Oct 2024 10:56:53 -0400 Subject: [PATCH 6/9] Separate out base hole generation Simplifies code for gridfinityBase, and prepares for future work. --- src/core/gridfinity-rebuilt-holes.scad | 2 +- src/core/gridfinity-rebuilt-utility.scad | 97 +++++++++++++----------- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/core/gridfinity-rebuilt-holes.scad b/src/core/gridfinity-rebuilt-holes.scad index 5b35c54..79f03de 100644 --- a/src/core/gridfinity-rebuilt-holes.scad +++ b/src/core/gridfinity-rebuilt-holes.scad @@ -263,7 +263,7 @@ module assert_hole_options_valid(hole_options) { * @brief A single magnet/screw hole. To be cut out of the base. * @details Supports multiple options that can be mixed and matched. * @pram hole_options @see bundle_hole_options - * @param o Offset + * @param o offset Grows or shrinks the final shapes. Similar to `scale`, but in mm. */ module block_base_hole(hole_options, o=0) { assert_hole_options_valid(hole_options); diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index 3c18378..267ede4 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -249,7 +249,7 @@ module gridfinityBase(grid_size, grid_dimensions=GRID_DIMENSIONS_MM, hole_option final_grid_size = [grid_size.x * divisions_per_grid.x, grid_size.y * divisions_per_grid.y]; base_center_distance_mm = [grid_dimensions.x / divisions_per_grid.x, grid_dimensions.y / divisions_per_grid.y]; - individual_base_size_mm = [base_center_distance_mm.x, base_center_distance_mm.y] - gap_mm; + individual_base_size_mm = base_center_distance_mm - gap_mm; // Final size of the base top. In mm. // subtracting gap_mm here to remove an outer lip along the peremiter. @@ -265,24 +265,11 @@ module gridfinityBase(grid_size, grid_dimensions=GRID_DIMENSIONS_MM, hole_option } if(only_corners) { - hole_position = foreach_add( - grid_size_mm/2, - - HOLE_DISTANCE_FROM_BOTTOM_EDGE - BASE_PROFILE_MAX.x - ); difference(){ pattern_linear(final_grid_size.x, final_grid_size.y, base_center_distance_mm.x, base_center_distance_mm.y) block_base(bundle_hole_options(), 0, individual_base_size_mm, thumbscrew=thumbscrew); - copy_mirror([0, 1, 0]) { - copy_mirror([1, 0, 0]) { - translate([ - hole_position.x, - hole_position.y, - 0 - ]) - block_base_hole(hole_options, off); - } - } + _base_holes(hole_options, off, grid_size_mm); } } else { @@ -306,6 +293,30 @@ module base_polygon() { polygon(solid_profile); } +/** + * @brief A single solid Gridfinity base. + * @param top_dimensions [x, y] size of a single base. Only set if deviating from the standard! + */ +module base_solid(top_dimensions=BASE_TOP_DIMENSIONS) { + assert(is_list(top_dimensions) && len(top_dimensions) == 2); + + base_bottom = base_bottom_dimensions(top_dimensions); + sweep_inner = foreach_add(base_bottom, -2*BASE_BOTTOM_RADIUS); + cube_size = foreach_add(base_bottom, -BASE_BOTTOM_RADIUS); + + assert(sweep_inner.x > 0 && sweep_inner.y > 0, + str("Minimum size of a single base must be greater than ", 2*BASE_TOP_RADIUS) + ); + + union(){ + sweep_rounded(sweep_inner) + base_polygon(); + + translate([0, 0, BASE_HEIGHT/2]) + cube([cube_size.x, cube_size.y, BASE_HEIGHT], center=true); + } +} + /** * @brief Internal function to create the negative for a Gridfinity Refined thumbscrew hole. * @details Magic constants are what the threads.ScrewHole function does. @@ -318,52 +329,50 @@ module _base_thumbscrew() { ); } +/** + * @brief Internal Code. Generates the 4 holes for a single base. + * @details Need this fancy code to support refined holes and non-square bases. + * @param hole_options @see bundle_hole_options + * @param offset @see block_base_hole.offset + */ +module _base_holes(hole_options, offset=0, top_dimensions=BASE_TOP_DIMENSIONS) { + hole_position = foreach_add( + base_bottom_dimensions(top_dimensions)/2, + -HOLE_DISTANCE_FROM_BOTTOM_EDGE + ); + + for(a=[0:90:270]){ + // i and j represent the 4 quadrants. + // The +1 is used to keep any values from being exactly 0. + j = sign(sin(a+1)); + i = sign(cos(a+1)); + translate([i * hole_position.x, j * hole_position.y, 0]) + rotate([0, 0, a]) + block_base_hole(hole_options, offset); + } +} + /** * @brief A single Gridfinity base. With holes (if set). * @param hole_options @see block_base_hole.hole_options - * @param off + * @param offset Grows or shrinks the final shapes. Similar to `scale`, but in mm. * @param top_dimensions [x, y] size of a single base. Only set if deviating from the standard! * @param thumbscrew Enable "gridfinity-refined" thumbscrew hole in the center of each base unit. This is a ISO Metric Profile, 15.0mm size, M15x1.5 designation. */ -module block_base(hole_options, off=0, top_dimensions=BASE_TOP_DIMENSIONS, thumbscrew=false) { +module block_base(hole_options, offset=0, top_dimensions=BASE_TOP_DIMENSIONS, thumbscrew=false) { assert(is_list(top_dimensions) && len(top_dimensions) == 2); assert(is_bool(thumbscrew)); base_bottom = base_bottom_dimensions(top_dimensions); - sweep_inner = foreach_add(base_bottom, -2*BASE_BOTTOM_RADIUS); - cube_size = foreach_add(base_bottom, -BASE_BOTTOM_RADIUS); - - assert(sweep_inner.x > 0 && sweep_inner.y > 0, - str("Minimum size of a single base must be greater than ", 2*BASE_TOP_RADIUS) - ); render(convexity = 2) difference() { - union(){ - sweep_rounded(sweep_inner) - base_polygon(); - - translate([0, 0, BASE_HEIGHT/2]) - cube([cube_size.x, cube_size.y, BASE_HEIGHT], center=true); - } + base_solid(top_dimensions); if (thumbscrew) { _base_thumbscrew(); } - // 4 holes - // Need this fancy code to support refined holes and non-square bases. - for(a=[0:90:270]){ - // i and j represent the 4 quadrants. - // The +1 is used to keep any values from being exactly 0. - j = sign(sin(a+1)); - i = sign(cos(a+1)); - translate([ - i * (base_bottom.x/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE), - j * (base_bottom.y/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE), - 0]) - rotate([0, 0, a]) - block_base_hole(hole_options, off); - } + _base_holes(hole_options, offset, top_dimensions); } } From f377230368372067ba6704cfd0e2fd4477e2ff7c Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sun, 27 Oct 2024 11:11:33 -0400 Subject: [PATCH 7/9] Respect only_corners for thumbscrews cutouts --- src/core/gridfinity-rebuilt-utility.scad | 27 +++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index 267ede4..1628aae 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -266,10 +266,19 @@ module gridfinityBase(grid_size, grid_dimensions=GRID_DIMENSIONS_MM, hole_option if(only_corners) { difference(){ - pattern_linear(final_grid_size.x, final_grid_size.y, base_center_distance_mm.x, base_center_distance_mm.y) - block_base(bundle_hole_options(), 0, individual_base_size_mm, thumbscrew=thumbscrew); + pattern_linear(final_grid_size.x, final_grid_size.y, base_center_distance_mm.x, base_center_distance_mm.y) { + base_solid(individual_base_size_mm); + } + + if(thumbscrew) { + thumbscrew_position = grid_size_mm - individual_base_size_mm; + pattern_linear(2, 2, thumbscrew_position.x, thumbscrew_position.y) { + _base_thumbscrew(); + } + } _base_holes(hole_options, off, grid_size_mm); + _base_preview_fix(); } } else { @@ -365,7 +374,6 @@ module block_base(hole_options, offset=0, top_dimensions=BASE_TOP_DIMENSIONS, th base_bottom = base_bottom_dimensions(top_dimensions); - render(convexity = 2) difference() { base_solid(top_dimensions); @@ -373,6 +381,19 @@ module block_base(hole_options, offset=0, top_dimensions=BASE_TOP_DIMENSIONS, th _base_thumbscrew(); } _base_holes(hole_options, offset, top_dimensions); + _base_preview_fix(); + } +} + +/** + * @brief Internal code. Fix base preview rendering issues. + * @details Preview does not like perfect top/bottoms. + */ +module _base_preview_fix() { + if($preview){ + cube([10000, 10000, 0.01], center=true); + translate([0, 0, BASE_HEIGHT]) + cube([10000, 10000, 0.01], center=true); } } From c7dce9f6d595ba23b8bf798dd5069c600709697a Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sun, 27 Oct 2024 16:26:40 -0400 Subject: [PATCH 8/9] Re-work vase mode base creation * Fix Cura not creating interior. (magic slice too thin) * Add a base_outer_shell module. * Use base_outer_shell to create the vase mode base. --- gridfinity-spiral-vase.scad | 93 ++++++++---------------- src/core/gridfinity-rebuilt-utility.scad | 25 +++++++ 2 files changed, 55 insertions(+), 63 deletions(-) diff --git a/gridfinity-spiral-vase.scad b/gridfinity-spiral-vase.scad index e5c636f..c1631c1 100644 --- a/gridfinity-spiral-vase.scad +++ b/gridfinity-spiral-vase.scad @@ -69,16 +69,13 @@ a_tab = 40; // ===== IMPLEMENTATION ===== // color("tomato") -if (type != 0) gridfinityBaseVase(); // Generate a single base +if (type != 0) gridfinityBaseVase(2*nozzle, d_bottom); // Generate a single base else gridfinityVase(); // Generate the bin // ===== CONSTRUCTION ===== // //Deprecated Variables -r_fo2 = 3.2 / 2; // outside radii 2 -r_fo3 = 1.6 / 2; // outside radii 3 -r_c2 = 2.4; // upper base chamfer "radius" d_hole = 26; // center-to-center distance between holes //End Deprecated Variables @@ -164,57 +161,45 @@ module gridfinityVase() { } } -module gridfinityBaseVase() { +module gridfinityBaseVase(wall_thickness, bottom_thickness) { difference() { - union() { - difference() { - intersection() { - block_base_blank(0); - translate([0,0,-BASE_HEIGHT-1]) - rounded_square([l_grid-0.5-0.005, l_grid-0.5-0.005, BASE_HEIGHT*10], BASE_TOP_RADIUS+0.001, center=true); + union() { + base_outer_shell(wall_thickness, bottom_thickness); + intersection() { + pattern_circular(4){ + rotate([0,0,45]) + translate([-wall_thickness/2, 3, 0]) + cube([wall_thickness, l_grid, BASE_PROFILE_MAX.y]); + + if (enable_holes) { + block_magnet_blank(wall_thickness); + } + } + base_solid(); + } + if (style_base != 4) { + translate([0, 0, BASE_PROFILE_MAX.y]) + linear_extrude(bottom_thickness) + profile_x(0.1); + } } - translate([0,0,0.01]) - difference() { - block_base_blank(nozzle*4); - translate([0,0,-BASE_HEIGHT]) - cube([l_grid*2,l_grid*2,d_bottom*2],center=true); + if (enable_holes) { + pattern_circular(4) + block_magnet_blank(0, false); } + // magic slice - rotate([0,0,90]) - translate([0,0,-BASE_HEIGHT+d_bottom+0.01]) - cube([0.001,l_grid*gridx,d_height+d_bottom*2]); - + // Tricks slicer into not ignoring the center. + rotate([0, 0, 90]) + translate([0, 0, bottom_thickness]) + cube([0.005, 2*l_grid, 2*BASE_HEIGHT]); } - - pattern_circular(4) - intersection() { - rotate([0,0,45]) - translate([-nozzle,3,-BASE_HEIGHT+d_bottom+0.01]) - cube([nozzle*2,l_grid*gridx,d_height+d_bottom*2]); - - block_base_blank(nozzle*4-0.1); - } - if (enable_holes) - pattern_circular(4) - block_magnet_blank(nozzle); - } - if (enable_holes) - pattern_circular(4) - block_magnet_blank(0, false); - - translate([0,0,BASE_HEIGHT/2]) - cube([l_grid*2, l_grid*2, BASE_HEIGHT], center = true); - } - - if (style_base != 4) - linear_extrude(d_bottom) - profile_x(0.1); } module block_magnet_blank(o = 0, half = true) { magnet_radius = MAGNET_HOLE_RADIUS + o; - translate([d_hole/2,d_hole/2,-BASE_HEIGHT+0.1]) + translate([d_hole/2, d_hole/2, 0.1]) difference() { hull() { cylinder(r = magnet_radius, h = MAGNET_HOLE_DEPTH*2, center = true); @@ -226,24 +211,6 @@ module block_magnet_blank(o = 0, half = true) { } } -module block_base_blank(o = 0) { - mirror([0,0,1]) { - hull() { - linear_extrude(BASE_HEIGHT) - rounded_square(l_grid-o-0.05-2*r_c2-2*r_c1, r_fo3, center=true); - linear_extrude(BASE_HEIGHT-r_c1) - rounded_square(l_grid-o-0.05-2*r_c2, r_fo2, center=true); - } - hull() { - linear_extrude(r_c2) - rounded_square(l_grid-o-0.05-2*r_c2, r_fo2, center=true); - mirror([0,0,1]) - linear_extrude(d_bottom) - rounded_square(l_grid-o-0.05, BASE_TOP_RADIUS, center=true); - } - } -} - module block_pinch(height_mm) { assert(is_num(height_mm)); diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index 1628aae..cffac2c 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -385,6 +385,31 @@ module block_base(hole_options, offset=0, top_dimensions=BASE_TOP_DIMENSIONS, th } } +/** + * @brief Outer shell of a Gridfinity base. + * @param wall_thickness How thick the walls are. + * @param bottom_thickness How thick the bottom is. + * @param top_dimensions [x, y] size of a single base. Only set if deviating from the standard! + */ +module base_outer_shell(wall_thickness, bottom_thickness, top_dimensions=BASE_TOP_DIMENSIONS) { + assert(is_num(wall_thickness) && wall_thickness > 0); + assert((is_num(bottom_thickness) && bottom_thickness > 0)); + + union(){ + difference(){ + base_solid(top_dimensions=top_dimensions); + base_solid(top_dimensions=foreach_add(top_dimensions, -2*wall_thickness)); + _base_preview_fix(); + } + //Bottom + intersection() { + translate([0, 0, bottom_thickness/2]) + cube([top_dimensions.x, top_dimensions.y, bottom_thickness], center=true); + base_solid(top_dimensions=top_dimensions); + } + } +} + /** * @brief Internal code. Fix base preview rendering issues. * @details Preview does not like perfect top/bottoms. From 3e4d8702c4c31e4a6e671afad43f698eafb5b673 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sun, 27 Oct 2024 22:45:37 -0400 Subject: [PATCH 9/9] Fix lite bases Use a completely different method to generate both the keep out zone and the base. --- gridfinity-rebuilt-lite.scad | 81 ++++++------------------ src/core/gridfinity-rebuilt-utility.scad | 62 ++++++++++++++++++ 2 files changed, 80 insertions(+), 63 deletions(-) diff --git a/gridfinity-rebuilt-lite.scad b/gridfinity-rebuilt-lite.scad index 2d8cf2b..d42201e 100644 --- a/gridfinity-rebuilt-lite.scad +++ b/gridfinity-rebuilt-lite.scad @@ -69,6 +69,7 @@ hole_options = bundle_hole_options(refined_holes, magnet_holes, screw_holes, cru // Input all the cutter types in here color("tomato") +render() gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap, l_grid, hole_options, only_corners) { cutEqual(n_divx = divx, n_divy = divy, style_tab = style_tab, scoop_weight = 0); } @@ -77,70 +78,24 @@ gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap, l_gri module gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap, length, style_hole, only_corners) { height_mm = height(gridz, gridz_define, style_lip, enable_zsnap); - union() { + + // Lower the bin start point by this amount. + // Made up for in bin height. + // Ensures divider walls smoothly transition to the bottom + lower_by_mm = BASE_HEIGHT + bottom_layer; + + difference() { + translate([0, 0, -lower_by_mm]) + gridfinityInit(gridx, gridy, height_mm+lower_by_mm, 0, length, sl=style_lip) + children(); + + // Underside of the base. Keep out zone. + render() difference() { - union() { - gridfinityInit(gridx, gridy, height_mm, 0, length, sl=style_lip) - children(); - gridfinityBase([gridx, gridy], [length, length], hole_options=style_hole, only_corners=only_corners); - } - - difference() { - union() { - intersection() { - difference() { - gridfinityBase([gridx, gridy], [length, length], hole_options=style_hole, -d_wall*2, false, only_corners=only_corners); - translate([-gridx*length/2,-gridy*length/2,2*BASE_HEIGHT]) - cube([gridx*length,gridy*length,1000]); - } - translate([0,0,-1]) - rounded_rectangle(gridx*length-0.5005-d_wall*2, gridy*length-0.5005-d_wall*2, 1000, r_f2); - translate([0,0,bottom_layer]) - rounded_rectangle(gridx*1000, gridy*1000, 1000, r_f2); - } - translate([0,0,BASE_HEIGHT+d_clear]) - rounded_rectangle(gridx*length-0.5005-d_wall*2, gridy*length-0.5005-d_wall*2, BASE_HEIGHT, r_f2); - } - - translate([0,0,-4*BASE_HEIGHT]) - gridfinityInit(gridx, gridy, height(20,0), 0, length, sl=style_lip) - children(); - } + cube([gridx*length, gridy*length, BASE_HEIGHT*2], center=true); + gridfinityBase([gridx, gridy], hole_options=style_hole, only_corners=only_corners); } - difference() { - translate([0,0,-1.6]) - difference() { - difference() { - union() { - gridfinityInit(gridx, gridy, height_mm, 0, length, sl=style_lip) - children(); - } - - difference() { - intersection() { - difference() { - gridfinityBase([gridx, gridy], [length, length], hole_options=style_hole, -d_wall*2, false, only_corners=only_corners); - translate([-gridx*length/2,-gridy*length/2,2*BASE_HEIGHT]) - cube([gridx*length,gridy*length,1000]); - } - translate([0,0,-1]) - rounded_rectangle(gridx*length-0.5005-d_wall*2, gridy*length-0.5005-d_wall*2, 1000, r_f2); - translate([0,0,bottom_layer]) - rounded_rectangle(gridx*1000, gridy*1000, 1000, r_f2); - } - - translate([0,0,-4*BASE_HEIGHT]) - gridfinityInit(gridx, gridy, height(20,0), 0, length, sl=style_lip) - children(); - } - - } - translate([0,0,9]) - rounded_rectangle(gridx*1000, gridy*1000, gridz*1000, gridz); - } - translate([0,0,0]) - rounded_rectangle(gridx*1000, gridy*1000, 5, r_f2); - } - } + + gridfinity_base_lite([gridx, gridy], d_wall, bottom_layer, hole_options=style_hole, only_corners=only_corners); } diff --git a/src/core/gridfinity-rebuilt-utility.scad b/src/core/gridfinity-rebuilt-utility.scad index cffac2c..711f448 100644 --- a/src/core/gridfinity-rebuilt-utility.scad +++ b/src/core/gridfinity-rebuilt-utility.scad @@ -287,6 +287,68 @@ module gridfinityBase(grid_size, grid_dimensions=GRID_DIMENSIONS_MM, hole_option } } +/** + * @brief Create the base of a gridfinity bin, or use it for a custom object. + * @param length X,Y size of a single Gridfinity base. + * @param grid_size Size in number of bases. [x, y] + * @param wall_thickness How thick the walls, and holes (if enabled) are. + * @param top_bottom_thickness How thick the top and bottom is. + * @param hole_options @see block_base_hole.hole_options + * @param only_corners Only put holes on each corner. + */ +module gridfinity_base_lite(grid_size, wall_thickness, top_bottom_thickness, hole_options=bundle_hole_options(), only_corners = false) { + assert(is_list(grid_size) && len(grid_size) == 2 && grid_size.x > 0 && grid_size.y > 0); + assert(is_num(wall_thickness) && wall_thickness > 0); + assert(is_num(top_bottom_thickness) && top_bottom_thickness > 0); + assert(is_bool(only_corners)); + + grid_dimensions = GRID_DIMENSIONS_MM; + + // Per spec, there's a 0.5mm gap between each base. + // This must be kept constant or half bins may not work correctly. + gap_mm = GRID_DIMENSIONS_MM - BASE_TOP_DIMENSIONS; + + // Final size of the base top. In mm. + // Gap needs to be removed to prevent an unwanted overhang off the edges. + grid_size_mm = [grid_dimensions.x * grid_size.x, grid_dimensions.y * grid_size.y] -gap_mm; + + //Bridging structure to tie the bases together + difference() { + translate([0, 0, BASE_HEIGHT-top_bottom_thickness]) + rounded_square([grid_size_mm.x, grid_size_mm.y, top_bottom_thickness], BASE_TOP_RADIUS, center=true); + + pattern_linear(grid_size.x, grid_size.y, grid_dimensions.x, grid_dimensions.y) + translate([0, 0, top_bottom_thickness]) + base_solid(); + } + + render() + if(only_corners) { + difference() { + union() { + pattern_linear(grid_size.x, grid_size.y, grid_dimensions.x, grid_dimensions.y) + base_outer_shell(wall_thickness, top_bottom_thickness); + _base_holes(hole_options, -wall_thickness, grid_size_mm); + } + + _base_holes(hole_options, 0, grid_size_mm); + _base_preview_fix(); + } + } + else { + pattern_linear(grid_size.x, grid_size.y, grid_dimensions.x, grid_dimensions.y) { + difference() { + union() { + base_outer_shell(wall_thickness, top_bottom_thickness); + _base_holes(hole_options, -wall_thickness); + } + _base_holes(hole_options, 0); + _base_preview_fix(); + } + } + } +} + /** * @brief Solid polygon of a gridfinity base. * @details Ready for use with `sweep_rounded(...)`.