$fn = 64; // --- Parameters --- projection = 75; // Total distance from wall to tip base_width = 25; // Width of the wall plate base_thickness = 5; // Thickness of the wall plate top_hole_z = 20; // Z position of top screw hole bottom_hole_z = -25; // Z position of bottom screw hole hole_dia = 4.5; // Screw shaft diameter cs_dia = 9; // Countersink head diameter cs_depth = 3; // Countersink depth // Hook arm profile points [Y, Z, Diameter] // Designed to ensure exactly 75mm projection and hold >2kg p1 = [5, -5, 14]; // Base connection p2 = [35, -5, 12]; // Straight outward section p3 = [55, 5, 10]; // Upward curve p4 = [69, 25, 12]; // Tip (69 + 12/2 = 75mm max projection) // --- Modules --- module base_plate() { hull() { translate([0, base_thickness, top_hole_z]) rotate([90, 0, 0]) cylinder(h=base_thickness, d=base_width); translate([0, base_thickness, bottom_hole_z]) rotate([90, 0, 0]) cylinder(h=base_thickness, d=base_width); } } module hook_arm() { hull() { translate([0, p1[0], p1[1]]) sphere(d=p1[2]); translate([0, p2[0], p2[1]]) sphere(d=p2[2]); } hull() { translate([0, p2[0], p2[1]]) sphere(d=p2[2]); translate([0, p3[0], p3[1]]) sphere(d=p3[2]); } hull() { translate([0, p3[0], p3[1]]) sphere(d=p3[2]); translate([0, p4[0], p4[1]]) sphere(d=p4[2]); } } module screw_hole(z_pos) { translate([0, base_thickness + 0.1, z_pos]) rotate([90, 0, 0]) { // Countersink cone cylinder(h=cs_depth + 0.1, d1=cs_dia, d2=hole_dia); // Screw shaft translate([0, 0, cs_depth]) cylinder(h=base_thickness + 2, d=hole_dia); } } // --- Main Geometry --- difference() { union() { base_plate(); hook_arm(); } // Subtractions for mounting hardware screw_hole(top_hole_z); screw_hole(bottom_hole_z); // Clean flush cut at the back (wall face) to ensure printability translate([-base_width, -50, bottom_hole_z - base_width]) cube([base_width * 2, 50, (top_hole_z - bottom_hole_z) + base_width * 2 + 50]); }