mohan-bee/stm32-midi-keys
Clips rectangular ground-region geometry to fit within the board’s scaled rounded-edge outline using polygon intersection.
- Version
- 1.0.2
- License
- unset
- Stars
- 0
scripts/validation-summary.py
import json, math
from collections import Counter
from pathlib import Path
d=json.loads(Path('dist/index/circuit.json').read_text())
reference=json.loads(Path('board.circuit.json').read_text())
source={x['source_component_id']:x['name'] for x in d if x['type']=='source_component'}
original_source={x['source_component_id']:x['name'] for x in reference if x['type']=='source_component'}
original_components={original_source[x['source_component_id']]:x for x in reference if x['type']=='pcb_component'}
positions=[]
pad_errors=[]
for c in (x for x in d if x['type']=='pcb_component'):
name=source[c['source_component_id']]
delta=math.dist(list(c['center'].values()),list(original_components[name]['center'].values()))
if delta>1e-6: positions.append({'component':name,'delta_mm':delta})
expected=[p for p in reference if p.get('pcb_component_id')==original_components[name]['pcb_component_id'] and p['type'] in ['pcb_smtpad','pcb_plated_hole','pcb_hole']]
actual=[p for p in d if p.get('pcb_component_id')==c['pcb_component_id'] and p['type'] in ['pcb_smtpad','pcb_plated_hole','pcb_hole']]
for p in expected:
if p.get('shape')=='polygon':
found=any(q.get('shape')=='polygon' and len(q.get('points',[]))==len(p['points']) and all(math.dist(list(a.values()),list(b.values()))<1e-6 for a,b in zip(p['points'],q['points'])) for q in actual)
else:
found=any('x' in q and math.hypot(p['x']-q['x'],p['y']-q['y'])<1e-6 for q in actual)
if not found: pad_errors.append({'component':name,'pad':p.get('port_hints'),'type':p['type']})
counts=Counter(x['type'] for x in d)
netnames={x['source_net_id']:x['name'] for x in d if x['type']=='source_net'}
electrodes={netnames.get(x.get('source_net_id')) for x in d if x['type']=='pcb_copper_pour'}
electrodes={n for n in electrodes if n and n.startswith('Keys_PAD_')}
errors={k:v for k,v in counts.items() if 'error' in k}
summary={'nativeComponentCount':counts['pcb_component'],'padAndHolePositionMismatches':pad_errors,'boundingBoxCenterVersusKiCadAnchorDifferences':positions,'schematicElementCount':sum(v for k,v in counts.items() if k.startswith('schematic_')),'nativeTouchElectrodeNets':sorted(electrodes),'nativeTraceCount':counts['pcb_trace'],'nativeViaCount':counts['pcb_via'],'errorsByType':errors,'fabricationReady':False}
Path('validation/summary.json').write_text(json.dumps(summary,indent=2))
print(json.dumps(summary,indent=2))
assert counts['pcb_component']==86 and not pad_errors
assert summary['schematicElementCount']==0
assert len(electrodes)==14, 'Native output lost a touch electrode'