Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
7315b96d0This file is pinned to the selected release. Download the original to open it in your design tool.
"""Pure placement geometry (phases 6-9).
Operates on rectangles read back from the real board — never the placer's own grid
model (which shows phantom overlaps). No EDA tool needed; fully testable offline.
A part = {"ref": str, "layer": "TOP"|"BOTTOM", "bbox": [x0, y0, x1, y1]} (mm).
"""
import math
def rect_gap(a, b):
"""Axis-aligned gap (mm) between two bboxes. >=0 = clear (corner distance if
diagonally separated); <0 = overlap penetration depth."""
sx = max(a[0] - b[2], b[0] - a[2])
sy = max(a[1] - b[3], b[1] - a[3])
if sx > 0 and sy > 0:
return math.hypot(sx, sy)
return max(sx, sy)
def spacing_audit(parts, min_gap=0.5, whitelist=()):
"""Same-layer pad-gap check. Returns a list of violations
{a, b, gap, limit}. `whitelist` = iterable of (refA, refB) pairs to skip."""
wl = {frozenset(p) for p in whitelist}
viol = []
n = len(parts)
for i in range(n):
for j in range(i + 1, n):
A, B = parts[i], parts[j]
if A["layer"] != B["layer"]:
continue
if frozenset((A["ref"], B["ref"])) in wl:
continue
g = round(rect_gap(A["bbox"], B["bbox"]), 4)
if g < min_gap - 1e-6:
viol.append({"a": A["ref"], "b": B["ref"], "gap": g, "limit": min_gap})
return viol
def keepout_intrusion(parts, keepouts):
"""Which parts intrude a circular keepout. keepouts = [{"x","y","r"}] (e.g. M2
mounting rings). Returns [{ref, keepout}]."""
hits = []
for p in parts:
x0, y0, x1, y1 = p["bbox"]
for k in keepouts:
nx = min(max(k["x"], x0), x1) # nearest point on the bbox to the centre
ny = min(max(k["y"], y0), y1)
if math.hypot(nx - k["x"], ny - k["y"]) < k["r"]:
hits.append({"ref": p["ref"], "keepout": (k["x"], k["y"], k["r"])})
return hits
def out_of_board(parts, outline, overhang=0.0):
"""Parts whose bbox extends beyond the board outline [x0,y0,x1,y1] by more than
`overhang` (connectors may be whitelisted by giving them a larger overhang)."""
bx0, by0, bx1, by1 = outline
out = []
for p in parts:
x0, y0, x1, y1 = p["bbox"]
if (x0 < bx0 - overhang or y0 < by0 - overhang
or x1 > bx1 + overhang or y1 > by1 + overhang):
out.append(p["ref"])
return out