$fn = 64; // --- Parameters --- width = 50; // Total width of the stand depth = 120; // Projection distance from the wall height = 140; // Height of the wall plate wall_t = 6; // Thickness of the outer shell and structural ribs lip_h = 25; // Height of the front retaining lip canvas_gap = 35; // Gap between front lip and backrest for canvas thickness hook_d = 8; // Depth of the wall rail hook hook_drop = 12; // Drop height of the wall rail hook bumper_h = 15; // Height of the bottom wall standoff // Calculated start point for the angled backrest rest_x = depth - wall_t - canvas_gap; module profile() { // Round the sharp convex outer edges slightly for a better feel offset(r=1) offset(r=-1) union() { // Main body wedge and canvas rest polygon([ [0, 0], [depth, 0], [depth, lip_h], [depth - wall_t, lip_h], [depth - wall_t, wall_t], [rest_x, wall_t], [wall_t, height], [0, height] ]); // Top wall rail hook (ArtArsenal / French cleat style) polygon([ [0, height], [-hook_d, height], [-hook_d, height - hook_drop], [0, height - hook_drop + hook_d] ]); // Bottom wall bumper to keep the stand vertical polygon([ [0, 0], [-hook_d, 0], [-hook_d, bumper_h], [0, bumper_h + hook_d] ]); } } module hollow_cutout() { // Inner triangular cutout to hollow the body, leaving sturdy structural ribs polygon([ [wall_t, wall_t], [rest_x - wall_t * 1.5, wall_t], [wall_t, height - wall_t * 2.5] ]); } // --- Main Object --- // The part is generated lying flat on its side. // This is the optimal orientation for 3D printing (no supports needed, maximum hook strength). difference() { // Solid outer body linear_extrude(width) profile(); // Hollow center translate([0, 0, wall_t]) linear_extrude(width - 2 * wall_t) hollow_cutout(); }