$fn = 64; // --- Parameters --- hook_width = 15; // Width of the hook thickness = 6; // Thickness of the hook (sturdy for 1.5kg capacity) inner_radius = 12; // Inner radius of the hook curve back_height = 45; // Height of the mounting backplate upturn_length = 15; // Length of the 30-degree upturn hole_diameter = 4.5; // Screw hole diameter (M4 clearance) head_diameter = 8.5; // Screw countersink head diameter // Derived parameter outer_radius = inner_radius + thickness; module j_hook_2d() { union() { // Vertical backplate translate([-outer_radius, -0.01]) square([thickness, back_height + 0.01]); // Rounded top of the backplate translate([-outer_radius + thickness/2, back_height]) circle(d=thickness); // Bottom curved section (180 to 300 degrees) difference() { circle(r=outer_radius); circle(r=inner_radius); // Remove the top half (y > 0) translate([-(outer_radius + 1), 0]) square([(outer_radius + 1)*2, outer_radius + 1]); // Remove the section from 300 to 360 degrees // A square rotated by 300 (-60) degrees covers exactly 300 to 30 degrees rotate(300) square(outer_radius + 1); } // 30-degree upturn lip rotate(300) { // Straight tangent extension translate([inner_radius, -0.01]) square([thickness, upturn_length + 0.01]); // Rounded tip of the upturn translate([inner_radius + thickness/2, upturn_length]) circle(d=thickness); } } } // Extrude the 2D profile and cut mounting holes difference() { // Main body linear_extrude(height=hook_width) j_hook_2d(); // Countersunk mounting holes for (y_pos = [10, back_height - 5]) { translate([-outer_radius + thickness + 0.1, y_pos, hook_width/2]) rotate([0, -90, 0]) { // Screw shaft cylinder(h=thickness + 0.2, d=hole_diameter); // Screw countersink cylinder(h=2.5, d1=head_diameter, d2=hole_diameter); } } }