1 module cartridge() 2 { 3 $fn = 50; 4 5 /* Rounding/fillet radius and additional margin of subtracted 6 material. The additional margin helps avoid geometry 7 problems. */ 8 9 rr = 1; 10 ro = rr; 11 extra = 0.1; 12 13 module fillet(r, h) { 14 translate([0, 0, -h/2]) 15 difference() { 16 cube([r + extra, r + extra, h]); 17 cylinder(r = r, h = h); 18 } 19 } 20 21 /* Cartridge dimensions. */ 22 23 width = 89.0; 24 height = 68.5; 25 depth = 16.5; 26 front_depth = 6.5; 27 back_depth = 11.0; 28 29 /* Details. */ 30 31 front_label_width = 83.0; 32 front_label_height = 46.0; 33 front_label_depth = 1.0; 34 front_label_offset_from_bottom = 19.5; 35 36 top_label_width = front_label_width; 37 top_label_height = 11.5; 38 top_label_depth = front_label_depth; 39 top_label_offset_from_front = 2.5; 40 41 groove_width = 2.5; /* how much the groove cuts out of the back */ 42 groove_depth = 1.0; /* how deep the groove goes into each side */ 43 top_groove_width = 1.0; 44 top_groove_depth = 2.0; 45 46 back_cavity_width = 68.0; 47 back_cavity_inner_width = 65.0; 48 back_cavity_offset_from_left = 10.5; 49 back_cavity_inner_offset_from_left = 12.0; 50 back_cavity_height = 13.5; 51 back_cavity_inner_height = 12.0; 52 back_cavity_depth = 1.5; 53 54 inner_back_cavity_offset = 1.0; 55 inner_back_cavity_offset_from_left = 2.0; 56 inner_back_slope_offset_from_left = 10.0; 57 inner_back_slope_width = 2.5; 58 inner_back_slope_depth = 2.5; 59 60 inner_back_edge_offset = 2.0; 61 inner_back_edge_width = 69.0; 62 inner_back_edge_height = 3.0; 63 inner_back_edge_depth = 1.5; 64 65 inner_front_edge_offset = 0.5; 66 inner_front_edge_width = 87.0; 67 inner_front_edge_height = 3.0; 68 inner_front_edge_depth = 1.5; 69 70 bottom_from_base = 13.5; 71 72 edge_connector_cutout_front_offset = 1.0; 73 edge_connector_cutout_front_depth = 1.0; 74 edge_connector_cutout_front_width = 15.0; 75 edge_connector_cutout_back_depth = 3.0; 76 edge_connector_cutout_back_width = 57.0; 77 78 /* Side thicknesses. */ 79 80 front = 2; 81 back = 3.5; 82 top = 3; 83 front_left = 1; 84 front_right = 1; 85 back_left = 2; 86 back_right = 2; 87 bottom = 2; 88 89 difference() { 90 91 /* The cartridge surfaces. */ 92 93 union() { 94 95 /* Front portion. */ 96 97 translate([0, -front_depth + front / 2, 0]) 98 cube([width, front, height], center = true); 99 translate([-width / 2 + front_left / 2, -front_depth / 2, 0]) 100 cube([front_left, front_depth, height], center = true); 101 translate([width / 2 - front_right / 2, -front_depth / 2, 0]) 102 cube([front_right, front_depth, height], center = true); 103 translate([0, -front_depth / 2, height / 2 - top / 2]) 104 cube([width, front_depth, top], center = true); 105 difference() { 106 translate([0, -front_depth / 2, 107 -height / 2 + bottom / 2 + bottom_from_base]) 108 cube([width, front_depth, bottom], center = true); 109 translate([-width / 2 + edge_connector_cutout_front_offset + 110 edge_connector_cutout_front_width / 2, 111 -edge_connector_cutout_front_depth / 2, 112 -height / 2 + bottom / 2 + bottom_from_base]) 113 cube([edge_connector_cutout_front_width, 114 edge_connector_cutout_front_depth, 115 bottom + extra], center = true); 116 translate([width / 2 - edge_connector_cutout_front_offset - 117 edge_connector_cutout_front_width / 2, 118 -edge_connector_cutout_front_depth / 2, 119 -height / 2 + bottom / 2 + bottom_from_base]) 120 cube([edge_connector_cutout_front_width, 121 edge_connector_cutout_front_depth, 122 bottom + extra], center = true); 123 } 124 125 /* Back portion. */ 126 127 translate([0, back_depth - back / 2, 0]) 128 cube([width, back, height], center = true); 129 translate([-width / 2 + back_left / 2, back_depth / 2, 0]) 130 cube([back_left, back_depth, height], center = true); 131 translate([width / 2 - back_right / 2, back_depth / 2, 0]) 132 cube([back_right, back_depth, height], center = true); 133 translate([0, back_depth / 2, height / 2 - top / 2]) 134 cube([width, back_depth, top], center = true); 135 difference() { 136 translate([0, back_depth / 2, 137 -height / 2 + bottom / 2 + bottom_from_base]) 138 cube([width, back_depth, bottom], center = true); 139 translate([0, edge_connector_cutout_back_depth / 2, 140 -height / 2 + bottom / 2 + bottom_from_base]) 141 cube([edge_connector_cutout_back_width, 142 edge_connector_cutout_back_depth, 143 bottom + extra], center = true); 144 } 145 } 146 147 /* Label insets. */ 148 149 union() { 150 151 /* Front label. */ 152 153 translate([-front_label_width / 2, -front_depth, 154 front_label_offset_from_bottom - height / 2]) 155 cube([front_label_width, front_label_depth, 156 front_label_height]); 157 158 /* Top label. */ 159 160 translate([-top_label_width / 2, 161 -front_depth + top_label_offset_from_front, 162 height / 2 - top_label_depth]) 163 cube([top_label_width, top_label_height, 164 top_label_depth]); 165 } 166 167 /* Top and side grooves, positioned in the back portion. */ 168 169 union() { 170 171 /* Left groove. */ 172 173 translate([-width / 2 + groove_depth / 2, groove_width / 2, 0]) 174 cube([groove_depth, groove_width, height], 175 center = true); 176 177 /* Right groove. */ 178 179 translate([width / 2 - groove_depth / 2, groove_width / 2, 0]) 180 cube([groove_depth, groove_width, height], 181 center = true); 182 183 /* Top grooves. */ 184 185 translate([0, groove_width / 2, height / 2 - groove_depth / 2]) 186 cube([width, groove_width, groove_depth], 187 center = true); 188 189 translate([0, top_groove_width / 2, 190 height / 2 - top_groove_depth / 2]) 191 cube([width, top_groove_width, top_groove_depth], 192 center = true); 193 } 194 195 /* Back cavity. */ 196 197 intersection() { 198 199 /* From the bottom upwards. */ 200 201 translate([0, back_depth, -height / 2]) 202 linear_extrude(height = back_cavity_height) 203 translate([-width / 2, 0, 0]) 204 polygon([ 205 [back_cavity_offset_from_left, 0], 206 [back_cavity_inner_offset_from_left, 207 -back_cavity_depth], 208 [back_cavity_inner_offset_from_left + 209 back_cavity_inner_width, 210 -back_cavity_depth], 211 [back_cavity_offset_from_left + 212 back_cavity_width, 0] 213 ]); 214 215 /* From left to right. */ 216 217 translate([back_cavity_width / 2, back_depth, -height / 2]) 218 rotate([0, -90, 0]) 219 linear_extrude(height = back_cavity_width) 220 polygon([ 221 [-extra, -back_cavity_depth], 222 [back_cavity_inner_height, 223 -back_cavity_depth], 224 [back_cavity_height, 0], 225 [-extra, 0] 226 ]); 227 } 228 229 /* Inner back cavities. */ 230 231 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 232 linear_extrude(height = bottom_from_base) 233 translate([-width / 2, 0, 0]) 234 polygon([ 235 [inner_back_cavity_offset_from_left, 0], 236 [inner_back_slope_offset_from_left, 0], 237 [inner_back_slope_offset_from_left + 238 inner_back_slope_width, 239 -inner_back_slope_depth], 240 [inner_back_cavity_offset_from_left, 241 -inner_back_slope_depth] 242 ]); 243 244 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 245 linear_extrude(height = bottom_from_base) 246 translate([-width / 2, 0, 0]) 247 polygon([ 248 [width - inner_back_slope_offset_from_left, 0], 249 [width - inner_back_cavity_offset_from_left, 0], 250 [width - inner_back_cavity_offset_from_left, 251 -inner_back_slope_depth], 252 [width - inner_back_slope_offset_from_left - 253 inner_back_slope_width, 254 -inner_back_slope_depth] 255 ]); 256 257 /* Inner back edge cavity. */ 258 259 translate([inner_back_edge_width / 2, 260 back_depth - inner_back_edge_offset, -height / 2]) 261 rotate([0, -90, 0]) 262 linear_extrude(height = inner_back_edge_width) 263 polygon([ 264 [-extra, -inner_back_edge_depth], 265 [inner_back_edge_height, -inner_back_edge_depth], 266 [0, 0], 267 [-extra, 0] 268 ]); 269 270 /* Inner front edge cavity. */ 271 272 translate([inner_front_edge_width / 2, 273 -front_depth + inner_front_edge_offset, -height / 2]) 274 rotate([0, -90, 0]) 275 linear_extrude(height = inner_front_edge_width) 276 polygon([ 277 [-extra, 0], 278 [0, 0], 279 [inner_front_edge_height, inner_front_edge_depth], 280 [-extra, inner_front_edge_depth], 281 ]); 282 283 /* Fillets to round off the edges. */ 284 285 union() { 286 287 /* Top left and right rounding. */ 288 289 translate([-width / 2 + ro, 0, height / 2 - ro]) 290 rotate([0, 0, 180]) 291 rotate([90, 0, 0]) 292 fillet(rr, depth); 293 translate([width / 2 - ro, 0, height / 2 - ro]) 294 rotate([90, 0, 0]) 295 fillet(rr, depth); 296 297 /* Top back and front rounding. */ 298 299 translate([0, back_depth - ro, height / 2 - ro]) 300 rotate([0, -90, 0]) 301 fillet(rr, width); 302 translate([0, -front_depth + ro, height / 2 - ro]) 303 rotate([0, 0, 180]) 304 rotate([0, -90, 0]) 305 fillet(rr, width); 306 307 /* Edge rounding. */ 308 309 translate([width / 2 - ro, back_depth - ro, 0]) 310 fillet(rr, height); 311 translate([-width / 2 + ro, back_depth - ro, 0]) 312 rotate([0, 0, 90]) 313 fillet(rr, height); 314 translate([-width / 2 + ro, -front_depth + ro, 0]) 315 rotate([0, 0, 180]) 316 fillet(rr, height); 317 translate([width / 2 - ro, -front_depth + ro, 0]) 318 rotate([0, 0, 270]) 319 fillet(rr, height); 320 } 321 } 322 } 323 324 cartridge(); 325