skill:solidworks-assembly 实测笔记与脚本、easyeda-sch-geometry 补充

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
zhou yang
2026-10-04 19:24:42 +08:00
共同撰写人 Claude Opus 5.5
父节点 22a255acd7
当前提交 cd01640c40
共修改 8 个文件,包含 2283 行新增和 1 行删除
@@ -0,0 +1,152 @@
# -*- coding: utf-8 -*-
u"""量 PCIE 插槽**顶面开口**的真实长宽 —— 判断刀片舌头 36.0 插不插得进。
为什么不能用碰撞法:插槽模型把簧片触点建成了**刚性**的,两排触点自由间隙只有
1.22 mm,而 STEP 里刀片板厚 1.67 ⇒ 干涉检查在任何位置都报"插不进",
与舌头宽度无关。所以必须**直接量开口**。
两条互相独立的口径(两个都给,不一致就说明哪条的假设不成立):
A. 顶面那个平面的**内环**(inner loop)包围盒 = 开口轮廓
B. 落在卡槽通道里(|y − 通道中心| 小)的所有面的 x 并集 = 通道长度
⛔ 全程不碰 IInterferenceDetectionMgr(NOTES §24)。
"""
import io, re, subprocess, sys, time
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
import pythoncom
import win32com.client as wc
BASE_STEP = r'D:\DCDC\新建文件夹\3D_BASE-PCB_2026-09-12.step'
def prop(o, name):
u"""0 参成员:多数是属性,但 GetFaces / GetLoops 这类是方法(NOTES §25)。
⛔ 不能用 callable() 判断(COM 对象一律 callable,§2),只认 python 方法类型。"""
v = getattr(o, name)
if type(v).__name__ in ('method', 'function', 'builtin_function_or_method'):
return v()
return v
def D(x):
return x if hasattr(x, '_oleobj_') else wc.Dispatch(x)
def sw_pids():
out = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq SLDWORKS.EXE', '/FO', 'CSV', '/NH'],
capture_output=True, text=True, encoding='gbk', errors='ignore').stdout
return sorted(re.findall(r'"SLDWORKS\.exe","(\d+)"', out, re.I))
app = None
try:
app = wc.GetActiveObject('SldWorks.Application')
print(u'✅ 复用现有实例(文档数 %s)' % app.GetDocumentCount)
except Exception as e:
print(u'✗ 连不上 (%s) → 自愈' % str(e)[:50])
if sw_pids():
subprocess.run(['taskkill', '/F', '/IM', 'SLDWORKS.exe'], capture_output=True)
time.sleep(4)
for k in range(20):
try:
app = wc.Dispatch('SldWorks.Application'); app.Visible = True
_ = app.RevisionNumber; break
except Exception:
if k == 19: raise
time.sleep(5)
if app.GetDocumentCount == 0:
print(u'导入底板 STEP…')
data = app.GetImportFileData(BASE_STEP)
err = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
t0 = time.time(); app.LoadFile4(BASE_STEP, 'r', data, err)
print(u' err=%s %.1fs' % (err.value, time.time() - t0))
part = None
for d in app.GetDocuments:
try:
if d.GetType == 1 and 'PCIE' in d.GetTitle.upper() and '64P11L' in d.GetTitle.upper():
part = d; break
except Exception:
pass
if part is None:
print(u'⛔ 没找到插槽零件'); sys.exit(1)
print(u'零件: %s' % part.GetTitle)
# 取面数最多的那个实体 = 塑料壳
shell, nmax = None, -1
for bd in part.GetBodies2(0, True):
b = D(bd)
try:
n = len(prop(b, 'GetFaces'))
except Exception:
continue
if n > nmax:
shell, nmax = b, n
print(u'塑料壳实体:%d 个面' % nmax)
faces = prop(shell, 'GetFaces')
# ── 找顶面(法线 +Z、z 最高的平面)───────────────────────────────────
top, topz = None, -1e9
info = []
for f in faces:
fc = D(f)
try:
s = prop(fc, 'GetSurface')
if not prop(s, 'IsPlane'):
continue
nz = list(prop(s, 'PlaneParams'))[2]
fb = [v * 1000 for v in prop(fc, 'GetBox')]
info.append((fc, nz, fb))
if nz > 0.99 and fb[5] > topz:
top, topz = fc, fb[5]
except Exception:
continue
print(u'顶面 z = %.3f' % topz)
# ── 口径 A:顶面的内环 ───────────────────────────────────────────────
print(u'\n=== 口径 A:顶面的环(内环 = 开口)===')
try:
loops = prop(top, 'GetLoops')
print(u' 共 %d 个环' % len(loops))
for li, lp in enumerate(loops):
L = D(lp)
try:
outer = prop(L, 'IsOuter')
except Exception:
outer = '?'
xs, ys = [], []
try:
for e in prop(L, 'GetEdges'):
E = D(e)
try:
cp = list(prop(E, 'GetCurveParams2'))
pts = [(cp[0], cp[1], cp[2]), (cp[3], cp[4], cp[5])]
except Exception:
pts = []
for p in pts:
xs.append(p[0] * 1000); ys.append(p[1] * 1000)
except Exception as ex:
print(u' 环%d 取边失败 %s' % (li, str(ex)[:50])); continue
if xs:
print(u' 环%-2d 外环=%-5s x %8.3f~%8.3f (%6.3f) y %7.3f~%7.3f (%5.3f)'
% (li, outer, min(xs), max(xs), max(xs) - min(xs),
min(ys), max(ys), max(ys) - min(ys)))
except Exception as e:
print(u' ⛔ 取环失败: %s' % str(e)[:90])
# ── 口径 B:卡槽通道里所有面的 x 并集 ────────────────────────────────
print(u'\n=== 口径 B:卡槽通道内各面的 x 并集 ===')
YC = 0.74 # 通道中心线(由两排触点 -0.56 / +2.04 推出)
for halfw in (0.7, 0.9, 1.2):
xs = []
for fc, nz, fb in info:
ymid = (fb[1] + fb[4]) / 2.0
if abs(ymid - YC) < halfw and fb[5] > 1.5 and fb[2] < topz + 0.01:
xs.append(fb[0]); xs.append(fb[3])
if xs:
print(u' |y−%.2f|<%.1f ⇒ x %8.3f ~ %8.3f,通道长 **%.2f mm**'
% (YC, halfw, min(xs), max(xs), max(xs) - min(xs)))
print(u'\n对照:刀片舌头 36.00 mm(TONGUE_X0/X1 = 27.0/63.0,板局部)')
print(u' 塑料体全长 41.00 mm,顶面平面跨度 39.00 mm')