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 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 /* Back portion. */ 129 130 translate([0, back_depth - back / 2, 0]) 131 cube([width, back, height], center = true); 132 translate([-width / 2 + back_left / 2, back_depth / 2, 0]) 133 cube([back_left, back_depth, height], center = true); 134 translate([width / 2 - back_right / 2, back_depth / 2, 0]) 135 cube([back_right, back_depth, height], center = true); 136 translate([0, back_depth / 2, height / 2 - top / 2]) 137 cube([width, back_depth, top], center = true); 138 difference() { 139 translate([0, back_depth / 2, 140 -height / 2 + bottom / 2 + bottom_from_base]) 141 cube([width, back_depth, bottom], center = true); 142 translate([0, edge_connector_cutout_back_depth / 2, 143 -height / 2 + bottom / 2 + bottom_from_base]) 144 cube([edge_connector_cutout_back_width, 145 edge_connector_cutout_back_depth, 146 bottom + extra], center = true); 147 } 148 } 149 150 /* Label insets. */ 151 152 union() { 153 154 /* Front label. */ 155 156 translate([-front_label_width / 2, -front_depth, 157 front_label_offset_from_bottom - height / 2]) 158 cube([front_label_width, front_label_depth, 159 front_label_height]); 160 161 /* Top label. */ 162 163 translate([-top_label_width / 2, 164 -front_depth + top_label_offset_from_front, 165 height / 2 - top_label_depth]) 166 cube([top_label_width, top_label_height, 167 top_label_depth]); 168 } 169 170 /* Top and side grooves, positioned in the back portion. */ 171 172 union() { 173 174 /* Left groove. */ 175 176 translate([-width / 2 + groove_depth / 2, groove_width / 2, 0]) 177 cube([groove_depth, groove_width, height], 178 center = true); 179 180 /* Right groove. */ 181 182 translate([width / 2 - groove_depth / 2, groove_width / 2, 0]) 183 cube([groove_depth, groove_width, height], 184 center = true); 185 186 /* Top grooves. */ 187 188 translate([0, groove_width / 2, height / 2 - groove_depth / 2]) 189 cube([width, groove_width, groove_depth], 190 center = true); 191 192 translate([0, top_groove_width / 2, 193 height / 2 - top_groove_depth / 2]) 194 cube([width, top_groove_width, top_groove_depth], 195 center = true); 196 197 /* Inner top cutout for the top of the back portion. */ 198 199 translate([0, -inner_top_front_cutout_depth / 2, height / 2 - 200 inner_top_front_cutout_offset - 201 inner_top_front_cutout_depth / 2]) 202 cube([inner_top_front_cutout_width, 203 inner_top_front_cutout_depth, 204 inner_top_front_cutout_depth], center = true); 205 } 206 207 /* Back cavity. */ 208 209 intersection() { 210 211 /* From the bottom upwards. */ 212 213 translate([0, back_depth, -height / 2]) 214 linear_extrude(height = back_cavity_height) 215 translate([-width / 2, 0, 0]) 216 polygon([ 217 [back_cavity_offset_from_left, 0], 218 [back_cavity_inner_offset_from_left, 219 -back_cavity_depth], 220 [back_cavity_inner_offset_from_left + 221 back_cavity_inner_width, 222 -back_cavity_depth], 223 [back_cavity_offset_from_left + 224 back_cavity_width, 0] 225 ]); 226 227 /* From left to right. */ 228 229 translate([back_cavity_width / 2, back_depth, -height / 2]) 230 rotate([0, -90, 0]) 231 linear_extrude(height = back_cavity_width) 232 polygon([ 233 [-extra, -back_cavity_depth], 234 [back_cavity_inner_height, 235 -back_cavity_depth], 236 [back_cavity_height, 0], 237 [-extra, 0] 238 ]); 239 } 240 241 /* Inner back cavities. */ 242 243 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 244 linear_extrude(height = bottom_from_base) 245 translate([-width / 2, 0, 0]) 246 polygon([ 247 [inner_back_cavity_offset_from_left, 0], 248 [inner_back_slope_offset_from_left, 0], 249 [inner_back_slope_offset_from_left + 250 inner_back_slope_width, 251 -inner_back_slope_depth], 252 [inner_back_cavity_offset_from_left, 253 -inner_back_slope_depth] 254 ]); 255 256 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 257 linear_extrude(height = bottom_from_base) 258 translate([-width / 2, 0, 0]) 259 polygon([ 260 [width - inner_back_slope_offset_from_left, 0], 261 [width - inner_back_cavity_offset_from_left, 0], 262 [width - inner_back_cavity_offset_from_left, 263 -inner_back_slope_depth], 264 [width - inner_back_slope_offset_from_left - 265 inner_back_slope_width, 266 -inner_back_slope_depth] 267 ]); 268 269 /* Inner back edge cavity. */ 270 271 translate([inner_back_edge_width / 2, 272 back_depth - inner_back_edge_offset, -height / 2]) 273 rotate([0, -90, 0]) 274 linear_extrude(height = inner_back_edge_width) 275 polygon([ 276 [-extra, -inner_back_edge_depth], 277 [inner_back_edge_height, -inner_back_edge_depth], 278 [0, 0], 279 [-extra, 0] 280 ]); 281 282 /* Inner front edge cavity. */ 283 284 translate([inner_front_edge_width / 2, 285 -front_depth + inner_front_edge_offset, -height / 2]) 286 rotate([0, -90, 0]) 287 linear_extrude(height = inner_front_edge_width) 288 polygon([ 289 [-extra, 0], 290 [0, 0], 291 [inner_front_edge_height, inner_front_edge_depth], 292 [-extra, inner_front_edge_depth], 293 ]); 294 295 /* Fillets to round off the edges. */ 296 297 union() { 298 299 /* Top left and right rounding. */ 300 301 translate([-width / 2 + ro, -front_depth / 2, height / 2 - ro]) 302 rotate([0, 0, 180]) 303 rotate([90, 0, 0]) 304 fillet(rr, front_depth); 305 translate([width / 2 - ro, -front_depth / 2, height / 2 - ro]) 306 rotate([90, 0, 0]) 307 fillet(rr, front_depth); 308 309 translate([-width / 2 + ro, back_depth / 2, height / 2 - ro]) 310 rotate([0, 0, 180]) 311 rotate([90, 0, 0]) 312 fillet(rr, back_depth); 313 translate([width / 2 - ro, back_depth / 2, height / 2 - ro]) 314 rotate([90, 0, 0]) 315 fillet(rr, back_depth); 316 317 /* Top back and front rounding. */ 318 319 translate([0, back_depth - ro, height / 2 - ro]) 320 rotate([0, -90, 0]) 321 fillet(rr, width); 322 translate([0, -front_depth + ro, height / 2 - ro]) 323 rotate([0, 0, 180]) 324 rotate([0, -90, 0]) 325 fillet(rr, width); 326 327 /* Edge rounding. */ 328 329 translate([width / 2 - ro, back_depth - ro, 0]) 330 fillet(rr, height); 331 translate([-width / 2 + ro, back_depth - ro, 0]) 332 rotate([0, 0, 90]) 333 fillet(rr, height); 334 translate([-width / 2 + ro, -front_depth + ro, 0]) 335 rotate([0, 0, 180]) 336 fillet(rr, height); 337 translate([width / 2 - ro, -front_depth + ro, 0]) 338 rotate([0, 0, 270]) 339 fillet(rr, height); 340 } 341 } 342 } 343 344 cartridge(); 345