文件

168 行
6.7 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
u"""把三块新板(南板 / 北板 / 顶盖)插进总装,封成盒子。
三块都**只平移不旋转**(旋转是本会话的重灾区,能不转就不转):
· 南板 `SouthPanel`:本地 y 0~2.4 ⇒ 平移 **dy = −6.4**,贴到托盘南边缘 y=−4 的外侧
· 北板 `NorthPanel`:本地 y 0~2.4 ⇒ 平移 **dy = +102**,贴到北边缘外侧
· 顶盖 `TopPanel` :本地 z 0~2.4 ⇒ 平移 **dz = +72**,内表面落在 z=72
(刀片顶 71.34 ⇒ 间隙 0.66,兼做上端导轨,咬边 ≤1 ✅)
⛔ `AddComponent4` 要求被插入的文档**处于打开状态**(NOTES §15)——
三个零件脚本收尾时都保持打开了,这里直接引用。
⛔ 判据:插完回读每块板的装配 box 与期望比对;再跑 fast 干涉,
基线是 360(5 刀片 × 72 簧片蹭),多出来的才是新板撞了。
"""
import io
import os
import sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', write_through=True)
import pythoncom
import win32com.client as wc
OUT = r'C:\Users\35138\.claude\jobs\11836093\tmp'
DIR = u'D:\\DCDC\\新建文件夹\\5blades\\'
ASM = 'PhoneRail_5blades'
EMPTY = wc.VARIANT(pythoncom.VT_DISPATCH, None)
IDENT = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
# (文件, 标识, 平移, 期望装配 box)
# ⛔ 南北板原来贴在 y=−4 / 102(托盘边缘)。端板改成 y 对称后占 **−1.655~104.345**,
# 北板 102~104.4 与端板重叠 2.345 ⇒ 实测干涉 589 mm³。
# ✅ 南北板改为贴在**端板外侧**:北板内表面 104.345、南板外表面 −1.655。
# 这样三块板与端板共面收口,也不再和托盘(−4~102)冲突(托盘比它们窄,缩在里面)。
EP_Y0, EP_Y1 = -1.655, 104.345 # 端板 y 对称范围
PANELS = [
# v2:Type-C 开孔由 11.94×6.0 放大到 13×9(原高度 6.0 带护套的线插不进去)
(u'SouthPanel_v2.SLDPRT', u'南板', (0.0, EP_Y0 - 2.4, 0.0),
[-27.4, EP_Y0 - 2.4, -10.0, 125.4, EP_Y0, 72.0]),
(u'NorthPanel_v2.SLDPRT', u'北板', (0.0, EP_Y1, 0.0),
[-27.4, EP_Y1, -10.0, 125.4, EP_Y1 + 2.4, 72.0]),
# v2:泄压缝改 11 条、按盒子中心 49 对称(原 8 条按底板坐标定,偏在东半侧)
(u'TopPanel_v2.SLDPRT', u'顶盖', (0.0, 0.0, 72.0),
[-27.4, -4.0, 72.0, 125.4, 102.0, 74.4]),
]
def prop(o, n):
v = getattr(o, n)
return v() if type(v).__name__ in ('method', 'function', 'builtin_function_or_method') else v
def P(*a):
print(*a)
app = wc.GetActiveObject('SldWorks.Application')
doc = None
for d in app.GetDocuments or []:
if ASM in (prop(d, 'GetTitle') or ''):
doc = d
break
if doc is None:
P(u'⛔ 没找到总装'); sys.exit(3)
e0 = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
app.ActivateDoc3(prop(doc, 'GetTitle'), False, 0, e0)
doc = app.ActiveDoc
P(u'总装 %s,现有顶层件 %d' % (prop(doc, 'GetTitle'), len(doc.GetComponents(True))))
# 幂等:先删掉已插过的三块板
for c in list(doc.GetComponents(True)):
nm = prop(c, 'Name2').upper()
if any(k in nm for k in ('SOUTHPANEL', 'NORTHPANEL', 'TOPPANEL')):
doc.ClearSelection2(True)
doc.Extension.SelectByID2(prop(c, 'Name2'), 'COMPONENT', 0, 0, 0, False, 0, EMPTY, 0)
doc.Extension.DeleteSelection2(0)
P(u' 删掉旧的 %s' % prop(c, 'Name2'))
doc.EditRebuild3
did = app._oleobj_.GetIDsOfNames('GetMathUtility')
mu = wc.Dispatch(app._oleobj_.Invoke(did, 0, pythoncom.DISPATCH_METHOD, 1))
d2 = mu._oleobj_.GetIDsOfNames('CreateTransform')
def mk(a16):
v = wc.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list(a16))
xf = wc.Dispatch(mu._oleobj_.Invoke(d2, 0, pythoncom.DISPATCH_METHOD, 1, v))
if max(abs(a - b) for a, b in zip(list(xf.ArrayData), a16)) > 1e-9:
raise RuntimeError(u'CreateTransform 回读不符')
return xf
P(u'\n插入三块板:')
allok = True
for fn, tag, t, want in PANELS:
path = DIR + fn
if not os.path.exists(path):
P(u' ⛔ %s 文件不存在' % tag); allok = False; continue
c = doc.AddComponent4(path, '', 0.0, 0.0, 0.0)
if c is None:
P(u' ⛔ %s AddComponent4 返回 None(零件没开着?)' % tag); allok = False; continue
xf = mk(IDENT + [t[0] / 1000.0, t[1] / 1000.0, t[2] / 1000.0, 1.0, 0.0, 0.0, 0.0])
try:
c.SetTransformAndSolve2(xf)
except Exception:
c.Transform2 = xf
doc.EditRebuild3
b = [round(v * 1000, 2) for v in c.GetBox(False, False)]
ok = all(abs(b[i] - want[i]) < 0.05 for i in range(6))
if not ok:
allok = False
P(u' %s %-18s box x %8.2f~%8.2f y %8.2f~%8.2f z %7.2f~%7.2f %s'
% (tag, prop(c, 'Name2')[:18], b[0], b[3], b[1], b[4], b[2], b[5],
u'✅' if ok else (u'⛔ 期望 %s' % want)))
for nm2, vid in ((u'box_iso', 7), (u'box_front', 1), (u'box_right', 4)):
try:
doc.ShowNamedView2('', vid)
doc.ViewZoomtofit2
doc.SaveBMP(os.path.join(OUT, '%s.bmp' % nm2), 1600, 1100)
except Exception as ex:
P(u'截图 %s 失败 %s' % (nm2, str(ex)[:40]))
P(u'\n截图完成')
e3 = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
w3 = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
doc.Extension.SaveAs3(prop(doc, 'GetPathName'), 0, 1, EMPTY, EMPTY, e3, w3)
P(u'存盘 err=%s' % e3.value)
P(u'\n干涉(fast,基线 360):')
try:
idm = doc.InterferenceDetectionManager
idm.TreatCoincidenceAsInterference = False
idm.IncludeMultibodyPartInterferences = False
idm.TreatSubAssembliesAsComponents = True
idm.IgnoreHiddenBodies = True
idm.UseTransform = False
try:
n = idm.GetInterferenceCount
except AttributeError:
dd = idm._oleobj_.GetIDsOfNames('GetInterferenceCount')
n = idm._oleobj_.Invoke(dd, 0, pythoncom.DISPATCH_PROPERTYGET, 1)
P(u' 干涉 %s 处' % n)
hits = []
if n:
try:
items = idm.GetInterferences
except AttributeError:
dd = idm._oleobj_.GetIDsOfNames('GetInterferences')
items = idm._oleobj_.Invoke(dd, 0, pythoncom.DISPATCH_PROPERTYGET, 1)
for it in items:
o = it if hasattr(it, 'Volume') else wc.Dispatch(it)
nms = [wc.Dispatch(x).Name2.split('/')[0] for x in o.Components]
if any(k in y.upper() for y in nms for k in ('PANEL',)):
hits.append((o.Volume * 1e9, nms))
if hits:
P(u' ⚠ 新板相关 %d 处:' % len(hits))
for vv, nms in sorted(hits, reverse=True)[:8]:
P(u' %.3f mm³ %s ↔ %s' % (vv, nms[0][:26], nms[1][:26]))
else:
P(u' ✅ 三块新板与所有件零干涉')
idm.Done()
except Exception as ex:
P(u' 干涉失败 %s' % str(ex)[:80])
try:
doc.InterferenceDetectionManager.Done()
except Exception:
pass