文件

248 行
9.6 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# -*- coding: utf-8 -*-
# v6:嵌入式 —— 外形 = 顶盖内腔四边各让 0.3,拧紧后顶面压住顶盖角柱底(z −10)、底面与墙底齐平(−13.6)
# v5:无滤网版 —— 西边缘 −17.9(不再托滤网/导轨),脚垫窝随中心重排
u"""**底盖 v4**(2026-09-13 外观美化 A + E)。
与 v3 的差别:
A 四边**内缩 0.5**:外形 x −24.3~115.4、y −3.555~106.245(顶盖外沿 −24.8~115.9 / −4.055~106.745),
接缝处形成一圈 0.5 阴影缝,藏住两件的打印公差;四角圆角用 R2.5(与顶盖 R3 同心)——圆角由 add_fillets 后做。
E **加厚 2.4 → 3.6**(向下长,底盖顶面仍在 z=−10,机内尺寸不变;整机高 +1.2):
· 四角 M3 过孔下方挖**沉头 Ø6.5 深 2.0**,螺丝头不外露,头下还剩 1.6(2.4 厚时只剩 0.4,会压裂)
· 4 个**脚垫窝 Ø10 深 1.0**(贴 Ø10 硅胶脚垫),放在螺丝内侧、不盖住螺丝 ⇒ 拆盖不用撕脚垫
PCB 立柱、柱顶螺母孔、四角过孔位置与 v3 相同。
本地坐标:板 z −3.6~0、立柱 0~10;装配 dz = −10 ⇒ 板 z −13.6~−10。
面上切除沿用 NOTES §37:进草图后读 ModelToSketchTransform 验平面,再按变换精确画。
"""
import io
import math
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\\BottomPlate_v6.SLDPRT'
EMPTY = wc.VARIANT(pythoncom.VT_DISPATCH, None)
CLR = 0.3 # v6:嵌进顶盖内腔,四边各让 0.3
X0, X1, Y0, Y1 = -16.0 + CLR, 113.5 - CLR, -1.655 + CLR, 104.345 - CLR # = 顶盖内腔 (-16.0, 113.5, -1.655, 104.345) 各让 CLR
T = 3.6
CORNER_HOLES = [(-11.0, 3.345), (-11.0, 99.345), (108.5, 3.345), (108.5, 99.345)]
R_THRU = 1.7
CB_R, CB_D = 3.25, 2.0 # 沉头 Ø6.5 深 2
PCB_POSTS = [(4.0, 4.0), (94.0, 4.0), (4.0, 94.0), (94.0, 94.0)]
POST_R, POST_H, R_INS = 4.0, 10.0, 2.1
FOOT_R, FOOT_D = 5.0, 1.0 # 脚垫窝 Ø10 深 1
_XC, _YC = (X0 + X1) / 2.0, 51.345
FEET = [(_XC - 45.0, _YC - 43.0), (_XC + 45.0, _YC - 43.0), (_XC - 45.0, _YC + 43.0), (_XC + 45.0, _YC + 43.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
app = wc.GetActiveObject('SldWorks.Application')
for d in list(app.GetDocuments or []):
try:
t = prop(d, 'GetTitle') or ''
if 'BOTTOMPLATE_V6' in t.upper():
app.CloseDoc(t)
except Exception:
pass
app.NewDocument(app.GetUserPreferenceStringValue(8), 0, 0.0, 0.0)
part = app.ActiveDoc
P(u'新建零件 %s' % prop(part, 'GetTitle'))
sm, fm = part.SketchManager, part.FeatureManager
def last_sketch():
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 boss(depth, rev):
if pick(last_sketch(), 'SKETCH') != 1:
raise RuntimeError(u'草图没选中')
return fm.FeatureExtrusion3(True, False, rev, 0, 0, M(depth), 0.0,
False, False, False, False, 0.0, 0.0,
False, False, False, False, True, True, True, 0, 0.0, False)
def bodies():
return part.GetBodies2(0, True) or []
def faces():
b = bodies()
return prop(D(b[0]), 'GetFaces') if b else []
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)]
def cyls():
out = []
for f in faces():
fc = D(f)
s = prop(fc, 'GetSurface')
if prop(s, 'IsCylinder'):
fb = [v * 1000 for v in prop(fc, 'GetBox')]
out.append((round(list(prop(s, 'CylinderParams'))[6] * 1000, 2), fb))
return out
def planes():
out = []
for f in faces():
fc = D(f)
s = prop(fc, 'GetSurface')
if not prop(s, 'IsPlane'):
continue
n = list(prop(s, 'PlaneParams'))[:3]
if prop(fc, 'FaceInSurfaceSense'):
n = [-v for v in n]
ax = max(range(3), key=lambda i: abs(n[i]))
out.append((ax, 1 if n[ax] > 0 else -1, [v * 1000 for v in prop(fc, 'GetBox')], prop(fc, 'GetArea') * 1e6, fc))
return out
def open_face_sketch(ax, sign, coord, tag):
for attempt in range(1, 4):
best, ba = None, -1.0
for a_, s_, fb, area, fc in planes():
if a_ == ax and s_ == sign and abs(fb[ax] - coord) < 0.02 and abs(fb[ax + 3] - coord) < 0.02 and area > ba:
best, ba = fc, area
if best is None:
P(u' ⛔ %s 选不到面' % tag); sys.exit(4)
part.ClearSelection2(True)
best.Select4(False, EMPTY)
sm.InsertSketch(True)
sk = prop(sm, 'ActiveSketch')
if sk:
arr = list(prop(D(sk), 'ModelToSketchTransform').ArrayData)
Mx = [[arr[3 * c + r] for c in range(3)] for r in range(3)]
X = (Mx, arr[9:12])
nax = max(range(3), key=lambda i: abs(Mx[2][i]))
probe = [0.0, 0.0, 0.0]
probe[ax] = coord / 1000.0
sz = (sum(Mx[2][i] * probe[i] for i in range(3)) + arr[11]) * 1000
ok = nax == ax and abs(sz) < 0.01
P(u' %s 进草图 第 %d 次:法线轴 %s、面上点草图 z=%.4f %s'
% (tag, attempt, 'xyz'[nax], sz, u'✅' if ok else u'✗ 退出重进'))
if ok:
return X
sm.InsertSketch(True)
P(u' ⛔ %s 进不到目标面' % tag); sys.exit(4)
def to_sketch(X, p):
Mx, t = X
q = [v / 1000.0 for v in p]
return [sum(Mx[r][c] * q[c] for c in range(3)) + t[r] for r in range(3)]
def cut(depth):
if pick(last_sketch(), 'SKETCH') != 1:
return None
return fm.FeatureCut4(True, False, False, 0, 0, M(depth), 0.0,
False, False, False, False, 0.0, 0.0,
False, False, False, False, False,
True, True, False, False, False, 0, 0.0, False, False)
P(u'\n[1] 平板 %.1f × %.1f × %.1f(嵌入顶盖,四边各让 %.1f)+ 四角 Ø%.1f 过孔' % (X1 - X0, Y1 - Y0, T, CLR, 2 * R_THRU))
pick(u'前视基准面', 'PLANE')
sm.InsertSketch(True)
sm.AddToDB = True
sm.CreateCornerRectangle(M(X0), M(Y0), 0.0, M(X1), M(Y1), 0.0)
for hx, hy in CORNER_HOLES:
sm.CreateCircleByRadius(M(hx), M(hy), 0.0, M(R_THRU))
sm.AddToDB = False
sm.InsertSketch(True)
boss(T, True)
P(u' box %s' % bbox())
P(u'\n[2] PCB 立柱 Ø%.0f × %.0f + 柱顶 Ø%.1f 螺母孔' % (2 * POST_R, POST_H, 2 * R_INS))
pick(u'前视基准面', 'PLANE')
sm.InsertSketch(True)
sm.AddToDB = True
for hx, hy in PCB_POSTS:
sm.CreateCircleByRadius(M(hx), M(hy), 0.0, M(POST_R))
sm.CreateCircleByRadius(M(hx), M(hy), 0.0, M(R_INS))
sm.AddToDB = False
sm.InsertSketch(True)
boss(POST_H, False)
b = bbox()
P(u' box %s(期望 x %.1f~%.1f y %.3f~%.3f z %.1f~%.1f)' % (b, X0, X1, Y0, Y1, -T, POST_H))
if b is None or any(abs(b[i] - w) > 0.02 for i, w in enumerate([X0, Y0, -T, X1, Y1, POST_H])):
P(u'⛔ 停手'); sys.exit(2)
for tag, pts, r, dep in ((u'沉头', CORNER_HOLES, CB_R, CB_D), (u'脚垫窝', FEET, FOOT_R, FOOT_D)):
P(u'\n[3] 底面 %s ×4:Ø%.1f 深 %.1f' % (tag, 2 * r, dep))
X = open_face_sketch(2, -1, -T, tag)
sm.AddToDB = True
for hx, hy in pts:
q = to_sketch(X, (hx, hy, -T))
sm.CreateCircleByRadius(q[0], q[1], 0.0, M(r))
sm.AddToDB = False
sm.InsertSketch(True)
c = cut(dep)
got = [fb for rr, fb in cyls() if abs(rr - r) < 0.01]
okp = len(got) == 4 and all(abs(fb[2] + T) < 0.05 and abs(fb[5] - (-T + dep)) < 0.05 for fb in got) and \
all(any(abs((fb[0] + fb[3]) / 2 - hx) < 0.05 and abs((fb[1] + fb[4]) / 2 - hy) < 0.05 for fb in got) for hx, hy in pts)
P(u' 切除 → %r;R%.2f 圆柱面 %d 个,z %.1f~%.1f、圆心在位 %s'
% (prop(c, 'Name') if c else c, r, len(got), -T, -T + dep, u'✅' if okp else u'⛔'))
if not okp:
P(u'⛔ 不存盘'); sys.exit(3)
h = {}
for rr, fb in cyls():
h[rr] = h.get(rr, 0) + 1
thru = [fb for rr, fb in cyls() if abs(rr - R_THRU) < 0.01]
ins = [fb for rr, fb in cyls() if abs(rr - R_INS) < 0.01]
P(u'\n[4] 验收 直方图 %s(期望 {1.7: 4, 2.1: 4, 3.25: 4, 4.0: 4, 5.0: 4})' % dict(sorted(h.items())))
ok_thru = len(thru) == 4 and all(abs(fb[2] - (-T + CB_D)) < 0.05 and abs(fb[5]) < 0.05 for fb in thru)
ok_ins = len(ins) == 4 and all(abs(fb[2]) < 0.05 and abs(fb[5] - POST_H) < 0.05 for fb in ins)
P(u' 过孔 z %.1f~0(沉头以上 1.6 实体)%s;柱顶螺母孔 z 0~10 盲孔 %s'
% (-T + CB_D, u'✅' if ok_thru else u'⛔', u'✅' if ok_ins else u'⛔'))
want = {1.7: 4, 2.1: 4, 3.25: 4, 4.0: 4, 5.0: 4}
if not (ok_thru and ok_ins) or any(h.get(k, 0) != v for k, v in want.items()):
P(u'⛔ 不存盘'); sys.exit(3)
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))