文件
phonerail/.claude/pcb2_del_box.py
T
zhou yang和Claude Opus 5 2bfe308b30 初始导入:PhoneRail 五路手机直供电源板
原理图/PCB 已在 EasyEDA 里做到 12 页跨页 0 漏接,固件刚完成骨架包 A1。
这次是把已有的一切一次性纳入版本控制,没有改动任何设计内容。

纳入:
- 设计与需求文档、PROGRESS.md、小米8 参考原理图 PDF 与追脚脚本
- .claude/ 下的 EasyEDA 桥接工具链与几何/网表缓存(eda-parts.json、
  pcb-parts.json、pcb-pads.json、p2-ch1.json 等,是重画各页的唯一事实来源)
- 117 张验证截图(本项目所有方向问题都是靠人眼看截图发现的,属于证据不是垃圾)
- firmware/ 的 A1 骨架与 site/ 文档站源码

.gitignore 排除:构建产物(firmware/build、host/build、sdkconfig)、
site/node_modules、__pycache__、桥接日志 _bridge.log、脚本自标的 *.stale。

.gitattributes 默认 `* -text`:现有 .py/.json 大多是 CRLF,原样存,
不让 git 重写行尾。唯一例外是 *.sh 强制 LF —— 带 \r 的 shell 脚本 bash 跑不了。

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QYuExfgyYa6DzRRcUso8M8
2026-09-06 18:18:14 +08:00

95 行
3.6 KiB
Python
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
u"""删掉指定矩形框里的**某个网络**的走线与过孔(板坐标或站内坐标)。
/c/Python314/python .claude/pcb2_del_box.py GND --site 54.9 36.8 56.5 37.5
/c/Python314/python .claude/pcb2_del_box.py GND --board 100 60 102 62
加 `--push` 才真删,不加只列出来。
## 为什么需要它
板上的铜是好几个脚本各画各的(`pcb2_dp_long` / `pcb2_fanout` / `pcb2_vo_vias` / `pcb2_route_sig`),
每个脚本的 `--push` 只删**自己上一轮**画的东西。挪了一个元件之后,
它那颗扇出孔就成了没人认领的孤儿 —— 谁的删除逻辑都不管,DRC 只报一条
「过孔没连上任何东西」,很容易被当成噪声放过去。
## 判据
- **完全落在框里**才删(导线两端都在框内、过孔中心在框内)。半进半出的一律不动,
免得把一条长线截断一半留在板上 —— 那比不删还糟。
- `--site` 是站内坐标,会自动展开到五个手机位(`pcb2_place.to_board`,4/5 站镜像)。
"""
import json
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from eda import run
from pcb2_place import SITES, to_board
PCB = 'f126ffb29c92f9b2'
MIL = 39.3700787401575
def boxes_from_argv():
if '--site' in sys.argv:
i = sys.argv.index('--site')
u0, v0, u1, v1 = [float(v) for v in sys.argv[i + 1:i + 5]]
out = []
for n in SITES:
ax, ay, _ = to_board(n, u0, v0)
bx, by, _ = to_board(n, u1, v1)
out.append((min(ax, bx), min(ay, by), max(ax, bx), max(ay, by)))
return out
i = sys.argv.index('--board')
x0, y0, x1, y1 = [float(v) for v in sys.argv[i + 1:i + 5]]
return [(min(x0, x1), min(y0, y1), max(x0, x1), max(y0, y1))]
JS = u"""
await eda.dmt_EditorControl.openDocument('%s');
await new Promise(r => setTimeout(r, 1500));
const M = 39.3700787401575, q = v => Math.round(v / M * 1e4) / 1e4;
const NET = %s, B = %s, DO = %s;
const inB = (x, y) => B.some(b => x >= b[0] && x <= b[2] && y >= b[1] && y <= b[3]);
const lines = [], vias = [];
for (const l of await eda.pcb_PrimitiveLine.getAll()) {
if ((l.net || '') !== NET) continue;
if (l.layer !== 1 && l.layer !== 2) continue;
if (inB(q(l.startX), q(l.startY)) && inB(q(l.endX), q(l.endY)))
lines.push([l.primitiveId, q(l.startX), q(l.startY), q(l.endX), q(l.endY), l.layer]);
}
for (const v of await eda.pcb_PrimitiveVia.getAll()) {
if ((v.net || '') !== NET) continue;
if (inB(q(v.x), q(v.y))) vias.push([v.primitiveId, q(v.x), q(v.y)]);
}
if (DO) {
if (lines.length) await eda.pcb_PrimitiveLine.delete(lines.map(l => l[0]));
if (vias.length) await eda.pcb_PrimitiveVia.delete(vias.map(v => v[0]));
await eda.pcb_Document.save();
}
return {lines: lines.map(l => l.slice(1)), vias: vias.map(v => v.slice(1)), did: DO};
"""
def main():
net = sys.argv[1]
boxes = boxes_from_argv()
do = '--push' in sys.argv
r = run(JS % (PCB, json.dumps(net), json.dumps(boxes), 'true' if do else 'false'),
timeout=600)
if not r.get('success'):
sys.exit(u'失败: ' + json.dumps(r, ensure_ascii=False)[:400])
x = r['result']
print(u'%s:%d 个框里有 %s 的导线 %d 条 / 过孔 %d 个'
% (u'已删' if do else u'(预览,加 --push 才删)', len(boxes), net,
len(x['lines']), len(x['vias'])))
for l in x['lines'][:20]:
print(u' 线 L%d (%.3f, %.3f) -> (%.3f, %.3f)' % (l[4], l[0], l[1], l[2], l[3]))
for v in x['vias'][:20]:
print(u' 孔 (%.3f, %.3f)' % (v[0], v[1]))
if __name__ == '__main__':
main()