muse/book-reading-clip-lamp

A tscircuit package created by muse.

Version
0.4.6
License
unset
Stars
0

search-94.py

exec(open('find-via-repair.py').read().split('obs=[]')[0].split("c=json.load")[0])
import json,math
c=json.load(open('dist/index/circuit.json'))
# Geometry helpers, independent of netlist labels.
text=open('find-via-repair.py').read();exec(text[text.index('def ds('):text.index('obs=[]')]);exec(text[text.index('def pointclear'):text.index('# Existing adjacent')])
patches=[]
for vid in ['pcb_via_94']:
 v=next(e for e in c if e.get('type')=='pcb_via' and e['pcb_via_id']==vid);target=v['pcb_trace_id'];old=(v['x'],v['y'])
 tr=next(e for e in c if e.get('type')=='pcb_trace' and e['pcb_trace_id']==target)
 idx=next(i for i,p in enumerate(tr['route']) if p['route_type']=='via' and math.hypot(p['x']-old[0],p['y']-old[1])<1e-6)
 a0=tr['route'][idx-8];b0=tr['route'][idx+8];a=(a0['x'],a0['y']);b=(b0['x'],b0['y']);la=a0['layer'];lb=b0['layer'];obs=[]
 for e in c:
  typ=e['type']
  if typ=='pcb_trace' and e['pcb_trace_id']!=target:
   for m,n in zip(e['route'],e['route'][1:]):
    if m['route_type']==n['route_type']=='wire' and m['layer']==n['layer']:
     obs.append(('seg',m['layer'],(m['x'],m['y']),(n['x'],n['y']),max(m['width'],n['width'])/2))
  if typ=='pcb_via' and e.get('pcb_trace_id')!=target:obs.append(('point','all',(e['x'],e['y']),None,e['outer_diameter']/2))
  if typ=='pcb_smtpad' and 'x' in e:
   if e.get('shape')=='circle':obs.append(('point',e['layer'],(e['x'],e['y']),None,e.get('radius',e.get('diameter',0)/2)))
   else:
    x,y=e['x'],e['y'];w=e.get('width',0)/2;h=e.get('height',0)/2;obs.append(('rect',e['layer'],(x-w,y-h),(x+w,y+h),0))
 # Restrict to neighborhood conservatively: anything intersecting candidate/connection bounds remains.
 loX=min(old[0]-3,a[0],b[0])-1;hiX=max(old[0]+3,a[0],b[0])+1;loY=min(old[1]-3,a[1],b[1])-1;hiY=max(old[1]+3,a[1],b[1])+1
 obs=[o for o in obs if not(max(o[2][0],(o[3] or o[2])[0])+o[4]<loX or min(o[2][0],(o[3] or o[2])[0])-o[4]>hiX or max(o[2][1],(o[3] or o[2])[1])+o[4]<loY or min(o[2][1],(o[3] or o[2])[1])-o[4]>hiY)]
 choices=[]
 diagnostics=[]
 for xi in range(round((old[0]-3)*20),round((old[0]+3)*20)+1):
  for yi in range(round((old[1]-3)*20),round((old[1]+3)*20)+1):
   p=(xi/20,yi/20);vc=min(pointclear(p,o)-.3 for o in obs)
   if vc<.17:continue
   lc=min([lineclear(a,p,o)-.075 for o in obs if o[1] in ['all',la]]+[lineclear(p,b,o)-.075 for o in obs if o[1] in ['all',lb]])
   diagnostics.append((lc,p,vc))
   if lc>=.149:choices.append((math.dist(p,old),p,vc,lc))
 if not choices:
  print('NO CANDIDATES',vid,'best',sorted(diagnostics,reverse=True)[:3], 'anchor_clear',min(pointclear(a,o)-.075 for o in obs if o[1] in ['all',la]),min(pointclear(b,o)-.075 for o in obs if o[1] in ['all',lb]))
  if diagnostics:
   p=max(diagnostics)[1]; print('WORST',min([(lineclear(a,p,o)-.075,o,'A') for o in obs if o[1] in ['all',la]]+[(lineclear(p,b,o)-.075,o,'B') for o in obs if o[1] in ['all',lb]],key=lambda x:x[0]))
  continue
 best=min(choices);p=best[1];print(vid,target,'old',old,'new',p,'clearances',best[2:],'choices',len(choices))
 patches.append({'traceId':target,'from':{'x':old[0],'y':old[1]},'to':{'x':p[0],'y':p[1]}})
 for pt in tr['route'][idx-1:idx+2]:pt['x'],pt['y']=p
 v['x'],v['y']=p
open('candidate-94.json','w').write(json.dumps(patches,indent=2)+'\n')