# -*- coding: utf-8 -*- u"""下发后逐孔对位置:板上的布线过孔是不是落在缓存给的位置上。 /c/Python314/python .claude/r2/via_check.py 为什么要查:2026-09-10 发现 USB3 掉头的 USB3_DM 孔在板上比缓存偏了 (−0.127, +0.127) = 正好一格 5 mil, 原因不明。孔偏了、线端没偏 ⇒ 线和孔之间只剩擦边,`board_check` 按「挨着就算连上」未必报。 缝合孔(GND、在 `pour_base` 的 4 mm 网格上)不在缓存里,单独计数、不参与对账。 """ import io import json import math import os import sys sys.stdout.reconfigure(encoding='utf-8') HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.dirname(HERE)) sys.path.insert(0, HERE) from eda import run # noqa: E402 import pcb_base as B # noqa: E402 import pour_base as PO # noqa: E402 TOL = 0.01 JS = u""" await eda.dmt_EditorControl.openDocument('%s'); await new Promise(r=>setTimeout(r,1500)); return ((await eda.pcb_PrimitiveVia.getAll()) || []).map(v => [v.x / %s, v.y / %s, String(v.net || '')]); """ % (B.PCB, B.MIL, B.MIL) def main(): r = run(JS, timeout=300) if not r.get('success'): sys.exit(u'读回过孔失败: ' + json.dumps(r, ensure_ascii=False)[:300]) board = r['result'] cache = json.load(io.open(os.path.join(HERE, '_base_routes.json'), encoding='utf-8'))['vias'] off, pitch = PO.INSET + 2.0, PO.STITCH_PITCH def on_stitch(v): return v[2] == 'GND' and all(abs((t - off) / pitch - round((t - off) / pitch)) < 1e-3 for t in v[:2]) used = [False] * len(cache) moved, extra, n_st = [], [], 0 for v in board: best, bd = None, 1e9 for i, m in enumerate(cache): if m[2] == v[2] and not used[i]: d = math.hypot(m[0] - v[0], m[1] - v[1]) if d < bd: best, bd = i, d if best is not None and bd < TOL: used[best] = True elif on_stitch(v): n_st += 1 elif best is not None and bd < 0.5: used[best] = True moved.append((v, cache[best], bd)) else: extra.append(v) missing = [cache[i] for i in range(len(cache)) if not used[i]] print(u'板上 %d 孔 = 对上缓存 %d + 缝合 %d + 位置偏了 %d + 缓存里没有 %d;缓存里有、板上没有 %d' % (len(board), sum(used) - len(moved), n_st, len(moved), len(extra), len(missing))) for v, m, d in moved: print(u' 偏了 %-12s 板上 (%.3f, %.3f) 缓存 (%.3f, %.3f) 差 %.3f' % (v[2], v[0], v[1], m[0], m[1], d)) for v in extra[:20]: print(u' 多出 %-12s (%.3f, %.3f)' % (v[2], v[0], v[1])) for m in missing[:20]: print(u' 缺了 %-12s (%.3f, %.3f)' % (m[2], m[0], m[1])) ok = not moved and not extra and not missing print(u'[OK] 布线过孔逐个对上' if ok else u'[X] 过孔位置对不上') return ok if __name__ == '__main__': sys.exit(0 if main() else 1)