$fn = 64; // --- Parameters --- width = 160; // Total width of the stand back_height = 160; // Height of the back support shelf_depth = 40; // Depth of the ledge holding the book lip_height = 20; // Height of the front lip to keep pages open thickness = 4; // Wall thickness tilt = 25; // Angle (in degrees) tilted back from vertical base_y = -25; // Leg extension downwards to form the flat base // --- Modules --- // 2D Profile of the resting tray (backrest, shelf, and lip) module tray_profile() { rotate([0, 0, -tilt]) { // Backrest square([thickness, back_height]); // Shelf translate([-shelf_depth + thickness, 0]) square([shelf_depth, thickness]); // Lip translate([-shelf_depth + thickness, 0]) square([thickness, lip_height]); } } // 2D Profile of the solid support legs module leg_profile() { // Calculate key outer points of the tray after rotation to attach the legs perfectly // Rotation formula: x' = x*cos(a) - y*sin(a), y' = x*sin(a) + y*cos(a) // Point slightly down from the top of the backrest P_top = [ thickness*cos(-tilt) - (back_height-30)*sin(-tilt), thickness*sin(-tilt) + (back_height-30)*cos(-tilt) ]; // Bottom corner where backrest meets shelf P_corner = [ thickness*cos(-tilt), thickness*sin(-tilt) ]; // Bottom outer corner of the front lip P_front = [ (-shelf_depth + thickness)*cos(-tilt), (-shelf_depth + thickness)*sin(-tilt) ]; polygon([ P_top, [P_top[0], base_y], // Drop down to base from back [P_front[0], base_y], // Flat base across to the front P_front, P_corner // Hug the bottom of the tray ]); } // Combined 2D profile for the leg sections module full_profile() { union() { tray_profile(); leg_profile(); } } // Complete 3D Stand module rulebook_stand() { union() { // Left leg translate([0, 0, 0]) rotate([90, 0, 90]) linear_extrude(thickness) full_profile(); // Right leg translate([width - thickness, 0, 0]) rotate([90, 0, 90]) linear_extrude(thickness) full_profile(); // Center leg translate([(width - thickness)/2, 0, 0]) rotate([90, 0, 90]) linear_extrude(thickness) full_profile(); // Main tray (spans the entire width) translate([0, 0, 0]) rotate([90, 0, 90]) linear_extrude(width) tray_profile(); } } // Center the stand on the build plate and lift so the base rests perfectly on Z=0 translate([-width/2, 0, -base_y]) rulebook_stand();