mirror of
https://github.com/kennetek/gridfinity-rebuilt-openscad.git
synced 2025-01-04 21:19:41 +00:00
Merge pull request #243 from EmperorArthur/base_updates
Base Updates. Fixes lite bins.
This commit is contained in:
commit
b3bb896eba
7 changed files with 361 additions and 256 deletions
|
@ -266,7 +266,7 @@ module hole_pattern(){
|
||||||
}
|
}
|
||||||
|
|
||||||
module cutter_countersink(){
|
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);
|
false, BASEPLATE_SCREW_COUNTERSINK_ADDITIONAL_RADIUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ module cutter_counterbore(){
|
||||||
screw_radius = SCREW_HOLE_RADIUS + d_clear;
|
screw_radius = SCREW_HOLE_RADIUS + d_clear;
|
||||||
counterbore_height = BASEPLATE_SCREW_COUNTERBORE_HEIGHT + 2*LAYER_HEIGHT;
|
counterbore_height = BASEPLATE_SCREW_COUNTERBORE_HEIGHT + 2*LAYER_HEIGHT;
|
||||||
union(){
|
union(){
|
||||||
cylinder(h=2*h_base, r=screw_radius);
|
cylinder(h=2*BASE_HEIGHT, r=screw_radius);
|
||||||
difference() {
|
difference() {
|
||||||
cylinder(h = counterbore_height, r=BASEPLATE_SCREW_COUNTERBORE_RADIUS);
|
cylinder(h = counterbore_height, r=BASEPLATE_SCREW_COUNTERBORE_RADIUS);
|
||||||
make_hole_printable(screw_radius, BASEPLATE_SCREW_COUNTERBORE_RADIUS, counterbore_height);
|
make_hole_printable(screw_radius, BASEPLATE_SCREW_COUNTERBORE_RADIUS, counterbore_height);
|
||||||
|
@ -321,7 +321,7 @@ module baseplate_lip(height=0, width=l_grid, length=l_grid) {
|
||||||
|
|
||||||
additional_height = height + BASEPLATE_CLEARANCE_HEIGHT;
|
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])
|
translate([translation_x, additional_height, 0])
|
||||||
polygon(concat(BASEPLATE_LIP, [
|
polygon(concat(BASEPLATE_LIP, [
|
||||||
[0, -additional_height],
|
[0, -additional_height],
|
||||||
|
@ -341,7 +341,7 @@ module square_baseplate_lip(height=0, size = l_grid) {
|
||||||
|
|
||||||
corner_center_distance = size/2 - BASEPLATE_OUTSIDE_RADIUS;
|
corner_center_distance = size/2 - BASEPLATE_OUTSIDE_RADIUS;
|
||||||
|
|
||||||
render(convexity = 2) // Fixes ghosting in preview
|
//render(convexity = 2) // Fixes ghosting in preview
|
||||||
union() {
|
union() {
|
||||||
baseplate_lip(height, size, size);
|
baseplate_lip(height, size, size);
|
||||||
pattern_circular(4)
|
pattern_circular(4)
|
||||||
|
|
|
@ -69,6 +69,7 @@ hole_options = bundle_hole_options(refined_holes, magnet_holes, screw_holes, cru
|
||||||
|
|
||||||
// Input all the cutter types in here
|
// Input all the cutter types in here
|
||||||
color("tomato")
|
color("tomato")
|
||||||
|
render()
|
||||||
gridfinityLite(gridx, gridy, gridz, gridz_define, style_lip, enable_zsnap, l_grid, hole_options, only_corners) {
|
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);
|
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) {
|
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);
|
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() {
|
difference() {
|
||||||
union() {
|
cube([gridx*length, gridy*length, BASE_HEIGHT*2], center=true);
|
||||||
gridfinityInit(gridx, gridy, height_mm, 0, length, sl=style_lip)
|
gridfinityBase([gridx, gridy], hole_options=style_hole, only_corners=only_corners);
|
||||||
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*h_base])
|
|
||||||
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,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,-4*h_base])
|
|
||||||
gridfinityInit(gridx, gridy, height(20,0), 0, length, sl=style_lip)
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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*h_base])
|
|
||||||
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*h_base])
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,26 +69,23 @@ a_tab = 40;
|
||||||
// ===== IMPLEMENTATION ===== //
|
// ===== IMPLEMENTATION ===== //
|
||||||
|
|
||||||
color("tomato")
|
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
|
else gridfinityVase(); // Generate the bin
|
||||||
|
|
||||||
|
|
||||||
// ===== CONSTRUCTION ===== //
|
// ===== CONSTRUCTION ===== //
|
||||||
|
|
||||||
//Deprecated Variables
|
//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
|
d_hole = 26; // center-to-center distance between holes
|
||||||
//End Deprecated Variables
|
//End Deprecated Variables
|
||||||
|
|
||||||
d_bottom = layer*(max(bottom_layer,1));
|
d_bottom = layer*(max(bottom_layer,1));
|
||||||
x_l = l_grid/2;
|
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);
|
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)-h_base;
|
d_height = (enable_zsnap?((abs(dht)%7==0)?dht:dht+7-abs(dht)%7):dht)-BASE_HEIGHT;
|
||||||
|
|
||||||
d_fo1 = 2*+BASE_OUTSIDE_RADIUS;
|
d_fo1 = 2*+BASE_TOP_RADIUS;
|
||||||
|
|
||||||
f2c = sqrt(2)*(sqrt(2)-1); // fillet to chamfer ratio
|
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;
|
me = ((gridx*l_grid-0.5)/n_divx)-nozzle*4-d_fo1-12.7-4;
|
||||||
|
@ -164,90 +161,60 @@ module gridfinityVase() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module gridfinityBaseVase() {
|
module gridfinityBaseVase(wall_thickness, bottom_thickness) {
|
||||||
difference() {
|
difference() {
|
||||||
union() {
|
union() {
|
||||||
difference() {
|
base_outer_shell(wall_thickness, bottom_thickness);
|
||||||
intersection() {
|
intersection() {
|
||||||
block_base_blank(0);
|
pattern_circular(4){
|
||||||
translate([0,0,-h_base-1])
|
rotate([0,0,45])
|
||||||
rounded_square([l_grid-0.5-0.005, l_grid-0.5-0.005, h_base*10], BASE_OUTSIDE_RADIUS+0.001, center=true);
|
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])
|
if (enable_holes) {
|
||||||
difference() {
|
pattern_circular(4)
|
||||||
block_base_blank(nozzle*4);
|
block_magnet_blank(0, false);
|
||||||
translate([0,0,-h_base])
|
|
||||||
cube([l_grid*2,l_grid*2,d_bottom*2],center=true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// magic slice
|
// magic slice
|
||||||
rotate([0,0,90])
|
// Tricks slicer into not ignoring the center.
|
||||||
translate([0,0,-h_base+d_bottom+0.01])
|
rotate([0, 0, 90])
|
||||||
cube([0.001,l_grid*gridx,d_height+d_bottom*2]);
|
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,-h_base+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,h_base/2])
|
|
||||||
cube([l_grid*2, l_grid*2, h_base], center = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (style_base != 4)
|
|
||||||
linear_extrude(d_bottom)
|
|
||||||
profile_x(0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module block_magnet_blank(o = 0, half = true) {
|
module block_magnet_blank(o = 0, half = true) {
|
||||||
magnet_radius = MAGNET_HOLE_RADIUS + o;
|
magnet_radius = MAGNET_HOLE_RADIUS + o;
|
||||||
|
|
||||||
translate([d_hole/2,d_hole/2,-h_base+0.1])
|
translate([d_hole/2, d_hole/2, 0.1])
|
||||||
difference() {
|
difference() {
|
||||||
hull() {
|
hull() {
|
||||||
cylinder(r = magnet_radius, h = MAGNET_HOLE_DEPTH*2, center = true);
|
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)
|
if (half)
|
||||||
mirror([0,0,1])
|
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)
|
|
||||||
rounded_square(l_grid-o-0.05-2*r_c2-2*r_c1, r_fo3, center=true);
|
|
||||||
linear_extrude(h_base-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_OUTSIDE_RADIUS, center=true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module block_pinch(height_mm) {
|
module block_pinch(height_mm) {
|
||||||
assert(is_num(height_mm));
|
assert(is_num(height_mm));
|
||||||
|
|
||||||
translate([0, 0, -h_base])
|
translate([0, 0, -BASE_HEIGHT])
|
||||||
block_wall(gridx, gridy, l_grid) {
|
block_wall(gridx, gridy, l_grid) {
|
||||||
translate([d_wall2-nozzle*2-d_clear*2,0,0])
|
translate([d_wall2-nozzle*2-d_clear*2,0,0])
|
||||||
profile_wall(height_mm);
|
profile_wall(height_mm);
|
||||||
|
@ -360,7 +327,7 @@ module block_funnel_outside() {
|
||||||
module block_vase_base() {
|
module block_vase_base() {
|
||||||
difference() {
|
difference() {
|
||||||
// base
|
// base
|
||||||
translate([0,0,-h_base]) {
|
translate([0,0,-BASE_HEIGHT]) {
|
||||||
translate([0,0,-0.1])
|
translate([0,0,-0.1])
|
||||||
color("firebrick")
|
color("firebrick")
|
||||||
block_bottom(d_bottom, gridx, gridy, l_grid);
|
block_bottom(d_bottom, gridx, gridy, l_grid);
|
||||||
|
|
|
@ -263,7 +263,7 @@ module assert_hole_options_valid(hole_options) {
|
||||||
* @brief A single magnet/screw hole. To be cut out of the base.
|
* @brief A single magnet/screw hole. To be cut out of the base.
|
||||||
* @details Supports multiple options that can be mixed and matched.
|
* @details Supports multiple options that can be mixed and matched.
|
||||||
* @pram hole_options @see bundle_hole_options
|
* @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) {
|
module block_base_hole(hole_options, o=0) {
|
||||||
assert_hole_options_valid(hole_options);
|
assert_hole_options_valid(hole_options);
|
||||||
|
@ -280,7 +280,7 @@ module block_base_hole(hole_options, o=0) {
|
||||||
screw_radius = SCREW_HOLE_RADIUS - (o/2);
|
screw_radius = SCREW_HOLE_RADIUS - (o/2);
|
||||||
magnet_radius = MAGNET_HOLE_RADIUS - (o/2);
|
magnet_radius = MAGNET_HOLE_RADIUS - (o/2);
|
||||||
magnet_inner_radius = MAGNET_HOLE_CRUSH_RIB_INNER_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.
|
// If using supportless / printable mode, need to add additional layers, so they can be removed later.
|
||||||
supportless_additional_layers = screw_hole ? 2 : 3;
|
supportless_additional_layers = screw_hole ? 2 : 3;
|
||||||
magnet_depth = MAGNET_HOLE_DEPTH - o +
|
magnet_depth = MAGNET_HOLE_DEPTH - o +
|
||||||
|
|
|
@ -31,7 +31,7 @@ function fromGridfinityUnits(gridfinityUnit, includeLipHeight = false) =
|
||||||
* @returns The final value in mm.
|
* @returns The final value in mm.
|
||||||
*/
|
*/
|
||||||
function includingFixedHeights(mmHeight, includeLipHeight = false) =
|
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.
|
* @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)+7-abs(hf(z,d,l))%7
|
||||||
)
|
)
|
||||||
:hf(z,d,l)
|
:hf(z,d,l)
|
||||||
) -h_base;
|
) - BASE_HEIGHT;
|
||||||
|
|
||||||
// Creates equally divided cutters for the bin
|
// 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
|
// 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) {
|
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)
|
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);
|
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
|
// 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
|
// See cut() module for parameter descriptions
|
||||||
module cut_move(x, y, w, h) {
|
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))
|
cut_move_unsafe(clp(x,0,$gxx), clp(y,0,$gyy), clp(w,0,$gxx-x), clp(h,0,$gyy-y))
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
@ -217,12 +217,12 @@ module cut_move(x, y, w, h) {
|
||||||
// ===== Modules ===== //
|
// ===== 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_size Number of bases in each dimension. [x, y]
|
||||||
* @param grid_dimensions [length, width] of a single Gridfinity base.
|
* @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.
|
* @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 &&
|
assert(is_list(grid_dimensions) && len(grid_dimensions) == 2 &&
|
||||||
grid_dimensions.x > 0 && grid_dimensions.y > 0);
|
grid_dimensions.x > 0 && grid_dimensions.y > 0);
|
||||||
assert(is_list(grid_size) && len(grid_size) == 2 &&
|
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.
|
// Per spec, there's a 0.5mm gap between each base.
|
||||||
// This must be kept constant or half bins may not work correctly.
|
// 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
|
// Divisions per grid
|
||||||
// Normal, half, or quarter grid sizes supported.
|
// Normal, half, or quarter grid sizes supported.
|
||||||
|
@ -249,36 +249,36 @@ 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];
|
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];
|
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 - gap_mm;
|
||||||
|
|
||||||
// Final size of the base top. In mm.
|
// Final size of the base top. In mm.
|
||||||
// subtracting gap_mm here to remove an outer lip along the peremiter.
|
// subtracting gap_mm here to remove an outer lip along the peremiter.
|
||||||
grid_size_mm = [
|
grid_size_mm = [
|
||||||
base_center_distance_mm.x * final_grid_size.x - gap_mm,
|
base_center_distance_mm.x * final_grid_size.x,
|
||||||
base_center_distance_mm.y * final_grid_size.y - gap_mm
|
base_center_distance_mm.y * final_grid_size.y
|
||||||
];
|
] - gap_mm;
|
||||||
|
|
||||||
// Top which ties all bases together
|
// Top which ties all bases together
|
||||||
if (final_cut) {
|
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_OUTSIDE_RADIUS, center=true);
|
rounded_square([grid_size_mm.x, grid_size_mm.y, h_bot], BASE_TOP_RADIUS, center=true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(only_corners) {
|
if(only_corners) {
|
||||||
difference(){
|
difference(){
|
||||||
pattern_linear(final_grid_size.x, final_grid_size.y, base_center_distance_mm.x, base_center_distance_mm.y)
|
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);
|
base_solid(individual_base_size_mm);
|
||||||
|
}
|
||||||
|
|
||||||
copy_mirror([0, 1, 0]) {
|
if(thumbscrew) {
|
||||||
copy_mirror([1, 0, 0]) {
|
thumbscrew_position = grid_size_mm - individual_base_size_mm;
|
||||||
translate([
|
pattern_linear(2, 2, thumbscrew_position.x, thumbscrew_position.y) {
|
||||||
grid_size_mm.x/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE - BASE_PROFILE_MAX.x,
|
_base_thumbscrew();
|
||||||
grid_size_mm.y/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE - BASE_PROFILE_MAX.x,
|
|
||||||
0
|
|
||||||
])
|
|
||||||
block_base_hole(hole_options, off);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_base_holes(hole_options, off, grid_size_mm);
|
||||||
|
_base_preview_fix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -287,82 +287,200 @@ module gridfinityBase(grid_size, grid_dimensions=[l_grid, l_grid], hole_options=
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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(...)`.
|
||||||
|
*/
|
||||||
|
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 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.
|
||||||
|
*/
|
||||||
|
module _base_thumbscrew() {
|
||||||
|
ScrewThread(
|
||||||
|
1.01 * BASE_THUMBSCREW_OUTER_DIAMETER + 1.25 * 0.4,
|
||||||
|
BASE_HEIGHT,
|
||||||
|
BASE_THUMBSCREW_PITCH
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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).
|
* @brief A single Gridfinity base. With holes (if set).
|
||||||
* @param hole_options @see block_base_hole.hole_options
|
* @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 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.
|
* @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) {
|
module block_base(hole_options, offset=0, top_dimensions=BASE_TOP_DIMENSIONS, thumbscrew=false) {
|
||||||
assert(
|
assert(is_list(top_dimensions) && len(top_dimensions) == 2);
|
||||||
is_list(size) &&
|
assert(is_bool(thumbscrew));
|
||||||
len(size) == 2 &&
|
|
||||||
is_bool(thumbscrew)
|
|
||||||
);
|
|
||||||
|
|
||||||
// How far, in the +x direction,
|
base_bottom = base_bottom_dimensions(top_dimensions);
|
||||||
// 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;
|
|
||||||
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
|
|
||||||
thumbscrew_outerdiam = 15;
|
|
||||||
thumbscrew_height = 5;
|
|
||||||
thumbscrew_tolerance = 0.4;
|
|
||||||
thumbscrew_tooth_angle = 30;
|
|
||||||
thumbscrew_pitch = 1.5;
|
|
||||||
|
|
||||||
|
|
||||||
render(convexity = 2)
|
|
||||||
difference() {
|
difference() {
|
||||||
union() {
|
base_solid(top_dimensions);
|
||||||
sweep_rounded(base_profile_size.x, base_profile_size.y)
|
|
||||||
translate([translation_x, 0, 0])
|
|
||||||
polygon(BASE_PROFILE);
|
|
||||||
|
|
||||||
rounded_square(
|
|
||||||
[
|
|
||||||
base_bottom_size.x + TOLLERANCE,
|
|
||||||
base_bottom_size.y + TOLLERANCE,
|
|
||||||
BASE_PROFILE_MAX.y
|
|
||||||
],
|
|
||||||
translation_x,
|
|
||||||
center=true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thumbscrew) {
|
if (thumbscrew) {
|
||||||
ScrewThread(
|
_base_thumbscrew();
|
||||||
1.01 * thumbscrew_outerdiam + 1.25 * thumbscrew_tolerance,
|
|
||||||
thumbscrew_height,
|
|
||||||
thumbscrew_pitch,
|
|
||||||
thumbscrew_tooth_angle,
|
|
||||||
thumbscrew_tolerance,
|
|
||||||
tooth_height=0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// 4 holes
|
_base_holes(hole_options, offset, top_dimensions);
|
||||||
// Need this fancy code to support refined holes and non-square bases.
|
_base_preview_fix();
|
||||||
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));
|
* @brief Outer shell of a Gridfinity base.
|
||||||
translate([
|
* @param wall_thickness How thick the walls are.
|
||||||
i * (base_bottom_size.x/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE),
|
* @param bottom_thickness How thick the bottom is.
|
||||||
j * (base_bottom_size.y/2 - HOLE_DISTANCE_FROM_BOTTOM_EDGE),
|
* @param top_dimensions [x, y] size of a single base. Only set if deviating from the standard!
|
||||||
0])
|
*/
|
||||||
rotate([0, 0, a])
|
module base_outer_shell(wall_thickness, bottom_thickness, top_dimensions=BASE_TOP_DIMENSIONS) {
|
||||||
block_base_hole(hole_options, off);
|
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.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,13 +565,13 @@ module profile_wall2(height_mm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module block_wall(gx, gy, l) {
|
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)
|
sweep_rounded([gx*l-2*r_base-0.5-0.001, gy*l-2*r_base-0.5-0.001])
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
||||||
module block_bottom( h = 2.2, gx, gy, l ) {
|
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);
|
rounded_rectangle(gx*l-0.5-d_wall/4, gy*l-0.5-d_wall/4, h, r_base+0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +597,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;
|
ycutlast = abs(y+h-$gyy)<0.001 && $style_lip == 0;
|
||||||
xcutfirst = x == 0 && $style_lip == 0;
|
xcutfirst = x == 0 && $style_lip == 0;
|
||||||
xcutlast = abs(x+w-$gxx)<0.001 && $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;
|
ylen = h*($gyy*l_grid+d_magic)/$gyy-d_div;
|
||||||
xlen = w*($gxx*l_grid+d_magic)/$gxx-d_div;
|
xlen = w*($gxx*l_grid+d_magic)/$gxx-d_div;
|
||||||
|
@ -491,7 +609,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;
|
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);
|
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]) {
|
rotate([90,0,-90]) {
|
||||||
|
|
||||||
if (!zsmall && xlen - tab_width > 4*r_f2 && (t != 0 && t != 5)) {
|
if (!zsmall && xlen - tab_width > 4*r_f2 && (t != 0 && t != 5)) {
|
||||||
|
|
|
@ -3,9 +3,16 @@
|
||||||
r_c1 = 0.8;
|
r_c1 = 0.8;
|
||||||
// bottom thiccness of bin
|
// bottom thiccness of bin
|
||||||
h_bot = 2.2;
|
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
|
// Outside rounded radius of bin
|
||||||
// Per spec, matches radius of upper base section.
|
// 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.
|
* @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, 0], // Inner tip
|
||||||
[0.7, 0.7], // Go out 45 degrees
|
[0.7, 0.7], // Go out 45 degrees
|
||||||
[0.7, (0.7+1.8)], // Vertical increase
|
[0.7, (0.7+1.8)], // Vertical increase
|
||||||
|
@ -110,7 +118,7 @@ RAW_STACKING_LIP = [
|
||||||
* Including wall thickness.
|
* Including wall thickness.
|
||||||
* "y": The height of the stacking lip.
|
* "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;
|
_stacking_lip_support_angle = 45;
|
||||||
|
|
||||||
|
@ -123,42 +131,78 @@ _stacking_lip_support_height_mm =
|
||||||
+ tan(90 - _stacking_lip_support_angle) * STACKING_LIP_SIZE.x;
|
+ 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.
|
* @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
|
[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, -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
|
// Base constants
|
||||||
// Based on https://gridfinity.xyz/specification/
|
// 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 = [
|
BASE_PROFILE = [
|
||||||
[0, 0], // Innermost bottom point
|
[0, 0], // Innermost bottom point
|
||||||
[0.8, 0.8], // Up and out at a 45 degree angle
|
[0.8, 0.8], // Up and out at a 45 degree angle
|
||||||
[0.8, (0.8+1.8)], // Straight up
|
[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.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
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Maximum [x,y] values/size of the base.
|
/**
|
||||||
BASE_PROFILE_MAX = BASE_PROFILE[3];
|
* @Summary Corner radius of the top of the base.
|
||||||
|
*/
|
||||||
// Each unit's base is 41.5mm x 41.5mm
|
BASE_TOP_RADIUS = r_base;
|
||||||
// Leaving 0.5mm gap with an l_grid of 42
|
|
||||||
BASE_SIZE = 41.5;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Height of the raw 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
|
||||||
*/
|
*/
|
||||||
h_base = BASE_PROFILE_MAX.y;
|
BASE_TOP_DIMENSIONS = [41.5, 41.5];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Summary Maximum [x,y] values/size of the base.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* 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];
|
||||||
|
|
||||||
|
// ***************
|
||||||
|
// Gridfinity Refined Thumbscrew
|
||||||
|
// See https://www.printables.com/model/413761-gridfinity-refined
|
||||||
|
// ***************
|
||||||
|
|
||||||
|
BASE_THUMBSCREW_OUTER_DIAMETER=15;
|
||||||
|
BASE_THUMBSCREW_PITCH=1.5;
|
||||||
|
|
||||||
// ****************************************
|
// ****************************************
|
||||||
// Baseplate constants
|
// Baseplate constants
|
||||||
|
@ -174,7 +218,7 @@ BASEPLATE_LIP = [
|
||||||
[0.7, (0.7+1.8)], // Straight up
|
[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.7+1.8+2.15)], // Up and out at a 45 degree angle
|
||||||
[(0.7+2.15), 0], // Straight down
|
[(0.7+2.15), 0], // Straight down
|
||||||
[0, 0] //Back to start
|
//[0, 0] // Implicit back to start
|
||||||
];
|
];
|
||||||
|
|
||||||
// Height of the baseplate lip.
|
// Height of the baseplate lip.
|
||||||
|
|
|
@ -174,12 +174,33 @@ function affine_scale(vector) = [
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a rectangle with rounded corners by sweeping a 2d object along a path.
|
* @brief Add something to each element in a list.
|
||||||
* Centered on origin.
|
* @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.
|
||||||
*/
|
*/
|
||||||
module sweep_rounded(width=10, length=10) {
|
function foreach_add(list, to_add) =
|
||||||
assert(width > 0 && length > 0);
|
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.
|
||||||
|
* 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(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_width = width/2;
|
||||||
half_length = length/2;
|
half_length = length/2;
|
||||||
path_points = [
|
path_points = [
|
||||||
|
|
Loading…
Reference in a new issue