"""
EXACT yoke connector for the ST3215 (STEP servo frame). Bolts to the real horn + idler
bolt circles (extracted from the STEP), no approximation. Output axis +Y through
(AX, AZ)=(-25.5, 0); horn front (y=9.6, holes at y=6), idler back (y=-28.2, holes y=-27.7).
"""
from build123d import Box, Cylinder, Pos, Rot, export_stl

AX, AZ = -25.5, 0.0
HORN_Y, HORN_HOLE_Y = 9.6, 6.0
IDLER_Y, IDLER_HOLE_Y = -28.2, -27.7
IDLER_SNUG = 0.9                          # move the back (idler/non-gear) plate IN this many mm so it
                                          # clamps FLUSH (print 1: 0.5 closer but small gap left -> 0.9)
PT = 4.0                                  # plate thickness (along Y)
HOLES_XZ = [(-32.5, 0.0), (-25.5, 7.0), (-25.5, -7.0), (-18.5, 0.0)]  # exact horn/idler pattern
BOLT_D, BORE_D = 2.9, 9.0
SPINE_X, SPINE_T = -45.0, 6.0             # spine out past the holder collar (clears it)
PLATE_X0, PLATE_X1 = -48.0, -15.0         # plate X extent (covers holes + reaches spine)
PLATE_Z = 26.0
LINK_SEC = (22.0, 16.0)                   # link cross-section (z-height, y-width)


def _hole_along_Y(x, yc, z, dia):
    return Pos(x, yc, z) * Rot(90, 0, 0) * Cylinder(dia / 2, PT * 4)


def make_yoke_exact(link_len=70.0):
    idler_y = IDLER_Y + IDLER_SNUG                    # back plate pulled in to clamp flush
    front_yc = HORN_Y + PT / 2
    back_yc = idler_y - PT / 2
    plate_xc = (PLATE_X0 + PLATE_X1) / 2
    plate_xw = PLATE_X1 - PLATE_X0
    spine_yc = (HORN_Y + idler_y) / 2
    spine_h = (HORN_Y + PT) - (idler_y - PT)
    link_xc = SPINE_X - SPINE_T / 2 - link_len / 2

    y = (Pos(plate_xc, front_yc, 0) * Box(plate_xw, PT, PLATE_Z)        # front plate (on horn)
         + Pos(plate_xc, back_yc, 0) * Box(plate_xw, PT, PLATE_Z)       # back plate (on idler)
         + Pos(SPINE_X, spine_yc, 0) * Box(SPINE_T, spine_h, PLATE_Z)   # spine around -X side
         + Pos(link_xc, spine_yc, 0) * Box(link_len, LINK_SEC[1], LINK_SEC[0]))  # link out -X
    # exact bolt holes through both plates + center bores
    for hx, hz in HOLES_XZ:
        y -= _hole_along_Y(hx, front_yc, hz, BOLT_D)
        y -= _hole_along_Y(hx, back_yc, hz, BOLT_D)
    y -= _hole_along_Y(AX, front_yc, AZ, BORE_D)
    y -= _hole_along_Y(AX, back_yc, AZ, BORE_D)
    return y


if __name__ == "__main__":
    import sys
    L = float(sys.argv[1]) if len(sys.argv) > 1 else 70.0
    export_stl(make_yoke_exact(L), "yoke_exact.stl", tolerance=0.1, ascii_format=False)
    print("yoke_exact ok")
