--- jupyter: description: 'A keyed hub as a 2D CAD exercise: a dimensioned drawing to model in planex2d or any CAD system, a solution as a fully constrained sketch with a keyway trimmed into the bore, and the area to check a model against.' --- # Keyed hub A hub carries a pulley, a gear or a lever on a shaft, and a key in the keyway of its bore takes the torque. As a sketch, it is two circles and a keyway trimmed into the bore. Model the hub 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 keyed hub exercise: a dimensioned drawing of a round hub with a bore and a keyway](../_static/gallery/keyed-hub.png){.result} ```python import math import planex as px ``` ```python nbsphinx="hidden" from docs_figures import Row ``` ## The circles and the keyway The hub is drawn as two circles around the origin, the outside and the bore, and the keyway as three lines from the bore up, its left side, its top and its right side. The lines are drawn roughly, the sides starting near the bore, and the dimensions in the next section give them their place and size. A vertex at the bottom of the bore is the point that the keyway's depth is measured from. `auto_constraint` turns what the drawing shows exactly into constraints. The two circles drawn at one center stay concentric, and with `"horizontal"` and `"vertical"` switched on, the keyway's lines, drawn level and plumb, stay so (Figure 1). ```python hub = px.Sketch(auto_constraint={"horizontal": True, "vertical": True}) hub.Circle(60 / 2, id="outside") hub.Circle(25 / 2, id="bore") hub.Move((-4, 12), dir=(0, 1)).Line(4, id="keyway_left") # dir=: the pen points up hub.Turn(-90).Line(8, id="keyway_top") # Turn(-90) turns the pen right, Turn(90) left hub.Turn(-90).Line(4, id="keyway_right") hub.Vertex("bore_bottom", (0, -12)); ``` ```python nbsphinx="hide-input" Row((hub, "The circles and the rough keyway, the vertex marked", {"fill": False, "marks": [hub.Location("bore_bottom")]}), caption="The circles and the keyway") ``` ## The dimensions The outside's center, which the bore shares, is the origin. The sides of the keyway start on the bore, and its top has its middle on the vertical axis. The keyway's depth runs from the far side of the bore to the keyway's top, 28.3 for a bore of 25, a size that a caliper can check across the bore. The vertex lies on the bore and on the vertical axis, and the depth is its distance from the top. With these, nothing in the sketch is left free (Figure 2): ```python hub.Constrain("outside.center", "origin", px.Coincident) hub.Constrain("outside", px.Diameter, 60, id="outside_d") hub.Constrain("bore", px.Diameter, 25, id="bore_d") hub.Constrain("keyway_left.start", "bore", px.Coincident) # a point on a circle hub.Constrain("keyway_right.end", "bore", px.Coincident) hub.Constrain("keyway_top", px.Distance, 8, id="keyway_w") hub.Constrain("keyway_top.mid", "V", px.Coincident) hub.Constrain("bore_bottom", "bore", px.Coincident) hub.Constrain("bore_bottom", "V", px.Coincident) hub.Constrain("bore_bottom", "keyway_top", px.Distance, 28.3, id="keyway_depth") print("status", hub.status, "| degrees of freedom", hub.dof) ``` ```python nbsphinx="hide-input" Row((hub, "Every dimension and tie of the sketch", {"constraints": True}), caption="The fully constrained sketch") ``` ## Trimming The dimensions have put the ends of the keyway's sides on the bore, so `Trim` can cut the bore there. The piece between the sides becomes construction, and the bore and the keyway form one outline (Figure 3). ```python hub.Trim(("bore", (0, 12.5))); # the piece of the bore nearest to (0, 12.5), between the sides, becomes construction ``` ```python nbsphinx="hide-input" Row((hub, "The bore trimmed between the keyway's sides, the piece dashed", {"fill": False}), caption="The trimmed bore") ``` ## The checks These are the area and the centroid of the hub, with its center at the origin, to compare with your own model. The area is the ring between the outside and the bore, less the keyway beyond the bore. That is the rectangle 8 wide from the bore's center up to the keyway's top, 28.3 − 12.5, less the part of the bore inside it. The keyway takes material above the center, so the centroid lies just below it, on the vertical axis (Figure 4): ```python face = hub.Face() under = 4 * math.sqrt(12.5**2 - 4**2) + 12.5**2 * math.asin(4 / 12.5) # the part of the bore inside the rectangle: above its center, |x| < 4 exact = math.pi / 4 * (60**2 - 25**2) - (8 * (28.3 - 12.5) - under) c = face.center print("area", round(face.mass, 2), "mm², exact", round(exact, 2)) print("centroid", round(-c[1], 3), "below the center, off the axis by", round(abs(c[0]), 6)) ``` ```python nbsphinx="hide-input" Row((face, "The hub, its centroid marked", {"marks": [c[:2]]}), caption="The hub") ``` The hub as DXF in millimeters, for another CAD system or a laser cutter: ```python hub.WriteDXF("keyed_hub.dxf", unit=px.mm, scale=1) # scale=1: the numbers as they are ``` The hub as DXF: [keyed_hub.dxf](keyed_hub.dxf) ```python nbsphinx="hidden" import sys sys.path.insert(0, "..") import matplotlib.pyplot as plt from drawings import SheetFigure, View from gallery import save_figure view = View([(hub, {"outside_d": (0, "across", -38), "bore_d": 45, "keyway_w": 40, "keyway_depth": -19})]) drawing = SheetFigure([view], margin=15, notes=("planex2d.org", "2D exercise 06")) print("scale 1 :", round(1 / drawing.planex_scale), "| paper", [round(v * 25.4) for v in drawing.get_size_inches()], "mm") save_figure(drawing, "keyed-hub", dpi=200) plt.close(drawing) ```