This commit is contained in:
Horldsence
2026-09-13 10:27:09 +08:00
parent b810ec7777
commit 82311a47cc
52 changed files with 2563 additions and 1278 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+33 -27
View File
@@ -1,48 +1,54 @@
# docs/figures —— 论文插图
每张图只输出 PNG,由 `scripts/make_figures.py` 用 matplotlib 生成。
每张图只输出 PNG。数据由 `scripts/build_figure_data.py` 从行为日志、覆盖计划与生产求解器
算好写入 `docs/figures/.data/*.mat`,再由 MATLAB(`scripts/matlab/*.m`)排版出图;
`manifest.json` 记录每张图的数据来源(路径 + sha256 前 12 位 + 行数)与生成命令。
```bash
uv run python scripts/make_figures.py # 全部 11 张
uv run python scripts/make_figures.py --list # 图名
uv run python scripts/make_figures.py --only geo-q3-seven-point-coverage
uv run python scripts/make_figures.py --scale 1.5 # 整体放大(尺寸倍率)
uv run python scripts/build_figure_data.py # 全部 11 张(数据 + 出图)
uv run python scripts/build_figure_data.py --prepare # 只写 .mat 数据
uv run python scripts/build_figure_data.py --list # 图名
uv run python scripts/build_figure_data.py --only geo-q3-seven-point-coverage
```
依赖:`matplotlib`、`Pillow`、`docs/paper/fonts/` 下的字体。
`matplotlib` 缓存写入仓库内 `.mpl-cache/`,不污染用户目录。
MATLAB 内手动出图:`cd scripts/matlab` 后执行 `run_all_figures`(每张图单独一个会话,
本机图形子系统连续渲染多张会崩)。
依赖:`numpy`、`scipy`(写 `.mat`)与 MATLAB R2025a。
## 约定
- 图内不放标题、图注与解释性文字,只保留坐标轴、图例与数据标注;
- **除回放画布(点运动图 `replay-webui-*`)外,全部使用 MATLAB 默认图形样式**:
默认配色(`defaultAxesColorOrder`)、默认字体与字号、默认坐标轴与图例;
不引入自定义调色板,不手绘图例色块。
- 图内不放标题、图注与解释性文字,只保留坐标轴、图例与必要的元素标注;
图的含义由文件名与下表承担,解释写在论文正文。
- 配色(`scripts/make_figures.py::C`):深蓝 `#1f4e79` 主流程与协议,
砖红 `#b03a2e` 真值源与关键结论,墨绿 `#1e7a5f` 清除与通过项,
土黄 `#b8860b` 后备与警示,灰色只用于网格与次要文字。
- 字体:中文宋体 `SongtiSC-Regular/Bold`,标题黑体 `HeitiSC-Light/Medium`,
数字与西文 Times New Roman,均取自 `docs/paper/fonts/`,与 `main.tex` 一致。
- 输出为 PNG(`savefig.dpi = 200`,另有 `--scale` 倍率),按 160 mm 宽排版时
与正文同字号。
- 图例一律用 MATLAB `legend` 放在坐标区外(`southoutside`),不压数据;
散点标签按候选方位自动避让,保证互不重叠。
- 输出 PNG(`exportgraphics`,300 dpi、白底),导出前关闭坐标轴工具条。
## 图清单
| 文件 | 内容 | 数据来源 |
| --- | --- | --- |
| `flow-overall-architecture.png` | 总体思路:题面抽象、在线三层、四问主线、三条闭环 | `src/mcm26b/config.py`、`docs/B题建模分析与实施计划.md` |
| `flow-overall-architecture.png` | 四层主线:题面抽象(L0)、在线三层(L1)、四问主线(L2)、三条闭环(L3) | `src/mcm26b/config.py`、`docs/B题建模分析与实施计划.md` |
| `steps-state-machine.png` | 会话状态机(IDLE / 倒计时 / OPEN / CLOSED) | `docs/协议规则表与状态机.md`、`src/mcm26b/protocol/client.py` |
| `timing-attachment-example-105-111-194-199.png` | 附件计时示例逐步推演 | `docs/协议规则表与状态机.md` |
| `timing-measured-q3-10-sources.png` | 实测一局的虚拟时间分解(累计曲线 + 构成) | `referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl` |
| `geo-q1-convex-intersection-zoom.png` | 问题一:角域交会总览 + 定位区域放大(直径圆与 MEC) | `output/q1/practice/U5ZW-P9KN-TCAG-R7ST_observations.json` |
| `geo-q1-diameter-circle-counterexample.png` | 问题一:直径圆不覆盖的反例(等边三角形布站) | `examples/q1/triangle.json` |
| `geo-q2-guaranteed-reception-disk.png` | 问题二:候选盘、截断角域外接圆、安全盘 `B(c, 1000−a)` | `src/mcm26b/config.py`、`docs/algo-2.md` |
| `geo-q3-seven-point-coverage.png` | 问题三:七点覆盖(7 个 1000 m 接收盘的并集覆盖 Ω)与三套计划对比 | `src/mcm26b/planner/seven.py`、`docs/algo-3.md` |
| `geo-q4-minimum-cover-31-points.png` | 问题四:31 点最小命中集与 `forward_half_disk` 语义 | `src/mcm26b/guarantee/plans/q4_mincover_v2.json` |
| `replay-webui-q3-omnidirectional.png` | WebUI 回放画布复现(全向局,10 源全清) | `referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl` |
| `replay-webui-q4-directional.png` | WebUI 回放画布复现(定向源局) | `referee-data/sessions/GM56-DFXZ-XKDM-XYV7/log.jsonl` |
| `timing-attachment-example-105-111-194-199.png` | 附件计时示例:逐动作耗时构成与单步合计 | `docs/协议规则表与状态机.md` |
| `timing-measured-q3-10-sources.png` | 实测一局:累计虚拟时间按动作类型的堆叠构成 | `referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl` |
| `geo-q1-convex-intersection-zoom.png` | 问题一:角域交会总览 + 定位区域放大(直径圆与最小包围圆) | `output/q1/practice/U5ZW-P9KN-TCAG-R7ST_observations.json` |
| `geo-q1-diameter-circle-counterexample.png` | 问题一:直径圆不覆盖定位区域的反例(等边三角形布站) | `examples/q1/triangle.json` |
| `geo-q2-guaranteed-reception-disk.png` | 问题二:截断角域外接圆 `B(c, a)` 与安全候选盘 `B(c, 1000 − a)`,右侧为半径分解 | `src/mcm26b/config.py`、`docs/algo-2.md` |
| `geo-q3-seven-point-coverage.png` | 问题三:七个 1000 m 接收盘覆盖 Ω,标出最差点 | `src/mcm26b/planner/seven.py`、`docs/algo-3.md` |
| `geo-q4-minimum-cover-31-points.png` | 问题四:31 点最小命中集与 ±90° 前向半盘语义 | `src/mcm26b/guarantee/plans/q4_mincover_v2.json` |
| `replay-webui-q3-omnidirectional.png` | 回放画布(点运动图,全向局):世界视图 + 事件流水 + 虚拟时间轴 | `referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl` |
| `replay-webui-q4-directional.png` | 回放画布(点运动图,定向源局):世界视图(含定向源 ±90° 前向半盘)+ 事件流水 + 虚拟时间轴 | `referee-data/sessions/GHSN-M38E-74GD-YLUD/log.jsonl` |
后两张对应 WebUI 的预览功能:把回放器画布上的 Ω 与真值源、运动轨迹、
检测示向度射线、清除标记,以及右侧事件流水与底部虚拟时间轴一起导出。
后两张是唯一保留自定义画布的图:把回放器画布上的 Ω 与真值源、移动轨迹、
检测示向度射线、定向源朝向与清除标记,连同右侧事件流水与底部虚拟时间轴一起导出;
定向源局额外画出每个定向源的 **±90° 前向半盘**(半径取该源 `r_eff_m`,朝向箭头即半盘半径)。
q4 回放固定用演练局 `GHSN-M38E-74GD-YLUD`(`build_figure_data.py::Q4_REPLAY_CASE`);
本机没有该局留档时回退到自动挑选,因此 `examples/replay/` 里归档了这一局。
## 数据来源与复现
Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 116 KiB

