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 + extra]); 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 inner_top_front_cutout_width = 87.0; 46 inner_top_front_cutout_depth = 1.0; 47 inner_top_front_cutout_offset = 2.0; 48 49 back_cavity_width = 68.0; 50 back_cavity_inner_width = 65.0; 51 back_cavity_offset_from_left = 10.5; 52 back_cavity_inner_offset_from_left = 12.0; 53 back_cavity_height = 13.5; 54 back_cavity_inner_height = 12.0; 55 back_cavity_depth = 1.5; 56 57 inner_back_cavity_offset = 1.0; 58 inner_back_cavity_offset_from_left = 2.0; 59 inner_back_slope_offset_from_left = 10.0; 60 inner_back_slope_width = 2.5; 61 inner_back_slope_depth = 2.5; 62 63 inner_back_edge_offset = 2.0; 64 inner_back_edge_width = 69.0; 65 inner_back_edge_height = 3.0; 66 inner_back_edge_depth = 1.5; 67 68 inner_front_edge_offset = 0.5; 69 inner_front_edge_width = 87.0; 70 inner_front_edge_height = 3.0; 71 inner_front_edge_depth = 1.5; 72 73 bottom_from_base = 13.5; 74 75 edge_connector_cutout_front_offset = 1.0; 76 edge_connector_cutout_front_depth = 1.0; 77 edge_connector_cutout_front_width = 15.0; 78 edge_connector_cutout_back_depth = 3.0; 79 edge_connector_cutout_back_width = 57.0; 80 81 /* Side thicknesses. */ 82 83 front = 2; 84 back = 3.5; 85 top = 3; 86 front_left = 1; 87 front_right = 1; 88 back_left = 2; 89 back_right = 2; 90 bottom = 2; 91 92 difference() { 93 94 /* The cartridge surfaces. */ 95 96 union() { 97 98 /* Front portion. */ 99 100 translate([0, -front_depth + front / 2, 0]) 101 cube([width, front, height], center = true); 102 translate([-width / 2 + front_left / 2, -front_depth / 2, 0]) 103 cube([front_left, front_depth, height], center = true); 104 translate([width / 2 - front_right / 2, -front_depth / 2, 0]) 105 cube([front_right, front_depth, height], center = true); 106 translate([0, -front_depth / 2, height / 2 - top / 2]) 107 cube([width, front_depth, top], center = true); 108 difference() { 109 translate([0, -front_depth / 2, 110 -height / 2 + bottom / 2 + bottom_from_base]) 111 cube([width, front_depth, bottom], center = true); 112 translate([-width / 2 + edge_connector_cutout_front_offset + 113 edge_connector_cutout_front_width / 2, 114 -edge_connector_cutout_front_depth / 2, 115 -height / 2 + bottom / 2 + bottom_from_base]) 116 cube([edge_connector_cutout_front_width, 117 edge_connector_cutout_front_depth, 118 bottom + extra], center = true); 119 translate([width / 2 - edge_connector_cutout_front_offset - 120 edge_connector_cutout_front_width / 2, 121 -edge_connector_cutout_front_depth / 2, 122 -height / 2 + bottom / 2 + bottom_from_base]) 123 cube([edge_connector_cutout_front_width, 124 edge_connector_cutout_front_depth, 125 bottom + extra], center = true); 126 } 127 } 128 129 /* Label insets. */ 130 131 union() { 132 133 /* Front label. */ 134 135 translate([-front_label_width / 2, -front_depth, 136 front_label_offset_from_bottom - height / 2]) 137 cube([front_label_width, front_label_depth, 138 front_label_height]); 139 140 /* Top label. */ 141 142 translate([-top_label_width / 2, 143 -front_depth + top_label_offset_from_front, 144 height / 2 - top_label_depth]) 145 cube([top_label_width, top_label_height, 146 top_label_depth]); 147 } 148 149 /* Inner front edge cavity. */ 150 151 translate([inner_front_edge_width / 2, 152 -front_depth + inner_front_edge_offset, -height / 2]) 153 rotate([0, -90, 0]) 154 linear_extrude(height = inner_front_edge_width) 155 polygon([ 156 [-extra, 0], 157 [0, 0], 158 [inner_front_edge_height, inner_front_edge_depth], 159 [-extra, inner_front_edge_depth], 160 ]); 161 162 /* Inner top cutout for the top of the back portion. */ 163 164 translate([0, -inner_top_front_cutout_depth / 2, height / 2 - 165 inner_top_front_cutout_offset - 166 inner_top_front_cutout_depth / 2]) 167 cube([inner_top_front_cutout_width, 168 inner_top_front_cutout_depth, 169 inner_top_front_cutout_depth], center = true); 170 171 /* Fillets to round off the edges. */ 172 173 union() { 174 175 /* Top left and right rounding. */ 176 177 translate([-width / 2 + ro, -front_depth / 2, height / 2 - ro]) 178 rotate([0, 0, 180]) 179 rotate([90, 0, 0]) 180 fillet(rr, front_depth); 181 translate([width / 2 - ro, -front_depth / 2, height / 2 - ro]) 182 rotate([90, 0, 0]) 183 fillet(rr, front_depth); 184 185 /* Top front rounding. */ 186 187 translate([0, -front_depth + ro, height / 2 - ro]) 188 rotate([0, 0, 180]) 189 rotate([0, -90, 0]) 190 fillet(rr, width); 191 192 /* Edge rounding. */ 193 194 translate([-width / 2 + ro, -front_depth + ro, 0]) 195 rotate([0, 0, 180]) 196 fillet(rr, height); 197 translate([width / 2 - ro, -front_depth + ro, 0]) 198 rotate([0, 0, 270]) 199 fillet(rr, height); 200 } 201 } 202 203 difference() { 204 205 /* The cartridge surfaces. */ 206 207 union() { 208 209 /* Back portion. */ 210 211 translate([0, back_depth - back / 2, 0]) 212 cube([width, back, height], center = true); 213 translate([-width / 2 + back_left / 2, back_depth / 2, 0]) 214 cube([back_left, back_depth, height], center = true); 215 translate([width / 2 - back_right / 2, back_depth / 2, 0]) 216 cube([back_right, back_depth, height], center = true); 217 translate([0, back_depth / 2, height / 2 - top / 2]) 218 cube([width, back_depth, top], center = true); 219 difference() { 220 translate([0, back_depth / 2, 221 -height / 2 + bottom / 2 + bottom_from_base]) 222 cube([width, back_depth, bottom], center = true); 223 translate([0, edge_connector_cutout_back_depth / 2, 224 -height / 2 + bottom / 2 + bottom_from_base]) 225 cube([edge_connector_cutout_back_width, 226 edge_connector_cutout_back_depth, 227 bottom + extra], center = true); 228 } 229 } 230 231 /* Label insets. */ 232 233 union() { 234 235 /* Top label. */ 236 237 translate([-top_label_width / 2, 238 -front_depth + top_label_offset_from_front, 239 height / 2 - top_label_depth]) 240 cube([top_label_width, top_label_height, 241 top_label_depth]); 242 } 243 244 /* Top and side grooves, positioned in the back portion. */ 245 246 union() { 247 248 /* Left groove. */ 249 250 translate([-width / 2 + groove_depth / 2, groove_width / 2, 0]) 251 cube([groove_depth, groove_width, height], 252 center = true); 253 254 /* Right groove. */ 255 256 translate([width / 2 - groove_depth / 2, groove_width / 2, 0]) 257 cube([groove_depth, groove_width, height], 258 center = true); 259 260 /* Top grooves. */ 261 262 translate([0, groove_width / 2, height / 2 - groove_depth / 2]) 263 cube([width, groove_width, groove_depth], 264 center = true); 265 266 translate([0, top_groove_width / 2, 267 height / 2 - top_groove_depth / 2]) 268 cube([width, top_groove_width, top_groove_depth], 269 center = true); 270 } 271 272 /* Back cavity. */ 273 274 intersection() { 275 276 /* From the bottom upwards. */ 277 278 translate([0, back_depth, -height / 2]) 279 linear_extrude(height = back_cavity_height) 280 translate([-width / 2, 0, 0]) 281 polygon([ 282 [back_cavity_offset_from_left, 0], 283 [back_cavity_inner_offset_from_left, 284 -back_cavity_depth], 285 [back_cavity_inner_offset_from_left + 286 back_cavity_inner_width, 287 -back_cavity_depth], 288 [back_cavity_offset_from_left + 289 back_cavity_width, 0] 290 ]); 291 292 /* From left to right. */ 293 294 translate([back_cavity_width / 2, back_depth, -height / 2]) 295 rotate([0, -90, 0]) 296 linear_extrude(height = back_cavity_width) 297 polygon([ 298 [-extra, -back_cavity_depth], 299 [back_cavity_inner_height, 300 -back_cavity_depth], 301 [back_cavity_height, 0], 302 [-extra, 0] 303 ]); 304 } 305 306 /* Inner back cavities. */ 307 308 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 309 linear_extrude(height = bottom_from_base) 310 translate([-width / 2, 0, 0]) 311 polygon([ 312 [inner_back_cavity_offset_from_left, 0], 313 [inner_back_slope_offset_from_left, 0], 314 [inner_back_slope_offset_from_left + 315 inner_back_slope_width, 316 -inner_back_slope_depth], 317 [inner_back_cavity_offset_from_left, 318 -inner_back_slope_depth] 319 ]); 320 321 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 322 linear_extrude(height = bottom_from_base) 323 translate([-width / 2, 0, 0]) 324 polygon([ 325 [width - inner_back_slope_offset_from_left, 0], 326 [width - inner_back_cavity_offset_from_left, 0], 327 [width - inner_back_cavity_offset_from_left, 328 -inner_back_slope_depth], 329 [width - inner_back_slope_offset_from_left - 330 inner_back_slope_width, 331 -inner_back_slope_depth] 332 ]); 333 334 /* Inner back edge cavity. */ 335 336 translate([inner_back_edge_width / 2, 337 back_depth - inner_back_edge_offset, -height / 2]) 338 rotate([0, -90, 0]) 339 linear_extrude(height = inner_back_edge_width) 340 polygon([ 341 [-extra, -inner_back_edge_depth], 342 [inner_back_edge_height, -inner_back_edge_depth], 343 [0, 0], 344 [-extra, 0] 345 ]); 346 347 /* Fillets to round off the edges. */ 348 349 union() { 350 351 /* Top left and right rounding. */ 352 353 translate([-width / 2 + ro, back_depth / 2, height / 2 - ro]) 354 rotate([0, 0, 180]) 355 rotate([90, 0, 0]) 356 fillet(rr, back_depth); 357 translate([width / 2 - ro, back_depth / 2, height / 2 - ro]) 358 rotate([90, 0, 0]) 359 fillet(rr, back_depth); 360 361 /* Top back rounding. */ 362 363 translate([0, back_depth - ro, height / 2 - ro]) 364 rotate([0, -90, 0]) 365 fillet(rr, width); 366 367 /* Edge rounding. */ 368 369 translate([width / 2 - ro, back_depth - ro, 0]) 370 fillet(rr, height); 371 translate([-width / 2 + ro, back_depth - ro, 0]) 372 rotate([0, 0, 90]) 373 fillet(rr, height); 374 } 375 } 376 } 377 378 cartridge(); 379