初始导入: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
这个提交包含在:
+70
@@ -0,0 +1,70 @@
|
||||
import fitz, math
|
||||
from collections import defaultdict
|
||||
|
||||
TOL = 0.6
|
||||
WIRE_COLORS = {(1.0,0.0,0.0), (0.5,0.0,0.25)} # red pin stubs + maroon wires
|
||||
|
||||
class DSU:
|
||||
def __init__(s): s.p={}
|
||||
def find(s,x):
|
||||
s.p.setdefault(x,x)
|
||||
while s.p[x]!=x:
|
||||
s.p[x]=s.p[s.p[x]]; x=s.p[x]
|
||||
return x
|
||||
def union(s,a,b):
|
||||
ra,rb=s.find(a),s.find(b)
|
||||
if ra!=rb: s.p[ra]=rb
|
||||
|
||||
def segs_of_page(page):
|
||||
out=[]
|
||||
for d in page.get_drawings():
|
||||
col=d.get('color')
|
||||
if col is None: continue
|
||||
c=tuple(round(v,3) for v in col)
|
||||
if c not in WIRE_COLORS: continue
|
||||
for it in d['items']:
|
||||
if it[0]=='l':
|
||||
p,q=it[1],it[2]
|
||||
out.append(((p.x,p.y),(q.x,q.y)))
|
||||
return [s for s in out if math.dist(s[0],s[1])>0.05]
|
||||
|
||||
def on_seg(p,a,b,tol=TOL):
|
||||
(px,py),(ax,ay),(bx,by)=p,a,b
|
||||
dx,dy=bx-ax,by-ay
|
||||
L2=dx*dx+dy*dy
|
||||
if L2==0: return False
|
||||
t=((px-ax)*dx+(py-ay)*dy)/L2
|
||||
if t<-1e-9 or t>1+1e-9: return False
|
||||
cx,cy=ax+t*dx,ay+t*dy
|
||||
return math.hypot(px-cx,py-cy)<=tol
|
||||
|
||||
|
||||
def junction_dots(page):
|
||||
out=[]
|
||||
for d in page.get_drawings():
|
||||
f=d.get('fill')
|
||||
if d['type']=='fs' and f and abs(f[0]-1)<.01 and f[1]<.01 and abs(f[2]-1)<.01:
|
||||
r=d['rect']; out.append(((r.x0+r.x1)/2,(r.y0+r.y1)/2))
|
||||
return out
|
||||
|
||||
def nets(page):
|
||||
segs=segs_of_page(page)
|
||||
dsu=DSU()
|
||||
key=lambda p:(round(p[0]*2)/2, round(p[1]*2)/2)
|
||||
for a,b in segs: dsu.union(key(a),key(b))
|
||||
for i,(a,b) in enumerate(segs):
|
||||
for p in (a,b):
|
||||
for j,(c,e) in enumerate(segs):
|
||||
if i==j: continue
|
||||
if on_seg(p,c,e):
|
||||
dsu.union(key(p),key(c)); dsu.union(key(p),key(e))
|
||||
for dc in junction_dots(page):
|
||||
hit=[]
|
||||
for a,b in segs:
|
||||
if on_seg(dc,a,b,tol=1.4): hit.append((a,b))
|
||||
for a,b in hit[1:]:
|
||||
dsu.union(key(a),key(hit[0][0])); dsu.union(key(b),key(hit[0][0]))
|
||||
comp=defaultdict(set)
|
||||
for a,b in segs:
|
||||
for p in (a,b): comp[dsu.find(key(p))].add(key(p))
|
||||
return segs,dsu,key,comp
|
||||
在新工单中引用
屏蔽一个用户