R2:底板 / 刀片布局布线脚本、快照、截图与规划文档更新(含外壳、打印件、布线归档)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
+37
-6
@@ -148,8 +148,18 @@ def seg_dist(px, py, x1, y1, x2, y2):
|
||||
return math.hypot(px - (x1 + t * dx), py - (y1 + t * dy))
|
||||
|
||||
|
||||
TRACKS_SNAP = os.path.join(HERE, '_blade_board_tracks.json')
|
||||
STITCH_PTS = os.path.join(HERE, '_blade_stitch_pts.json')
|
||||
|
||||
|
||||
def board_tracks():
|
||||
u"""从板上读回所有铜层导线 [(x1,y1,x2,y2,半宽)],用来给缝合过孔让路。"""
|
||||
u"""从板上读回所有铜层导线 [(x1,y1,x2,y2,半宽)],用来给缝合过孔让路。
|
||||
|
||||
⚠ 2026-09-11:缝合孔落点是「扫孔位」,按 CLAUDE.md 也只在服务器上算。服务器上没有桥接 ⇒
|
||||
读本机 `--snapshot-tracks` 写的快照(remote_blade.sh MODE=stitch 自动先抓)。
|
||||
"""
|
||||
if os.environ.get('DCDC_ROUTE_SERVER'):
|
||||
return [tuple(t) for t in json.load(io.open(TRACKS_SNAP, encoding='utf-8'))]
|
||||
r = run(OPEN + "return (await eda.pcb_PrimitiveLine.getAll()||[])"
|
||||
".filter(l=>[1,2,15,16].includes(l.layer))"
|
||||
".map(l=>[l.startX,l.startY,l.endX,l.endY,l.lineWidth]);", timeout=300)
|
||||
@@ -228,13 +238,24 @@ def stitch_points():
|
||||
|
||||
|
||||
def stitch():
|
||||
pts = stitch_points()
|
||||
print(u'GND 缝合过孔 %d 个(%g mm 网格)' % (len(pts), STITCH_PITCH))
|
||||
u"""下发缝合过孔 —— **只吃服务器算好的落点**(`_blade_stitch_pts.json`),本机不扫孔位。"""
|
||||
if not os.path.exists(STITCH_PTS):
|
||||
sys.exit(u'⛔ 没有 %s:先 MODE=stitch bash .claude/r2/remote_blade.sh(服务器上算落点)'
|
||||
% os.path.basename(STITCH_PTS))
|
||||
pts = [tuple(p) for p in json.load(io.open(STITCH_PTS, encoding='utf-8'))]
|
||||
print(u'GND 缝合过孔 %d 个(%g mm 网格,服务器算的)' % (len(pts), STITCH_PITCH))
|
||||
# ⛔ 2026-09-11:原来是「删掉板上**所有** GND 孔再打」—— 连布线器自己的 GND 孔一起删了:
|
||||
# 金手指地指母线(BUS_Y 7.0 / 8.2)上那 23 个孔是地指下到 L2 的**唯一**通路(外层铜面从 y 11.5 才开始),
|
||||
# 删掉之后地指只剩母线挂着,DRC 未必报、board_check 也看不出(地指挨着母线的铜)。
|
||||
# ⇒ 只删「不在布线缓存里」的 GND 孔(= 上一轮的缝合孔),缓存里的原样留着。
|
||||
cache = json.load(io.open(os.path.join(HERE, '_blade_routes.json'), encoding='utf-8'))
|
||||
keep = [[v[0], v[1]] for v in cache['vias'] if v[2] == 'GND']
|
||||
JS = OPEN + u"""
|
||||
const MIL = %s, P = %s, D = %s, H = %s;
|
||||
const MIL = %s, P = %s, D = %s, H = %s, K = %s;
|
||||
const isKeep = v => K.some(k => Math.abs(k[0]*MIL - v.x) < 0.5 && Math.abs(k[1]*MIL - v.y) < 0.5);
|
||||
let old = 0;
|
||||
for (const v of (await eda.pcb_PrimitiveVia.getAll()||[]))
|
||||
if (String(v.net) === 'GND') { await eda.pcb_PrimitiveVia.delete(v.primitiveId); old++; }
|
||||
if (String(v.net) === 'GND' && !isKeep(v)) { await eda.pcb_PrimitiveVia.delete(v.primitiveId); old++; }
|
||||
let n = 0;
|
||||
for (const p of P) {
|
||||
try { await eda.pcb_PrimitiveVia.create('GND', p[0]*MIL, p[1]*MIL, H*MIL, D*MIL); n++; }
|
||||
@@ -243,7 +264,7 @@ for (const p of P) {
|
||||
await eda.pcb_Document.save();
|
||||
return {deleted: old, made: n,
|
||||
now: (await eda.pcb_PrimitiveVia.getAll()||[]).length};
|
||||
""" % (MIL, json.dumps(pts), VIA_D, VIA_HOLE)
|
||||
""" % (MIL, json.dumps(pts), VIA_D, VIA_HOLE, json.dumps(keep))
|
||||
print(call(JS, timeout=600))
|
||||
|
||||
|
||||
@@ -314,6 +335,16 @@ if __name__ == '__main__':
|
||||
dump_pads()
|
||||
if '--clear' in sys.argv:
|
||||
clear()
|
||||
if '--snapshot-tracks' in sys.argv:
|
||||
t = board_tracks()
|
||||
io.open(TRACKS_SNAP, 'w', encoding='utf-8').write(json.dumps(t))
|
||||
print(u'板上导线快照 %d 段 -> %s' % (len(t), os.path.basename(TRACKS_SNAP)))
|
||||
if '--stitch-plan' in sys.argv:
|
||||
if not os.environ.get('DCDC_ROUTE_SERVER'):
|
||||
sys.exit(u'⛔ 缝合孔落点只在 10.5.5.13 上算:MODE=stitch bash .claude/r2/remote_blade.sh')
|
||||
p = stitch_points()
|
||||
io.open(STITCH_PTS, 'w', encoding='utf-8').write(json.dumps(p))
|
||||
print(u'缝合孔落点 %d 个 -> %s' % (len(p), os.path.basename(STITCH_PTS)))
|
||||
if '--stitch' in sys.argv:
|
||||
stitch()
|
||||
if '--auto' in sys.argv:
|
||||
|
||||
在新工单中引用
屏蔽一个用户