$fn=64; // --- Parameters --- stand_width = 180; // Total width of the stand stand_depth = 160; // Total depth of the base stand_height = 220; // Total height of the stand wall = 16; // Thickness of structural parts lip_depth = 45; // Depth of the canvas slot (fits thick gallery canvases) lip_height = 40; // Height of the front retaining lip tilt = 15; // Tilt angle of the backrest (degrees) leg_width = 20; // Width of the solid left and right side legs // Derived values canvas_start = wall; back_start = canvas_start + lip_depth; eps = 0.05; // Small overlap to ensure manifold geometry // 2D Profile of a single leg module 2d_leg() { union() { // Front lip square([wall, lip_height]); translate([wall/2, lip_height]) circle(d=wall); // Base square([stand_depth, wall]); // Angled backrest translate([back_start, wall]) rotate([0, 0, -tilt]) square([wall, stand_height - wall]); // Structural gusset (reinforcement triangle) hull() { translate([back_start, wall]) square([wall, 0.1]); translate([back_start, wall]) rotate([0, 0, -tilt]) translate([0, (stand_height - wall) * 0.5]) square([wall, 0.1]); translate([stand_depth - wall, 0]) square([wall, wall]); } } } // Extrude and orient the 2D profile into 3D module leg_3d() { rotate([90, 0, 90]) linear_extrude(height = leg_width) 2d_leg(); } // Generates a perfectly flush crossbar with a flat bottom for 3D printing bridges module backrest_crossbar(z_bottom, h) { intersection() { // Horizontal bridging block translate([leg_width - eps, 0, z_bottom]) cube([stand_width - 2*leg_width + 2*eps, stand_depth, h]); // Solid backrest projection translate([0, back_start, wall]) rotate([-tilt, 0, 0]) cube([stand_width, wall, stand_height * 2]); } } // Assemble the complete stand module canvas_stand() { // Left Leg leg_3d(); // Right Leg translate([stand_width - leg_width, 0, 0]) leg_3d(); // 1. Front Lip Crossbar translate([leg_width - eps, 0, 0]) cube([stand_width - 2*leg_width + 2*eps, wall, lip_height]); // Front Lip Rounded Top translate([leg_width - eps, wall/2, lip_height]) rotate([0, 90, 0]) cylinder(h=stand_width - 2*leg_width + 2*eps, d=wall); // 2. Base Front Crossbar (Canvas Rest) translate([leg_width - eps, wall - eps, 0]) cube([stand_width - 2*leg_width + 2*eps, lip_depth + 2*eps, wall]); // 3. Base Rear Crossbar translate([leg_width - eps, stand_depth - wall, 0]) cube([stand_width - 2*leg_width + 2*eps, wall, wall]); // 4. Backrest Top Crossbar (Flat bottom for clean bridging) backrest_crossbar(stand_height - 35, 20); // 5. Backrest Middle Crossbar (Flat bottom for clean bridging) backrest_crossbar((stand_height + wall)/2 - 10, 20); } // Render the model canvas_stand();