"""Primary injection test pin ("tulip") for testing molded case circuit breakers. One end is a milled hex that slides through the breaker's terminal cover into the set-screw box lug. A short round neck blends through a tangent "tulip" flare into the full round body, so there is no sharp shoulder where the pin levers against the lug mouth. The other end is a solid rounded-square bar (no holes) that the test cable's lug is clamped to with vise-grips. The whole pin is turned and milled from one square bar of C18150 or C18200 copper alloy, TH04 temper, left bare. `size` picks one of four sizes (the hex fits the smallest maximum wire in its frame range, the hex length clears the deepest cover found plus the lug depth plus 0.25 in). `hex_length` and `square_length` can be overridden. Pin axis along +x, hex tip at the origin, a hex corner pointing +z. Dimensions are set in inches; the model is built in mm. """ import math import cadquery as cq from steve import Model size = "2" # Size hex_length = 0 # in Hex length override (0 = size default) square_length = 4.0 # in Square clamp end length IN = 25.4 SIZES = { # hex across flats, hex length, neck length, flare length, body length, square width, corner radius, body dia "1": dict(AF=0.3125, Lh=2.50, Ln=0.25, Lf=0.50, Lb=0.50, sq=0.75, rc=0.09, Db=0.70), "2": dict(AF=0.375, Lh=3.25, Ln=0.25, Lf=0.50, Lb=0.50, sq=0.75, rc=0.09, Db=0.70), "3": dict(AF=0.500, Lh=3.75, Ln=0.25, Lf=0.625, Lb=0.50, sq=1.00, rc=0.125, Db=0.94), "4": dict(AF=0.625, Lh=4.00, Ln=0.25, Lf=0.625, Lb=0.50, sq=1.00, rc=0.125, Db=0.94), } s = dict(SIZES[str(size)]) if hex_length: if not 1.0 <= hex_length <= 8.0: raise ValueError("hex_length must be 0 (size default) or between 1 and 8 in.") s["Lh"] = float(hex_length) if not 1.0 <= square_length <= 12.0: raise ValueError("square_length must be between 1 and 12 in.") LSQ = float(square_length) AF, Lh = s["AF"], s["Lh"] AC = AF / math.cos(math.radians(30)) # across corners Dn = math.ceil((AC + 0.01) * 200) / 200 # neck just over across-corners, so the flats run out cleanly x_neck = Lh x_flare = x_neck + s["Ln"] x_body = x_flare + s["Lf"] x_sq = x_body + s["Lb"] def u(v): return v * IN # hex prism along +x with a 30 degree chamfered tip hexp = cq.Workplane("YZ").polygon(6, u(AC)).extrude(u(Lh + 0.02)) r0 = 0.45 * AF r1 = AC / 2 + 0.02 dx = (r1 - r0) * math.tan(math.radians(30)) lim = (cq.Workplane("XY").polyline([(0, 0), (0, u(r0)), (u(dx), u(r1)), (u(Lh + 0.02), u(r1)), (u(Lh + 0.02), 0)]) .close().revolve(360, (0, 0, 0), (1, 0, 0))) hexp = hexp.intersect(lim) # neck, tangent tulip flare, body rn, rb = Dn / 2, s["Db"] / 2 prof = (cq.Workplane("XY").moveTo(u(x_neck), 0).lineTo(u(x_neck), u(rn)).lineTo(u(x_flare), u(rn)) .spline([(u(x_body), u(rb))], tangents=[(1, 0), (1, 0)], includeCurrent=True) .lineTo(u(x_sq + 0.01), u(rb)).lineTo(u(x_sq + 0.01), 0).close()) rev = prof.revolve(360, (0, 0, 0), (1, 0, 0)) # solid rounded-square clamp end, no holes sqb = (cq.Workplane("YZ").workplane(offset=u(x_sq)).rect(u(s["sq"]), u(s["sq"])).extrude(u(LSQ)) .edges("|X").fillet(u(s["rc"]))) sqb = sqb.faces(">X").edges().chamfer(u(0.03)) pin = hexp.union(rev).union(sqb) try: pin = pin.faces("