# -*- coding: utf-8 -*- u"""导入 Orion OD6010(60×60×10)STEP → 另存 SLDPRT → 解剖:包围盒、安装孔、风道。 沿用 NOTES §32 的做法:LoadFile4 得到未保存零件(GetPathName 为空)⇒ 必须先 SaveAs3 才能 AddComponent4。 判据沿用 §32 的教训:配对安装孔前先按「关于原点对称 + 贯穿全厚」筛,别对 |x|、|y| 各取极值。 """ 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 SRC = u'D:\\DCDC\\新建文件夹\\OD6010_m0_frame.stp' DST = u'D:\\DCDC\\新建文件夹\\OD6010_m0_frame.SLDPRT' EMPTY = wc.VARIANT(pythoncom.VT_DISPATCH, None) def prop(o, n): v = getattr(o, n) return v() if type(v).__name__ in ('method', 'function', 'builtin_function_or_method') else v def D(x): return x if hasattr(x, '_oleobj_') else wc.Dispatch(x) def P(*a): print(*a) app = wc.GetActiveObject('SldWorks.Application') for d in list(app.GetDocuments or []): t = prop(d, 'GetTitle') or '' if 'OD6015' in t.upper() or 'OD6010' in t.upper(): app.CloseDoc(t) data = app.GetImportFileData(SRC) err = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0) app.LoadFile4(SRC, 'r', data, err) P(u'LoadFile4 err=%s' % err.value) part = app.ActiveDoc P(u'文档 %s type=%s' % (prop(part, 'GetTitle'), prop(part, 'GetType'))) if prop(part, 'GetType') != 1: P(u'⛔ 不是单体零件,停手'); sys.exit(2) bodies = part.GetBodies2(0, True) or [] P(u'实体 %d 个' % len(bodies)) bx = None for b in bodies: bb = [round(v * 1000, 3) for v in prop(D(b), 'GetBodyBox')] bx = bb if bx is None else [min(bx[i], bb[i]) for i in range(3)] + [max(bx[i + 3], bb[i + 3]) for i in range(3)] P(u'包围盒 x %.3f~%.3f y %.3f~%.3f z %.3f~%.3f ⇒ %.2f × %.2f × %.2f' % (bx[0], bx[3], bx[1], bx[4], bx[2], bx[5], bx[3] - bx[0], bx[4] - bx[1], bx[5] - bx[2])) thick_ax = min(range(3), key=lambda i: bx[i + 3] - bx[i]) P(u'厚度方向 = %s(%.3f)' % ('xyz'[thick_ax], bx[thick_ax + 3] - bx[thick_ax])) cands = [] big = [] for b in bodies: for f in prop(D(b), 'GetFaces'): fc = D(f) s = prop(fc, 'GetSurface') if not prop(s, 'IsCylinder'): continue cp = list(prop(s, 'CylinderParams')) r = cp[6] * 1000 ax = max(range(3), key=lambda i: abs(cp[3 + i])) fb = [v * 1000 for v in prop(fc, 'GetBox')] c = [(fb[i] + fb[i + 3]) / 2 for i in range(3)] if ax == thick_ax and 1.5 < r < 2.8: cands.append((round(r, 3), c, fb[thick_ax], fb[thick_ax + 3])) if ax == thick_ax and r > 25: big.append((round(r, 3), fb[thick_ax], fb[thick_ax + 3])) o = [i for i in range(3) if i != thick_ax] full = bx[thick_ax + 3] - bx[thick_ax] P(u'\n安装孔候选(半径 1.5~2.8、轴沿厚度方向)%d 个:' % len(cands)) for r, c, z0, z1 in cands: P(u' R%.3f (%s=%.3f, %s=%.3f) 厚度向 %.2f~%.2f%s' % (r, 'xyz'[o[0]], c[o[0]], 'xyz'[o[1]], c[o[1]], z0, z1, u' ← 贯穿' if abs((z1 - z0) - full) < 0.05 else u'')) thru = [(r, c) for r, c, z0, z1 in cands if abs((z1 - z0) - full) < 0.05] P(u'\n贯穿全厚的安装孔 %d 个:' % len(thru)) cx = (bx[o[0]] + bx[o[0] + 3]) / 2 cy = (bx[o[1]] + bx[o[1] + 3]) / 2 for r, c in thru: P(u' R%.3f 相对中心 (%+.3f, %+.3f)' % (r, c[o[0]] - cx, c[o[1]] - cy)) if len(thru) == 4: dxs = sorted(abs(c[o[0]] - cx) for _, c in thru) dys = sorted(abs(c[o[1]] - cy) for _, c in thru) P(u' ⇒ 孔距 %.3f × %.3f(标准 60 风扇应为 50.00 × 50.00)' % (2 * sum(dxs) / 4, 2 * sum(dys) / 4)) P(u'风道圆柱(R>25):%s' % big) e1 = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0) w1 = wc.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0) part.Extension.SaveAs3(DST, 0, 1, EMPTY, EMPTY, e1, w1) P(u'\n另存 err=%s 存在=%s %.0f KB(零件保持打开,供 AddComponent4)' % (e1.value, os.path.exists(DST), os.path.getsize(DST) / 1024.0 if os.path.exists(DST) else 0))