"""Metric nut: hexagon (ISO 4032), thin (ISO 4035), nylon-insert lock (DIN 985), all-metal lock (DIN 980), flange (DIN 6923), domed cap (DIN 1587) or square (DIN 557). Envelope model for assemblies: the wrenching shape at its nominal (maximum) width across flats s, the height of the standard, and a plain bore at the nominal thread diameter d (the thread is not modelled). Lock nuts are the hexagon over their full height h (the insert or clamping part is not modelled separately); the flange nut has its flange diameter dc and thickness c; the cap nut a hemispherical dome of diameter dk and a blind bore as deep as its thread. The bearing face is on the XY plane at the origin, the nut along +Z; hexagon corners lie on the X axis. """ from steve import Model style = "hex" # Nut style size = "M3" # Thread size material = "steel" # Material NOMINAL = { "M1.6": 1.6, "M2": 2.0, "M2.5": 2.5, "M3": 3.0, "M3.5": 3.5, "M4": 4.0, "M5": 5.0, "M6": 6.0, "M7": 7.0, "M8": 8.0, "M10": 10.0, "M12": 12.0, "M14": 14.0, "M16": 16.0, "M18": 18.0, "M20": 20.0, "M22": 22.0, "M24": 24.0, "M27": 27.0, "M30": 30.0, "M33": 33.0, "M36": 36.0, "M39": 39.0, "M42": 42.0, "M45": 45.0, "M48": 48.0, "M52": 52.0, "M56": 56.0, "M60": 60.0, "M64": 64.0, } # ISO 4032 Tables 1 and 2 (ISO 4032:1999 as BS EN ISO 4032:2001, # https://www.engineersedge.com/hardware/bs_en_iso_4032_hexagon_nuts__14571.htm; https://www.fasteners.eu/standards/ISO/4032/). size: (s max, m max) HEX = { "M1.6": (3.2, 1.3), "M2": (4.0, 1.6), "M2.5": (5.0, 2.0), "M3": (5.5, 2.4), "M3.5": (6.0, 2.8), "M4": (7.0, 3.2), "M5": (8.0, 4.7), "M6": (10.0, 5.2), "M8": (13.0, 6.8), "M10": (16.0, 8.4), "M12": (18.0, 10.8), "M14": (21.0, 12.8), "M16": (24.0, 14.8), "M18": (27.0, 15.8), "M20": (30.0, 18.0), "M22": (34.0, 19.4), "M24": (36.0, 21.5), "M27": (41.0, 23.8), "M30": (46.0, 25.6), "M33": (50.0, 28.7), "M36": (55.0, 31.0), "M39": (60.0, 33.4), "M42": (65.0, 34.0), "M45": (70.0, 36.0), "M48": (75.0, 38.0), "M52": (80.0, 42.0), "M56": (85.0, 45.0), "M60": (90.0, 48.0), "M64": (95.0, 51.0), } # ISO 4035 Tables 1 and 2 (DIN EN ISO 4035:2001-03 = ISO 4035:1999, https://fasten.it/norms/norm/din_en_iso_4035; # https://www.engineersedge.com/hardware/bs_en_iso_4035_14574.htm). size: (s max, m max) THIN = { "M1.6": (3.2, 1.0), "M2": (4.0, 1.2), "M2.5": (5.0, 1.6), "M3": (5.5, 1.8), "M3.5": (6.0, 2.0), "M4": (7.0, 2.2), "M5": (8.0, 2.7), "M6": (10.0, 3.2), "M8": (13.0, 4.0), "M10": (16.0, 5.0), "M12": (18.0, 6.0), "M14": (21.0, 7.0), "M16": (24.0, 8.0), "M18": (27.0, 9.0), "M20": (30.0, 10.0), "M22": (34.0, 11.0), "M24": (36.0, 12.0), "M27": (41.0, 13.5), "M30": (46.0, 15.0), "M33": (50.0, 16.5), "M36": (55.0, 18.0), "M39": (60.0, 19.5), "M42": (65.0, 21.0), "M45": (70.0, 22.5), "M48": (75.0, 24.0), "M52": (80.0, 26.0), "M56": (85.0, 28.0), "M60": (90.0, 30.0), "M64": (95.0, 32.0), } # DIN 985:1987-05 table (https://fasten.it/norms/norm/din_985; https://www.fasteners.eu/standards/DIN/985/). size: (s max, h max) NYLON = { "M3": (5.5, 4.0), "M4": (7.0, 5.0), "M5": (8.0, 5.0), "M6": (10.0, 6.0), "M7": (11.0, 7.5), "M8": (13.0, 8.0), "M10": (17.0, 10.0), "M12": (19.0, 12.0), "M14": (22.0, 14.0), "M16": (24.0, 16.0), "M18": (27.0, 18.5), "M20": (30.0, 20.0), "M22": (32.0, 22.0), "M24": (36.0, 24.0), "M27": (41.0, 27.0), "M30": (46.0, 30.0), "M33": (50.0, 33.0), "M36": (55.0, 36.0), "M39": (60.0, 39.0), "M42": (65.0, 42.0), "M45": (70.0, 45.0), "M48": (75.0, 48.0), } # DIN 980:1987-05 table, all-metal prevailing torque nut (https://fasten.it/norms/norm/din_980; https://www.fasteners.eu/standards/DIN/980/). size: (s max, h max) ALL_METAL = { "M3": (5.5, 3.7), "M4": (7.0, 4.2), "M5": (8.0, 5.1), "M6": (10.0, 6.0), "M7": (11.0, 7.0), "M8": (13.0, 8.0), "M10": (17.0, 10.0), "M12": (19.0, 12.0), "M14": (22.0, 14.0), "M16": (24.0, 16.0), "M18": (27.0, 18.0), "M20": (30.0, 20.0), "M22": (32.0, 22.0), "M24": (36.0, 24.0), "M27": (41.0, 27.0), "M30": (46.0, 30.0), "M33": (50.0, 33.0), "M36": (55.0, 36.0), "M39": (60.0, 39.0), } # DIN 6923:1983-06 table (s, m, dc: https://fasten.it/norms/norm/din_6923; c min: https://www.fasteners.eu/standards/DIN/6923/). size: (s max, m max, flange diameter dc max, flange thickness c min) FLANGE = { "M5": (8.0, 5.0, 11.8, 1.0), "M6": (10.0, 6.0, 14.2, 1.1), "M8": (13.0, 8.0, 17.9, 1.2), "M10": (15.0, 10.0, 21.8, 1.5), "M12": (18.0, 12.0, 26.0, 1.8), "M14": (21.0, 14.0, 29.9, 2.1), "M16": (24.0, 16.0, 34.5, 2.4), "M20": (30.0, 20.0, 42.8, 3.0), } # DIN 1587:2000-10 table (https://www.fasteners.eu/standards/DIN/1587/; M10 m 8 as in fasten.it's fine-thread table and # https://www.fabory.com/en-GB/p/47340100001, fasteners.eu's 8,8 contradicts its own m min 7,64). size: (s max, hexagon height m max, overall height h max, dome diameter dk max, thread depth t max) CAP = { "M4": (7.0, 3.2, 8.0, 6.5, 5.74), "M5": (8.0, 4.0, 10.0, 7.5, 7.79), "M6": (10.0, 5.0, 12.0, 9.5, 8.29), "M8": (13.0, 6.5, 15.0, 12.5, 11.35), "M10": (16.0, 8.0, 18.0, 15.0, 13.35), "M12": (18.0, 10.0, 22.0, 17.0, 16.35), "M14": (21.0, 11.0, 25.0, 20.0, 18.35), "M16": (24.0, 13.0, 28.0, 23.0, 21.42), "M18": (27.0, 15.0, 32.0, 26.0, 25.42), "M20": (30.0, 16.0, 34.0, 28.0, 26.42), "M22": (34.0, 18.0, 39.0, 33.0, 29.42), "M24": (36.0, 19.0, 42.0, 34.0, 31.5), } # DIN 557:1994-01 table, product grade C (https://fasten.it/norms/norm/din_557; https://www.fasteners.eu/standards/DIN/557/). size: (s max, m max) SQUARE = { "M5": (8.0, 4.0), "M6": (10.0, 5.0), "M8": (13.0, 6.5), "M10": (17.0, 8.0), "M12": (19.0, 10.0), "M16": (24.0, 13.0), } STYLES = {"hex": HEX, "thin": THIN, "nylon-insert": NYLON, "all-metal": ALL_METAL, "flange": FLANGE, "cap": CAP, "square": SQUARE} STANDARDS = {"hex": "ISO 4032", "thin": "ISO 4035", "nylon-insert": "DIN 985", "all-metal": "DIN 980", "flange": "DIN 6923", "cap": "DIN 1587", "square": "DIN 557"} # material choice: (STEVE material library id, appearance colour) MATERIALS = { "steel": ("steel-generic", "#b9bdc2"), # property class 8 / 10, zinc plated "stainless-a2": ("stainless-304", "#c9ccd0"), # ISO 3506-2 A2 "stainless-a4": ("stainless-316", "#c9ccd0"), # ISO 3506-2 A4 } table = STYLES[style] if size not in table: raise ValueError(f"{STANDARDS[style]} has no size {size}; sizes: {', '.join(table)}") row = table[size] s = row[0] d = NOMINAL[size] material_id, colour = MATERIALS[material] model = Model() if style == "square": height = row[1] with model.sketch("body_sketch", on="XY", name="Square") as sk: sk.center_rect("square", (0, 0), s, s) sk.circle("bore", (0, 0), d / 2) model.extrude("body", "body_sketch", distance=height, name="Nut") elif style == "flange": height, dc, c = row[1], row[2], row[3] with model.sketch("flange_sketch", on="XY", name="Flange") as sk: sk.circle("flange_circle", (0, 0), dc / 2) model.extrude("flange", "flange_sketch", distance=c, name="Flange") with model.sketch("hex_sketch", on="XY", name="Hexagon") as sk: sk.polygon("hex", (0, 0), s / 2, 6, inscribed=False) model.extrude("body", "hex_sketch", distance=height, name="Hexagon") with model.sketch("bore_sketch", on="XY", name="Bore") as sk: sk.circle("bore", (0, 0), d / 2) model.extrude("bore", "bore_sketch", distance=height, op="cut", name="Bore") elif style == "cap": m, height, dk, t = row[1], row[2], row[3], row[4] r = dk / 2 with model.sketch("hex_sketch", on="XY", name="Hexagon") as sk: sk.polygon("hex", (0, 0), s / 2, 6, inscribed=False) model.extrude("body", "hex_sketch", distance=m, name="Hexagon") with model.sketch("dome_profile", on="XZ", name="Dome profile") as sk: sk.polyline("dome_side", [(0, m), (r, m), (r, height - r)], closed=False) sk.arc("dome_arc", (0, height - r), r, 0, 90) sk.line("dome_axis", (0, height), (0, m)) model.revolve("dome", "dome_profile", axis="Z", name="Dome") with model.sketch("bore_sketch", on="XY", name="Bore") as sk: sk.circle("bore", (0, 0), d / 2) model.extrude("bore", "bore_sketch", distance=t, op="cut", name="Thread bore") else: height = row[1] with model.sketch("body_sketch", on="XY", name="Hexagon") as sk: sk.polygon("hex", (0, 0), s / 2, 6, inscribed=False) sk.circle("bore", (0, 0), d / 2) model.extrude("body", "body_sketch", distance=height, name="Nut") model.material(material_id, color=colour) result = model.result()