main
John Lauer KiCad's library model checked against ams' limits and kept (foot 0.529 mm at the gauge plane, in 0.45..0.75); four LODs… cb10da4 12d ago
#!/usr/bin/env python3
"""Measure a gull-wing package STEP: overall extents, body size above the leads, foot widths/pitch.
usage: dims.py part.step z_body z_foot   (prints JSON)"""
import sys, json, cadquery as cq
from OCP.BRepAlgoAPI import BRepAlgoAPI_Section
from OCP.gp import gp_Pln, gp_Pnt, gp_Dir
s = cq.importers.importStep(sys.argv[1]).val()
zb, zf = float(sys.argv[2]), float(sys.argv[3])
def sect(z):
    sec = BRepAlgoAPI_Section(s.wrapped, gp_Pln(gp_Pnt(0, 0, z), gp_Dir(0, 0, 1))); sec.Build()
    return cq.Shape.cast(sec.Shape())
bb = s.BoundingBox()
b = sect(zb).BoundingBox()
edges = sect(zf).Edges()
# cluster foot edges into feet by connectivity of bboxes
boxes = [e.BoundingBox() for e in edges]
feet = []
for e in boxes:
    for f in feet:
        if e.xmin <= f[2] + 1e-3 and e.xmax >= f[0] - 1e-3 and e.ymin <= f[3] + 1e-3 and e.ymax >= f[1] - 1e-3:
            f[0], f[1], f[2], f[3] = min(f[0], e.xmin), min(f[1], e.ymin), max(f[2], e.xmax), max(f[3], e.ymax); break
    else:
        feet.append([e.xmin, e.ymin, e.xmax, e.ymax])
# merge passes
changed = True
while changed:
    changed = False
    for i in range(len(feet)):
        for j in range(i + 1, len(feet)):
            a, c = feet[i], feet[j]
            if a[0] <= c[2] + 1e-3 and a[2] >= c[0] - 1e-3 and a[1] <= c[3] + 1e-3 and a[3] >= c[1] - 1e-3:
                feet[i] = [min(a[0], c[0]), min(a[1], c[1]), max(a[2], c[2]), max(a[3], c[3])]; del feet[j]; changed = True; break
        if changed: break
# left row (min x) feet
left = sorted([f for f in feet if f[0] < bb.xmin + 0.05], key=lambda f: f[1])
widths = [round(f[3] - f[1], 3) for f in left]
cent = [(f[1] + f[3]) / 2 for f in left]
pitch = [round(cent[i + 1] - cent[i], 3) for i in range(len(cent) - 1)]
foot_len = [round(f[2] - f[0], 3) for f in left]
print(json.dumps(dict(overall=dict(x=round(bb.xlen, 3), y=round(bb.ylen, 3), z=round(bb.zmax - bb.zmin, 3), zmin=round(bb.zmin, 3)),
    body_at_z=zb, body=dict(x=round(b.xlen, 3), y=round(b.ylen, 3)), feet_total=len(feet), left_row=len(left),
    lead_width=sorted(set(widths)), pitch=sorted(set(pitch)), foot_len_at_z=sorted(set(foot_len))), indent=None))