--- jupyter: description: 'A crane hook as a 2D CAD exercise: a dimensioned drawing to model in planex2d or any CAD system, a solution as a fully constrained sketch, and the area and centroid to check a model against.' --- # Crane hook A crane hook carries its load in the throat, the round inside of the hook, and hangs from its shank. Its outline is a classic drafting exercise, a chain of arcs, each tangent to the next. Model the hook from the drawing in planex2d or in any CAD system, then check its area and centroid against the values at the end of the page. A solution in planex2d follows. ![The crane hook exercise: a dimensioned drawing of a hook with a shank, a throat of 50 and a point of radius 12](../_static/gallery/crane-hook.png){.result} ```python import math import planex as px ``` ```python nbsphinx="hidden" from docs_figures import Row ``` ## The construction circles The hook is drawn on three circles: - the throat, 50 in diameter, which takes the load, with its center at the origin; - the back, of radius 50, with its center 12 below on the same vertical; - the tip, of radius 12, tangent to both. They are construction circles, so they place the outline but are not part of it (Figure 1). With `auto_constraint=True`, every drawing helper also becomes a constraint: the tip circle stays tangent to the other two when a dimension changes. ```python hook = px.Sketch(auto_constraint=True) hook.Circle(25, id="throat", construction=True) hook.Circle(50, center=(0, -12), id="back", construction=True) hook.Circle(12, id="tip", construction=True, tangent=("throat", "back")) print("tip center", tuple(round(v, 3) for v in hook.Location("tip.center"))) ``` ```python nbsphinx="hide-input" above = {"throat": 6, "back": -6, "tip": 6} centers = {c: hook.Location(c + ".center") for c in above} Row((hook, "The throat, the back and the tip circle", {"fill": False, "marks": list(centers.values()), "rotate": 90, "labels": [(c, (x + above[c], y)) for c, (x, y) in centers.items()]}), caption="The construction circles, their centers marked") ``` ## The outline The outline starts at the top left of the shank, 30 wide and 100 above the throat's center. The right side runs down to the throat, and the inner arc follows the throat almost all the way round, to the tip circle. It runs the other way round than an arc's default, so it takes `reverse=True`. The point follows the tip circle over its top to the back, the outer arc follows the back around the belly, and `Close` draws the left side up to the start. Two fillets then blend the shank into the hook, R 20 on the left and R 8 on the right (Figure 2). ```python hook.Move((-15, 100)).Line((15, 100), id="top") hook.Line("throat", angle=-90, id="right") # straight down until it meets the throat circle hook.Arc("tip", coincident="throat", reverse=True, id="inner") hook.Arc("back", coincident="tip", id="point") hook.Arc((-15, -12 + math.sqrt(50**2 - 15**2)), coincident="back", id="outer") hook.Close(id="left") hook.Fillet("outer.end", 20, id="flare") hook.Fillet("right.end", 8, id="neck"); ``` ```python nbsphinx="hide-input" Row((hook, "The outline on the construction circles, with both fillets", {"fill": False, "rotate": 90}), caption="The outline") ``` ## The dimensions The sizes of the drawing become the sketch's dimensions. The shank stays centered on the throat by its symmetry about the vertical axis, its top is horizontal and its left side vertical, which makes the right side vertical too. With these, nothing in the sketch is left free (Figure 3): ```python hook.Constrain("throat.center", "origin", px.Coincident) hook.Constrain("throat", px.Diameter, 50, id="throat_d") hook.Constrain("back", px.Radius, 50, id="back_r") hook.Constrain("tip", px.Radius, 12, id="tip_r") hook.Constrain("back.center", "throat.center", px.Distance, 12, id="offset") hook.Constrain("back.center", "V", px.Coincident) hook.Constrain("top", px.Distance, 30, id="width") hook.Constrain("top", "throat.center", px.Distance, 100, id="height") hook.Constrain("left", "right", "V", px.SymmetricCarriers) hook.Constrain("top", px.Horizontal) hook.Constrain("left", px.Vertical) print("status", hook.status, "| degrees of freedom", hook.dof) ``` ```python nbsphinx="hide-input" Row((hook, "Every dimension and tie of the sketch", {"constraints": True}), caption="The fully constrained sketch", height=60) ``` ## The checks These are the area and the centroid of the hook, with the throat's center at the origin, to compare with your own model (Figure 4): ```python face = hook.Face() print("area", round(face.mass, 2), "mm²") print("centroid", tuple(round(v, 2) for v in face.center[:2])) ``` ```python nbsphinx="hide-input" Row((face, "The hook, its centroid marked", {"marks": [face.center[:2]], "rotate": 90}), caption="The hook") ``` The outline as DXF in millimeters, for another CAD system or a laser cutter: ```python hook.WriteDXF("crane_hook.dxf", unit=px.mm, scale=1) # scale=1: the numbers as they are ``` The outline as DXF: [crane_hook.dxf](crane_hook.dxf) ```python nbsphinx="hidden" import sys sys.path.insert(0, "..") import matplotlib.pyplot as plt from drawings import DrawingFigure from gallery import save_figure drawing = DrawingFigure(hook, {"width": 112, "height": 76, "offset": 76, "throat_d": 160, "back_r": -150, "tip_r": 60, "flare.r": (-10, "inside"), "neck.r": -50}, centers={"throat": "lines-h", "back": "cross-h"}, axes=[((0, -28), (0, 103), (0, 0))], notes=("planex2d.org", "2D exercise 01")) save_figure(drawing, "crane-hook", dpi=200) plt.close(drawing) ```