# -*- coding: utf-8 -*- u"""把一页原理图的全部图元读回成 JSON(跨工程搬版图用)。 /c/Python314/python .claude/r2/dump_page.py 读回的六类: parts [位号, 器件名, 子部件, x, y, rot, mirror, uuid, libraryUuid, 引脚] 引脚 = [[脚号, 脚名, x, y], ...] ← 跨工程重放时的断言基准(§6c:方向表一张都别信) wires [[x1,y1],[x2,y2]] ← **按 §5 的端点对解析**,不是折线 flags [种类, 网名, x, y, rot] 种类 = Power / Ground(按符号名判) ports [dir, 网名, x, y, rot] dir 来自 getState_Component().name(§8b 尾) texts [x, y, 内容, rot, 字号] rects/polys 只数个数(本项目 P2 没有) ⚠️ 只读,不写。切工程会改变客户端的活动工程,跑完记得切回去。 """ import io import json import os import sys HERE = os.path.dirname(os.path.abspath(__file__)) # ⚠ `.claude` 下有和 r2 同名的 R1 脚本(pcb_pour / pcb_rules / pcb_place)。 # 只插父目录的话,**后面任何一个 `import pcb_rules` 都会拿到 R1 那一份**, # 而且不报错,只在调到 R2 专有的函数时才炸(2026-09-08 踩过)。 # 规矩:两行都要写,HERE 后插(在 sys.path 最前)。 sys.path.insert(0, os.path.dirname(HERE)) sys.path.insert(0, HERE) from eda import run # noqa: E402 JS = u""" await eda.dmt_Project.openProject('%(proj)s'); await new Promise(r => setTimeout(r, 2500)); await eda.dmt_EditorControl.openDocument('%(page)s'); await new Promise(r => setTimeout(r, 2500)); const cur = await eda.dmt_Schematic.getCurrentSchematicPageInfo(); const parts = [], flags = [], ports = []; for (const c of await eda.sch_PrimitiveComponent.getAll()) { const t = c.getState_ComponentType(); const x = c.getState_X(), y = c.getState_Y(), r = c.getState_Rotation(); const comp = c.getState_Component() || {}; if (t === 'part') { const pins = (await c.getAllPins()).map(p => [p.getState_PinNumber(), (p.getState_PinName ? p.getState_PinName() : ''), Math.round(p.getState_X()), Math.round(p.getState_Y())]); parts.push([c.getState_Designator(), comp.name, c.getState_SubPartName(), x, y, r, !!c.getState_Mirror(), comp.uuid, comp.libraryUuid, pins]); } else if (t === 'netflag') { flags.push([comp.name, c.getState_Net(), x, y, r]); } else if (t === 'netport') { ports.push([comp.name, c.getState_Net(), x, y, r]); } } const wires = []; for (const w of await eda.sch_PrimitiveWire.getAll()) { const p = w.getState_Line(); for (let i = 0; i + 1 < p.length; i += 2) wires.push([p[i], p[i + 1]]); } const texts = []; for (const t of await eda.sch_PrimitiveText.getAll()) { texts.push([t.getState_X(), t.getState_Y(), t.getState_Content(), t.getState_Rotation(), t.getState_FontSize()]); } return {page: cur && cur.name, parts, flags, ports, wires, texts, nRect: (await eda.sch_PrimitiveRectangle.getAll()).length, nPoly: (await eda.sch_PrimitivePolygon.getAll()).length}; """ def main(): proj, page, out = sys.argv[1], sys.argv[2], sys.argv[3] r = run(JS % {'proj': proj, 'page': page}, timeout=300) if not r.get('success'): raise SystemExit(json.dumps(r, ensure_ascii=False)[:600]) d = r['result'] io.open(out, 'w', encoding='utf-8').write( json.dumps(d, ensure_ascii=False, indent=1)) print(u'页 %s:元件 %d / 导线段 %d / 旗 %d / 端口 %d / 文字 %d / 矩形 %d / 多边形 %d' % (d['page'], len(d['parts']), len(d['wires']), len(d['flags']), len(d['ports']), len(d['texts']), d['nRect'], d['nPoly'])) print(u'-> ' + out) if __name__ == '__main__': main()