102 行
4.5 KiB
Python
102 行
4.5 KiB
Python
# -*- coding: utf-8 -*-
|
||
u"""下板 PCB1 板框 + 定位孔(2026-09-06 两板对齐版)。
|
||
|
||
/c/Python314/python .claude/pcb1_outline.py --push
|
||
|
||
板框 220 × 135、左下角 (−30,−5)(下板坐标原点不动,= 载板坐标 − (30,5));
|
||
定位孔取 `pcb1_place.MH`(= 载板 `pcb2_place.MH` 减 (30,5),四角 + 两侧中点)。
|
||
原来 `pcb_place.py --outline` 干这件事,但那个单板时代的脚本在 import 时就要找 J2 之类早就删掉的位号,
|
||
跑不起来了;这里把它的 `outline_poly` / `push_outline` 抠出来独立跑(同样的多段线 + MULTI 层自由焊盘写法,
|
||
注意事项见 pcb_place.push_outline 的 docstring)。
|
||
"""
|
||
import json
|
||
import os
|
||
import sys
|
||
|
||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
sys.path.insert(0, HERE)
|
||
from eda import run # noqa: E402
|
||
from pcb1_place import MH, PCB, MIL, MH_HOLE, MH_PAD # noqa: E402
|
||
|
||
# ⚠️ 不能 `from pcb_place import ...`:那个单板时代的脚本在 import 时就跑 put() 表,找不到 J2 直接 assert。
|
||
# 板框常量在这里独立维护(和 pcb_place.py 里的 OX/OY/OW/OH 同值)。
|
||
OX, OY, OW, OH = -30.0, -5.0, 220.0, 135.0
|
||
CORNER_R = 5.0
|
||
|
||
|
||
def outline_poly():
|
||
u"""板框多边形 -> TPCB_PolygonSourceArray(mil),逆时针、四角 R5、末段圆弧回到起点(抄自 pcb_place.outline_poly)。"""
|
||
R = CORNER_R
|
||
X0, Y0, X1, Y1 = OX, OY, OX + OW, OY + OH
|
||
pts = []
|
||
L = lambda x, y: pts.append(('L', x, y))
|
||
A = lambda x, y: pts.append(('ARC', 90.0, x, y))
|
||
start = (X0 + R, Y0)
|
||
L(X1 - R, Y0); A(X1, Y0 + R)
|
||
L(X1, Y1 - R); A(X1 - R, Y1)
|
||
L(X0 + R, Y1); A(X0, Y1 - R)
|
||
L(X0, Y0 + R); A(X0 + R, Y0)
|
||
src, mode = [start[0] * MIL, start[1] * MIL], None
|
||
for q in pts:
|
||
if q[0] == 'L':
|
||
if mode != 'L':
|
||
src.append('L'); mode = 'L'
|
||
src += [q[1] * MIL, q[2] * MIL]
|
||
else:
|
||
src.append('ARC'); mode = 'ARC'
|
||
src += [q[1], q[2] * MIL, q[3] * MIL]
|
||
return [round(v, 4) if isinstance(v, float) else v for v in src]
|
||
|
||
OPEN = ("await eda.dmt_EditorControl.openDocument('%s');"
|
||
"await new Promise(r=>setTimeout(r,1500));" % PCB)
|
||
|
||
|
||
def call(body, timeout=240):
|
||
r = run(OPEN + body, timeout=timeout)
|
||
if not r.get('success'):
|
||
sys.exit(u'下发失败: ' + json.dumps(r, ensure_ascii=False)[:500])
|
||
return r['result']
|
||
|
||
|
||
def main():
|
||
if '--push' not in sys.argv:
|
||
print(u'板框 %.0f×%.0f 左下角 (%.0f,%.0f);定位孔 %s(加 --push 下发)' % (OW, OH, OX, OY, MH))
|
||
return
|
||
n = call("""
|
||
let del = 0;
|
||
for (const l of await eda.pcb_PrimitiveLine.getAll())
|
||
if (l.getState_Layer() === 11) { await eda.pcb_PrimitiveLine.delete(l.getState_PrimitiveId()); del++; }
|
||
for (const p of await eda.pcb_PrimitivePolyline.getAll())
|
||
if (p.getState_Layer() === 11) { await eda.pcb_PrimitivePolyline.delete(p.getState_PrimitiveId()); del++; }
|
||
const poly = await eda.pcb_MathPolygon.createPolygon(%s);
|
||
const r = await eda.pcb_PrimitivePolyline.create('', 11, poly, 5);
|
||
const left = (await eda.pcb_PrimitivePolyline.getAll()).filter(p => p.layer === 11).length;
|
||
return {del, made: r ? r.primitiveId : null, left};
|
||
""" % json.dumps(outline_poly()))
|
||
if n['left'] != 1:
|
||
sys.exit(u'!! layer 11 上有 %d 条多段线,应为 1' % n['left'])
|
||
print(u'板框: %.0f × %.0f,左下角 (%.0f,%.0f),R%.0f;删旧 %d' % (OW, OH, OX, OY, CORNER_R, n['del']))
|
||
k = call("""
|
||
const MH = %s;
|
||
let del = 0;
|
||
for (const p of await eda.pcb_PrimitivePad.getAll()) {
|
||
const num = p.getState_PadNumber();
|
||
let parent = null; try { parent = p.getState_ParentPrimitiveId ? p.getState_ParentPrimitiveId() : null; } catch (e) {}
|
||
if (typeof num === 'string' && num.indexOf('MH') === 0 && !parent) { await eda.pcb_PrimitivePad.delete(p.getState_PrimitiveId()); del++; }
|
||
}
|
||
let k = 0;
|
||
for (let i = 0; i < MH.length; i++) {
|
||
await eda.pcb_PrimitivePad.create(12, 'MH' + (i + 1), MH[i][0], MH[i][1], 0,
|
||
['ELLIPSE', %.2f, %.2f], 'GND', ['ROUND', %.4f], 0, 0, 0, true);
|
||
k++;
|
||
}
|
||
await eda.pcb_Document.save();
|
||
return {del, k};
|
||
""" % (json.dumps([[round(x * MIL, 2), round(y * MIL, 2)] for x, y in MH]),
|
||
MH_PAD * MIL, MH_PAD * MIL, MH_HOLE * MIL))
|
||
print(u'定位孔: 删旧 %d / 新建 %d(Φ%.1f / 焊盘 Φ%.1f / 接 GND)' % (k['del'], k['k'], MH_HOLE, MH_PAD))
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|