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 插槽 3D 模型,是没建腔的实心块,还是真连接器?
结论口径:
实心块 → 实体体积/包围盒 ≈ 1,面数个位~十几 ⇒ 3D **量不出**插入深度 d,
也判不了"舌头是不是比腔长"
真连接器 → 体积比明显 <1,面数几百 ⇒ 干涉结论可信,可以继续追
为什么独立成一个脚本:它**不需要装配体、不需要刀片、更不碰 IInterferenceDetectionMgr**。
重度用 IDM 之后 SolidWorks 会丢掉运行对象表注册(NOTES §22/§24),
所以把这个判据做成"一个进程内从头到尾跑完"的形式,不依赖既有连接。
"""
import io
import os
import re
import subprocess
import sys
import 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 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))
def rot_count():
try:
rot = pythoncom.GetRunningObjectTable()
return sum(1 for _ in rot.EnumRunning())
except Exception as e:
return u'枚举失败 %s' % str(e)[:40]
print(u'=== 诊断 ===')
print(u' SLDWORKS 进程: %s' % sw_pids())
print(u' 运行对象表条数: %s' % rot_count())
app = None
try:
app = wc.GetActiveObject('SldWorks.Application')
print(u' ✅ 现有实例可连,不重启')
except Exception as e:
print(u' ✗ 连不上 (%s)' % str(e)[:50])
if app is None:
if sw_pids():
print(u'\n=== 结束现有实例(已失联,救不回来)===')
subprocess.run(['taskkill', '/F', '/IM', 'SLDWORKS.exe'],
capture_output=True, text=True)
time.sleep(4)
print(u' 剩余: %s' % sw_pids())
print(u'\n=== 启动新实例 ===')
for k in range(20):
try:
app = wc.Dispatch('SldWorks.Application')
app.Visible = True
_ = app.RevisionNumber
break
except Exception as e:
if k == 19:
raise
print(u' 重试 %d/20 (%s)' % (k + 1, str(e)[:50]))
time.sleep(5)
print(u' Revision %s 文档数 %s' % (app.RevisionNumber, app.GetDocumentCount))
if app.GetDocumentCount == 0:
print(u'\n=== 导入底板 STEP(≈50 s)===')
t0 = time.time()
data = app.GetImportFileData(BASE_STEP)
err = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
app.LoadFile4(BASE_STEP, 'r', data, err)
print(u' err=%s 用时 %.1fs 文档数 %s' % (err.value, time.time() - t0, app.GetDocumentCount))
# ── 直接在打开的文档里按标题找插槽**零件**,不经装配树 ──────────────────
print(u'\n=== 找插槽零件 ===')
cand = []
for d in app.GetDocuments:
try:
t, ty = d.GetTitle, d.GetType
except Exception:
continue
if ty == 1 and 'PCIE' in t.upper() and '64P11L' in t.upper():
cand.append(d)
print(u' 命中 %d 个零件文档' % len(cand))
if not cand:
print(u' ⛔ 没找到;打开的零件标题样本:')
for d in list(app.GetDocuments)[:12]:
try:
if d.GetType == 1:
print(u' %s' % d.GetTitle[:80])
except Exception:
pass
sys.exit(1)
part = cand[0]
print(u' 用: %s' % part.GetTitle)
bb = [v * 1000 for v in part.GetPartBox(True)]
bbv = (bb[3] - bb[0]) * (bb[4] - bb[1]) * (bb[5] - bb[2])
print(u' 包围盒 %.2f x %.2f x %.2f = %.1f mm^3'
% (bb[3] - bb[0], bb[4] - bb[1], bb[5] - bb[2], bbv))
bodies = None
for args in ((0, True), (-1, True), (0, False)):
try:
bodies = part.GetBodies2(*args)
if bodies:
print(u' GetBodies2%s → %d 个实体' % (str(args), len(bodies)))
break
except Exception as e:
print(u' GetBodies2%s 失败 %s' % (str(args), str(e)[:60]))
if not bodies:
print(u' ⛔ 取不到实体'); sys.exit(1)
tot, faces = 0.0, 0
for i, bd in enumerate(bodies):
o = bd if hasattr(bd, 'GetMassProperties') else wc.Dispatch(bd)
try:
tot += o.GetMassProperties(1.0)[3] * 1e9
except Exception as e:
print(u' 实体%d 体积失败 %s' % (i, str(e)[:60]))
try:
nf = o.GetFaceCount
faces += nf
if i < 8:
print(u' 实体%-2d 面数 %s' % (i, nf))
except Exception:
pass
r = tot / bbv if bbv else 0
print(u'\n 实体体积 %.1f mm^3 / 包围盒 %.1f = **%.3f**' % (tot, bbv, r))
print(u' 总面数 **%d**%s' % (faces, u' ⚠ 0 是假值(实体不可能 0 面),忽略它' if faces == 0 else u''))
print()
# ⛔⛔ 教训:原来这里写的是 `if r > 0.80 or faces < 30`,
# 结果 `GetFaceCount` 返回假值 0 → `faces < 30` 成立 → 一票推翻了
# 体积比 0.492 给出的相反证据,打印出错误的"实心块"结论。
# ⇒ 不要把强弱不同的信号用 `or` 并列;面数只在**读到非 0** 时才参与判断。
faces_ok = faces > 0
if r > 0.80 or (faces_ok and faces < 30):
print(u' ⇒ **实心块,没有槽腔**。')
print(u' 3D 量不出插入深度 d;"舌头 36.0 比腔长"也**无法由 3D 判定** ——')
print(u' 刀片停在塑料体顶面纯粹是因为模型没开口。只能靠卡尺实测。')
else:
print(u' ⇒ **模型建了腔**,几何冲突是真的,干涉结论可信,可以继续追。')