main
John Lauer Place all ESC references close to parts, including every test point; preserve native DRC evidence ce6eaaa 20d ago
from pathlib import Path
import json,math,uuid
D=Path(__file__).parent
code=(D/'layout.py').read_text().split('# Reference association')[0]
code=code.replace('.buffer(.06)', '.buffer(.01)').replace('max(.6,max(map(len,lines))*size*.82)','max(.25,max(map(len,lines))*size*.82)')
code=code.replace('for gap in [.15,.3,.5', 'for gap in [.02,.05,.1,.15,.3,.5')
ns={'__file__':str(D/'layout.py')};exec(code,ns)
box=ns['box'];rotate=ns['rotate'];translate=ns['translate'];LineString=ns['LineString']
manifest=json.load(open(D/'labels-v11.json'));original=manifest['labels'];labels=ns['labels'];labels[:]=original
ns['leaders'][:]=manifest['leaders'];placed=ns['placed']
for side in placed:placed[side]=[]
for l in labels:
 lines=l['text'].split('\n');w=max(.25,max(map(len,lines))*l['size']*.82);h=l['size']*1.5*len(lines)
 g=translate(rotate(box(-w/2,-h/2,w/2,h/2),l.get('angle',0),origin=(0,0)),l['x'],l['y']);placed[l['layer']].append(g)
for v in ns['leaders']:placed['F.SilkS'].append(LineString([v['start'],v['end']]).buffer(.12))
initial=len(labels);p=next(p for p in ns['parts'] if p['ref']=='C9');ok=False
for size in [.3,.25,.2]:
 if ns['close_label'](p,'C9',size,'close reference in dense cluster'):ok=True;break
print('C9',ok,labels[-1] if ok else '',flush=True)
# Small paired values, collision checked against all front labels and leaders.
for p in ns['parts']:
 r=p['ref'];v=p['value']
 if not r.startswith(('R','C')):continue
 own=next((l for l in labels if l.get('reference')==r),None)
 if not own or own.get('angle',0):continue
 value=v+('F' if r.startswith('C') and v[-1:] in ['u','n','p'] else '')
 for sz in [.5,.3,.2]:
  good=False
  for dy in [own['size']*.75+sz*.75+.18,-own['size']*.75-sz*.75-.18]:
   x,y=own['x'],own['y']+dy;g=box(x-len(value)*sz*.82/2,y-sz*.75,x+len(value)*sz*.82/2,y+sz*.75)
   if g.distance(p['geom'])>1.8:continue
   if ns['add'](value,x,y,sz,source=r+' actual board property',role='paired value'):
    labels[-1]['reference']=r;good=True;break
  if good:break
j=next(p for p in ns['parts'] if p['ref']=='J1')
for ii,(pin,net) in enumerate(j['nets']):
 source='J1 pad '+pin+' actual net'
 if any(l['layer']=='F.SilkS' and l['source']==source for l in labels):continue
 text=pin+' '+('NC' if net.startswith('unconnected') else ns['clean'](net).replace('UART ','U'))
 assert ns['add'](text,153.2+(ii%2)*7.5,69.2+(ii//2)*.85,.4,source=source,role='interface key'),source
new=[]
for l in labels[initial:]:
 mirror=' (justify mirror)' if l['layer']=='B.SilkS' else ''
 new.append(f'(gr_text {json.dumps(l["text"])} (at {l["x"]} {l["y"]} {l.get("angle",0)}) (layer "{l["layer"]}") (uuid "{uuid.uuid5(uuid.NAMESPACE_URL,json.dumps(l,sort_keys=True))}") (effects (font (size {l["size"]} {l["size"]}) (thickness {min(.08,l["size"]*.15)})){mirror}))')
for line in ns['leaders'][len(manifest['leaders']):]:
 new.append(f'(gr_line (start {line["start"][0]:.4f} {line["start"][1]:.4f}) (end {line["end"][0]:.4f} {line["end"][1]:.4f}) (stroke (width 0.10) (type default)) (layer "F.SilkS") (uuid "{uuid.uuid5(uuid.NAMESPACE_URL,json.dumps(line,sort_keys=True))}"))')
src=D/'esc-g431-astra-silkscreen-v11.kicad_pcb';out=D/'esc-g431-astra-silkscreen-v13.kicad_pcb';out.write_text(src.read_text().rstrip()[:-1]+'\n'+'\n'.join(new)+'\n)\n')
manifest.update(board=str(out),labels=labels,leaders=ns['leaders']);manifest['omittedNearby']=[v for v in manifest['omittedNearby'] if not(ok and v['ref']=='C9')];manifest['notes']=['Artwork font sizes include 0.2mm; physical process legibility not measured.','Non-silkscreen geometry unchanged. Passive outline strokes removed only where redundant; polar capacitor markings retained.'];(D/'labels.json').write_text(json.dumps(manifest,indent=2));print('total',len(labels),'missing',manifest['omittedNearby'],'newvalues',len(labels)-initial-int(ok))