"""Inch specialty nuts, Unified threads: nylon-insert and all-metal prevailing-torque lock nuts (ASME B18.16.6), hex flange nuts (ASME B18.2.2 Table 12) and low-crown acorn nuts (SAE J483). Envelope models for assemblies, axis along +Z, sitting on the XY plane, centred on the origin; the thread is not modelled (a bore at the ASME B1.1 basic major diameter D) and corner chamfers are not modelled: - nylon, all-metal: a hex prism, width across flats F (max), height H (max, overall; the nylon collar and the all-metal nut's locking crimp are within it and not modelled separately); - flange: a flange disc dc (max) x c (min, the flange's edge thickness) under a hex prism F (max) up to the overall thickness m (max); the flange's taper from its edge up to the hex is not modelled; bore through; - acorn: a hex prism F (max) x Q (hex height), then the crown: a body of diameter A to the overall height H, its top rounded with the body radius S (the nose radius R is not modelled); a blind bore of depth T (max drill depth). The model is in millimetres (1 in = 25.4 mm); the tables are in inches as in the sources. """ import math from steve import Model size = "1/4-20" # Thread (Unified, ASME B1.1) style = "nylon" # Nut style material = "steel" # Material THREADS = { "#2-56": "#2", "#4-40": "#4", "#6-32": "#6", "#8-32": "#8", "#10-24": "#10", "#10-32": "#10", "1/4-20": "1/4", "1/4-28": "1/4", "5/16-18": "5/16", "5/16-24": "5/16", "3/8-16": "3/8", "3/8-24": "3/8", "1/2-13": "1/2", "1/2-20": "1/2", } # Inches. ASME B1.1 basic major diameter D. DIAMETERS = {"#2": 0.086, "#4": 0.112, "#6": 0.138, "#8": 0.164, "#10": 0.19, "1/4": 0.25, "5/16": 0.3125, "3/8": 0.375, "1/2": 0.5} # ASME B18.16.6-2017 nylon-insert lock nuts, standard height: style NM (#2-#10) and NE (1/4-1/2): (s max, h max) NYLON = {"#2": (0.251, 0.153), "#4": (0.251, 0.153), "#6": (0.313, 0.188), "#8": (0.345, 0.239), "#10": (0.376, 0.249), "1/4": (0.439, 0.328), "5/16": (0.502, 0.359), "3/8": (0.564, 0.468), "1/2": (0.752, 0.609)} # ASME B18.16.6-2017 prevailing-torque all-metal hex nuts: (s max, h max) ALL_METAL = {"#4": (0.251, 0.163), "#6": (0.313, 0.171), "#8": (0.345, 0.191), "#10": (0.376, 0.241), "1/4": (0.4385, 0.288), "5/16": (0.502, 0.336), "3/8": (0.5645, 0.415), "1/2": (0.752, 0.573)} # ASME B18.2.2-2015 Table 12 hex flange nuts: (s max, dc max, m max, c min) FLANGE = {"#6": (0.312, 0.422, 0.171, 0.02), "#8": (0.344, 0.469, 0.203, 0.02), "#10": (0.375, 0.5, 0.219, 0.03), "1/4": (0.438, 0.594, 0.236, 0.04), "5/16": (0.5, 0.68, 0.283, 0.04), "3/8": (0.562, 0.75, 0.347, 0.04), "1/2": (0.75, 1.031, 0.458, 0.05)} # SAE J483 low-crown acorn nuts: (F max, Q hex height, A body diameter, H overall height, S body radius, T max drill # depth) ACORN = {"#6": (0.3125, 0.16, 0.30, 0.34, 0.17, 0.25), "#8": (0.3125, 0.16, 0.30, 0.34, 0.17, 0.25), "#10": (0.375, 0.19, 0.36, 0.41, 0.22, 0.28), "1/4": (0.4375, 0.22, 0.41, 0.47, 0.25, 0.34), "5/16": (0.5, 0.25, 0.47, 0.53, 0.28, 0.41), "3/8": (0.5625, 0.28, 0.53, 0.62, 0.33, 0.45), "1/2": (0.75, 0.38, 0.72, 0.81, 0.42, 0.59)} MATERIALS = { "steel": ("steel-generic", "#b8bcc2"), # carbon steel, zinc plated "stainless-18-8": ("stainless-304", "#c9ccd0"), } INCH = 25.4 nominal = THREADS[size] d = DIAMETERS[nominal] * INCH material_id, colour = MATERIALS[material] tables = {"nylon": NYLON, "all-metal": ALL_METAL, "flange": FLANGE, "acorn": ACORN} if nominal not in tables[style]: raise ValueError(f"No {style} nut for {nominal} in the sourced table.") row = [v * INCH for v in tables[style][nominal]] model = Model() if style in ("nylon", "all-metal"): F, H = row with model.sketch("nut_sketch", on="XY", name="Nut") as sk: sk.polygon("hex", (0, 0), F / 2, 6, inscribed=False) sk.circle("bore", (0, 0), d / 2) model.extrude("nut", "nut_sketch", distance=H, name="Nut") elif style == "flange": F, dc, m, c = row model.cylinder("flange", dc / 2, c, name="Flange") model.plane("hex_plane", on="XY", offset=c, name="Flange top") with model.sketch("hex_sketch", on="hex_plane", name="Hex") as sk: sk.polygon("hex", (0, 0), F / 2, 6, inscribed=False) model.extrude("hex", "hex_sketch", distance=m - c, op="join", name="Hex") model.cylinder("bore", d / 2, m, op="cut", name="Bore") else: F, Q, A, H, S, T = row with model.sketch("hex_sketch", on="XY", name="Hex") as sk: sk.polygon("hex", (0, 0), F / 2, 6, inscribed=False) model.extrude("hex", "hex_sketch", distance=Q, name="Hex") model.cylinder("crown", A / 2, H - Q, at=(0, 0, Q), op="new", name="Crown") model.sphere("dome", S, at=(0, 0, H - S), op="new", name="Dome") model.combine("crown_shape", "crown", ["dome"], op="intersect", name="Crown shape") model.combine("nut", "hex", ["crown"], op="join", name="Nut") model.cylinder("bore", d / 2, T, op="cut", name="Bore") model.material(material_id, color=colour) result = model.result()