feat: support crosshair base for single magnet

This commit is contained in:
pimlie 2024-07-28 14:48:33 +02:00
parent 3f2c6e28c5
commit f8a623d6b4
4 changed files with 83 additions and 34 deletions

View file

@ -48,12 +48,15 @@ fity = 0; // [-1:0.1:1]
/* [Styles] */
// baseplate styles
style_plate = 0; // [0: thin, 1:weighted, 2:skeletonized, 3: screw together, 4: screw together minimal]
style_plate = 0; // [0: thin, 1:weighted, 2:skeletonized, 3: screw together, 4: screw together minimal, 5:crosshair, 6:screw together crosshair]
// hole styles
style_hole = 2; // [0:none, 1:countersink, 2:counterbore]
// spoke width of crosshair
spoke_width = 3; // [2:1:24]
/* [Magnet Hole] */
// Baseplate will have holes for 6mm Diameter x 2mm high magnets.
enable_magnet = true;
@ -64,12 +67,12 @@ chamfer_holes = true;
hole_options = bundle_hole_options(refined_hole=false, magnet_hole=enable_magnet, screw_hole=false, crush_ribs=crush_ribs, chamfer=chamfer_holes, supportless=false);
// ===== IMPLEMENTATION ===== //
color("tomato")
gridfinityBaseplate(gridx, gridy, l_grid, distancex, distancey, style_plate, hole_options, style_hole, fitx, fity);
// ===== CONSTRUCTION ===== //
module gridfinityBaseplate(gridx, gridy, length, dix, diy, sp, hole_options, sh, fitx, fity) {
@ -109,9 +112,12 @@ module gridfinityBaseplate(gridx, gridy, length, dix, diy, sp, hole_options, sh,
else if (sp == 4)
translate([0,0,-5*(h_base+off)])
rounded_square(length-2*r_c2-2*r_c1, 10*(h_base+off), r_fo3);
else if (sp == 5 || sp == 6)
linear_extrude(10*(h_base+off), center = true)
profile_crosshair();
hole_pattern(){
single_hole=sp==5||sp==6;
hole_pattern(l=l_grid, single_hole){
mirror([0, 0, 1])
block_base_hole(hole_options);
@ -121,15 +127,14 @@ module gridfinityBaseplate(gridx, gridy, length, dix, diy, sp, hole_options, sh,
}
}
}
screw_together = sp == 3 || sp == 4;
screw_together = sp == 3 || sp == 4 || sp == 6;
if (screw_together) cutter_screw_together(gx, gy, off);
}
}
function calculate_offset(style_plate, enable_magnet, style_hole) =
assert(style_plate >=0 && style_plate <=4)
let (screw_together = style_plate == 3 || style_plate == 4)
assert(style_plate >= 0 && style_plate <= 6)
let (screw_together = style_plate == 3 || style_plate == 4 || style_plate == 6)
screw_together ? 6.75 :
style_plate==0 ? 0 :
style_plate==1 ? bp_h_bot :
@ -157,13 +162,6 @@ module cutter_weight() {
}
}
}
module hole_pattern(){
pattern_circular(4)
translate([l_grid/2-d_hole_from_side, l_grid/2-d_hole_from_side, 0]) {
render();
children();
}
}
module cutter_countersink(){
screw_hole(SCREW_HOLE_RADIUS + d_clear, 2*h_base,
@ -198,6 +196,27 @@ module profile_skeleton() {
}
}
module profile_crosshair() {
l_grid_inner = l_grid - 2*r_c2 - 2*r_c1; // l without chamfers
l_grid_inner_minkowski = l_grid_inner / 2 - r_f1;
// sqrt 2 because of 45 degree angle
spoke_offset=sqrt(2)*spoke_width/2;
pattern_circular(4)
difference() {
minkowski() {
polygon([
[spoke_offset, 0],
[l_grid_inner_minkowski, l_grid_inner_minkowski - spoke_offset],
[l_grid_inner_minkowski, -l_grid_inner_minkowski + spoke_offset],
]);
circle(r_f1);
}
circle(MAGNET_HOLE_RADIUS+r_skel);
}
}
module cutter_screw_together(gx, gy, off) {
screw(gx, gy);

View file

@ -78,6 +78,8 @@ scoop = 1; //[0:0.1:1]
div_base_x = 0;
// number of divisions per 1 unit of base along the Y axis. (default 1, only use integers. 0 means automatically guess the right division)
div_base_y = 0;
// Base will have a single hole in the center (use with crosshair style base)
single_hole = false;
/* [Base Hole Options] */
// only cut magnet/screw holes at the corners of the bin to save uneccesary print time
@ -111,7 +113,7 @@ gridfinityInit(gridx, gridy, height(gridz, gridz_define, style_lip, enable_zsnap
cutCylinders(n_divx=cdivx, n_divy=cdivy, cylinder_diameter=cd, cylinder_height=ch, coutout_depth=c_depth, orientation=c_orientation, chamfer=c_chamfer);
}
}
gridfinityBase(gridx, gridy, l_grid, div_base_x, div_base_y, hole_options, only_corners=only_corners);
gridfinityBase(gridx, gridy, l_grid, div_base_x, div_base_y, hole_options, only_corners=only_corners, single_hole=single_hole);
}

View file

@ -210,7 +210,7 @@ module profile_base() {
]);
}
module gridfinityBase(gx, gy, l, dx, dy, hole_options=bundle_hole_options(), off=0, final_cut=true, only_corners=false) {
module gridfinityBase(gx, gy, l, dx, dy, hole_options=bundle_hole_options(), off=0, final_cut=true, only_corners=false, single_hole=false) {
dbnxt = [for (i=[1:5]) if (abs(gx*i)%1 < 0.001 || abs(gx*i)%1 > 0.999) i];
dbnyt = [for (i=[1:5]) if (abs(gy*i)%1 < 0.001 || abs(gy*i)%1 > 0.999) i];
dbnx = 1/(dx==0 ? len(dbnxt) > 0 ? dbnxt[0] : 1 : round(dx));
@ -218,25 +218,27 @@ module gridfinityBase(gx, gy, l, dx, dy, hole_options=bundle_hole_options(), off
xx = gx*l-0.5;
yy = gy*l-0.5;
if (final_cut)
if (final_cut) {
translate([0,0,h_base])
rounded_rectangle(xx+0.002, yy+0.002, h_bot/1.5, r_fo1+0.001);
}
intersection(){
if (final_cut)
if (final_cut) {
translate([0,0,-1])
rounded_rectangle(xx+0.005, yy+0.005, h_base+h_bot/2*10, r_fo1+0.001);
}
if(only_corners) {
difference(){
pattern_linear(gx/dbnx, gy/dbny, dbnx*l, dbny*l)
block_base(gx, gy, l, dbnx, dbny, 0, off);
block_base(gx, gy, l, dbnx, dbny, [], off);
copy_mirror([0, 1, 0]) {
copy_mirror([1, 0, 0]) {
translate([
(gx/2)*l_grid - d_hole_from_side,
(gy/2) * l_grid - d_hole_from_side,
(gx/2)*l_grid - (single_hole ? l_grid/2 : d_hole_from_side),
(gy/2)*l_grid - (single_hole ? l_grid/2 : d_hole_from_side),
0
])
block_base_hole(hole_options, off);
@ -246,11 +248,27 @@ module gridfinityBase(gx, gy, l, dx, dy, hole_options=bundle_hole_options(), off
}
else {
pattern_linear(gx/dbnx, gy/dbny, dbnx*l, dbny*l)
block_base(gx, gy, l, dbnx, dbny, hole_options, off);
block_base(gx, gy, l, dbnx, dbny, hole_options, off, single_hole=single_hole);
}
}
}
/**
* @brief Apply hole pattern to children
* @param l
* @param single_hole Use a single hole, default = false
*/
module hole_pattern(l, single_hole=false){
hole_offset = single_hole ? 0 : l/2 - d_hole_from_side;
steps= (single_hole || abs(l - d_hole_from_side/2) < 0.001) ? 1 : 4;
pattern_circular(steps)
translate([hole_offset, hole_offset, 0]) {
render();
children();
}
}
/**
* @brief A single Gridfinity base. With holes (if set).
* @param gx
@ -261,15 +279,15 @@ module gridfinityBase(gx, gy, l, dx, dy, hole_options=bundle_hole_options(), off
* @param hole_options @see block_base_hole.hole_options
* @param off
*/
module block_base(gx, gy, l, dbnx, dbny, hole_options, off) {
module block_base(gx, gy, l, dbnx, dbny, hole_options, off, single_hole=false) {
render(convexity = 2)
difference() {
block_base_solid(dbnx, dbny, l, off);
pattern_circular(abs(l-d_hole_from_side/2)<0.001?1:4)
translate([l/2-d_hole_from_side, l/2-d_hole_from_side, 0])
hole_pattern(l, single_hole=single_hole) {
block_base_hole(hole_options, off);
}
}
}
/**

View file

@ -111,6 +111,16 @@ class TestBasePlateHoles(unittest.TestCase):
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
self.scad_runner.create_image([], Path('magnet_and_counterbored_screw_holes_top.png'))
def test_crosshair_with_magnet(self):
vars = self.scad_runner.parameters
vars["enable_magnet"] = True
vars["chamfer_holes"] = False
vars["crush_ribs"] = False
vars["style_plate"] = 5
self.scad_runner.create_image([], Path('crosshair_with_magnet_bottom.png'))
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
self.scad_runner.create_image([], Path('crosshair_with_magnet_top.png'))
if __name__ == '__main__':
unittest.main()