"""Split lock washer (spring washer), DIN 127 form B (square ends), M2 to M100. One helical turn of a rectangular section: inner diameter d1 (min), outer diameter d2 (max), thickness s and free height h (form B, max). The section stays in the plane through the axis as it climbs, so the washer is exactly h high and d2 wide; the split is where the two ends meet, h - s apart. It lies on the XY plane at the origin, climbing along +Z. """ import cadquery as cq from steve import Model size = "M3" # Thread size material = "spring-steel" # Material # DIN 127:1987-10 table (https://fasten.it/norms/norm/din_127). size: (d1 min, d2 max, s nominal, h max form B) DIMENSIONS = { "M2": (2.1, 4.4, 0.5, 1.2), "M2.2": (2.3, 4.8, 0.6, 1.4), "M2.5": (2.6, 5.1, 0.6, 1.4), "M3": (3.1, 6.2, 0.8, 1.9), "M3.5": (3.6, 6.7, 0.8, 1.9), "M4": (4.1, 7.6, 0.9, 2.1), "M5": (5.1, 9.2, 1.2, 2.8), "M6": (6.1, 11.8, 1.6, 3.8), "M7": (7.1, 12.8, 1.6, 3.8), "M8": (8.1, 14.8, 2.0, 4.7), "M10": (10.2, 18.1, 2.2, 5.2), "M12": (12.2, 21.1, 2.5, 5.9), "M14": (14.2, 24.1, 3.0, 7.1), "M16": (16.2, 27.4, 3.5, 8.3), "M18": (18.2, 29.4, 3.5, 8.3), "M20": (20.2, 33.6, 4.0, 9.4), "M22": (22.5, 35.9, 4.0, 9.4), "M24": (24.5, 40.0, 5.0, 11.8), "M27": (27.5, 43.0, 5.0, 11.8), "M30": (30.5, 48.2, 6.0, 14.2), "M36": (36.5, 58.2, 6.0, 14.2), "M39": (39.5, 61.2, 6.0, 14.2), "M42": (42.5, 68.2, 7.0, 16.5), "M45": (45.5, 71.2, 7.0, 16.5), "M48": (49.0, 75.0, 7.0, 16.5), "M52": (53.0, 83.0, 8.0, 18.9), "M56": (57.0, 87.0, 8.0, 18.9), "M60": (61.0, 91.0, 8.0, 18.9), "M64": (65.0, 95.0, 8.0, 18.9), "M68": (69.0, 99.0, 8.0, 18.9), "M72": (73.0, 103.0, 8.0, 18.9), "M80": (81.0, 111.0, 8.0, 18.9), "M90": (91.0, 121.0, 8.0, 18.9), "M100": (101.0, 131.0, 8.0, 18.9), } # material choice: (STEVE material library id, appearance colour) MATERIALS = { "spring-steel": ("steel-c60e", "#2f3134"), # spring steel, black / phosphated "stainless-a2": ("stainless-304", "#c9ccd0"), "stainless-a4": ("stainless-316", "#c9ccd0"), } d1, d2, s, h = DIMENSIONS[size] material_id, colour = MATERIALS[material] r1 = d1 / 2 r2 = d2 / 2 rise = h - s path = cq.Wire.makeHelix(rise, rise, (r1 + r2) / 2) section = cq.Workplane("XZ").center((r1 + r2) / 2, s / 2).rect(r2 - r1, s) coil = section.sweep(cq.Workplane().add(path), isFrenet=True) # on a helix the Frenet frame keeps the section in its axial plane model = Model() model.add("washer", coil, name="Washer") model.material(material_id, color=colour) result = model.result()