DeepSeek V4.1 Flash
|
34365b3c1c
|
perf(size): 用自写整数格式化替换全部 std::to_wstring / std::to_string
背景:Code Review 报告 §10.3 / §11.5 建议「替换 std::to_wstring / std::to_string,
可去掉 gdtoa 链(≈33 KB)」。本轮把它做完,并给出这条建议的**真实边界**。
一、新增 `Utf8Util::FormatInteger*`(手写十进制展开,不经 printf)
* `FormatInteger(long long)` / `FormatIntegerUnsigned(unsigned long long)` /
`FormatIntegerNarrow(long long)`(后者供 MatLoader 拼 HDF5 成员路径)。
* 语义与 `std::to_wstring` / `std::to_string` 完全一致:`0` → `"0"`、负数带 `-`、
`LLONG_MIN` 用模 2^64 语义取绝对值(不会溢出)。
* 这样做的直接理由:预编译 libstdc++ 的 `to_string` 内部转调 `__mingw_swprintf`,
工程里只要留一处,MinGW 的 printf 引擎(`mingw_wpformat.o`)+ gdtoa 就必然被链入。
二、全仓替换(76 处 `to_wstring` + 2 处 `to_string`,20 个文件)
* `MatLoader.cpp` 的 `TrimNumber` 整数分支也改为 `FormatInteger`(它曾是产物里
**最后一个**引用 MinGW printf 的调用点)。
* 需要的地方补 `#include "Utf8Util.hpp"`(仅 `MatLoader.cpp` 一个新 include,其余由
`PlotViewInternal` / `SignalPanelInternal` / `ApplicationInternal` / `DataModelInternal`
已经包含)。
三、⚠️ 实测结论:gdtoa **去不掉**(把这件事彻底查清并写进 Makefile 注释)
* 只替换 `to_wstring`/`to_string`:**−1,024 B**(787,968 → 786,944)。
* 再叠加 `-D__USE_MINGW_ANSI_STDIO=0`(把 `swprintf` 让给系统 UCRT):**0 字节**。
* 根因(定位到文件与行):libstdc++ 的
`lib/gcc/.../include/c++/x86_64-w64-mingw32/bits/os_defines.h:48-51` **无条件**执行
`#undef __USE_MINGW_ANSI_STDIO` + `#define __USE_MINGW_ANSI_STDIO 1`
(注释:libstdc++ depends on POSIX-definitions of those functions)。
`g++ -E -dM` 实测最终值恒为 1 ⇒ **任何 C++ TU 的 `swprintf` / `strtod` 都是 MinGW 版本**,
命令行无法覆盖。
* 要真省这 33 KB 只能自己实现「浮点 → 十进制(正确舍入)」与「浮点解析的
十六进制/inf/nan 分支」,等价于重写 gdtoa。**判定:不做**(风险 >> 收益)。
* 该开关已回退,Makefile 里保留一段说明,避免后续接手者重复这两次实验。
四、验证
* 新增单元测试 `integer_replacement_matches_std`:12 个有符号样本(含 LLONG_MIN/MAX)
+ 5 个无符号样本(含 ULLONG_MAX),与 `std::to_wstring` **逐字符对照**,
并校验窄/宽版本内容一致。
* `UnitTests`:`checks=260 failed=0 cases=19`(新增 41 条断言)。
* `OffscreenChecks -all`:6 个检查全 PASS,`checks=87 failed=0`。
* `panels -mode compare`:7 个面板像素哈希与几何**逐项不变**
(整数文本从 `to_wstring` 换到手写实现后,渲染结果零差异 —— 这是最强的语义证据)。
* release 全量零 error / 零 warning;产物 787,968 → **786,944 B**。
|
2026-11-04 14:31:02 +08:00 |
|
DeepSeek V4.1 Flash
|
97b361dedd
|
fix(ui): 采样统计显示一致化、GX 拖拽在布局边界下可用、信号「移动到…」与拖拽排序
一、采样间隔/频率显示不一致(用户报告 1ms vs 1000us、100us 0ns)
* FormatDurationCompound 改为「先量化到整数皮秒、再整数分解」,
彻底消除同一数值因浮点噪声落到不同单位/留下零尾数的问题;
秒级分支与亚秒分支共用 totalPs 方案,次级进位/单位升级集中在一处。
* FormatFrequency 的单位选择改为按「舍入后的显示值」判定(999.9999999Hz
与 1000Hz 均为 1.000kHz),并做向下校正避免 0.001kHz。
二、选区截取面板
* 提示文本改为用户指定原文「启用双光标模式以进行选区截取」。
* EdgePanelWidth 计入该提示的实际文本宽度;绘制改用 UiTextClipped 不再省略。
* viewHeight 补回漏减的 bottomPad,修掉条目区与按钮之间的空白。
三、未展开的信号条目栏悬停不再变成手型光标。
四、开启「显示布局边界」后 GX 标签可正常拖拽排序
* 抽出 PaintLaneReorderOverlay(吸附槽位 + 被拖轮廓),贴图与整幅重绘共用。
* 整幅重绘在 LANE_REORDER 时按 LaneDragOffset 逐格平移重画(被拖网格最后画),
修掉调试模式下不跟随鼠标、无吸附提示、只能盲拖的问题。
五、信号右键新增「移动到…」二级菜单(位于「仅显示该信号」之上)
* 条目为「分组 N(组名)」,当前组打勾;无标题行;底部「新建分组」。
* MenuItem::submenuMaxRows + PopupMenu 独立子菜单滚动(滚动条、滚轮、视口命中过滤),
IsScrollable 计入子菜单可滚状态。
* 数据层 DataSet::MoveSignalToGroup/MoveSignal 让时间轴随信号搬运
(独占则移动、共享则复制);TabConfig::RemapAfterSignalMove 改写引用而非先删后插。
* Application::MoveSignalCore 统一入口,保证派生计算暂停、引用修正、选中迁移与同步一致。
六、信号列表支持按住拖拽排序(组内重排 / 跨组移动)
* 4px 阈值进入拖拽;条目脱离原位跟随鼠标(阴影 + 强调色描边 + 插入指示线)。
* 其它信号行/分组行按插入位置做避让位移动画(RowRect 统一叠加插值位移,
宿主 kScrollTimerId 驱动 AdvanceSignalDragAnimation)。
* 数据层 DataSet::MoveSignal 支持任意位置;TabConfig::RemapAfterSignalReorder 线性重映射。
* 拖拽中禁用组名悬浮;双击改名与 InvalidateRows 均正确终止拖拽态。
验证:删 .o 全量重编译零 error / 零 warning;产物 873,984 B(< 1MB 预警阈值)。
本轮未使用鼠标/键盘/屏幕,未运行任何 GUI 探针,仅编译验证 + 源码级核对。
|
2026-11-03 19:27:43 +08:00 |
|
DeepSeek V4.1 Flash
|
c4300bd0e1
|
fix(resample): 重采样间隔/频率按真实值显示(次级单位与频率保留三位小数)
问题(用户实测 MF4-Record.MF4 / m_MOT_Current_DCom[0]):
- 最小数据间隔真实值 0.003696631s,却被显示成 3ms 700us(us 部分被向上截取);
- 对应频率真实值 270.516586589Hz,却被显示成 270.27Hz;
- 最大数据间隔 0.016182614s 显示成 16ms 200us、频率显示成 61.7284Hz,同样不准。
根因(两个,同一个坑):
1. RoundIntervalForDisplay() 把间隔先舍入到 3 位有效数字(0.003696631 -> 0.0037),
次级单位因此变成 700us,真实尾数被抹掉;
2. 频率用舍入后的 3.70ms 换算得 270.27Hz,而输入框用原值得 270.517Hz,两处不一致。
修法(一律使用真实值,舍入只发生在输出文本的最后一步):
- Utf8Util 新增 FormatDecimalFixed(value, decimals=3):固定小数位、保留尾随 0、
绝不出现科学计数法;
- Utf8Util 新增 FormatSubUnit(value, maxDecimals):带小数才补到 3 位,整数不加小数点
(5.06s -> 5s 60ms,而不是 5s 60.000ms);
- FormatDurationCompound 的两处次级单位(s+ms、ms/us/ns)改用它;
- FormatFrequency 改为 FormatDecimalFixed(scaled, 3);若保留 3 位后变成 0.000
(超低频,如 1/3662s ≈ 0.27mHz)则退回 FormatDecimal,避免有意义的值显示成 0;
- PlotViewInternal.hpp 删除 RoundIntervalForDisplay,FormatIntervalText 直接用真实值;
- PlotViewPaint.cpp 的统计行尾缀与频率输入框都用真实 interval 换算。
修复后的显示:
min interval 0.003696631s -> 3ms 696.631us
frequency 1/0.003696631 -> 270.517 Hz
max interval 0.016182614s -> 16ms 182.614us
frequency 1/0.016182614 -> 61.795 Hz
同时撤销了此前两次仅修改 agent_mem.md 的提交(47b1213 / caa035a,内容为乱码且无有效信息),
并按正确编码重新整理本轮记忆章节。
面板仍为四行(最大间隔 / 最小间隔 / 重采样间隔 / 重采样频率),未改动任何 UI 布局。
make release 零 warning。
|
2026-11-03 14:16:25 +08:00 |
|
DeepSeek-V4.1-Flash
|
74456b9305
|
fix(formula,resample): 公式映射卡顿根治 + 语法/输入框完善 + 重采样面板三处修正
一、「公式映射」卡顿(用户报告:只是点进输入框就卡,编辑过公式后彻底没法用)
1. 真因:菜单内联编辑提交时无条件回写初值 ⇒ 点进输入框再点别处就把
formula = "f(t)" 写进样式;而 HasFormula() 只判 !empty(),于是
DrawTransformOrderPreserving() 变 false、ComputeLaneRange() 每帧逐点扫描
整条信号(2580 万采样 ≈ 960ms/帧)。
修法:新增 FormulaIsIdentity()(空串与 f(t) 等价);提交时归一化后恒等即清空;
BuildLaneVisuals() 为「网格幅值范围」加指纹缓存(数据指针/长度/统计值 +
影响数值的样式字段),键不变直接复用(实测 0.0005ms)。
2. 真实公式仍然贵:新增 PlotView::AcquireFormulaEnvelope()(变换后的逐分组
包络,65536 组,按需算一次并缓存),BuildPolyline 的包络带改用它。
实测:静止 215→21ms、中键拖动 8ms、缩放最坏 843→81ms;极值仍逐点统计
(不会漏尖峰)。
3. AcquireProgram 只比 data() 指针 + 长度 ⇒ std::wstring 短串走 SSO 时,
等长改公式会一直复用旧程序(f(t)^2→f(t)^3 波形不更新)。改为按内容判定。
二、公式语法(Utilities/FormulaEval)
- 新增 ^ 幂(右结合,2^3^2=512、2^-1=0.5、-2^2=-4),支持 2^f(t) 与 f(t)^2;
- 常量 e / pi(大小写均接受,保存前统一小写);
- 数据点只允许 X / x / f(t):单独的 f 不再接受(且不归一化,直接报错);
- 数字扫描修正:2e 里的 e 不再被当成指数吞掉。
三、「公式映射」输入框(SignalPanelMenu)
- Y= 画在输入框内部(非编辑态),进入编辑态只显示公式本身;
- label 留空 ⇒ 输入框占满整行,与下方「系数调整」同宽。
四、「重采样」面板
- 修复点进间隔/频率输入框后输入框整块消失(paintOverlays 的 PaintEditField
名单漏了 RESAMPLE_INTERVAL / RESAMPLE_FREQUENCY);
- 最大/最小数据间隔:3 位有效数字 + Δt 复合单位,末尾追加(频率)尾缀;
- 间隔显示自适应单位、编辑态用秒;频率显示自适应单位、编辑态用 Hz(均不带单位);
- 面板宽度按含(频率)尾缀的文本量宽。
五、十进制格式化(Utf8Util)
- 新增 FormatDecimal(绝不产生科学计数法);FormatDurationCompound /
FormatDurationSeconds / FormatFrequency 改用它,Δt/间隔/频率读数不再出现 1e-05。
验证:离屏探针 .preflight/perf/probe/formulacheck_main.cpp 75/75;
make release / make debug 零 warning;Release 856,064 B。
|
2026-11-03 02:55:22 +08:00 |
|
DeepSeek V4.1 Flash
|
1e1c2432ae
|
feat(resample): 实验性功能新增「重采样」(位于「自由标记」上方)
- Lane::ResampleItem + resample/resampleItems/resamplePanel/resampleScroll,
并在 LaneCarry / SplitLane / PruneLaneSignalItems / RemapAfterSignalInsert|Removal 同步
- 面板:可滚动分组列表(信号色条目栏 + 复选框 + 展开三角),展开后 4 行:
最大/最小数据间隔(只读,勾选时一次性缓存,绘制不扫描采样)+ 重采样间隔/频率(输入)
- 输入框联动:改间隔同步频率,改频率同步间隔(输入单位分别为秒 / Hz)
- 「构建为新信号」:DataSet::AppendGroupAxis 追加新时间轴 + InsertDerivedSignal,
采样值先按公式/系数/绝对值/镜像/Y偏移变换再等间隔线性插值,时间轴偏移不烘值
- 新信号名 <原信号> (重采样 <自适应单位频率>);Utf8Util::FormatFrequency 为唯一实现
- 非单调轴 / 点太少 / 间隔过大 / 点数超 2000 万 ⇒ 拒绝构建并给出自绘提示
- 顺带加入 FormulaEval(公式编译/求值,供 ApplyDrawTransform 与后续 UI 使用)
|
2026-11-02 20:41:26 +08:00 |
|
DeepSeek V4.1 Flash
|
53b981a2a9
|
全项目大检查:修复数据层/UI 真 BUG、清理死代码与过期注释、并评估二进制体积
按「性能 / BUG / 错误 / 过期注释 / 命名与实际含义不符」四项对全仓做了一次审查,
四个只读子审查交叉核对后逐条回到源码确认再改。
一、数据层真 BUG
- MatH5:U8/U16/U32/U64 用逐字节 Cached() 拼装,而 Cached 只服务「完全落在同一个
64KB 块内」的请求 => 跨块时静默读成 0(U32 整段为 0、U64 高 32 位为 0),分块 B-tree
的 chunk 偏移/子节点地址被破坏且无任何报错。新增 ScalarLE():命中缓存用缓存,
否则退回一次 ReadAt;U64 顺带从 8 次缓存查找降到 1 次。
- Mf4Loader::IsBlock 未校验链接表是否落在块内 => DataOffset 越界,随后
block_len - (data - offset) 在 uint64 上下溢,得到一个约 2^64 的"可用字节数",
下游 vector(usable+1) 直接 bad_alloc。同时把 offset + bytes > size 改成不产生回绕的写法。
- DecodeRawValue 的整数路径:bit_offset%8 != 0 且位宽 64 时需 9 个字节,先拼成 64 位
再整体右移会把最高字节静默丢弃 => 改为逐字节带位偏移累加。
- cg_cycle_count 加「数据段总字节 / 记录字节」上限(压缩段按 deflate 最大膨胀比估算)。
- CsvLoader 表头分支同样跳过 #/% 注释行(否则整份文件按 1 列解析并被丢弃)。
- MatLoader:double -> int 的越界转换加了范围检查;普通对象递归加深度上限与成环检测。
- Utf8Util::BuildTicks:double -> long long 越界转换前先判商是否落在 ±9e18 内。
二、界面 BUG
- 工具栏按钮永远不显示悬停高亮:Paint 读的 Button::hover 全仓从未赋值,改为按 m_hoverIndex 判断。
- 菜单打开时"取消底层拖拽"对每个消息都执行,把菜单自己的 Target::EDIT_FIELD 也清掉
=> 菜单内联输入框无法拖拽框选。排除 EDIT_FIELD。
- GdiplusShutdown 之前未释放 PlotView 的 GDI+ 位图(Application 是进程单例,成员析构在
WinMain 之后)=> 新增 PlotView::ReleaseGraphicsResources() 并在 Shutdown 里调用。
- WM_KILLFOCUS 现在会提交标签页/绘图区编辑并复位捕获与拖拽状态。
- WM_LBUTTONUP 不再抢走中键平移的鼠标捕获。
- TextEdit:被过滤器拒绝的字符返回 false;无选区时 Ctrl+X 只复制、不再清空整段文本。
- SignalPanel::InvalidateRows 作废编辑/待确认/改名计时等行下标状态。
- EndFilterEdit 改走 ApplyFilterText(否则输入纯空格后回车,列表仍停在筛选结果)。
- 新增 SignalBadgeVisible 作为唯一判据(原来命中只看"可见",绘制还要求"已分配网格")。
- 折起动画结束后夹取滚动量;双击分组名改名时清掉该组正在播放的折起动画。
- ScrollToSignal 复用 SignalScrollTarget(含悬浮组名避让)。
- RowNameRect 与绘制使用同一最小宽度(原来退化时返回空矩形)。
- 分隔条拖拽上限改用与 Relayout 同一公式;UpdateDragCursor 补 SPLITTER/EDIT_FIELD。
- SignalPanel 里几个守卫改为判断真正被解引用的指针;分组行 ✕ 也返回手型光标。
三、PlotView
- FindStyleOnlyLanes 改用完整的 SceneStyleEntry::operator==(原来只比 4 个字段,
另一个网格同时改"调整"时带着旧像素被当成最新)。
- 宽基底图层不再烘焙拖拽光晕(LaneLayerHash 不含它),改由 PaintHoverHighlight 每帧叠加。
- PaintLaneLegend 提前返回前清掉本网格的命中矩形(否则能点中看不见的图例条目)。
- 面板主体改为完全不透明(消除平移后 4% 透出的旧波形,零额外代价)。
- PAN / Shift+滚轮改走 SetTimeView,使"自动点线"判据随平移重算。
- 内联输入框命中字体与绘制统一为 monoSmall。
- 派生曲线取值与窗口按 SourceIndexFor 映射(水平镜像时不再读到镜像另一端)。
- EdgePanelWidth 补 style/axis 空指针守卫;二分结果夹到 count。
四、清理
- 删除 Toolbar::ActionLabel、Theme::statusBg、PopupMenu 的 editResult 死机制、
Toolbar::Layout 的重复 clear()、HitRow 的恒假分支、OnDoubleClick 的重复判定、
PaintUtil 里孤立的注释块。
- 修正一批过期/错误注释(包络带"不做加宽"、LaneLayerHash 的图例说法、
均值滤波曲线的窗口说法、样式区行数与「调整」按钮顺序、FIT_ALL 退出缩放模式、
RemoveSignal 的 ✕ 位置、.mat/.dat 格式文档、MatH5 的"映射视图"、DataModel 的
"点线/被移除文件"、SignalPanel 的"行高连续缩小"、TextEdit 的 PaintUtil 引用等)。
五、二进制体积评估(按要求只评估,未做压缩修改)
- release 809,472 字节;.text 652KB、.xdata+.pdata 约 75KB、.rdata 42KB、
.rsrc 20KB、.idata 11.5KB。
- 去掉 -ld3d11 -ldwmapi -ld3dcompiler(仓内无任何调用)实测 0 字节收益
(静态库只拉取被引用的对象)=> 删链接库不是压缩手段,只是配置整洁。
- 仓内已无 <iostream>/<sstream>/<filesystem>/<regex>/<locale> 等体积炸弹。
- 结论:已无明显的浪费可捡;要显著变小只能改变取舍(动态 CRT / UPX / 砍功能),
需要用户决策,本轮未动。
验证
- editcheck 20/20、round3check 31/31、round4check 34/34、round5check 5/5、convcheck 18/18。
- check 136/137:唯一失败项经 git stash 回到改动前复现同一数值,属该探针自身的既有
不稳定项(取决于前置用例留下的缓存/时序),与本轮改动无关。
- 真实数据:4 个 MF4 => 283/8/18/24 个信号;.mat 样例 8 信号、
带无障碍对照-防夹力曲线数据 8 信号、BIG_MAT.mat 5 信号(私有内存 +741MB)。
- make release / make debug 零警告。
文档:Documents/agent_mem.md 同步 §10 变更日志、§11.2 第 171-180 条硬约束
与文末本轮小节(含体积评估数据)。
|
2026-10-20 16:10:29 +08:00 |
|
DeepSeek V4.1 Flash
|
fc77b0262f
|
「调整」行:系数/偏移 按钮 + 偏移调整(Y 轴/时间轴)二级面板;结算顺序加入偏移;派生信号继承调整变换
按钮与面板:
- 「系数」按钮改名为「系数/偏移」;点击展开的二级面板在原「系数调整」输入框下方新增「偏移调整」:
与「系数调整」同一套绘制(标题 + 标题栏右侧的还原图标),下面两行分别是「Y轴」「时间轴」,
每行左侧说明文字、右侧内联输入框(整行数值框)。
- 「Y轴」默认 0.00,非编辑态**始终带正负号**(+0.00 / -12.50),小数不足两位时补两位、更高精度保留更多位。
- 「时间轴」默认 0.00,非编辑态显示与双光标差值同一套复合单位文本(`Δt:500ms`、`Δt:1h 1min 2s`);
进入编辑态时显示以**秒**为单位的数值,并在输入框最右侧提示单位 `s`。
- 「偏移调整」的还原图标把两个偏移恢复为默认值 0;「系数调整」的还原图标仍只重置系数。
- 面板/输入框的编辑初值与显示文本分离(`MenuItem::editValue` / `editSuffix`),
非编辑态(`Δt:…`)与编辑态(`3662`)不一致时也能正确回显。
语义与结算顺序:
- 结算顺序变为 **系数 → 绝对值 → 镜像 → 偏移**(前三步不变)。
- Y 偏移:给绘制值加常数(波形上下移动);时间偏移:采样绘制在 `t + offsetTime` 处
(例如 t=1s、偏移 -0.5s → 画在 0.5s)。
- ⚠️ Y 偏移以**未镜像空间**为准:垂直镜像开关变化时同步取反偏移量,
使绘制等价于「先加上偏移再镜像」(开关来回切换可逆)。
- 绘制链路全部跟随偏移:`BuildPolyline`(逐点描边 / 像素列包络 / 跨列边界插值 / 粗粒度分组层,
保序的 Y 偏移直接加在分组极值上)、派生预览曲线、光标取值读数(含 Δt)、
可见区间 Y 轴自适应、整段自适应的区间映射;折线缓存键、场景指纹、样式快照与图层指纹都纳入两个偏移。
派生信号(实验性功能「构建为新信号」):
- 修复「预览是调整后的波形、构建出来却按原始状态绘制」:新信号**继承源信号的调整变换**
(系数/绝对值/两个镜像/两个偏移)——网格预览绘制的是 `变换(滤波结果)`,
而构建出的信号只存了滤波结果,因此必须把变换一并继承;
时间轴偏移**只能**靠继承(派生信号与源信号共用同一文件时间轴,无法把时间平移烘进数据)。
离屏验证(不干扰用户):
- ⚠️ harness 现在在每次注入鼠标消息后**立即释放本窗口的鼠标捕获**
(宿主 WM_LBUTTONDOWN 会 SetCapture,隐藏窗口同样会把用户的真实鼠标输入吸走);
后续消息本来就是直接投递,无需捕获。
- 新增 [AP]:按钮标签不裁切、面板 5 行顺序与「偏移调整」位于系数输入框下方、
Y轴/时间轴行的标签与输入框同行且默认值/单位提示正确、时间轴编辑态显示秒值并在最右侧提示 `s`、
Y 偏移提交/显示正负号/波形整体平移量、时间偏移提交/Δt 复合单位(含 3662 → Δt:1h 1min 2s)/
编辑态为秒、**按"偏移若干个采样点"构造的精确几何验证**(采样被画到移位后的像素位置、且不再画在原处)、
读数跟随、两个还原图标、垂直镜像对 Y 偏移取反(可逆)、
以及派生信号继承变换;[AL] 补充「系数→绝对值→镜像→偏移」的顺序与区间映射(含 Y 偏移)。
- 合计 645/645 通过;make clean && make all 零警告。
|
2026-10-13 17:56:00 +08:00 |
|
DeepSeek V4.1 Flash
|
8801c8f019
|
修复缩放视界下拖拽与改色卡顿、加载字节进度、光标越界三角与中心轴均值滤波统一
1. 修复选区放大后的拖拽/改色卡顿(先实测再修,不猜)
- 用离屏探针量化:缩放视界下一帧要画约 250 条网格线,GDI+ DrawLine 每条 0.1~0.19ms,
整帧 26.4ms;而包络带填充本身只要 0.36ms,真正的瓶颈是逐条直线调用。
- 网格线、时间轴刻度、绘图区边框、网格分隔线全部改为 GDI 批量 1px 直线绘制
(一次 SaveDC/IntersectClipRect/创建画笔,逐段 MoveToEx/LineTo);
纵轴数值胶囊改为把所有圆角矩形合并成一个路径、只调用一次填充。
- 半透明网格线颜色先用底色预混成不透明色,否则 GDI 无法绘制透明度;
GDI 绘制不受 GDI+ 裁剪约束,批量绘制一律显式设置裁剪矩形。
- 实测:缩放视界下场景缓存失效帧 26.4 -> 8.25ms,改色应用 7.1 -> 3.15ms,
缓存命中帧 2.06 -> 0.30ms。
2. 读取文件时显示"已读取 / 总大小 百分比"
- 解析进度回调扩展为携带真实字节数(已读字节、文件总字节);
列重组等没有字节可计的阶段只显示百分比。
- 新增字节数格式化:单位在 GB / MB / KB 之间自适应,只输出数字与单位;
已读大小随进度自动切换单位。
- 进度浮层按"已读取 / 文件总大小 百分比"显示,两个大小与百分比都保留两位小数,
完全取代原来的整数百分比。
3. 网格编号拖拽重排的绘制修复
- GX 编号悬停时保持普通箭头光标(不再变成四向箭头),按下拖拽时才使用上下箭头。
- 拖拽时先把整幅静态场景(含主时间轴)贴回,再把目标槽位高亮、被拖网格的轮廓与
投影裁剪在绘图区内,因此拖到工具栏甚至更上方、或拖到时间轴及下方都不再出现
残留与错乱。
4. 网格 Y 轴数值只在完全移出可视区时才不绘制
- 原来只要碰到边界就整条不画;现在按可见范围裁剪胶囊与数值,
部分可见时绘制未被遮挡的部分。
5. 边沿计数横向光标的读数与越界指示
- 幅值读数右移,让开横线左端的三角把手,不再遮挡。
- 幅值超出视界时(横线贴边显示)在读数上方/下方绘制方向三角,
并且与读数水平居中对齐。
6. 常规光标读数越界与双光标叠放
- 光标滞留在视界之外时,时间读数同样绘制方向三角。
- 双光标读数重叠时按时间值排序:小值在上、大值在下(原来固定把第二个上移,
左右光标交换后会显示成大的在上)。
- 双光标同时越界到同一侧时,两条时间读数与时间差值读数在同一列垂直对齐,
并为差值读数绘制方向三角;叠放间距按三角深度放宽,三角不会再压在相邻读数上。
7. 中心轴边沿计数与均值滤波统一
- 参数由单一的"平滑点数 N"改为按信号的"均值点数 X + 阶数 N",与实验性功能中的
均值滤波完全同构(同样的命名、同样的作用、同样的曲线实现),
两条曲线逐位一致,光标处的取值标注规则也统一。
- 浮动面板改为自上而下的逐信号条目,每个条目三排:
第一排信号名与复选框,第二排均值点数与阶数输入框,第三排该信号的上升沿/下降沿统计;
取消勾选即不显示该信号的参数编辑与统计结果,启用时默认只勾选第一个可见信号。
- 网格重建继承、拆分网格、信号插入/删除的下标修正与场景缓存指纹都同步覆盖新条目。
测试:离屏自动验证套件新增一组检查(字节数格式化、解析进度字节、编号悬停/拖拽光标、
双光标读数排序与对齐、中心轴三排布局与参数、横向光标越界三角、加载浮层渲染等),
合计 241 项检查全部通过;验证过程不显示窗口、不移动鼠标键盘、不抓屏。
|
2026-10-10 16:47:05 +08:00 |
|
DeepSeek V4.1 Flash
|
350538c634
|
命名审查与垃圾代码清理(纯重命名 / 死代码删除,无行为变更)
前提:加载完成后全部采样都已驻留内存,程序此后与源文件再无联系。
据此修正了一批会让人误以为"仍在读写文件"的命名:
- SampleFileAt → SampleSignalAt(取的是内存信号在给定时刻的采样值)。
- DataSet::AddPreparedFile → AddDataFile。
- PlotView::InvalidatePolylineCache → InvalidateDerivedCaches
(它同时清空折线、边沿统计、中心平均值曲线、静态场景缓存与悬停引用)。
- PlotView::CursorColor(int which) → CursorColor()(两条光标同色,参数从未使用)。
- UiEllipsize(g,…) → UiEllipsize(…):纯测量不绘制,删掉被忽略的绘图上下文参数;
同时删除与 UiMeasureTextWidth 完全重复的 UiTextWidth,调用点统一到 UiMeasureTextWidth。
清理残留参数((void)xxx;):
- TabConfig 的可见性/网格族(SetVisible / ToggleVisible / SetFileVisible / SetAllVisible /
SoloSignal / SetMode / SyncLanes / FileHasVisible / FileAllVisible)去掉从未使用的
const DataSet& 参数(仅 SyncToDataSet 真正需要数据层,保留)。
- PlotView::OnLButtonUp(int y)、OnMouseWheel(int delta, bool shift);PainterSignalHalo 去掉未用的 ref。
- BuildDataFile 中未使用的局部 rowCount。
删除无人调用的死函数:
DataSet::Clear / AddFromTable;SignalColorCount;WideToUtf8 / StartsWith;
PlotView::ViewMinTime / ViewMaxTime / EdgePanelRect / EdgePanelCloseRect /
EdgeCenterPanelRect / ScaleLaneRange / BeginLaneValueEdit / LaneContentHeight;
SignalPanel::NeedsScrollBar / IsFilterEditing / FilterText / ContentHeight;
PopupMenu::EditingItemId;TabBar::IsDragging;TextEdit::PlaceCaret。
删除只写不读的死字段:CsvTable::sourceRowCount(与 rowCount 等义)与 skippedRowCount。
以 VERY_BIG_DATA.CSV 回归验证:加载与勾选、筛选框(含"无匹配的筛选信号")、
样式区线宽文案省略、选区放大(横向与纵向)、双光标读数与 Δt、右键菜单(Y 轴数值与
实验性功能子菜单)、合并/拆分网格、标签与信号重命名省略号,行为均与改动前一致;
make clean && make all 无任何警告。
|
2026-10-09 21:52:46 +08:00 |
|
DeepSeek V4.1 Flash
|
45b44eae57
|
网格菜单重构、大文件异步加载与内存/解析优化、修复应用图标
网格右键菜单:
- 菜单顺序改为: 网格 N / Y 轴最大值 / Y 轴最小值 / 选区 Y 轴自适应 / --分隔线-- /
Y 轴自适应 / 时间轴自适应 / 全部自适应
(恢复自适应移到分隔线以下、时间轴自适应上方)
- Y 轴最大值/最小值改为菜单内联输入框:点击就地编辑、回车提交,菜单不关闭,
处理方式与拾色器的 RGB 内联编辑一致;提交后按真实夹取结果回写菜单显示值,
并同步刷新自适应项的文案/对勾/可用状态
- 新增"选区 Y 轴自适应":只按当前显示时间段内的数据做幅值自适应
(时间单调时二分定位区间,非单调时全扫并按区间过滤)
大文件加载:
- 加载改为工作线程执行(解析 + 按列重组),主线程抽送消息并播放过渡动画
(旋转弧线 + 进度条 + 文件名 + 百分比 + 按 Esc 取消),界面不再整块卡死
- 加载完成后主线程只做一次 O(1) 的移动入队,不会产生可见卡顿
- 新增 DataModel::BuildDataFile / DataSet::AddPreparedFile:不依赖 DataSet,
因此可以安全地在线程上运行
内存与解析效率:
- CsvTable 由"行优先二维数组"改为"列优先":百万行文件原先会产生上百万次独立堆分配
(每行还有 vector 控制块与容量对齐开销),现在每列一整块连续内存
- 解析改为流式分块读取(4MB),不再把整个文件读入内存,也没有体积上限
(原先超过 512MB 直接拒绝);实测 51MB 文件峰值内存约 126MB(数据本身 113MB)
- BuildDataFile 直接把整列移动进 SignalData(零拷贝),不再逐元素复制
- TryParseDouble 增加十进制快速路径:ucrt strtod 实测约 335ns/次,手写路径约 13ns
(快 25 倍);非十进制写法(十六进制浮点、inf/nan、带尾部杂字符)原样交回 strtod,
输入接受语义完全不变(实测与 strtod 的差异不超过 1 ULP)
→ 640MB 测试文件加载时间由约 40s 降到 2s 以内
交互流畅性:
- 拖拽(平移/框选/拖动信号)期间关闭波形抗锯齿并压缩顶点预算(2 像素一列包络),
松开后立即恢复全质量绘制;实测 BIG_DATA 10 信号全显示的帧耗时由
105~168ms 降到 75~90ms(其中折线绘制 55ms→23ms)
- 折线包络抽稀改为"列边界单调推进"的二分,避免每列在全区间二分造成缓存缺失
- 未对波形构建引入多线程:构建已由几何键缓存消除,且拖拽降级后仅约 1~2ms/帧,
并行化收益不足以抵消线程与同步的复杂度(加载路径的多线程收益明确,故只在该处引入)
图标:
- 窗口类与 WM_SETICON 原先使用系统默认图标 IDI_APPLICATION,导致标题栏、
任务栏与 Alt+Tab 缩略图都显示成通用应用图标;改为按 SM_CXICON/SM_CXSMICON
从应用的 IDI_APP_ICON 资源加载(多尺寸 ICO 会挑选最接近的一帧)
其他:
- PopupMenu 新增 EDIT 项类型(菜单内联输入框)与 UpdateItemValue/UpdateItemLabel
|
2026-09-30 18:46:56 +08:00 |
|
DeepSeek V4.1 Flash
|
53768b8b25
|
fix: 统一输入框编辑能力、修复拖拽合并网格并支持光标吸附数据点
统一文本输入(新增 Utilities/Inc/TextEdit.hpp + TextEdit.cpp)
- 一个共享的编辑模型,提供光标/选区/过滤/限长,接入全部输入框:
样式区数值与信号名/分组名、波形图例改名、视图标签页改名、
拾色器 R/G/B 与色号、光标时间与网格上下限。
- 新增能力:Ctrl+A/C/X/V(含剪贴板清洗)、Shift+方向键与 Home/End 选区、
退格与删除清除选区、代理对安全的光标步进。
- 渲染改为选区高亮 + 插入符,文本超出框宽时水平滚动并让插入符始终可见;
初始态为整段选中,首字符键入即整体替换(保持"登录框"式交互)。
- 新增 Utf8Util::PasteTextFromClipboard(换行/制表符折叠为空格)。
修复网格合并(Utilities/Src/DataModel.cpp)
- 拖拽信号到其它网格时先固定目标网格的锚信号,再移除源信号并按引用找回目标,
避免空网格回收导致下标错位,从"与原网格交换位置"改为真正合并。
- 自定义划分下未分配网格的可见信号改为各自独占一个新网格,
修复"拖拽合并后再勾选新信号被并入该合并网格"的问题。
绘图区(Components/PlotView)
- 网格右键菜单新增"时间轴自适应(匹配本网格)",把时间轴对齐到该网格信号范围。
- 时间轴放大到采样点在屏幕上可分辨(>=6 逻辑像素)时,拖动光标吸附到最近数据点;
缩小到无法分辨时保持自由移动,避免光标"跳格"。
验证:真实输入脚本逐项核对——拖拽合并后单网格含两条曲线、拖拽合并再勾选新信号得 G2 独立网格、
Shift 选区 + Delete 清除、Ctrl+A/C/V 复制粘贴、46 字符文本水平滚动、拾色器色号 1E90FF、
标签页改名 A1、光标时间框复制粘贴、全视图拖动得 0.522213(不吸附)而放大后得 0.28125(= 225 × 0.00125,已吸附)。
|
2026-09-30 13:40:58 +08:00 |
|
DeepSeek V4.1 Flash
|
261b8ac07d
|
fix: 修正滑块填充残留、数值内联输入与信号/分组重命名,拖拽虚影跟随鼠标
- 滑块最小值时不再有超出圆钮的填充残留,三处滑块统一为共享实现
- 透明度/RGB/色号支持点击或双击直接输入,整段高亮、首次键入替换、回车提交、Ctrl+C 复制
- 双击信号行或分组名进入重命名编辑;分组竖线改为绘制而非字符
- 拖拽信号时曲线虚影跟随鼠标纵向位移
- 数据层新增展示名覆盖,面板改为持有可写数据集合
|
2026-09-30 09:38:22 +08:00 |
|
DeepSeek V4.1 Flash
|
132b305544
|
feat: 搭建 Just DataInspector 波形数据查看器基础功能
基于 Win32 API + GDI+ 从零实现仿真数据检查器,用于替代 Simulink.sdi.view 查看带时间轴的 CSV 数据。
- 新增 Utilities 层:UTF-8/宽字符与数值格式化工具、CSV 解析器(自动识别分隔符与引号)、
信号数据集模型(时间轴识别、信号名解析、取值采样)、Solarised Light 主题色板与绘图基础工具
- 新增 Toolbar 组件:打开 CSV、适应窗口、适应时间、放大、缩小、合并网格、每信号一格
- 新增 SignalPanel 组件:信号列表(可见性开关、颜色标识、所属网格标记)、样式编辑区
(颜色、线宽、线段/散点/点线/阶梯显示方式、所属网格),支持右键上下文菜单与滚轮滚动
- 新增 PlotView 组件:多网格波形绘制、自适应时间轴与幅值轴、网格线、信号图例、
时间光标与实时数值读数、纵向滚动条
- 新增 Application 组件:DPI 感知(Per-Monitor V2)、双缓冲绘制、区域布局与分隔条拖拽、
鼠标与键盘消息分发、文件拖放、状态栏提示
- 交互能力:滚轮缩放、Shift+滚轮平移、Ctrl+滚轮缩放幅值、拖拽平移、幅值轴纵向缩放、
右键框选缩放、单击固定/取消时间光标、双击自适应、方向键平移与滚动
- 补齐 Makefile 的源文件与头文件索引,并新增 gdiplus、comdlg32 链接库
|
2026-09-29 15:05:29 +08:00 |
|