| 1 | /* |
| 2 | GNU AGPLv3 (or later at your option) |
| 3 | see bottom for more license info. |
| 4 | please do not remove this notice. |
| 5 | */ |
| 6 | |
| 7 | ones_place(); |
| 8 | //tens_place(); |
| 9 | //hundreds_place(); |
| 10 | //thousands_place(); |
| 11 | |
| 12 | // use this while editing so previewing is faster: |
| 13 | //$fn = 30; |
| 14 | // use this for generating STL so model is more accurate: |
| 15 | $fn = 100; |
| 16 | |
| 17 | // how big each ones place side is in millimeters |
| 18 | side_length = 10; |
| 19 | |
| 20 | // modify this to your aesthetic taste |
| 21 | corner_radius = side_length / 6; |
| 22 | |
| 23 | connector_thickness = side_length / 4; |
| 24 | |
| 25 | fudge = 0.1; |
| 26 | |
| 27 | module fillet(r) { |
| 28 | offset(-r) { offset(r) { children(); } } } |
| 29 | |
| 30 | module round_inside_corners(r) { |
| 31 | fillet(r) children(); } |
| 32 | |
| 33 | module round_outside_corners(r) { |
| 34 | fillet(-r) children(); } |
| 35 | |
| 36 | module connector_base(connector_thickness) { |
| 37 | rotate([0, -90, -90]) { |
| 38 | translate([corner_radius / 2, 0, 0]) { |
| 39 | linear_extrude(height = connector_thickness) { |
| 40 | intersection() { |
| 41 | circle(corner_radius, $fn = 3); |
| 42 | translate([-corner_radius, -corner_radius]) { |
| 43 | square([corner_radius, 2 * corner_radius]); } } |
| 44 | round_outside_corners(corner_radius / 3) { |
| 45 | circle(corner_radius, $fn = 3); } } } } } |
| 46 | |
| 47 | module ones_place() { |
| 48 | difference() { |
| 49 | linear_extrude(height = side_length) { |
| 50 | round_outside_corners(corner_radius) { |
| 51 | square(side_length); } } |
| 52 | translate([side_length / 2, -0.1, -0.1]) { |
| 53 | connector_base(connector_thickness); } |
| 54 | translate([side_length / 2, |
| 55 | side_length - connector_thickness + fudge, |
| 56 | -fudge]) { |
| 57 | connector_base(connector_thickness); } } |
| 58 | translate([side_length / 2, |
| 59 | 0, |
| 60 | side_length - 3 * fudge]) { |
| 61 | connector_base(connector_thickness - 3 * fudge); } |
| 62 | translate([side_length / 2, |
| 63 | side_length - connector_thickness + 3 * fudge, |
| 64 | side_length - 3 * fudge]) { |
| 65 | connector_base(connector_thickness - 3 * fudge); } } |
| 66 | |
| 67 | module tens_place() { |
| 68 | for(ones_index = [0 : (10 - 1)]) { |
| 69 | translate([ones_index * side_length, 0]) { |
| 70 | ones_place(); } } } |
| 71 | |
| 72 | module hundreds_place() { |
| 73 | for(tens_index = [0 : (10 - 1)]) { |
| 74 | for(ones_index = [0 : (10 - 1)]) { |
| 75 | translate([ones_index * side_length, |
| 76 | tens_index * side_length]) { |
| 77 | ones_place(); } } } } |
| 78 | |
| 79 | module thousands_place() { |
| 80 | for(hundreds_index = [0 : (10 - 1)]) { |
| 81 | for(tens_index = [0 : (10 - 1)]) { |
| 82 | for(ones_index = [0 : (10 - 1)]) { |
| 83 | translate([ones_index * side_length, |
| 84 | tens_index * side_length, |
| 85 | hundreds_index * side_length]) { |
| 86 | ones_place(); } } } } } |
| 87 | |
| 88 | |
| 89 | |
| 90 | //connector_base(connector_thickness); |