# -*- coding: utf-8 -*- """Generate phased implementation plan chart from 3D光学仿真扩展实施计划.md.""" from __future__ import annotations from pathlib import Path import matplotlib.pyplot as plt import matplotlib.patches as mpatches OUT = Path(__file__).resolve().parent plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei", "Arial"] plt.rcParams["axes.unicode_minus"] = False GREEN = "#75BD42" GREEN_EDGE = "#4A7C3F" GREEN_LIGHT = "#E8F5E0" GRAY = "#E8E8E8" GRAY_EDGE = "#AAAAAA" GRAY_TEXT = "#666666" DARK = "#2C3E50" WHITE = "#FFFFFF" # 前三个阶段标绿:阶段 1、2、3 DONE_STAGES = {1, 2, 3} FOUNDATION_STAGE = 0 STAGES = [ (0, "工程基础(并行)", [ "Test_Main 命令行/环境变量指定 JSON", "export_phy_to_json.m(PBC/PEC 块)", "EnsureOutputDir、错误码返回", ]), (1, "本征频率闭环", [ "EigenFreq::Assemble 补 P^T A P", "Run() / Post()", "Post_3D_EigenFreq 输出 freq/Ex/Ey/Ez/normE", "FEM_Interface FemType=5 完整链路", ]), (2, "散射基础边界", [ "Assemble_PEC_ELE() 边 DOF 消元", "接入 OpticsFEM_3D_Scatter::Assemble()", "ELE 激励(ef JSON 块)", ]), (3, "周期边界 PBC", [ "Mesh_3D::GetIndexOfPBC()", "3D 散射 Assemble_PBC()(单周期)", "双周期 PBC(散射+本征)", "JSON 导出 PBC 块", ]), (4, "源项与背景场边界", [ "Assemble_BELE() / MAG() / SCD()", "Assemble_MPD() / EPD()", "Post_GetEb() 3D 背景场", ]), (5, "吸收层与端口", [ "3D PML 体积分/边界", "3D Port 散射", "Beam 高斯光束", ]), (6, "本征模式 & 高阶(扩展)", [ "OpticsFEM_3D_EigenMode 新类", "二阶 Nedelec 基函数", "棱柱/四边形边界网格读取", ]), ] def stage_height(n_tasks: int) -> float: return 0.055 + n_tasks * 0.032 def draw_stage(ax, x: float, y: float, w: float, stage_id: int, title: str, tasks: list[str]): h = stage_height(len(tasks)) done = stage_id in DONE_STAGES foundation = stage_id == FOUNDATION_STAGE if done: face, edge = GREEN, GREEN_EDGE title_color, text_color = WHITE, "#F5FFF0" elif foundation: face, edge = GREEN_LIGHT, GREEN_EDGE title_color, text_color = DARK, "#2D5016" else: face, edge = GRAY, GRAY_EDGE title_color, text_color = DARK, GRAY_TEXT box = mpatches.FancyBboxPatch( (x, y - h), w, h, boxstyle="round,pad=0.008,rounding_size=0.012", facecolor=face, edgecolor=edge, linewidth=2.0 if (done or foundation) else 1.2, alpha=0.96, ) ax.add_patch(box) ax.text( x + 0.015, y - 0.028, f"阶段 {stage_id} — {title}", ha="left", va="top", fontsize=11, fontweight="bold", color=title_color, ) ty = y - 0.052 for task in tasks: ax.text(x + 0.02, ty, f"• {task}", ha="left", va="top", fontsize=9, color=text_color) ty -= 0.032 return h def main() -> None: col_w = 0.44 x_left, x_right = 0.05, 0.51 y = 0.88 fig_h = 12.0 fig, ax = plt.subplots(figsize=(13, fig_h), facecolor=WHITE) ax.set_xlim(0, 1) ax.set_ylim(0, 1) ax.axis("off") ax.text(0.5, 0.97, "OpticsFEM 3D 光学仿真扩展 — 分阶段实施计划", ha="center", va="top", fontsize=17, fontweight="bold", color=DARK) layout = [(0, x_left), (1, x_right), (2, x_left), (3, x_right), (4, x_left), (5, x_right), (6, x_left)] y_left, y_right = 0.92, 0.92 gap = 0.012 for stage_id, title, tasks in STAGES: col_x = x_left if stage_id in (0, 2, 4, 6) else x_right if stage_id in (0, 2, 4, 6): y_cur = y_left else: y_cur = y_right h = draw_stage(ax, col_x, y_cur, col_w, stage_id, title, tasks) if stage_id in (0, 2, 4, 6): y_left = y_cur - h - gap else: y_right = y_cur - h - gap ax.add_patch(mpatches.Rectangle((0.05, 0.015), 0.022, 0.022, fc=GREEN, ec=GREEN_EDGE)) ax.text(0.08, 0.026, "已完成(阶段 1–3)", fontsize=10, va="center", color=DARK) ax.add_patch(mpatches.Rectangle((0.27, 0.015), 0.022, 0.022, fc=GREEN_LIGHT, ec=GREEN_EDGE)) ax.text(0.30, 0.026, "工程基础(阶段 0)", fontsize=10, va="center", color=DARK) ax.add_patch(mpatches.Rectangle((0.50, 0.015), 0.022, 0.022, fc=GRAY, ec=GRAY_EDGE)) ax.text(0.53, 0.026, "待实施(阶段 4–6)", fontsize=10, va="center", color=DARK) out = OUT / "implementation_plan_stages.png" fig.savefig(out, dpi=180, bbox_inches="tight", facecolor=WHITE) plt.close(fig) print(f"Saved {out}") if __name__ == "__main__": main()