$fn = 64; // --- Parameters --- tube_diameter = 26; // Diameter for standard paint tubes (acrylic/oil) tube_depth = 40; // Depth of the slots hole_angle = 30; // Angle of tubes leaning back cols = 5; // Number of columns rows = 2; // Number of rows (10 tubes total) spacing_x = 34; // Horizontal spacing between holes spacing_y = 35; // Depth spacing between rows depth = 95; // Overall depth of the rack body height_front = 35; // Height at the front height_back = 75; // Height at the back width = cols * spacing_x + 10; // Overall width module rack() { union() { // Main Body with Angled Slots difference() { // Solid wedge body hull() { cube([width, depth, 0.1]); // Base translate([0, depth - 0.1, 0]) cube([width, 0.1, height_back]); // Back face translate([0, 0, 0]) cube([width, 0.1, height_front]); // Front face } // Subtracted Tube Holes for (c = [0 : cols - 1]) { for (r = [0 : rows - 1]) { // Calculate positions x_pos = 5 + (spacing_x / 2) + c * spacing_x; y_pos = 30 + r * spacing_y; z_pos = height_front + (y_pos / depth) * (height_back - height_front); // Main cylindrical hole translate([x_pos, y_pos, z_pos + 5]) rotate([-hole_angle, 0, 0]) translate([0, 0, -tube_depth - 5]) cylinder(d=tube_diameter, h=tube_depth + 15); // Chamfered rim for easy tube insertion translate([x_pos, y_pos, z_pos + 2]) rotate([-hole_angle, 0, 0]) translate([0, 0, -4]) cylinder(d1=tube_diameter, d2=tube_diameter + 4, h=6); } } } // --- ArtArsenal / Universal Wall Rail Mount --- // Upper Standoff translate([0, depth, height_back - 15]) cube([width, 10, 15]); // Downward Hook (Cleat) translate([0, depth + 10, height_back - 15]) hull() { translate([0, -4, 0]) cube([width, 4, 15]); // Base attached to standoff translate([0, -8, -10]) cube([width, 2, 2]); // Angled tip hooking downward } // Lower Spacer (keeps the rack parallel to the wall) translate([0, depth, 5]) cube([width, 10, 10]); } } // Render the final object rack();