"""Parametric V1 connecting-rod sample routed to the build123d backend.""" from math import atan2, degrees, hypot from build123d import ( Align, Box, BuildPart, BuildSketch, Cylinder, Location, Locations, Mode, Plane, SlotOverall, extrude, fillet, ) CENTER_DISTANCE = 120.0 THICKNESS = 14.0 BIG_END_OUTER_DIAMETER = 56.0 BIG_END_BORE_DIAMETER = 36.0 SMALL_END_OUTER_DIAMETER = 36.0 SMALL_END_BORE_DIAMETER = 20.0 WEB_WIDTH = 24.0 POCKET_LENGTH = 72.0 POCKET_WIDTH = 12.0 POCKET_DEPTH = 3.0 VIEWER_SLOT_START = (-28.73179347578467, -0.3844822039559189) VIEWER_SLOT_END = (24.36043904920138, -0.24367243243227724) VIEWER_SLOT_SURFACE_Z = THICKNESS - POCKET_DEPTH VIEWER_SLOT_WIDTH = 2.0 VIEWER_SLOT_BLIND_DEPTH = 2.0 VIEWER_EDGE_E14_FILLET_RADIUS = 1.0 VIEWER_HOLE_CENTER = (-22.122781376227962, -9.435525387895417) VIEWER_HOLE_DIAMETER = 6.0 VIEWER_HOLE_BLIND_DEPTH = 6.0 VIEWER_HOLE_SURFACE_Z = THICKNESS VIEWER_HOLE_BOOLEAN_OVERTRAVEL = 0.2 VIEWER_SLOT_CENTER = ( (VIEWER_SLOT_START[0] + VIEWER_SLOT_END[0]) / 2.0, (VIEWER_SLOT_START[1] + VIEWER_SLOT_END[1]) / 2.0, ) VIEWER_SLOT_LENGTH = hypot( VIEWER_SLOT_END[0] - VIEWER_SLOT_START[0], VIEWER_SLOT_END[1] - VIEWER_SLOT_START[1], ) VIEWER_SLOT_ROTATION = degrees( atan2( VIEWER_SLOT_END[1] - VIEWER_SLOT_START[1], VIEWER_SLOT_END[0] - VIEWER_SLOT_START[0], ) ) def _viewer_edge_e14(part): """Select the big-end top outer edge selected in CAD Viewer as e14.""" selected_edges = [] for edge in part.edges(): try: edge_radius = edge.radius edge_center = edge.arc_center edge_normal = edge.normal() except Exception: continue if abs(edge_radius - BIG_END_OUTER_DIAMETER / 2.0) > 0.05: continue if abs(edge_center.X + CENTER_DISTANCE / 2.0) > 0.05: continue if abs(edge_center.Y) > 0.05: continue if abs(edge_center.Z - THICKNESS) > 0.05: continue if abs(edge_normal.Z) < 1.0 - 1e-4: continue selected_edges.append(edge) if len(selected_edges) != 1: raise RuntimeError(f"Expected one viewer-selected e14 edge, found {len(selected_edges)}") return selected_edges def gen_step(): """Return a closed, STEP-ready connecting-rod solid in millimeters.""" half_distance = CENTER_DISTANCE / 2.0 with BuildPart() as rod: with Locations(Location((-half_distance, 0.0, 0.0))): Cylinder( radius=BIG_END_OUTER_DIAMETER / 2.0, height=THICKNESS, align=(Align.CENTER, Align.CENTER, Align.MIN), ) with Locations(Location((half_distance, 0.0, 0.0))): Cylinder( radius=SMALL_END_OUTER_DIAMETER / 2.0, height=THICKNESS, align=(Align.CENTER, Align.CENTER, Align.MIN), ) Box( CENTER_DISTANCE, WEB_WIDTH, THICKNESS, align=(Align.CENTER, Align.CENTER, Align.MIN), ) with Locations(Location((-half_distance, 0.0, -1.0))): Cylinder( radius=BIG_END_BORE_DIAMETER / 2.0, height=THICKNESS + 2.0, align=(Align.CENTER, Align.CENTER, Align.MIN), mode=Mode.SUBTRACT, ) with Locations(Location((half_distance, 0.0, -1.0))): Cylinder( radius=SMALL_END_BORE_DIAMETER / 2.0, height=THICKNESS + 2.0, align=(Align.CENTER, Align.CENTER, Align.MIN), mode=Mode.SUBTRACT, ) with BuildSketch(Plane.XY): SlotOverall(width=POCKET_LENGTH, height=POCKET_WIDTH) extrude(amount=POCKET_DEPTH, mode=Mode.SUBTRACT) with BuildSketch(Plane.XY.offset(THICKNESS - POCKET_DEPTH)): SlotOverall(width=POCKET_LENGTH, height=POCKET_WIDTH) extrude(amount=POCKET_DEPTH, mode=Mode.SUBTRACT) with BuildSketch(Plane.XY.offset(VIEWER_SLOT_SURFACE_Z - VIEWER_SLOT_BLIND_DEPTH)): with Locations(Location((VIEWER_SLOT_CENTER[0], VIEWER_SLOT_CENTER[1], 0.0))): SlotOverall( width=VIEWER_SLOT_LENGTH, height=VIEWER_SLOT_WIDTH, rotation=VIEWER_SLOT_ROTATION, ) extrude(amount=VIEWER_SLOT_BLIND_DEPTH, mode=Mode.SUBTRACT) with Locations( Location( ( VIEWER_HOLE_CENTER[0], VIEWER_HOLE_CENTER[1], VIEWER_HOLE_SURFACE_Z - VIEWER_HOLE_BLIND_DEPTH, ) ) ): Cylinder( radius=VIEWER_HOLE_DIAMETER / 2.0, height=VIEWER_HOLE_BLIND_DEPTH + VIEWER_HOLE_BOOLEAN_OVERTRAVEL, align=(Align.CENTER, Align.CENTER, Align.MIN), mode=Mode.SUBTRACT, ) result = rod.part result = fillet(_viewer_edge_e14(result), radius=VIEWER_EDGE_E14_FILLET_RADIUS) result.label = "cad_router_v1_connecting_rod" return result