# -*- coding: utf-8 -*- u"""派生 topshell_v4.py / place_v4.py(2026-09-13 用户要求): · 去掉北墙 J33 调试插针窗口 + J26/J27 风扇插座出线窗口; · 南墙两个 Type-C 开口改为**完全等于母座口内侧轮廓**:8.34 × 2.60、四角 R0.7, 中心 J1 (12.50, −1.65) / J23 (84.00, −1.65)(STEP 实测,见 probe_usbc2.py)。 ⚠ 用户已知悉:母座口在墙外表面内 4.26 mm,护套进不了墙,普通数据线可能插不到底。 纯文本补丁,锚点断言次数。""" import io import sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', write_through=True) T = u'C:\\Users\\35138\\.claude\\jobs\\11836093\\tmp\\' s = open(T + 'topshell_v3.py', encoding='utf-8').read() for old, new, n in ((u"TopShell_v3.SLDPRT'", u"TopShell_v4.SLDPRT'", 1), (u"'TOPSHELL_V3'", u"'TOPSHELL_V4'", 1)): if s.count(old) != n: raise SystemExit(u'锚点 %r ×%d' % (old, s.count(old))) s = s.replace(old, new) a = s.index(u"P(u'\\n[5] ") b = s.index(u'\n# ── [6b]') if u'NORTH_WINDOWS, IY1, Y1))' not in s[a:b]: raise SystemExit(u'⛔ [5]/[6] 区块不是预期内容') NEW = u'''# ── [5] 南墙 Type-C:完全等于母座口内侧轮廓(用户拍板 2026-09-13)────────────── # 母座 USB-C_SMD-TYPE-C-31-M-12 实测(STEP,本地→装配 x=12.5−lx / z=−lz): # 内侧平直边 x ±4.17、z 0.35~2.95(本地)⇒ 8.34 × 2.60;四角圆柱 R0.70,圆心 (±3.47, 1.05/2.25) # ⇒ 装配口中心 J1 (12.50, −1.65)、J23 (84.00, −1.65);口面 y=0.20,墙外表面 y=−4.055(缩进 4.26) # 北墙原有 J33 / 风扇出线两个窗口:用户要求去掉,不再切。 USB_W, USB_H, USB_R = 8.34, 2.60, 0.70 USB_CX = (12.50, 84.00) USB_CZ = -1.65 P(u'\\n[5] 南墙 Type-C ×2:%.2f × %.2f、R%.2f,中心 z=%.2f(= 母座口内侧轮廓)' % (USB_W, USB_H, USB_R, USB_CZ)) def usb_shapes(cx): hw, hh, r, cz = USB_W / 2, USB_H / 2, USB_R, L(USB_CZ) lines = [((cx + hw - r, cz + hh), (cx - hw + r, cz + hh)), ((cx - hw, cz + hh - r), (cx - hw, cz - hh + r)), ((cx - hw + r, cz - hh), (cx + hw - r, cz - hh)), ((cx + hw, cz - hh + r), (cx + hw, cz + hh - r))] arcs = [((cx + hw - r, cz + hh - r), (cx + hw, cz + hh - r), (cx + hw - r, cz + hh)), ((cx - hw + r, cz + hh - r), (cx - hw + r, cz + hh), (cx - hw, cz + hh - r)), ((cx - hw + r, cz - hh + r), (cx - hw, cz - hh + r), (cx - hw + r, cz - hh)), ((cx + hw - r, cz - hh + r), (cx + hw - r, cz - hh), (cx + hw, cz - hh + r))] return lines, arcs def usb_verify(): hw, hh, r, cz = USB_W / 2, USB_H / 2, USB_R, L(USB_CZ) cs = cyls() ps = planes() for cx in USB_CX: for ccx, ccz in ((cx + hw - r, cz + hh - r), (cx - hw + r, cz + hh - r), (cx - hw + r, cz - hh + r), (cx + hw - r, cz - hh + r)): if not any(abs(rr - r) < 0.01 and ax_ == 1 and fb[1] >= Y0 - 0.05 and fb[4] <= IY0 + 0.05 and (abs(fb[0] - (ccx - r)) < 0.05 or abs(fb[3] - (ccx + r)) < 0.05) and (abs(fb[2] - (ccz - r)) < 0.05 or abs(fb[5] - (ccz + r)) < 0.05) for rr, ax_, fb in cs): return False for xe in (cx - hw, cx + hw): if not any(ax_ == 0 and abs(fb[0] - xe) < 0.05 and abs(fb[3] - xe) < 0.05 and abs(fb[2] - (cz - hh + r)) < 0.05 and abs(fb[5] - (cz + hh - r)) < 0.05 for ax_, sg, fb, a_, _ in ps): return False for ze in (cz - hh, cz + hh): if not any(ax_ == 2 and abs(fb[2] - ze) < 0.05 and abs(fb[5] - ze) < 0.05 and abs(fb[0] - (cx - hw + r)) < 0.05 and abs(fb[3] - (cx + hw - r)) < 0.05 for ax_, sg, fb, a_, _ in ps): return False return True nbefore = len(faces()) X = open_face_sketch((1, -1, Y0), u'南墙') sm.AddToDB = True nseg = 0 for cx in USB_CX: lines, arcs = usb_shapes(cx) for p0, p1 in lines: q0, q1 = to_sketch(X, (p0[0], Y0, p0[1])), to_sketch(X, (p1[0], Y0, p1[1])) nseg += bool(sm.CreateLine(q0[0], q0[1], 0.0, q1[0], q1[1], 0.0)) for c, p1, p2 in arcs: qc = to_sketch(X, (c[0], Y0, c[1])) q1 = to_sketch(X, (p1[0], Y0, p1[1])) q2 = to_sketch(X, (p2[0], Y0, p2[1])) cross = (q1[0] - qc[0]) * (q2[1] - qc[1]) - (q1[1] - qc[1]) * (q2[0] - qc[0]) dirn = 1 if cross > 0 else -1 # 草图坐标系里取 90° 短弧:叉积正 = 逆时针 nseg += bool(sm.CreateArc(qc[0], qc[1], 0.0, q1[0], q1[1], 0.0, q2[0], q2[1], 0.0, dirn)) sm.AddToDB = False P(u' 草图段 %d(期望 16 = 2 × (4 直线 + 4 圆弧))' % nseg) sm.InsertSketch(True) if nseg != 16: P(u' ⛔ 草图段数不对,停手'); sys.exit(5) c = do_cut(T + 0.2) ok = usb_verify() P(u' 南墙 切除 → %-12r 面数 %d→%d 母座口轮廓 %s' % (prop(c, 'Name') if c else c, nbefore, len(faces()), u'✅ 4 圆角 + 4 直边 ×2 全在位' if ok else u'⛔')) if not ok: P(u' ⛔⛔ 开口没落在母座口轮廓上 —— 停手、不存盘'); sys.exit(5) ''' s = s[:a] + NEW + s[b:] s = s.replace(u"if h.get(2.6, 0) != 8 or h.get(2.1, 0) != 4 or h.get(30.0, 0) != 2:", u"if h.get(2.6, 0) != 8 or h.get(2.1, 0) != 4 or h.get(30.0, 0) != 2 or h.get(0.7, 0) != 8:") s = s.replace(u"(期望 {2.1: 4, 2.6: 8, 3.0: 4, 30.0: 2})", u"(期望 {0.7: 8, 2.1: 4, 2.6: 8, 3.0: 4, 30.0: 2})") if u'h.get(0.7, 0) != 8' not in s: raise SystemExit(u'⛔ 验收行没改上') s = s.replace(u'# -*- coding: utf-8 -*-\n', u'# -*- coding: utf-8 -*-\n# v4:去北墙两个窗口;南墙 Type-C 开口 = 母座口内侧轮廓 8.34×2.60 R0.7\n', 1) open(T + 'topshell_v4.py', 'w', encoding='utf-8').write(s) print(u'写出 topshell_v4.py') p = open(T + 'place_v3.py', encoding='utf-8').read() for old, new in ((u"(u'TopShell_v3.SLDPRT',", u"(u'TopShell_v4.SLDPRT',"), (u"((u'v3_iso', 7), (u'v3_west', 3), (u'v3_top', 1))", u"((u'v4_iso', 7), (u'v4_south', 6), (u'v4_north', 5))")): if p.count(old) != 1: raise SystemExit(u'place 锚点 %r ×%d' % (old, p.count(old))) p = p.replace(old, new) open(T + 'place_v4.py', 'w', encoding='utf-8').write(p) print(u'写出 place_v4.py')