$fn=64; // --- Parameters --- can_diameter = 68; // Standard spray paint can is ~65-68mm clearance = 2; // Clearance for easy insertion wall_thickness = 3.5; // Thickness of the rack walls rack_height = 60; // Overall height of the rack base_thickness = 3; // Bottom thickness num_cans = 3; // Number of slots in the rack // --- Calculated Variables --- hole_d = can_diameter + clearance; outer_d = hole_d + (wall_thickness * 2); spacing = outer_d - wall_thickness; // Overlap to merge walls between slots // --- Main Geometry --- difference() { // Outer Body hull() { for(i = [0 : num_cans - 1]) { translate([i * spacing, 0, 0]) cylinder(d=outer_d, h=rack_height); } } for(i = [0 : num_cans - 1]) { // Main cylinder cutout for the can translate([i * spacing, 0, base_thickness]) cylinder(d=hole_d, h=rack_height + 1); // Front viewing/access slot (allows seeing the can label/color) translate([i * spacing, -outer_d/2, base_thickness + 15 + rack_height/2]) cube([hole_d * 0.65, outer_d, rack_height], center=true); // Bottom material-saving / push-out hole translate([i * spacing, 0, -1]) cylinder(d=hole_d * 0.5, h=base_thickness + 2); // Wall mounting screw holes in the back wall translate([i * spacing, outer_d/2, rack_height - 15]) rotate([90, 0, 0]) cylinder(d=5, h=wall_thickness * 4, center=true); // Screw head countersink/clearance translate([i * spacing, outer_d/2 - wall_thickness + 1, rack_height - 15]) rotate([90, 0, 0]) cylinder(d=10, h=wall_thickness * 2, center=true); } }