refactor(panels): 平行数组合并为 std::vector<PanelRow>(消除错位与字段重载)
对应 Code_Review_Report §15.6 第 1 项(方案 B:有结构,无列视图)。
结构
- EdgePanelLayout 的 16 个平行 std::vector 合并为 std::vector<PanelRow> rows,
PanelRow 带 17 个具名成员:ref / header / nameRect / nameClose / triangle / check /
stats / levelTrack / levelValue / levelReset / iterTrack / iterValue / iterReset /
infoMaxInterval / infoMinInterval / intervalField / frequencyField。
- 唯一新增入口:AppendRow(ref, header, nameRect, triangle, check)(返回新行引用)与
AppendMarkerGroupRow(ref, nameRect, nameClose)(「自由标记」分组行)。
参数行/重采样行一律 layout.rows.back().xxx = … 赋值。
- 原 int rows(可见信号数)与新容器同名 ⇒ 改名 signalCount,并注明它与 rows.size()
在 MARK 面板里不相等(只有有固定点的信号才有行)。
消掉的两类问题
1. 某分支漏 push 一列 ⇒ 该列之后所有行读到别人的矩形(静默错位)。现在一行一次成型。
2. rowRefs 字段重载(列表式 = 行信号 / MARK = 分组信号,其余 12 列必须为空)。
现在每行自带 ref,语义由“填哪些字段”表达;不变式简化为语义断言
(每行必须有名称区;MARK 行不得带 header/check/stats/滑块/重采样字段)。
顺带清理
- 合并后 rowIndex < layout.rowXxx.size() 全部变成恒真,批量删除 50+ 处
(含 15 元组长度数组、? x : gd::RectF() 三元判空、if(...){extendRow(...)} 包裹)。
- 调试框与缓存键改为逐行遍历(新增字段只需在 PanelRow 与这两处循环各加一行)。
等价性证明(rowgeom 键名刻意保持不变,故可逐键比对)
old keys = 919, new keys = 965
仅存在于旧 = 0;已有键值变化 = 20(全部是 ".count":0 -> N)
仅存在于新 = 46(全部是新增列的 [NNN],值 0.00,0.00,0.00,0.00)
⇒ 逐行逐字段的真实几何零位移;7 个面板像素哈希(含 resample=2BFC74B3D9B3239C)逐项不变。
验证
- make release:零 warning;784,896 → 782,336 B(−2,560);make debug / make -C Tools 同样零 warning
- UnitTests:checks=260 failed=0 cases=19
- OffscreenChecks -all:7 检查 / 133 断言(上轮 127)全 PASS
- panels -mode compare:7 面板像素哈希逐项不变
- rowgeom -mode compare:965+7 键 0 差异;-data MF4-Record.MF4 时 1268+7 键 0 差异
- 读点:旧 243 处 layout.rowXxx[…] → 现 95 处 layout.rows[…](84 命中判定 / 11 绘制)
过程记录:清理恒真判空时曾用整段替换把「均值滤波」双滑块段误换成「弱峰」双滑块,
编译器报 brace 不平衡,用备份回滚后重做 —— 整段替换必须先精确读出上下文。
文档:Plan §十一、Progress 第 39 轮、Report §16、agent_mem 第 39 轮、Tools/README §4.1/§4.4
This commit is contained in:
1 parent
f07ac74988
commit
1463f9d3f8
11 files changed
+672
-591
No files matched your search
@@ -550,3 +550,82 @@ only-in-OLD lines NOT belonging to rowPoints/rowIterations = 0
|
||||
| `rowgeom -mode compare` | 919 + 7 键,0 差异 |
|
||||
| 行数 | `PlotViewPaint.cpp` 5575 → 5565;`PlotViewPanelPaint.cpp` 1016 → 1020(净增 4 行:函数头 + 文档) |
|
||||
|
||||
---
|
||||
|
||||
## 第 39 轮(2026-11-04):平行数组合并为 `std::vector<PanelRow>`(§15.6 第 1 项)
|
||||
|
||||
> 这是"面板改一次就出错"的**最后一个机制性隐患**:旧的 16 个平行数组靠"每个布局分支
|
||||
> 按同一顺序 push 恰好 N 项"维持对齐,任何一处漏推都是静默错位。
|
||||
|
||||
### P33 合并成 `std::vector<PanelRow>`
|
||||
|
||||
```cpp
|
||||
struct PanelRow
|
||||
{
|
||||
SignalRef ref; // 该行的信号(MARK = 分组的代表信号)
|
||||
gd::RectF header; // 信号色叠底条目栏 / 分组栏
|
||||
gd::RectF nameRect; // 名称区
|
||||
gd::RectF nameClose; // 名称右侧 ✕(仅 MARK)
|
||||
gd::RectF triangle; // 展开/收起三角
|
||||
gd::RectF check; // 右端复选框
|
||||
gd::RectF stats; // 「中心轴」上升/下降沿统计行
|
||||
gd::RectF levelTrack / levelValue / levelReset; // 滑块 1
|
||||
gd::RectF iterTrack / iterValue / iterReset; // 滑块 2
|
||||
gd::RectF infoMaxInterval / infoMinInterval; // 「重采样」两行只读统计
|
||||
gd::RectF intervalField / frequencyField; // 「重采样」两行输入框
|
||||
};
|
||||
std::vector<PanelRow> rows; // 唯一的行容器
|
||||
```
|
||||
|
||||
* 唯一入口:`AppendRow(ref, header, nameRect, triangle, check)`(返回新行引用)
|
||||
与 `AppendMarkerGroupRow(ref, nameRect, nameClose)`(「自由标记」分组行)。
|
||||
两者都**没有**"补齐其余列"这一步 —— 因为字段天生就在同一行里。
|
||||
* 参数行 / 重采样行从 `layout.rowXxx.back() = …` 变成 `layout.rows.back().xxx = …`。
|
||||
* 原来的 `int rows`(可见信号数)与新容器同名 ⇒ 改名 **`signalCount`**,
|
||||
并注明它与 `rows.size()` 在 MARK 面板里**不相等**(只有有固定点的信号才有行)。
|
||||
|
||||
### P34 顺带消失的两类问题
|
||||
|
||||
| 旧问题 | 现在 |
|
||||
| --- | --- |
|
||||
| 某分支漏推一列 ⇒ 该列之后所有行读到别人的矩形 | `rows.push_back(row)` 一次成型,**不可能**错位 |
|
||||
| `rowRefs` 字段重载(MARK 借它表示"分组",其余 12 列必须为空,长度不变式要按类别分流判定) | 每行自带 `ref`,语义由"填哪些字段"表达;不变式简化为"每行都要有名称区 + MARK 行不得带参数行字段" |
|
||||
|
||||
### P35 清理恒真判空
|
||||
|
||||
合并后 `rowIndex < layout.rowXxx.size()` 一律变成 `rowIndex < layout.rows.size()`,
|
||||
而它们全都在 `for (… rowIndex < layout.rows.size(); …)` 循环体内 ⇒ **恒真**。
|
||||
用正则批量删除 50+ 处(含 `a.size() != rows` 的 15 元组长度数组、`? x : gd::RectF()` 三元判空、
|
||||
`if (rowIndex < …) { extendRow(...); }` 包裹),并逐文件编译验证。
|
||||
|
||||
⚠️ 中途有一次误操作:把"均值滤波双滑块"那段替换成了"弱峰双滑块",
|
||||
编译器报 brace 不平衡 + 大面积类型错误 ⇒ 用备份 `Temp/PanelPaint.pre-cleanup.cpp` 回滚后重做。
|
||||
**教训**:这类"整段替换"必须先用 `read_file` 精确读出 5 行上下文,不要凭记忆拼 oldString。
|
||||
|
||||
### 等价性证明(本轮最关键的一步)
|
||||
|
||||
```
|
||||
old keys = 919, new keys = 965
|
||||
仅存在于旧 = 0 ← 没有任何键消失
|
||||
已有键的值变化 = 20 ← 全部是 ".count":0 -> N
|
||||
仅存在于新 = 46 ← 全部是 <column>[NNN],值全为 0.00,0.00,0.00,0.00
|
||||
```
|
||||
|
||||
⇒ 旧结构里"某列没被 push"的那些行,现在每行都拥有该字段但值为空矩形;
|
||||
**逐行逐字段的真实几何一位都没变**,7 个面板的像素哈希(含 `resample=2BFC74B3D9B3239C`)
|
||||
也逐项未变。之后按新结构重录正式基线(965 条键)。
|
||||
|
||||
### 本轮验证
|
||||
|
||||
| 项 | 结果 |
|
||||
| --- | --- |
|
||||
| `make release`(全量) | 零 error / 零 warning;产物 784,896 → **782,336 B**(−2,560) |
|
||||
| `make debug` / `make -C Tools` | 零 error / 零 warning |
|
||||
| `UnitTests` | `checks=260 failed=0 cases=19` |
|
||||
| `OffscreenChecks -all` | 7/7 PASS,`checks=133 failed=0`(上轮 127:新增行结构断言) |
|
||||
| `panels -mode compare` | 7 个面板像素哈希**逐项不变** |
|
||||
| `rowgeom -mode compare` | 965 + 7 键,0 差异(默认数据);1268 + 7 键(MF4 566 行),0 差异 |
|
||||
| 读点数 | 旧的 243 处 `layout.rowXxx[…]` 全部消失;现在 95 处 `layout.rows[…]`(84 在命中判定、11 在绘制) |
|
||||
| 行数 | `PlotView.hpp` 4795;`PlotViewInteraction.cpp` 4399;`PlotViewPanelPaint.cpp` 935;`PlotViewPaint.cpp` 5534;`PlotViewPanels.cpp` 1729 |
|
||||
|
||||
|
||||
Reference in new issue
Block a user