--- jupyter: description: 'A gear pump cover as a 3D CAD exercise: a dimensioned drawing with a full section to model in planex2d or any CAD system, a solution from the gasket''s figure-eight outline padded, bearing bores, bosses and a seal seat, and ten counterbored holes along the gasket''s bolt line, and the exact volume, the mass and center of mass to check a model against.' --- # Gear pump cover The cover closes the housing of the [gear pump](pump-gasket.md) over its gasket. It carries the bearings of the two gear shafts, the [rotors](pump-rotors.md), and lets the drive shaft out through a seal. Its outline and its bolt holes are the gasket's, so they come from the same opening and the same bolt line, and the bearings are bores into bosses around the gears' centers. Model the cover from the drawing in planex2d or in any CAD system, then check its volume, mass and center of mass against the values at the end of the page. A solution in planex2d follows. ![The gear pump cover exercise: a dimensioned drawing of a figure-eight cover plate with two bosses, a through bore with a seal seat, a blind bearing bore and ten counterbored holes, in a full section, a top view and an isometric](../_static/gallery/pump-cover.png){.result} ```python import math import netgen.occ as occ import planex as px ``` ```python nbsphinx="hidden" from docs_figures import Row, Views ``` ## The plate The cover's outline is the gasket's, the two chambers of 38.5 around the gears' centers, 34 apart on the $x$ axis, united and offset 16 outward. The bolt line is the opening offset by 8. The plate is the outline padded 12 up from the xy plane, which is the face against the gasket (Figure 1): ```python opening = px.Unify([px.Circle((-17, 0), 38.5 / 2).Face(), px.Circle((17, 0), 38.5 / 2).Face()]).Face() outline = opening.Offset(16, inplace=False).Face() # as the gasket's bolt_line = opening.Offset(8, inplace=False).Face().outer plate = px.Pad(outline, 12) ``` ```python nbsphinx="hide-input" Row((outline, "The outline, the bolt line dashed", {"dashed": [bolt_line]}), (plate, "Padded 12", {"views": [(plate, "shade"), (plate, "ink")], "angles": (-60, 0, 30)}), caption="The plate") ``` ## The boss and the bores A boss stands 8 above the plate around both gears' centers. It is two discs of 36 around them, united into one figure eight, so that no narrow gap stays between them, sketched on the plate's top and padded. The idler gear's shaft, on the left, runs in a blind bore of 15, 10 deep from the underside. The drive shaft, on the right, passes through a bore of 15 through the plate and its boss, and a seal sits in a seat of 24, 5 deep, at the boss's top (Figure 2): ```python boss = px.Unify([px.Circle((-17, 0), 18).Face(), px.Circle((17, 0), 18).Face()]).Face() cover = plate + px.Pad(boss.Translated((0, 0, 12)), 8) idler = px.QuickSketch(px.XY).Circle(15 / 2, center=(-17, 0)) # on the underside's plane cover = px.Pocket(cover, idler, 10, reverse=True) # 10 deep, along the plane's normal: up into the plate drive = px.QuickSketch(px.Plane(px.XY, 20)).Circle(15 / 2, center=(17, 0)) # the boss's top, 12 + 8 up cover = px.Pocket(cover, drive, 20) seal = px.QuickSketch(px.Plane(px.XY, 20)).Circle(24 / 2, center=(17, 0)) cover = px.Pocket(cover, seal, 5) ``` ```python nbsphinx="hide-input" Views(("The boss, the drive shaft's bore and its seal seat", [(cover, "shade"), (cover, "ink")]), angles=(-60, 0, 30), caption="The boss and the bores") ``` ## The bolt holes The ten holes lie where the gasket's do, equally spaced along the bolt line, the first half a pitch from the corner where it starts. `along` walks the bolt line with `PointAt`, as on the [gasket's page](pump-gasket.md). Each hole is a clearance hole of 6.6 through the plate with a counterbore of 11, 6.5 deep from the top, for an M6 socket head screw (Figure 3): ```python def along(wire, n): """n points equally spaced along a closed wire, the first half a pitch from its start""" pitch = wire.mass / n targets = [pitch / 2 + k * pitch for k in range(n)] points, walked = [], 0.0 for e in wire.edges: length = e.Measure()["length"] points += [e.PointAt((t - walked) / length) for t in targets if walked <= t < walked + length] walked += length return [(p.x, p.y) for p in points] centers = along(bolt_line, 10) counterbores = px.QuickSketch(px.Plane(px.XY, 12)) holes = px.QuickSketch(px.Plane(px.XY, 12)) for c in centers: counterbores.Circle(11 / 2, center=c) holes.Circle(6.6 / 2, center=c) cover = px.Pocket(cover, counterbores, 6.5) cover = px.Pocket(cover, holes, 12) ``` ```python nbsphinx="hide-input" Views(("The counterbored holes along the bolt line", [(cover, "shade"), (cover, "ink")]), angles=(-60, 0, 30), caption="The bolt holes") ``` ## The checks These are the volume, the mass in aluminum EN AC-AlSi10Mg (2.68 g/cm³) and the center of mass, with the origin in the middle between the gears' centers on the underside, to compare with your own model. The outline is the union of two circles of 35.25 and the boss the union of two of 18, each $2 \pi r^2$ less the lens of the two circles, $2 r^2 \arccos\left(\tfrac{d}{2r}\right) - \tfrac{d}{2} \sqrt{4 r^2 - d^2}$. Every other part is a cylinder or a ring. The cover is symmetric about the plane $y = 0$, so its center of mass lies in it: ```python def union(r, d=34): return 2 * math.pi * r**2 - (2 * r**2 * math.acos(d / (2 * r)) - d / 2 * math.sqrt(4 * r**2 - d**2)) def disc(d): return math.pi * d**2 / 4 exact = (union(35.25) * 12 + union(18) * 8 - disc(15) * 10 - disc(15) * 20 - (disc(24) - disc(15)) * 5 - 10 * disc(6.6) * 12 - 10 * (disc(11) - disc(6.6)) * 6.5) c = cover.center print("volume", round(cover.mass, 2), "mm³, exact", round(exact, 2)) print("mass", round(cover.mass * 2.68e-6, 4), "kg") print("center of mass", (round(c.x, 4), round(c.z, 4)), "| off the plane y = 0 by", round(abs(c.y), 6)) ``` The cover as STEP, for another CAD system: ```python cover.WriteStep("pump_cover.step") ``` The cover as STEP: [pump_cover.step](pump_cover.step) ```python nbsphinx="hidden" import sys sys.path.insert(0, "..") import matplotlib.pyplot as plt from drawings import LANDSCAPE, Pictorial, SheetFigure, View from gallery import save_figure # first angle: the full section through the plane y = 0 in front (the symmetry plane: no designation), the part # behind it seen from the front with its cut faces hatched; the top view below it front = px.XZ # x to the right, z up behind = cover * occ.Box((-60, 0, -1), (60, 45, 25)) cut = [f for f in behind.faces if abs(f.center.y) < 1e-6 and f.bounding_box[1].y - f.bounding_box[0].y < 1e-6] section = View([], solid=behind, plane=front, hidden_edges=False, hatch=cut, axes=[((-17, -4), (-17, 24)), ((17, -4), (17, 24)), ((-44.25, -3), (-44.25, 15)), ((44.25, -3), (44.25, 15))], measures=[((-52.25, 0), (-52.25, 12), -60, 12), ((33, 12), (33, 20), 62, 8), ((-24.5, 0), (-24.5, 10), -32, 10), ((11, 15), (23, 15), 28, "⌀24"), ((12.5, 20), (12.5, 15), 6, 5), ((-24.5, 0), (-9.5, 0), -8, "⌀15"), ((9.5, 0), (24.5, 0), -8, "⌀15"), ((38.75, 12), (49.75, 12), 18, "⌀11"), ((49.75, 12), (49.75, 5.5), 58, 6.5)]) top = View([], solid=cover, plane=px.XY, at=(0, -78), hidden_edges=False, axes=[bolt_line.Polylines(1e-3)[0], ((-58, 0), (58, 0)), ((-17, -20), (-17, 20)), ((17, -20), (17, 20))], radii=[((17, 0), 35.25, (40, "outside")), ((-17, 0), 27.25, (160, "outside")), ((-17, 0), 18, (240, "inside"))], diameters=[(centers[0], 3.3, (100, "leader", 10, "EQS"))], measures=[((-17, 0), (17, 0), -50, 34)]) pictorial = Pictorial(cover, at=(118, -40), width=70, angles=(-60, 0, 30)) drawing = SheetFigure([section, top, pictorial], margin=16, notes=("planex2d.org", "3D exercise 29"), first_angle=True, sheet=LANDSCAPE) print("scale", drawing.planex_scale, "| paper", [round(v * 25.4) for v in drawing.get_size_inches()], "mm") save_figure(drawing, "pump-cover", dpi=200) plt.close(drawing) ```