"""Gantry wrist bracket: adapter plate from the Y-carriage (M4 pattern) to the first wrist servo/holder
(STS3215 M3 pattern), with an output-shaft clearance. Origin-centered, printable."""
import trimesh
def box(x0,x1,y0,y1,z0,z1):
    b=trimesh.creation.box(extents=[x1-x0,y1-y0,z1-z0]); b.apply_translation([(x0+x1)/2,(y0+y1)/2,(z0+z1)/2]); return b
def cylZ(x,y,r,z0,z1):
    c=trimesh.creation.cylinder(radius=r,height=z1-z0,sections=40); c.apply_translation([x,y,(z0+z1)/2]); return c
def U(p): return trimesh.boolean.union(p,engine="manifold")
def D(a,b): return trimesh.boolean.difference([a,b],engine="manifold")
# top plate bolts to Y-carriage (M4 @ 36x28), drops a skirt, bottom face mounts STS3215 holder (M3 @ 32x18)
plate=box(-28,28,-24,24,0,6)
for x in (-18,18):                          # M4 to carriage
    for y in (-14,14): plate=D(plate,cylZ(x,y,2.2,-1,7))
b=plate
b=U([b,box(-28,28,-24,-18,6,26),box(-28,28,18,24,6,26)])   # 2 side skirts down to servo face
sf=box(-28,28,-24,24,26,32)                 # bottom servo-mount face
for x in (-16,16):                          # M3 to servo holder
    for y in (-9,9): sf=D(sf,cylZ(x,y,1.7,25,33))
sf=D(sf,cylZ(0,0,7,25,33))                  # output-shaft clearance
brk=U([b,sf]); brk.export("gantry_wrist_bracket.stl")
print(f"wrist_bracket: wt={brk.is_watertight} bodies={len(brk.split(only_watertight=False))} bbox={[round(v,1) for v in brk.extents]}")
