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,173 @@
# -*- coding: utf-8 -*-
u"""量 PCIE 插槽的**可插入深度** —— 卡降到哪里会被挡住。
限制插入深度的有两个独立约束,必须分开算(很容易只算一个就下结论):
1. **槽底**:开口区域内最高的朝上平面。
2. **防呆键筋**:键筋从顶面往下伸多深。刀片缺口只有 NOTCH_D=7.45 深 ——
若键筋比缺口深,卡会被**键筋顶住**,先于槽底停下。
开口尺寸由 slot_opening_measure.py 量得(顶面 z=10.000,x ±17.540,y −0.160~1.640,
键筋 x −5.390~−4.610)。
⛔ 全程不碰 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'
TOP_Z = 10.000 # 塑料体顶面(零件本地)
OPEN_X0, OPEN_X1 = -17.540, 17.540 # 开口 x
OPEN_Y0, OPEN_Y1 = -0.160, 1.640 # 开口 y
KEY_X0, KEY_X1 = -5.390, -4.610 # 防呆键筋 x
BLADE_T = 1.67 # STEP 刀片板厚
NOTCH_D = 7.45 # 刀片缺口深度(fp_edge.NOTCH_D)
# 装配坐标换算(由槽3 反推):assembly_z = part_z + 2.33;底板板面 assembly z = 1.67
Z_OFF, BOARD_TOP = 2.33, 1.67
def prop(o, name):
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)
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 个面\n' % nmax)
# 刀片板料在通道里实际占据的 y 带(按开口中心对中)
yc = (OPEN_Y0 + OPEN_Y1) / 2.0
BY0, BY1 = yc - BLADE_T / 2.0, yc + BLADE_T / 2.0
print(u'开口 y %.3f~%.3f(宽 %.2f);刀片料占 y %.3f~%.3f(厚 %.2f)'
% (OPEN_Y0, OPEN_Y1, OPEN_Y1 - OPEN_Y0, BY0, BY1, BLADE_T))
def ovl(a0, a1, b0, b1):
return min(a1, b1) - max(a0, b0)
up_in_slot, key_faces, all_in = [], [], []
for f in prop(shell, 'GetFaces'):
fc = D(f)
try:
fb = [v * 1000 for v in prop(fc, 'GetBox')]
except Exception:
continue
if fb[2] > TOP_Z - 1e-6: # 完全在顶面及以上,跳过
continue
# 与刀片料所占空间在 x/y 上有重叠的面
if ovl(fb[0], fb[3], OPEN_X0, OPEN_X1) <= 1e-6:
continue
if ovl(fb[1], fb[4], BY0, BY1) <= 1e-6:
continue
nz = None
try:
s = prop(fc, 'GetSurface')
if prop(s, 'IsPlane'):
nz = list(prop(s, 'PlaneParams'))[2]
except Exception:
pass
is_key = ovl(fb[0], fb[3], KEY_X0, KEY_X1) > 1e-6 and (fb[3] - fb[0]) < 2.0
all_in.append((fb[5], fb, nz, is_key))
if is_key:
key_faces.append((fb[5], fb))
elif nz is not None and nz > 0.99:
up_in_slot.append((fb[5], fb))
print(u'\n=== 通道内(与刀片料重叠)的面:按 z 顶端排序,前 14 ===')
all_in.sort(reverse=True)
for z, fb, nz, is_key in all_in[:14]:
print(u' z顶 %7.3f z底 %7.3f x %8.3f~%8.3f y %7.3f~%7.3f 法线z=%s %s'
% (fb[5], fb[2], fb[0], fb[3], fb[1], fb[4],
('%+.2f' % nz) if nz is not None else ' 曲面', u'← 键筋' if is_key else u''))
print(u'\n=== 约束 1:槽底(通道内最高的朝上平面,已排除键筋)===')
if up_in_slot:
up_in_slot.sort(reverse=True)
z, fb = up_in_slot[0]
d1 = TOP_Z - z
print(u' 槽底 z = %.3f x %.3f~%.3f y %.3f~%.3f' % (z, fb[0], fb[3], fb[1], fb[4]))
print(u' ⇒ 槽深(顶面到槽底)= %.2f − %.2f = **%.2f mm**' % (TOP_Z, z, d1))
else:
d1 = None
print(u' ⛔ 通道内没有朝上平面')
print(u'\n=== 约束 2:防呆键筋 ===')
if key_faces:
kz_top = max(k[0] for k in key_faces)
kz_bot = min(k[1][2] for k in key_faces)
kh = kz_top - kz_bot
print(u' 键筋 z %.3f ~ %.3f,高 **%.2f mm**' % (kz_bot, kz_top, kh))
print(u' 刀片缺口深 %.2f ⇒ %s' % (NOTCH_D,
u'缺口比键筋深 %.2f,键筋不限制插入' % (NOTCH_D - kh) if NOTCH_D >= kh
else u'**键筋比缺口深 %.2f,卡会被键筋顶住**' % (kh - NOTCH_D)))
d2 = NOTCH_D if kh > NOTCH_D else None
else:
kh, d2 = None, None
print(u' ⛔ 没识别出键筋面')
print(u'\n=== 结论 ===')
cands = [(u'槽底', d1), (u'防呆键筋', d2)]
cands = [(n, v) for n, v in cands if v is not None]
if cands:
name, d = min(cands, key=lambda t: t[1])
print(u' 实际可插入深度 d = **%.2f mm**(受「%s」限制)' % (d, name))
print(u' ⇒ 刀片底边在底板局部 z = %.2f − %.2f = %.2f'
% (TOP_Z + Z_OFF, d, TOP_Z + Z_OFF - d))
print(u' ⇒ **刀片底边离底板板面 = %.2f mm**(板面 z=%.2f)'
% (TOP_Z + Z_OFF - d - BOARD_TOP, BOARD_TOP))
print(u' ⇒ 对照设计文档写的「抬高约 11 mm」:上限 10.66(完全不插),实际 %.2f'
% (TOP_Z + Z_OFF - d - BOARD_TOP))