epsilon = 0.01; but_top_x = 10; but_top_y = but_top_x+5; but_top_z = 1.5; but_corner_r = 2; but_base_border = 1; but_base_x = but_top_x+2*but_base_border; but_base_y = but_top_y+2*but_base_border; but_base_z = 0.5; but_fillet_r = 0.4; but_chamfer_r = 0.2; $fn = 40; /* ----- Basic solids ------------------------------------------------------ */ module torus(r0, r1) { rotate_extrude() translate([r0, 0, 0]) circle(r = r1); } /* ----- Helper elements for fillets --------------------------------------- */ module fillet_line(x, r) { translate([-x/2, 0, 0]) difference() { cube([x, r, r]); translate([0, r, r]) rotate([0, 90, 0]) translate([0, 0, -epsilon]) cylinder(h = x+2*epsilon, r = r); } } module fillet_circle(r, fillet_r) { difference() { cylinder(h = fillet_r, r = r+fillet_r); translate([0, 0, fillet_r]) torus(r+fillet_r, fillet_r); } } /* ----- Helper elements for chamfers -------------------------------------- */ module chamfer_line(x, r) { translate([-x/2, -r, -r]) difference() { cube([x, r+epsilon, r+epsilon]); rotate([0, 90, 0]) translate([0, 0, -epsilon]) cylinder(h = x+2*epsilon, r = r); } } module chamfer_circle(r, fillet_r) { difference() { translate([-r-epsilon, -r-epsilon, -fillet_r]) cube([2*(r+epsilon), 2*(r+epsilon), fillet_r+epsilon]); translate([0, 0, -fillet_r]) cylinder(h = fillet_r, r = r-fillet_r); translate([0, 0, -fillet_r]) torus(r-fillet_r, fillet_r); } } /* ----- Box with rounded corners ------------------------------------------ */ module rbox_core(x, y, z, r) { union() { translate([0, 0, z/2]) cube([x-2*r, y, z], center = true); translate([0, 0, z/2]) cube([x, y-2*r, z], center = true); } } module rbox(x, y, z, r) { union() { rbox_core(x, y, z, r); for (dx = [-1, 1]) { for (dy = [-1, 1]) { translate([dx*(x/2-r), dy*(y/2-r), 0]) cylinder(h = z, r = r); } } } } module rbox_fillet_bottom(x, y, z, r, fillet_r) { union() { for (a = [0, 180]) { rotate([0, 0, a]) translate([0, y/2, 0]) fillet_line(x-2*r, fillet_r); rotate([0, 0, a+90]) translate([0, x/2, 0]) fillet_line(y-2*r, fillet_r); } for (dx = [-1, 1]) { for (dy = [-1, 1]) { translate([dx*(x/2-r), dy*(y/2-r), 0]) fillet_circle(r, fillet_r); } } } } module rbox_chamfer_top_corners(x, y, z, r, chamfer_r) { difference() { union() { for (dx = [-1, 1]) { for (dy = [-1, 1]) { translate([dx*(x/2-r), dy*(y/2-r), z]) chamfer_circle(r, chamfer_r); } } } rbox_core(x-epsilon, y-epsilon, z, r); } } module rbox_chamfer_top(x, y, z, r, chamfer_r) { union() { for (a = [0, 180]) { rotate([0, 0, a]) translate([0, y/2, z]) chamfer_line(x-2*r, chamfer_r); rotate([0, 0, a+90]) translate([0, x/2, z]) chamfer_line(y-2*r, chamfer_r); } rbox_chamfer_top_corners(x, y, z, r, chamfer_r); } } module rbox_chamfer_bottom(x, y, z, r, chamfer_r) { rotate([180, 0, 0]) translate([0, 0, -z]) rbox_chamfer_top(x, y, z, r, chamfer_r); } /* ----- Button ------------------------------------------------------------ */ module button_top() { union() { difference() { rbox(but_top_x, but_top_y, but_top_z, but_corner_r); rbox_chamfer_top(but_top_x, but_top_y, but_top_z, but_corner_r, but_chamfer_r); } rbox_fillet_bottom(but_top_x, but_top_y, but_top_z, but_corner_r, but_fillet_r); } } module button_base() { translate([0, 0, -but_base_z]) difference() { rbox(but_base_x, but_base_y, but_base_z, but_corner_r); rbox_chamfer_top(but_base_x, but_base_y, but_base_z, but_corner_r, but_chamfer_r); rbox_chamfer_bottom(but_base_x, but_base_y, but_base_z, but_corner_r, but_chamfer_r); } } module button() { union() { button_top(); button_base(); } } button();