+31 -55
View File
@@ -1,36 +1,12 @@
{
"generator": "scripts/make_figures.py",
"command": "uv run python scripts/make_figures.py",
"palette": {
"ink": "#1c2430",
"muted": "#5c6673",
"grid": "#e4e9ee",
"primary": "#1f4e79",
"primary_fill": "#dce6f1",
"accent": "#b03a2e",
"accent_fill": "#f6dcd8",
"success": "#1e7a5f",
"success_fill": "#d8ece5",
"warn": "#b8860b",
"warn_fill": "#f6ecd2",
"violet": "#5b4b8a"
},
"fonts": {
"dir": "docs/paper/fonts",
"map": {
"song": "SongtiSC-Regular.ttf",
"song_bold": "SongtiSC-Bold.ttf",
"hei": "HeitiSC-Light.ttf",
"hei_bold": "HeitiSC-Medium.ttf",
"times": "Times New Roman.ttf",
"times_bold": "Times New Roman Bold.ttf"
}
},
"generator": "scripts/build_figure_data.py(数据)+ scripts/matlab/*.m(MATLAB 出图)",
"command": "uv run python scripts/build_figure_data.py",
"manual": "MATLAB 中 cd scripts/matlab 后执行 run_all_figures",
"figures": [
{
"stem": "flow-overall-architecture",
"png": "docs/figures/flow-overall-architecture.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_flow_overall.m",
"sources": [
{
"path": "src/mcm26b/config.py",
@@ -47,7 +23,7 @@
{
"stem": "steps-state-machine",
"png": "docs/figures/steps-state-machine.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_steps_state_machine.m",
"sources": [
{
"path": "docs/协议规则表与状态机.md",
@@ -64,7 +40,7 @@
{
"stem": "timing-attachment-example-105-111-194-199",
"png": "docs/figures/timing-attachment-example-105-111-194-199.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_timing_attachment.m",
"sources": [
{
"path": "docs/协议规则表与状态机.md",
@@ -73,10 +49,24 @@
}
]
},
{
"stem": "timing-measured-q3-10-sources",
"png": "docs/figures/timing-measured-q3-10-sources.png",
"matlab": "scripts/matlab/fig_timing_measured.m",
"sources": [
{
"path": "referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl",
"sha256_12": "5a308e53ed09",
"lines": 133,
"case_code": "BBM9-HZG2-77N5-NKKC",
"module": "q3_practice"
}
]
},
{
"stem": "geo-q1-convex-intersection-zoom",
"png": "docs/figures/geo-q1-convex-intersection-zoom.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_geo_q1_meetup.m",
"sources": [
{
"path": "output/q1/practice/U5ZW-P9KN-TCAG-R7ST_observations.json",
@@ -88,7 +78,7 @@
{
"stem": "geo-q1-diameter-circle-counterexample",
"png": "docs/figures/geo-q1-diameter-circle-counterexample.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_geo_q1_counterexample.m",
"sources": [
{
"path": "examples/q1/triangle.json",
@@ -100,7 +90,7 @@
{
"stem": "geo-q2-guaranteed-reception-disk",
"png": "docs/figures/geo-q2-guaranteed-reception-disk.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_geo_q2_safe_disk.m",
"sources": [
{
"path": "src/mcm26b/config.py",
@@ -117,7 +107,7 @@
{
"stem": "geo-q3-seven-point-coverage",
"png": "docs/figures/geo-q3-seven-point-coverage.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_geo_q3_coverage.m",
"sources": [
{
"path": "src/mcm26b/planner/seven.py",
@@ -134,7 +124,7 @@
{
"stem": "geo-q4-minimum-cover-31-points",
"png": "docs/figures/geo-q4-minimum-cover-31-points.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_geo_q4_mincover.m",
"sources": [
{
"path": "src/mcm26b/guarantee/plans/q4_mincover_v2.json",
@@ -148,24 +138,10 @@
}
]
},
{
"stem": "timing-measured-q3-10-sources",
"png": "docs/figures/timing-measured-q3-10-sources.png",
"scale": 1.0,
"sources": [
{
"path": "referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl",
"sha256_12": "5a308e53ed09",
"lines": 133,
"case_code": "BBM9-HZG2-77N5-NKKC",
"module": "q3_practice"
}
]
},
{
"stem": "replay-webui-q3-omnidirectional",
"png": "docs/figures/replay-webui-q3-omnidirectional.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_replay.m",
"sources": [
{
"path": "referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl",
@@ -178,13 +154,13 @@
{
"stem": "replay-webui-q4-directional",
"png": "docs/figures/replay-webui-q4-directional.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_replay.m",
"sources": [
{
"path": "referee-data/sessions/GM56-DFXZ-XKDM-XYV7/log.jsonl",
"sha256_12": "f498b2073cdf",
"lines": 421,
"case_code": "GM56-DFXZ-XKDM-XYV7"
"path": "referee-data/sessions/GHSN-M38E-74GD-YLUD/log.jsonl",
"sha256_12": "280696d901b4",
"lines": 429,
"case_code": "GHSN-M38E-74GD-YLUD"
}
]
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 101 KiB