153 行
5.0 KiB
Python
153 行
5.0 KiB
Python
# -*- coding: utf-8 -*-
|
||
u"""北侧板 v3 —— 跟着 15 mm 分风腔加长(2026-09-13)。
|
||
|
||
与 v2 的差别同南板 v4:长度 152.8 → **175.0**(x −38.4~136.4)、
|
||
A 组螺丝孔挪到端板角柱中心 **x −31/129,z 10/60**(旧的 x −13.70/111.70 打在空气里)。
|
||
两个开口(J33 应急排针、J26/J27 风扇座出线)对准的是底板上的座子,座子没动 ⇒ 位置不动。
|
||
|
||
⛔ 竖板、法线沿 y ⇒ 上视基准面,草图 (u,v) → 模型 (x, −z)。
|
||
⛔ 画草图前 `sm.AddToDB = True`。
|
||
"""
|
||
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
|
||
|
||
DST = u'D:\\DCDC\\新建文件夹\\5blades\\NorthPanel_v3.SLDPRT'
|
||
EMPTY = wc.VARIANT(pythoncom.VT_DISPATCH, None)
|
||
|
||
X0, X1 = -38.4, 136.4
|
||
Z0, Z1 = -10.0, 72.0
|
||
PANEL_T = 2.4
|
||
OPENINGS = [(72.14, 87.85, -3.0, 12.0), # J33 应急排针
|
||
(0.53, 19.03, -3.0, 15.0)] # J26/J27 风扇座出线
|
||
|
||
SCREW_D = 3.4
|
||
POST_CX_W, POST_CX_E = -31.0, 129.0
|
||
SCREW_HOLES = [(POST_CX_W, 10.0), (POST_CX_W, 60.0),
|
||
(POST_CX_E, 10.0), (POST_CX_E, 60.0),
|
||
(30.0, -5.0), (49.0, -5.0), (68.0, -5.0)]
|
||
|
||
|
||
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)
|
||
|
||
|
||
def M(v):
|
||
return v / 1000.0
|
||
|
||
|
||
def UZ(z):
|
||
return M(-z)
|
||
|
||
|
||
app = wc.GetActiveObject('SldWorks.Application')
|
||
for d in list(app.GetDocuments or []):
|
||
try:
|
||
t = prop(d, 'GetTitle') or ''
|
||
if 'NORTHPANEL_V3' in t.upper():
|
||
app.CloseDoc(t)
|
||
P(u'关掉旧文档 %s' % t)
|
||
except Exception:
|
||
pass
|
||
|
||
tmpl = app.GetUserPreferenceStringValue(8)
|
||
app.NewDocument(tmpl, 0, 0.0, 0.0)
|
||
part = app.ActiveDoc
|
||
P(u'新建零件 %s' % prop(part, 'GetTitle'))
|
||
sm, fm = part.SketchManager, part.FeatureManager
|
||
|
||
|
||
def sk_name():
|
||
nm, f = None, prop(part, 'FirstFeature')
|
||
while f:
|
||
if prop(f, 'GetTypeName2') == 'ProfileFeature':
|
||
nm = prop(f, 'Name')
|
||
f = prop(f, 'GetNextFeature')
|
||
return nm
|
||
|
||
|
||
def pick(name, typ):
|
||
part.ClearSelection2(True)
|
||
part.Extension.SelectByID2(name, typ, 0, 0, 0, False, 0, EMPTY, 0)
|
||
return part.SelectionManager.GetSelectedObjectCount2(-1)
|
||
|
||
|
||
def bodies():
|
||
return part.GetBodies2(0, True) or []
|
||
|
||
|
||
def bbox():
|
||
b = bodies()
|
||
if not b:
|
||
return None
|
||
xs = [[round(v * 1000, 3) for v in prop(D(x), 'GetBodyBox')] for x in b]
|
||
return [min(v[0] for v in xs), min(v[1] for v in xs), min(v[2] for v in xs),
|
||
max(v[3] for v in xs), max(v[4] for v in xs), max(v[5] for v in xs)]
|
||
|
||
|
||
P(u'\n[1] 板本体 %.1f(x) × %.1f(z) × %.1f,含 %d 个开口 + %d 个 Ø%.1f 螺丝孔'
|
||
% (X1 - X0, Z1 - Z0, PANEL_T, len(OPENINGS), len(SCREW_HOLES), SCREW_D))
|
||
pick(u'上视基准面', 'PLANE')
|
||
sm.InsertSketch(True)
|
||
sm.AddToDB = True
|
||
sm.CreateCornerRectangle(M(X0), UZ(Z0), 0.0, M(X1), UZ(Z1), 0.0)
|
||
for ox0, ox1, oz0, oz1 in OPENINGS:
|
||
sm.CreateCornerRectangle(M(ox0), UZ(oz0), 0.0, M(ox1), UZ(oz1), 0.0)
|
||
for sx, sz in SCREW_HOLES:
|
||
sm.CreateCircleByRadius(M(sx), UZ(sz), 0.0, M(SCREW_D / 2))
|
||
sm.AddToDB = False
|
||
_segs = prop(D(prop(sm, 'ActiveSketch')), 'GetSketchSegments')
|
||
want_segs = 4 * (1 + len(OPENINGS)) + len(SCREW_HOLES)
|
||
P(u' 草图 segment = %d(期望 %d)' % (len(_segs) if _segs else 0, want_segs))
|
||
sm.InsertSketch(True)
|
||
|
||
if pick(sk_name(), 'SKETCH') != 1:
|
||
P(u'⛔ 草图没选中'); sys.exit(2)
|
||
feat = fm.FeatureExtrusion3(True, False, False, 0, 0, M(PANEL_T), 0.0,
|
||
False, False, False, False, 0.0, 0.0,
|
||
False, False, False, False, True, True, True, 0, 0.0, False)
|
||
P(u' 拉伸 → %r' % (prop(feat, 'Name') if feat else feat))
|
||
b = bbox()
|
||
P(u' box %s' % b)
|
||
if not b:
|
||
P(u'⛔ 没出实体,停手'); sys.exit(3)
|
||
|
||
bd = D(bodies()[0])
|
||
nf = len(prop(bd, 'GetFaces'))
|
||
want_faces = 6 + 4 * len(OPENINGS)
|
||
P(u' 面数 = %d(期望 ≥ %d)%s' % (nf, want_faces, u'✅' if nf >= want_faces else u'⛔ 开口没成形'))
|
||
hist = {}
|
||
for f in prop(bd, 'GetFaces'):
|
||
s = prop(D(f), 'GetSurface')
|
||
if prop(s, 'IsCylinder'):
|
||
r = round(list(prop(s, 'CylinderParams'))[6] * 1000, 2)
|
||
hist[r] = hist.get(r, 0) + 1
|
||
P(u' 圆柱面直方图 %s' % dict(sorted(hist.items())))
|
||
n34 = hist.get(round(SCREW_D / 2, 2), 0)
|
||
P(u' Ø%.1f 螺丝孔 = %d 个(期望 %d)%s'
|
||
% (SCREW_D, n34, len(SCREW_HOLES), u'✅' if n34 >= len(SCREW_HOLES) else u'⛔ 没打全'))
|
||
if n34 < len(SCREW_HOLES):
|
||
P(u'⛔ 停手'); sys.exit(4)
|
||
|
||
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'
|
||
% (e1.value, os.path.exists(DST), os.path.getsize(DST) / 1024.0 if os.path.exists(DST) else 0))
|
||
if not os.path.exists(DST):
|
||
P(u'⛔ 没落盘,停手'); sys.exit(5)
|
||
P(u'⚠ 零件保持打开')
|