"""20 x 20 V-slot aluminium extrusion, any length. The section, centred on the origin in the XY plane, extruded along +Z by `length`: a 20 x 20 square with 0.5 mm corner radii and a V-slot in each face. Each slot: a 45 degree V from the face opening down to the lip tips, the lips' flat undersides, the undercut's straight walls, 45 degree walls down to the core and the core's small V notch; a 4.2 mm centre bore. All four slots are the same, turned 90 degrees. Geometry measured from the published FreeCAD-library model "2020x50_V_slot_profile-Part.step" (hasecilu, CC-BY-3.0); there is no manufacturer drawing. See the README. """ import math from steve import Model length = 100 # mm Length finish = "clear" # Anodising # mm, measured on the reference model's cross-section at mid-length (OCCT section, edges read exactly; the model's # own values are given to 0.05 mm, the 45 degree walls' ends to 1e-4 mm). x across the top slot from its centre line, # y up from the profile's centre. SECTION = { "outer": 20.0, # outside, square "corner_r": 0.5, # outside corner radius "opening": 9.7, # slot width at the face (x = +-4.85) "tip": 6.1, # between the lip tips (x = +-3.05), 1.8 below the face: the V is 45 degrees "lip_y": 8.2, # lip underside (flat, out to the undercut wall) "undercut": 11.0, # undercut width (walls at x = +-5.5) "wall_y": 6.5607, # where the undercut wall turns into the 45 degree wall "floor": 5.6786, # core face width at y = core_y (x = +-2.8393) "core_y": 3.9, # core face "notch": 0.4, # V notch in the core face, 0.2 deep "notch_depth": 0.2, "bore": 4.2, # centre bore } FINISHES = {"clear": "#cfd2d6", "black": "#2b2c2e"} s = SECTION half = s["outer"] / 2 rc = s["corner_r"] # one slot, the top one, left to right (the outline runs clockwise: top face, then right face, ...) slot = [(-s["opening"] / 2, half), (-s["tip"] / 2, s["lip_y"]), (-s["undercut"] / 2, s["lip_y"]), (-s["undercut"] / 2, s["wall_y"]), (-s["floor"] / 2, s["core_y"]), (-s["notch"] / 2, s["core_y"]), (0.0, s["core_y"] - s["notch_depth"]), (s["notch"] / 2, s["core_y"]), (s["floor"] / 2, s["core_y"]), (s["undercut"] / 2, s["wall_y"]), (s["undercut"] / 2, s["lip_y"]), (s["tip"] / 2, s["lip_y"]), (s["opening"] / 2, half)] def turn(points, quarter): a = -math.pi / 2 * quarter return [(x * math.cos(a) - y * math.sin(a), x * math.sin(a) + y * math.cos(a)) for x, y in points] model = Model() with model.sketch("section", on="XY", name="Section") as sk: for q in range(4): # top, right, bottom, left side: the top one turned 90 degrees clockwise each time pts = turn([(-half + rc, half)] + slot + [(half - rc, half)], q) sk.polyline(f"side_{q}", pts, closed=False) cx, cy = turn([(half - rc, half - rc)], q)[0] start = 90 - 90 * q - 90 sk.arc(f"corner_{q}", (cx, cy), rc, start, start + 90) sk.circle("bore", (0, 0), s["bore"] / 2) model.extrude("profile", "section", distance=length, name="Profile") model.material("aluminum-generic", color=FINISHES[finish]) # 6063-T5 typical (no STEVE entry for 6063) result = model.result()