mirror of
https://github.com/kennetek/gridfinity-rebuilt-openscad.git
synced 2024-12-22 23:03:28 +00:00
Updated solid base creation logic
* Simplified. * More readable. * Prevents gaps that could be left by old logic. (rounded_square)
This commit is contained in:
parent
1ee99f9c6f
commit
d47043fa51
4 changed files with 102 additions and 62 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -324,19 +335,11 @@ 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);
|
||||
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);
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue