"""生成 VI 手册里的标志构成与安全区标注图(docs/design/vi/diagrams/)。 标注数值直接取自 logo_lib 的实际几何,保证和正式资产一致。 用法:.work/venv/bin/python scripts/vi_diagrams.py """ from logo_lib import (FINAL, FINAL_INSET, LOGO, NAVY, SB, SEAL_GAP, SEAL_SCALE, SL, SR, ST, CN_H, GAP, PY_CAP, seal_group, wordmark) OUT = LOGO.parent / "vi/diagrams" OUT.mkdir(parents=True, exist_ok=True) BLUE = "#2F5BD3" FONT = 'font-family="PingFang SC, Noto Sans SC, sans-serif"' body, W, H = wordmark(FINAL, NAVY, inset=FINAL_INSET) SEAL_H = H * SEAL_SCALE SEAL_TOP = -(SEAL_H - H) / 2 SEAL_W = (SR - SL) * SEAL_H / (SB - ST) GAP_X = SEAL_H * SEAL_GAP TX = SEAL_W + GAP_X def label(x, y, text, anchor="middle", size=7.5): return f'{text}' def hline(x1, x2, y, dash=True): d = ' stroke-dasharray="2 2"' if dash else "" return f'' def vline(x, y1, y2, dash=True): d = ' stroke-dasharray="2 2"' if dash else "" return f'' def dim_v(x, y1, y2, text, side="left"): """竖向尺寸线,带两端短横。""" t = 2.5 lx = x - 4 if side == "left" else x + 4 return (vline(x, y1, y2, dash=False) + hline(x - t, x + t, y1, dash=False) + hline(x - t, x + t, y2, dash=False) + label(lx, (y1 + y2) / 2 + 2.6, text, "end" if side == "left" else "start")) def dim_h(x1, x2, y, text, below=False): t = 2.5 ly = y + 9 if below else y - 3.5 return (hline(x1, x2, y, dash=False) + vline(x1, y - t, y + t, dash=False) + vline(x2, y - t, y + t, dash=False) + label((x1 + x2) / 2, ly, text)) def construction_h(): seal, _ = seal_group("clean", 0, SEAL_TOP, SEAL_H) py_top = CN_H * (1 + GAP) x_end = TX + W parts = [seal, f'{body}'] # 文字块上下边界与印章边界 parts += [hline(-30, x_end + 12, 0), hline(-30, x_end + 12, H), hline(-30, SEAL_W + 4, SEAL_TOP), hline(-30, SEAL_W + 4, SEAL_TOP + SEAL_H)] parts.append(dim_v(-12, 0, H, "H")) parts.append(dim_v(-26, SEAL_TOP, SEAL_TOP + SEAL_H, "1.02H")) # 印章与文字间距 parts.append(dim_h(SEAL_W, TX, H + 18, "0.3 × 印章高", below=True)) parts += [vline(SEAL_W, SEAL_TOP + SEAL_H, H + 22), vline(TX, H, H + 22)] # 字标内部:中文字高、间距、拼音高 rx = x_end + 10 parts.append(dim_v(rx, 0, CN_H, "中文字高 100", side="right")) parts.append(dim_v(rx, CN_H, py_top, "间距 14", side="right")) parts.append(dim_v(rx, py_top, H, "拼音 20", side="right")) # 英文视觉内缩 parts += [vline(TX, py_top - 6, H + 4), vline(x_end, py_top - 6, H + 4)] parts.append(vline(TX + FINAL_INSET[0], py_top - 6, H + 4)) parts.append(vline(x_end - FINAL_INSET[1], py_top - 6, H + 4)) parts.append(label(TX + 2.5, H + 12, f"内缩 {FINAL_INSET[0]:g}", "start", 6.5)) parts.append(label(x_end - 2.5, H + 12, f"内缩 {FINAL_INSET[1]:g}", "end", 6.5)) vb = (-60, SEAL_TOP - 14, x_end + 150, SEAL_H + 56) return f'{"".join(parts)}' def construction_v(): seal_h = W * 0.5 seal, _ = seal_group("clean", (W - seal_h) / 2, 0, seal_h) gap = seal_h * 0.18 y_wm = seal_h + gap parts = [seal, f'{body}'] parts += [vline(0, -8, y_wm + H + 6), vline(W, -8, y_wm + H + 6)] parts.append(dim_h(0, W, -14, "字标宽 W")) parts.append(dim_h((W - seal_h) / 2, (W + seal_h) / 2, seal_h + 5, "0.5W", below=True)) parts.append(dim_v(W + 12, seal_h, y_wm, "0.18 × 印章边长", side="right")) parts += [hline((W + seal_h) / 2, W + 14, seal_h), hline(W, W + 14, y_wm)] vb = (-20, -30, W + 130, y_wm + H + 40) return f'{"".join(parts)}' def clearspace(): seal, _ = seal_group("clean", 0, SEAL_TOP, SEAL_H) m = H / 4 x0, y0 = -m, SEAL_TOP - m x1, y1 = TX + W + m, SEAL_TOP + SEAL_H + m parts = [f'', f'', seal, f'{body}'] # 四边标注 H/4 parts.append(dim_h(x0, 0, SEAL_TOP + SEAL_H / 2, "H/4")) parts.append(dim_h(TX + W, x1, SEAL_TOP + SEAL_H / 2, "H/4")) parts.append(dim_v(TX + W / 2, y0, SEAL_TOP, "H/4", side="right")) parts.append(dim_v(TX + W / 2, SEAL_TOP + SEAL_H, y1, "H/4", side="right")) vb = (x0 - 10, y0 - 10, x1 - x0 + 20, y1 - y0 + 20) return f'{"".join(parts)}' (OUT / "construction-horizontal.svg").write_text(construction_h()) (OUT / "construction-vertical.svg").write_text(construction_v()) (OUT / "clearspace.svg").write_text(clearspace()) print("ok", sorted(p.name for p in OUT.iterdir()))