"""Aesthetic pass over the gripper support blocks (run AFTER gen_gripper_urdf.py — rewrites gnode_*.stl):
- servo_to_finger plate: rectangle -> rounded pentagon; the unused far-bottom corner is cut by a diagonal
  from under connector1 up to the fixed_conn root, so the plate hugs the load path instead of overhanging.
- connector1: clipped to the holder x-footprint (no more hovering under the servo).
- finger_adj pad: outline rounded (r=5) in plan; jaw contact face stays planar.
Mating zones are preserved: connector1 zone keeps full plate height; strut roots stay buried."""
import numpy as np, trimesh
from shapely.geometry import Polygon

s = trimesh.load("gripper_from_blender.glb")
def wbox(node):
    T, gn = s.graph[node]
    w = trimesh.transform_points(s.geometry[gn].vertices, np.array(T, float)) * 100.0
    return w.min(0), w.max(0)

def rext(pts, r, z0, z1):
    p = Polygon(pts).buffer(-r, join_style=2).buffer(r, join_style=1, resolution=8)
    m = trimesh.creation.extrude_polygon(p, z1 - z0)
    m.apply_translation([0, 0, z0])
    return m

plo, phi = wbox("servo_to_finger"); alo, ahi = wbox("finger_adj"); hlo, hhi = wbox("holder")
# plate: full height over the connector1 zone (x >= -15), diagonal up to the strut-root zone at the far end
plate = rext([(phi[0], plo[1]), (phi[0], phi[1]), (plo[0], phi[1]), (plo[0], 2.0), (-15.0, plo[1])],
             4.0, plo[2], phi[2])
plate.export("gnode_servo_to_finger.stl")
# connector1: clip to the holder footprint in x
c1 = trimesh.load("gnode_connector1.stl", force="mesh")
clip = trimesh.creation.box(extents=[hhi[0] - hlo[0], 200, 200])
clip.apply_translation([(hlo[0] + hhi[0]) / 2, 0, 0])
c1 = trimesh.boolean.intersection([c1, clip], engine="manifold")
c1.export("gnode_connector1.stl")
# finger_adj: rounded plan outline, planar contact face
pad = rext([(alo[0], alo[1]), (ahi[0], alo[1]), (ahi[0], ahi[1]), (alo[0], ahi[1])], 5.0, alo[2], ahi[2])
pad.export("gnode_finger_adj.stl")
# rebuild the round-trip GLB from the polished gnode set
SKIP = ("yoke_conn", "fixed_conn", "horn_mount", "yoke", "Cube", "cam_conn.001")
EXTRA = ["cam_conn"]
nodes = [n for n in s.graph.nodes_geometry if n not in SKIP] + ["yoke", "yoke_conn", "fixed_conn"] + EXTRA
out = trimesh.Scene()
for node in nodes:
    m = trimesh.load(f"gnode_{node}.stl", force="mesh"); m.apply_scale(0.01)
    out.add_geometry(m, node_name=node, geom_name=node)
out.export("gripper.glb")
print(f"plate wt={plate.is_watertight} c1 wt={c1.is_watertight} pad wt={pad.is_watertight}; gripper.glb rebuilt")
