sync: HP_BOWEI 2026-09-09

This commit is contained in:
Myfro9
2026-09-09 09:51:06 +08:00
parent 01b7a00b12
commit 170f4eb53f
10 changed files with 1926 additions and 5 deletions
+100
View File
@@ -0,0 +1,100 @@
"""dump_kicad_vec.py — 把 KiCad 板的离散几何导成 JSON,供 cmp_vec.py 比对。必须用 KiCad python 跑。
输出(单位一律 mm,KiCad 原生坐标系:y 向下):
vias.json [{x, y, drill, top, bot, net}]
pads.json [{x, y, layer, net, ref, pad, drill}]
tracks.json [{x1, y1, x2, y2, width, layer, net}]
meta.json {counts, layers}
用法(KiCad python 路径见 ~/skills_env.md 的 KICAD_PYTHON):
D:\\KiCad\\10.0\\bin\\python.exe dump_kicad_vec.py \\
--board E:\\Kicad_design\\FOO\\FOO.kicad_pcb \\
--out E:\\Kicad_design\\FOO\\_migration\\gerber\\kicad_vec
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
def main() -> int:
ap = argparse.ArgumentParser(description="Dump KiCad board discrete geometry to JSON (mm)")
ap.add_argument("--board", required=True)
ap.add_argument("--out", required=True)
args = ap.parse_args()
try:
import pcbnew
except ImportError:
print("[ERROR] 导不到 pcbnew —— 用 KiCad 自带 python 跑(~\\skills_env.md 的 KICAD_PYTHON)。")
return 1
out = Path(args.out)
out.mkdir(parents=True, exist_ok=True)
board = pcbnew.LoadBoard(args.board)
mm = pcbnew.ToMM
def via_size(v) -> float:
"""KiCad 10 起 PCB_VIA::GetWidth() 必须带层参数,不带会断言中止进程。
老版本又只接受无参形式,所以两种都试。size 只是给人看的,取不到就算了。"""
for call in (lambda: v.GetWidth(v.TopLayer()), lambda: v.GetWidth()):
try:
return mm(call())
except Exception:
continue
return 0.0
vias, tracks = [], []
for t in board.GetTracks():
if isinstance(t, pcbnew.PCB_VIA):
vias.append({
"x": mm(t.GetPosition().x), "y": mm(t.GetPosition().y),
"drill": mm(t.GetDrill()), "size": via_size(t),
"top": board.GetLayerName(t.TopLayer()),
"bot": board.GetLayerName(t.BottomLayer()),
"net": t.GetNetname(),
})
else:
tracks.append({
"x1": mm(t.GetStart().x), "y1": mm(t.GetStart().y),
"x2": mm(t.GetEnd().x), "y2": mm(t.GetEnd().y),
"width": mm(t.GetWidth()),
"layer": board.GetLayerName(t.GetLayer()),
"net": t.GetNetname(),
})
pads = []
for fp in board.GetFootprints():
ref = fp.GetReference()
for p in fp.Pads():
pads.append({
"x": mm(p.GetPosition().x), "y": mm(p.GetPosition().y),
"layer": board.GetLayerName(p.GetLayer()),
"net": p.GetNetname(), "ref": ref, "pad": p.GetNumber(),
"drill": mm(p.GetDrillSizeX()),
})
layers = sorted({t["layer"] for t in tracks})
for name, data in (("vias", vias), ("tracks", tracks), ("pads", pads)):
(out / f"{name}.json").write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
(out / "meta.json").write_text(json.dumps({
"units": "mm", "y_axis": "down (KiCad native)",
"counts": {"vias": len(vias), "tracks": len(tracks), "pads": len(pads)},
"copper_layers_with_tracks": layers,
}, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"[dump] vias={len(vias)} tracks={len(tracks)} pads={len(pads)} -> {out}")
print(f"[layers] 有走线的铜层:{', '.join(layers)}")
print("[next] Altium 侧用 eda-agent 导同名 JSON 到 altium_vec/(格式见 "
"references\\vector-compare.md),然后跑 cmp_vec.py。")
return 0
if __name__ == "__main__":
try:
sys.stdout.reconfigure(encoding="utf-8")
except Exception:
pass
sys.exit(main())