# -*- coding: utf-8 -*- u"""在载板中央走廊里找两个中跨 M3 孔的位置(2026-09-05 用户拍板要加)。 判据:孔中心到**任何**已有焊盘 / 电解罐体的净间距 >= CLR。 孔按 NPTH Ø3.2 **无焊盘**算 —— 有焊盘的话 Ø6 塞不进走廊(见输出)。 罐体半径来自 pcb2_place.py 的 C801_BODY_R(Ø12.5 含余量)。 """ import json import math import os import sys sys.stdout.reconfigure(encoding='utf-8') HERE = os.path.dirname(os.path.abspath(__file__)) MIL = 39.3700787401575 pads = json.load(open(os.path.join(HERE, '_pcb2_pads.json'), encoding='utf-8')) def box(shape, rot, x, y): kind = shape[0] if kind == 'POLYGON': pts = [v for v in shape[1] if isinstance(v, (int, float))] xs, ys = pts[0::2], pts[1::2] return ((min(xs) + max(xs)) / 2 / MIL, (min(ys) + max(ys)) / 2 / MIL, (max(xs) - min(xs)) / 2 / MIL, (max(ys) - min(ys)) / 2 / MIL) w, h = float(shape[1]) / MIL, float(shape[2]) / MIL d = rot * 180.0 / math.pi if abs(rot) <= 2 * math.pi + 1e-6 else rot if round(d) % 180 == 90: w, h = h, w return x / MIL, y / MIL, w / 2.0, h / 2.0 P = [box(s, r, x, y) for lay, x, y, r, s, net, num in pads] # 五个 Ø10 电解罐(顶层,按 Ø12.5 留),中心从 pcb2_place.py 的 BAND['c1'] 折算 CANS = [(17.0, 74.5), (88.5, 74.5), (160.0, 74.5), (95.84, 60.66), (167.34, 60.66)] CAN_R = 6.25 HOLE_R = 1.6 # NPTH Ø3.2 CLR = 0.5 # 到任何铜/罐体的净间距 def clearance(cx, cy): best = 1e9 for px, py, hw, hh in P: d = max(abs(cx - px) - hw, abs(cy - py) - hh) - HOLE_R best = min(best, d) for qx, qy in CANS: best = min(best, math.hypot(cx - qx, cy - qy) - CAN_R - HOLE_R) return best # 走廊:两排手机本体之间(CH4/CH5 顶 49.66,CH1~3 底 85.5) best = [] x = 20.0 while x <= 200.0: y = 51.0 while y <= 84.0: c = clearance(x, y) if c >= CLR: best.append((round(c, 2), round(x, 1), round(y, 1))) y += 0.25 x += 0.25 print(u'走廊里净间距 >= %.1f mm 的候选点 %d 个' % (CLR, len(best))) # 按 x 分簇,报出每一簇里最宽敞的一个 best.sort(key=lambda t: -t[0]) picked = [] for c, x, y in best: if all(math.hypot(x - a[1], y - a[2]) > 12 for a in picked): picked.append((c, x, y)) if len(picked) >= 12: break print(u'%-8s %-8s %-8s' % (u'净间距', 'x', 'y')) for c, x, y in sorted(picked, key=lambda t: t[1]): print(u'%8.2f %8.2f %8.2f' % (c, x, y))