$fn = 64; // --- Parameters --- num_slots = 5; // Number of palette slots slot_width = 8; // Thickness of the slots (fits most standard palettes) slot_depth = 35; // How deep the palettes sit in the stand wall_thickness = 4; // Thickness of dividers between slots stand_width = 100; // Total width of the stand slot_angle = 15; // Tilt angle of the palettes (degrees) base_thickness = 5; // Thickness of the solid base floor corner_radius = 3; // Radius for the rounded outer corners // --- Calculated Values --- // Calculate Y spacing to maintain uniform wall thickness between angled slots y_spacing = slot_width + wall_thickness + (slot_depth * sin(slot_angle)); stand_depth = wall_thickness + (num_slots * y_spacing); stand_height = base_thickness + (slot_depth * cos(slot_angle)); // Helper module for a box with rounded vertical corners module rounded_box(w, d, h, r) { hull() { translate([r, r, 0]) cylinder(r=r, h=h); translate([w-r, r, 0]) cylinder(r=r, h=h); translate([r, d-r, 0]) cylinder(r=r, h=h); translate([w-r, d-r, 0]) cylinder(r=r, h=h); } } module palette_stand() { difference() { // Main Body rounded_box(stand_width, stand_depth, stand_height, corner_radius); // Angled Slots for(i = [0 : num_slots - 1]) { cutter_w = stand_width + 2; cutter_h = stand_height * 2; y_pos = wall_thickness + i * y_spacing; // Offset Z so the lowest point of the angled cut rests exactly on the base floor z_offset = base_thickness + (slot_width * sin(slot_angle)); translate([-1, y_pos, z_offset]) rotate([-slot_angle, 0, 0]) cube([cutter_w, slot_width, cutter_h]); } // Center cutout for easy grabbing and material saving cutout_width = stand_width * 0.6; side_rail_width = (stand_width - cutout_width) / 2; // Leaves solid walls on the sides, front, back, and bottom translate([side_rail_width, wall_thickness * 1.5, base_thickness]) cube([cutout_width, stand_depth - (wall_thickness * 3), stand_height + 1]); } } palette_stand();