125 行
5.1 KiB
Python
125 行
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
u"""把 topshell_v3.py 里「候选映射逐个试」的切除换成「读草图变换 + 先验平面再下刀」。
|
||
|
||
起因(2026-09-13 实测):东端墙那一刀 Select4 返回 True、选中数 1、选中面 box 也对,
|
||
但 InsertSketch 之后草图却建在了**顶板**上(风口从顶上切穿),靠「切出了东西但不在目标位置」才拦下。
|
||
⇒ 选中数不能证明草图建在哪;**进草图后读 ActiveSketch.ModelToSketchTransform**:
|
||
列主序 M[r][c] = a[3c+r],s = M·p + t(米);第 3 行 = 草图法线。
|
||
法线轴 ≠ 目标轴 或 墙面上一点的草图 z ≠ 0 ⇒ 退出重进,三次不成就停手。
|
||
同一个变换顺带给出精确的 uv 映射,不再需要候选法。
|
||
"""
|
||
import io
|
||
import sys
|
||
|
||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', write_through=True)
|
||
P_ = u'C:\\Users\\35138\\.claude\\jobs\\11836093\\tmp\\topshell_v3.py'
|
||
s = open(P_, encoding='utf-8').read()
|
||
a = s.index(u'def try_cut(')
|
||
b = s.index(u'\n# ── [6b]')
|
||
NEW = u'''def sketch_xform():
|
||
sk = prop(sm, 'ActiveSketch')
|
||
if not sk:
|
||
return None
|
||
arr = list(prop(D(sk), 'ModelToSketchTransform').ArrayData)
|
||
Mx = [[arr[3 * c + r] for c in range(3)] for r in range(3)] # 列主序
|
||
return Mx, arr[9:12]
|
||
|
||
|
||
def to_sketch(X, p):
|
||
u"""模型点 p(mm)→ 草图坐标(米)"""
|
||
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 open_face_sketch(face, tag):
|
||
ax, sign, coord = face
|
||
for attempt in range(1, 4):
|
||
if not pick_face(*face):
|
||
P(u' ⛔ %s 选不到面' % tag); sys.exit(4)
|
||
sm.InsertSketch(True)
|
||
X = sketch_xform()
|
||
ok, nax, sz = False, -1, 99.0
|
||
if X:
|
||
nax = max(range(3), key=lambda i: abs(X[0][2][i]))
|
||
probe = [0.0, 0.0, 0.0]
|
||
probe[ax] = coord
|
||
sz = to_sketch(X, probe)[2] * 1000.0
|
||
ok = nax == ax and abs(sz) < 0.01
|
||
P(u' %s 进草图 第 %d 次:法线轴 %s(目标 %s)、墙面点草图 z = %.4f mm %s'
|
||
% (tag, attempt, 'xyz'[nax] if nax >= 0 else '?', 'xyz'[ax], sz, u'✅' if ok else u'✗ 平面不对,退出重进'))
|
||
if ok:
|
||
return X
|
||
sm.InsertSketch(True)
|
||
P(u' ⛔ %s 三次都没进到目标面,停手' % tag); sys.exit(4)
|
||
|
||
|
||
def cut_shapes(tag, face, circles, rects, verify):
|
||
nbefore = len(faces())
|
||
X = open_face_sketch(face, tag)
|
||
sm.AddToDB = True
|
||
for p, r in circles:
|
||
q = to_sketch(X, p)
|
||
sm.CreateCircleByRadius(q[0], q[1], 0.0, M(r))
|
||
for p0, p1 in rects:
|
||
q0, q1 = to_sketch(X, p0), to_sketch(X, p1)
|
||
sm.CreateCornerRectangle(q0[0], q0[1], 0.0, q1[0], q1[1], 0.0)
|
||
sm.AddToDB = False
|
||
sm.InsertSketch(True)
|
||
c = do_cut(T + 0.2)
|
||
ok = verify()
|
||
P(u' %s 切除 → %-12r 面数 %d→%d 目标 %s'
|
||
% (tag, prop(c, 'Name') if c else c, nbefore, len(faces()), u'✅' if ok else u'⛔'))
|
||
if not ok:
|
||
P(u' ⛔⛔ 目标没出现在设计位置 —— 停手、不存盘'); sys.exit(5)
|
||
|
||
|
||
def end_verify(xwall):
|
||
def v():
|
||
cs = cyls()
|
||
for cy, cz, r in END_CIRCLES:
|
||
hit = any(abs(rr - r) < 0.01 and ax_ == 0 and
|
||
abs((fb[1] + fb[4]) / 2 - cy) < 0.05 and abs((fb[2] + fb[5]) / 2 - L(cz)) < 0.05 and
|
||
min(abs(fb[0] - xwall), abs(fb[3] - xwall)) < 0.05
|
||
for rr, ax_, fb in cs)
|
||
if not hit:
|
||
return False
|
||
return True
|
||
return v
|
||
|
||
|
||
def rect_verify(wins, ywall0, ywall1):
|
||
def v():
|
||
ps = planes()
|
||
for x0, x1, z0, z1 in wins:
|
||
for xe in (x0, x1):
|
||
hit = any(ax_ == 0 and abs(fb[0] - xe) < 0.05 and abs(fb[3] - xe) < 0.05 and
|
||
abs(fb[2] - L(z0)) < 0.05 and abs(fb[5] - L(z1)) < 0.05 and
|
||
fb[1] >= ywall0 - 0.05 and fb[4] <= ywall1 + 0.05
|
||
for ax_, sg, fb, a_, _ in ps)
|
||
if not hit:
|
||
return False
|
||
return True
|
||
return v
|
||
|
||
|
||
P(u'\\n[4] 端墙:Ø60 风口 + 4 × Ø%.1f 风扇孔(孔距 %.1f)' % (2 * R_FAN, 2 * abs(END_CIRCLES[1][0] - FAN_CY)))
|
||
cut_shapes(u'西端墙', (0, -1, X0), [((X0, cy, L(cz)), r) for cy, cz, r in END_CIRCLES], [], end_verify(X0))
|
||
cut_shapes(u'东端墙', (0, +1, X1), [((X1, cy, L(cz)), r) for cy, cz, r in END_CIRCLES], [], end_verify(X1))
|
||
|
||
P(u'\\n[5] 南墙:2 个 13×9 Type-C 窗口')
|
||
cut_shapes(u'南墙', (1, -1, Y0), [],
|
||
[((x0, Y0, L(z0)), (x1, Y0, L(z1))) for x0, x1, z0, z1 in SOUTH_WINDOWS],
|
||
rect_verify(SOUTH_WINDOWS, Y0, IY0))
|
||
P(u'\\n[6] 北墙:J33 窗口 + 风扇出线窗口')
|
||
cut_shapes(u'北墙', (1, +1, Y1), [],
|
||
[((x0, Y1, L(z0)), (x1, Y1, L(z1))) for x0, x1, z0, z1 in NORTH_WINDOWS],
|
||
rect_verify(NORTH_WINDOWS, IY1, Y1))
|
||
|
||
'''
|
||
s = s[:a] + NEW + s[b:]
|
||
if s.count(u'try_cut(') or s.count(u'X_CANDS'):
|
||
raise SystemExit(u'⛔ 旧的候选法残留')
|
||
open(P_, 'w', encoding='utf-8').write(s)
|
||
print(u'topshell_v3.py 已换成「读草图变换 + 先验平面」版')
|