master
John Lauer Preserve BQ independent routing, narration and native copper-retention evidence a4b7711 1mo ago
import json,sys,math
from geometry import Geometry,ROOT
from plan import connect
source=ROOT/(sys.argv[1] if len(sys.argv)>1 else 'pass-03');out=ROOT/(sys.argv[2] if len(sys.argv)>2 else 'repair-01');out.mkdir(exist_ok=False)
r=json.loads((source/'candidate-plan.json').read_text());m=Geometry()
for q in r['routes']:m.add_route(q['net'],[(p['layer'],p['points'],p['width']) for p in q['parts']],q['vias'])
# Recompute connected pad groups from generated copper, including same-net branches.
from shapely.ops import unary_union
from shapely.geometry import Point
from shapely.strtree import STRtree

def components(net):
 pads=m.groups[net];parent=list(range(len(pads)))
 def find(i):
  while parent[i]!=i:i=parent[i]
  return i
 shapes=[(p['shape'],p['layers']) for p in pads]+[(g,[l]) for n,l,g in m.copper if n==net]
 parent=list(range(len(shapes)))
 for i,(s,ls) in enumerate(shapes):
  for j in range(i):
   t,ts=shapes[j]
   if set(ls)&set(ts) and s.intersection(t).area>1e-8:parent[find(i)]=find(j)
 # Through vias connect their four layer shapes via a shared position.
 for v in m.vias:
  if v['net']!=net:continue
  hit=[i for i,(s,ls) in enumerate(shapes) if s.covers(Point(v['at']))]
  for i in hit[1:]:parent[find(i)]=find(hit[0])
 return [find(i) for i in range(len(pads))]
priority=['ACDRV2','ACDRV1','!QON']
for net in sorted(m.groups,key=lambda n:(priority.index(n) if n in priority else 99,n)):
 if len(set(components(net)))==1:continue
 pads=m.groups[net]
 pairs=sorted([(math.dist(a['at'],b['at']),i,j) for i,a in enumerate(pads) for j,b in enumerate(pads[:i])])
 for _,i,j in pairs:
  c=components(net)
  if c[i]==c[j]:continue
  result=connect(m,pads[i],pads[j],net,.15,True)
  print(net,pads[i]['name'],pads[j]['name'],bool(result),flush=True)
  if result:m.add_route(net,*result)
  (out/'candidate-plan.json').write_text(json.dumps({'status':'experimental - native validation pending','routes':m.routes},indent=2));m.export(out/'bq25792-astra-candidate.brd')
print({n:len(set(components(n))) for n in m.groups},flush=True)