為學術論文建立可編輯的 draw.io 圖表
您可透過一個 Python 建置腳本(記錄的產出物:每個座標、角色與大小都儲存在其中,因此圖表可重新生成與重新設定主題)將圖表建立為原生 draw.io 物件。切勿追蹤像素,切勿將文字點陣化。每個呼叫與規則的詳細說明:REFERENCE.md。可複製的範例:EXAMPLES.md。
執行工具
所有程式碼都包含在一個檔案中。以下指令中的 T 代表 python drawio_toolkit.py:
T <工具> [參數] # 例如 T lint_drawio fig.drawio --theme theme.yaml (任何工具:--help)
T unpack ./tidyfigs # 可選:正常資料夾 scripts/ assets/ examples/;然後 python scripts/<工具>.py
在 Python 中:import drawio_toolkit; drawio_toolkit.setup() → from drawio_kit import Diagram、from figlib import *、from drawio_doc import Doc。生成的建置腳本會自行找到函式庫。
無法執行程式碼? 仍遵循相同方法:為使用者編寫建置腳本(或對於小型圖表,直接編寫 draw.io XML — 請參閱 REFERENCE §14),並要求他們提供預覽/lint 輸出或螢幕截圖,而非自行檢視。
選擇模式
| 輸入 | 模式 | 輸出 |
|---|---|---|
| 要重建的點陣圖 | A 圖片 | <img>.drawio + <img>#drawio.png(300 dpi)放置在圖片旁 |
| 文章 / 論文章節 / 方程式 | B 文字 | 3 個原型 → 使用者挑選 → <name>.drawio |
| 現有的 .drawio 使其符合發表標準 | C 增強 | <name>#ENHANCED.drawio + PDF/SVG/PNG 匯出 |
A 或 B 模式後通常接著 C 模式。僅在請求確實不明確時才詢問使用哪種模式。
共享規則(所有模式)
- 僅使用主題角色。 顏色、字型、大小、筆畫、透明度來自 YAML/TOML/JSON 主題檔(
fill="primary"、size="body"、sw="thick"、fill_opacity="tint")。淡色 = 現有角色 + 透明度角色,而非新的十六進位色碼。需要新顏色?新增一個語意角色(highlight、chunk_b)並告知使用者。Lint 會報告每個離題的值;最終版本不應有任何離題值。 - 根據意圖正規化:同級物件使用相同大小,行列使用一個間距(
row、row_widths、fit_row、column、grid_boxes),共享邊緣使用相同座標;將標籤置中對齊於其所標示的物件(x + w/2)。忽略 ±1 像素的雜訊。 - 附加連接器:每當線條觸及形狀時,使用
src/tgt(+exit/entry分數);pts僅列出 draw.io 無法計算的部分(自由起點、轉折點、自由終點)。自由點僅用於分隔線、繪圖軸線、獨立向量。 - 曲線邊緣(
route="curved"、flex_arrow、cycle):轉折點即為控制點;曲線會通過連續轉折點之間的中點。 - Z 順序 = 建立順序(後建立的在上層):畫布 → 面板 → 填充 → 形狀 → 連接器 → 文字 → 註解。將一起移動的物件組成群組(
with d.group("tile"))。 - 重要頂點使用穩定 ID(便於邊緣連接與可讀的 lint)。
- 文字標記:
**粗體***斜體*__底線__{角色|彩色}\n\*;行內 LaTeX\( … \);顯示數學使用d.equation(r"...")(原生 MathJax,可編輯)。raw=True可傳遞 HTML。 - 透過檢視驗證:每次建置後,使用您的圖片工具檢視 PNG 預覽;數字(lint、分數、稽核)提供指引,但視覺檢查做最終決定。預覽近似 draw.io:表情符號 = 灰色方塊,圓柱/文件 = 矩形,無小型大寫字母,數學透過 mathtext 呈現。
- 工作區整潔:暫存腳本、探測和裁切內容放在
<工作目錄>/scratch/中,絕不與使用者的檔案放在一起。 - 學術預設值:白色背景、圖內無標題(改為撰寫標題)、最多 3 種色調 + 淡色、顏色絕非唯一編碼方式、一種字型家族、最多 6–7 個大小角色、最多約 25 個文字項目。
模式 A — 圖片 → 可編輯的 draw.io
方法:量測 → 規劃 → 主題 → 建置腳本 → 渲染 → 比較 → 修正,直到預覽結果在佈局上與原始圖片相符。座標是在真實網格上量測的原始圖片像素(目測縮放過的檢視是轉換不良的首要原因)。
A0 分類(設定工作量;先閱讀 EXAMPLES.md 中最接近的範例):
| 層級 | 看起來像 | 主要技術 | 迭代次數 | 最終分數 |
|---|---|---|---|---|
| 1 簡單 | 方塊、標籤、直線/肘形箭頭、1–3 個面板 | rect、text、已附加 edge、row | 2–3 | ≥ 0.88 |
| 2 網格/儀表板 | 帶圖示的方塊、欄位、小型流程、項目符號 | panel、群組、fit_row/grid_boxes、icon、正交邊緣 | 3–5 | ≥ 0.88 |
| 3 繪圖/幾何 | 軸線、向量、點、圓形、波浪箭頭、旋轉標籤 | dot、circle、錨點、flex_arrow、曲線邊緣、rotation | 3–6 | ≥ 0.85 |
| 4 複雜 | 3D 曲面、網格、照片、密集散點圖、圖說 | surface_mesh、polygon、image_crop、scatter_*、callout、z 圖層 | 5–10 | ≥ 0.78 |
A1 支架 + 檢查:T new_build images/fig.png [--theme user.yaml] [--scale 1] 會建立 images/fig_drawio_work/(build.py、theme.yaml、NOTES.md、inspect/、iterations/、scratch/、history.json;請保留)。閱讀 inspect/summary.md 並檢視 source.grid*.png(位置)、source.boxes.png/.json(精確邊界框 + 中位數顏色 — 直接使用)、source.ocr.png/.json(文字 + 字型大小:使用符合寬度的 est_px_if_regular/bold,透過檢視挑選)、source.palette.png(顏色 → 最近的角色,ΔE)。支架會在 build.py 中預先填入偵測到的方塊 — 請優化它們。放大任何區域:T inspect_image zoom SRC --box x0 y0 x1 y1 --factor 3 --step 10;以數值方式探測細薄/淺色特徵(T inspect_image probe SRC --box … 或 numpy,請參閱 REFERENCE §6.1)。OCR 可能誤讀,且偵測器會合併相鄰的形狀 — 務必視覺檢查。
A2 在 NOTES.md 中規劃:按 Z 順序逐區域清點。為每個元素決定:原生頂點(方塊、面板、藥丸形、圓形、菱形、圓柱)· 原生文字(所有文字,永遠)· 已附加 edge(連接)· 自由 edge(軸線、分隔線)· flex_arrow(寬/波浪)· 群組中的 dot(散點圖 ≤ ~400)· polygon/svg_layer/surface_mesh(區塊、光束、網格、3D)· image_crop(僅照片、紋理、標誌 — 在其上重建原生標籤)· 函式庫形狀或表情符號 icon(圖示;說明是哪個)。記錄每個非原生決策以供報告使用。
A3 主題:使用者顏色/字型 → 角色,將每個原始顏色對應到最近的角色;否則將原始的主要顏色去重至最多 6–8 個角色。將 OCR 大小聚類成最多 6–7 個大小角色(相同視覺層級 ⇒ 相同角色)。最接近的網頁安全字型家族(Helvetica/Arial;Times New Roman 用於 LaTeX 風格的襯線字型);google: true 用於 Roboto/Inter。在放大後量測筆畫粗細。
A4 撰寫 build.py(Diagram.from_source 已預先配置;完整 API 請參閱 REFERENCE §2):
pid, (cx, cy, cw, ch) = d.panel(52, 110, 620, 570, "**AUTO-ENCODING**", header_h=70, header_fill="primary",
header_color="background", title_size="heading")
for (x, y, w, h), t in zip(d.row_widths(182, 336, [97, 138, 97, 97], 62, gap=13), ["[A]", "[MASK]", "[C]", "[D]"]):
d.rect(x, y, w, h, t, fill="token", stroke="text", rounded=4, size="body", id="tok_" + t.strip("[]"))
d.rect(275, 455, 170, 62, "**Encoder**", fill="primary", color="background", rounded=4, id="enc")
d.edge([], src="enc", tgt="tok_MASK", sw="thick", exit=(.5, 0), entry=(.5, 1))
d.edge([(108, 486)], tgt="enc", entry=(0, .5)) # 自由起點,附加終點
d.text("Dimension 2", 365, 144, size="small", rotation=-90)
d.image_crop((49, 199, 143, 309), border="text") # 從原始圖片複製的照片
隨機內容(散點圖)使用固定的 seed 和標籤周圍的保留矩形。超過 ~600 個頂點 → 將裝飾性標記合併為一個 svg_layer。原始圖片很小 → --scale 2 使文字 ≥ 10 px。
A5 迭代:T iterate images/fig_drawio_work --note "what changed" = 建置 → 渲染 → 比較 → lint → 快照 + 歷史。檢視 iter_NN_side.png(所有內容:用詞、大小、粗細、換行)、iter_NN_edges.png(紅色 = 僅原始圖片,青色 = 僅預覽;迭代直到成對合併)、iter_NN_heat.png + 最差的區塊(接下來放大那些)。分階段進行:(1) 畫布、面板、網格 → (2) 形狀對齊到偵測到的邊界框並正規化 → (3) 每個連接器使用埠附加 → (4) 字型角色、粗細、置中、valign → (5) 邊緣差異優化。每次迭代更改少數相關項目;如果分數下降,則還原。停止時機:每個清點元素都存在(重新按區域閱讀原始圖片),lint 0 錯誤且無溢出/重疊/離題警告,並排顯示無錯位或錯誤文字,分數趨於平穩(2 次迭代增益 < 0.005)。如果 draw.io CLI 存在:最後一次 T render_preview OUT --engine drawio。
A6 最終化:images/fig.drawio 是最新建置結果;匯出 T render_preview images/fig.drawio -o "images/fig#drawio.png" --dpi 300。圖片資料夾僅包含原始圖片、.drawio、#drawio.png(+ 工作目錄)。報告:路徑;原生 vs 嵌入(照片、SVG 圖層、表情符號佔位符);已使用/新增的角色;已知偏差;保留的原始拼寫錯誤;如何重新設定主題(編輯 theme.yaml → python build.py)和重新縮放。
模式 B — 文字 → 三個可編輯的圖表原型
閱讀文章,清點其主張,建立三個不同的圖表家族,檢查它們,呈現並排工作表;使用者挑選;您進行最終化。
輸出位置:檔案 drafts/methods.md → drafts/methods_figures/;貼上的文字 → ./figures/<slug>/;多章節/長篇輸入 → 每個段落一個子資料夾 p1_<slug>/ …;使用者命名的資料夾 → 完全符合該名稱(--out-dir)。告知使用者路徑。所有段落共用一個主題(--theme 或在輸出的根目錄中編輯 theme.yaml)。
B1 支架 + 分析:T new_figures drafts/methods.md [--theme t.yaml] [--split|--whole] [--passages 1,3] 或 T new_figures --text "<passage>" --name rag_pipeline。會列印每個段落的:字數、方程式、結構線索、三個建議的圖表家族。≤ 350 字且無標題 = 一個段落。沒有值得製作圖表的結構(純敘述)?請直接說明,而非強迫製作圖表。
B2 清點(NOTES.md):實體、有序步驟(及其動詞)、關係(方向 + 動詞)、帶單位的數量、修飾語、結論 — 每個都附帶一個簡短引用。確認圖表家族(請參閱 REFERENCE §7):預設 = 主要結構的三種佈局(詳細 / 簡潔概覽 / 替代視角);強烈的第二結構 → 兩種 + 一種;方程式 → 方程式三重奏(除非是附帶的)。這三種必須在拓撲(泳道 / 堆疊 / 徑向 / 矩陣 / 圖表 / 板塊)上有所不同,而非樣式。對於數學、科學、演算法類的文章,偏好主動演示(填充的矩陣計算、連續座標/度量空間、貝氏板塊、因果 DAG),而非靜態的項目符號卡片。
B3 撰寫 build.py — 三個建置器,每個都使用其畫布大小的新 Diagram:
from figlib import *
INFERRED = ["v1: 序數評分解釋了文章中的定性措辭"] # 向使用者報告
ALLOWED_TERMS = ["layer"] # 結構性詞彙,非主張
LINT_IGNORE = [] # 故意接受的警告(子字串)
def v1(d): # 泳道管線
lane(d, 20, 20, 1060, 175, "Offline indexing")
chain(d, ["Inspection reports\n(scanned)", "OCR\nto text", "Semantic\nchunking"], 80, 78, 140, 60,
shapes=["document", None, None], ids=["rep", "ocr", "chk"])
VARIANTS = [dict(key="v1", name="swimlane_pipeline", size=(1100, 400), build=v1,
about="一行說明", caption="使用文章用語的草稿標題。"), ...]
規則:僅使用主題角色,相同類別 = 三個原型中樣式相同;同級物件共享大小和一個間距(使用輔助函數,非手動調整的數字);連接器已附加,回饋用虛線/次要;最多約 25 個文字項目,少於 ~150 個頂點(否則拆分為兩個圖表);圖內無標題 — 改為編寫 caption;標籤使用文章的用語(透過刪減而非同義詞縮短;保留修飾語、數字、單位、縮寫原文)。解釋性裝置(評分、邊界、“最佳擬合”、軸順序、文章中未出現的數學事實)僅在列於 INFERRED 中時才使用。
B4 原型、檢查、修正(≥ 2 輪):T prototype <passage dir> [--only v2] --note "…" 會建置全部三個原型,渲染、執行 lint、執行忠實度檢查、撰寫 prototypes.png/.md、記錄 err/warn/miss。檢視每個 PNG 和工作表。修正每個 lint 警告,或新增一個故意的 LINT_IGNORE;解決每個 NOT-IN-PASSAGE 的詞彙(使用文章的術語重新措辭 · 如果結構性則使用 ALLOWED_TERMS · 如果是解釋則使用 INFERRED)。檢查 lint 無法檢查的項目:箭頭穿過標籤、擁擠的角落、薄弱的層級結構、不平衡的空白、兩個原型過於相似、每個箭頭的方向與清點結果相比對。當達到 0/0/0(或接受的警告)且在全尺寸下乾淨時完成。
B5 呈現:顯示 prototypes.png;每個原型一行說明其重點、其草稿標題、其 INFERRED 項目;指出原始來源的異常(拼寫錯誤、不一致的名稱),而非默默修正。要求使用者挑選(或要求更改 / 組合 → 編輯 build.py,重新執行)。
B6 最終化:T finalize <passage dir> --pick v2 [--name rag_pipeline] [--clean] → <name>.drawio(+ .png)和 CHOSEN.md(標題、推論)。--clean 會刪除其他原型,但保留 _work/。提供 C 模式以進行特定發表場域的優化。
模式 C — 增強 .drawio 以符合發表標準
一次深思熟慮的處理:理解圖表的任務 → 以印刷尺寸量測 → 更改以服務該任務 → 驗證 → 匯出。 在訪談之前絕不編輯。
C1 開始:T start_enhance path/FIG.drawio [--source-image] [--text] [--artifacts DIR] [--theme]。它會探索上下文(模式 A 工作目錄:原始圖片、build.py、主題、NOTES;模式 B 文章資料夾:passage.md、build.py VARIANTS、CHOSEN.md、標題、INFERRED),偵測生成後的手動編輯,建議一條路線,稽核“之前”,撰寫 <stem>_enhance_work/(context.md、before_audit.md、brief.yaml、questions.md、theme.yaml、build_enhanced.py 如果…