"""
EXACT servo HOLDER for the ST3215 (STEP frame). Bolts to the 4 corner body-mount holes
(front and back faces) extracted from the STEP — a U-bracket wrapping the body, sitting on
the +X portion of the faces so it's clear of the horn/idler/yoke (which live at x=-25.5).
Output axis +Y through (-25.5,0). Mount holes along +Y.
"""
from build123d import Box, Cylinder, Pos, Rot, export_stl

FRONT_Y, BACK_Y = 9.6, -28.2
PT = 4.0
BOLT_D = 2.5
# exact corner mount holes (x,z) on front (y~6.4) and back (y~-25.6) faces
FRONT_HOLES = [(-17.2, 10.2), (-17.2, -10.2), (3.5, 10.2), (3.5, -10.2)]
BACK_HOLES = [(-17.2, 10.2), (-17.2, -10.2), (7.2, 10.2), (7.2, -10.2)]
PLATE_X0, PLATE_X1 = -22.0, 9.0     # plate X extent (covers corner holes, clears horn at -25.5)
PLATE_Z = 28.0
SPINE_X, SPINE_T = 14.0, 5.0        # back wall on +X side (past body +X face 9.6)


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


def make_holder_exact():
    front_yc = FRONT_Y + PT / 2
    back_yc = BACK_Y - PT / 2
    xc = (PLATE_X0 + PLATE_X1) / 2
    xw = PLATE_X1 - PLATE_X0
    spine_yc = (FRONT_Y + PT + BACK_Y - PT) / 2
    spine_h = (FRONT_Y + PT) - (BACK_Y - PT)

    h = (Pos(xc, front_yc, 0) * Box(xw, PT, PLATE_Z)              # front plate
         + Pos(xc, back_yc, 0) * Box(xw, PT, PLATE_Z)            # back plate
         + Pos(SPINE_X, spine_yc, 0) * Box(SPINE_T, spine_h, PLATE_Z))  # back wall (+X)
    for hx, hz in FRONT_HOLES:
        h -= _hole_Y(hx, front_yc, hz, BOLT_D)
    for hx, hz in BACK_HOLES:
        h -= _hole_Y(hx, back_yc, hz, BOLT_D)
    return h


if __name__ == "__main__":
    export_stl(make_holder_exact(), "holder_exact.stl", tolerance=0.1, ascii_format=False)
    print("holder_exact ok")
