"""Extract every screw hole from the ST3215 STEP as exact BREP cylinders, group them,
print exact centers, and write hole_markers.json for visualization. Run with build123d venv."""
import json
from collections import defaultdict
import numpy as np
from build123d import import_step
from OCP.BRepAdaptor import BRepAdaptor_Surface
from OCP.GeomAbs import GeomAbs_Cylinder

STEP = "/data/cameron/repos/cad_experiments/parts/waveshare_feetech_st3215_servo.step"
s = import_step(STEP)
bb = s.bounding_box()
print("bbox min", [round(v, 1) for v in tuple(bb.min)], "max", [round(v, 1) for v in tuple(bb.max)])

cyl = []
for f in s.faces():
    ad = BRepAdaptor_Surface(f.wrapped)
    if ad.GetType() != GeomAbs_Cylinder:
        continue
    c = ad.Cylinder(); ax = c.Axis(); loc = ax.Location(); d = ax.Direction()
    cyl.append((c.Radius(), np.array([loc.X(), loc.Y(), loc.Z()]),
                np.array([d.X(), d.Y(), d.Z()])))


def card(d):
    i = int(np.argmax(np.abs(d)))
    return tuple(int(np.sign(d[i]) if k == i else 0) for k in range(3)), i


groups = defaultdict(list)
for r, p, d in cyl:
    if 1.0 <= r <= 2.5:
        key, i = card(d)
        groups[(key, round(float(p[i])), round(r, 2))].append(p)

out = []
print("\n== hole groups (axis, face@mm, holeR) ==")
for (key, fp, r), pts in sorted(groups.items(), key=lambda kv: -len(kv[1])):
    P = np.unique(np.round(np.array(pts), 1), axis=0)
    if len(P) < 2 or abs(fp) > 30:   # drop singletons + out-of-body artifacts
        continue
    ctr = P.mean(0); spread = float(np.mean(np.linalg.norm(P - ctr, axis=1)))
    print(f"  axis={key} face@{fp} r={r}mm n={len(P)} center={[round(x,1) for x in ctr]} circleR={round(spread,1)}")
    for p in P:
        print(f"       ({p[0]:6.1f},{p[1]:6.1f},{p[2]:6.1f})")
    out.append({"axis": list(key), "face": fp, "r": r, "circleR": round(spread, 1),
                "center": [round(float(x), 2) for x in ctr],
                "pts": [[round(float(v), 2) for v in q] for q in P]})

json.dump(out, open("hole_markers.json", "w"), indent=1)
print(f"\nwrote hole_markers.json ({len(out)} groups)")
