// Shepherd’s Hook Bolt // A bent bolt with a curved hook, typically used for hanging or anchoring loads. The threaded end allows secure attachment to surfaces or materials, while the curved hook resists pull-out under tension. // Set units in millimeters (mm) @settings(defaultLengthUnit = mm, kclVersion = 1.0) // Define bolt geometry parameters boltDiameter = 5 hookRadius = 12 shankLength = 5 threadedEndLength = 30 nutDistance = 20 hookStartAngle = 290 hookEndAngle = 150 approximatePitch = boltDiameter * 0.15 threadDepth = 0.6134 * approximatePitch innerRadius = boltDiameter / 2 - threadDepth boltNumberOfRevolutions = threadedEndLength / approximatePitch // Helper values for computing geometry transitions between straight shaft and hook arc hypotenuse = hookRadius / cos(hookStartAngle - 270) side = sqrt(pow(hypotenuse, exp = 2) - pow(hookRadius, exp = 2)) shankOffset = hypotenuse + side // Converts polar coordinates to cartesian points for drawing arcs fn polarToCartesian(radius, angle) { x = radius * cos(angle) y = radius * sin(angle) return [x, y] } // Create the hook and shank profile path // Includes straight segment and two connected arcs forming the hook hookProfilePlane = startSketchOn(XZ) hookProfileShape = startProfile(hookProfilePlane, at = [0, -shankOffset - shankLength]) |> line(endAbsolute = [0, -shankOffset]) |> tangentialArc(endAbsolute = polarToCartesian(radius = hookRadius, angle = hookStartAngle)) |> tangentialArc(endAbsolute = polarToCartesian(radius = hookRadius, angle = hookEndAngle), tag = $hook) // Create the circular cross-section used for sweeping along the hook path hookSectionPlane = offsetPlane(XY, offset = -shankOffset - shankLength) hookSectionShape = circle(hookSectionPlane, center = [0, 0], radius = boltDiameter / 2) // Sweep the section along the hook profile to form the main body of the hook bolt hookBody = sweep(hookSectionShape, path = hookProfileShape, sectional = true) // Add a cylindrical tip at the hook end tipPlane = startSketchOn(hookBody, face = END) tipShape = circle( tipPlane, center = [hookRadius, 0], radius = boltDiameter / 2, tag = $seg01, ) tipBody = extrude( tipShape, length = hookRadius * 0.5, tagStart = $startTag, tagEnd = $capEnd001, ) |> fillet( radius = boltDiameter / 4, tags = [ getCommonEdge(faces = [seg01, capEnd001]) ], ) // Create the threaded end of the bolt // Construct the triangular profile for thread cutting boltThreadSectionPlane = startSketchOn(XZ) boltThreadSectionShapeForRevolve = startProfile( boltThreadSectionPlane, at = [ innerRadius, -shankOffset - shankLength - threadedEndLength ], ) |> line(end = [threadDepth, approximatePitch / 2]) |> line(end = [-threadDepth, approximatePitch / 2]) |> patternLinear2d(axis = [0, 1], instances = boltNumberOfRevolutions, distance = approximatePitch) |> xLine(length = -innerRadius * 0.9) |> yLine(length = -threadedEndLength) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close() // Create a revolved solid representing the thread geometry by repeating and revolving the profile around the shaft boltThreadRevolve = revolve(boltThreadSectionShapeForRevolve, angle = 360, axis = Y)