多层加载拖拽卡顿根治 + 高亮命中线段中段 / 散点高亮 + 选区放大也高亮 + 自动点线判定与规则修正
一、三明治加载后拖拽视界卡顿(39.2ms → 8.2ms 均值,47.9ms → 10.3ms 最坏)—— 四个叠加根因 1) RenderLaneLayerRegion 每次「横向补条」都调用两次 BuildLaneVisuals()(对全部网格算 ComputeLaneRange,O(网格数))⇒ 253 网格时单帧 RollWideBuffer = 26.8ms。 修法:进入前快照 m_lanes / m_laneContentHeight,结束时直接拷回(它只渲染一个网格)。 2) 横向「重新居中」本来就不是正确性要求:BlitWideBuffer 按 (ViewMin - layer.wideMin) * scale 算源偏移,不滚动也画得对 ⇒ 新增 kLayerRollQuantumX=32(不足一个量子不滚)+ kLayerRollsPerFrame=3(每帧最多重居中 3 个网格,分帧摊销)。 3) 位移过大时旧实现「立刻整块重画」:巨型信号(25M 采样)一次 20~130ms,实测拖拽最坏帧 28ms。 修法:kLayerRollMaxShiftPixels=160,超出就作废图层 + 登记待重画,本帧由 BlitWideBuffer 的 网格底衬兜底(正是用户要求的“没来得及画信号就按只有网格叠底继续拖”); 并且 RollWideBuffer 只处理可视/预取带内的网格(离屏网格不做像素工作)。 4) 包络带路径也支持横向补条裁剪:包络是逐像素列独立计算的,只构建条带覆盖的列即可。 旧实现对包络带总是构建整幅可见范围 ⇒ 巨型信号一条 32px 竖带要 5ms。 二、鼠标悬停「两点之间的连线」无法高亮(放大到自动点线后) 根因:HitTestSignal 的横向窗口用 upper_bound(fx+tol) 取顶点区间,只扫 [first, last) 的线段; 放大后相邻点相距几十像素,鼠标落在两点中间时两端都在窗口外 ⇒ windowFirst >= windowLast ⇒ 跳过。 修法:线段扫描上界改为 min(stop, windowLast + 1)(必须包含“一端在窗口内、另一端在窗口外”的线段); 散点命中的顶点范围也向两侧各扩一个。实测 11 段长线段中点命中 0/11 → 11/11。 三、散点模式补充高亮(用户要求:原线段/点线高亮“去掉数据点之间连线的部分”) PaintSignalHalo 原来对 DrawMode::SCATTER 直接 return ⇒ 只有拖拽提示、没有高亮。 现在给每个参与绘制的散点套一圈半透明强调色圆环(步长与绘制同源 kMaxScatterPoints)。 线段 / 点线保持原有的折线光晕。列表 / 图例 / 样式区「目标」行联动高亮走同一条路径,自动生效。 四、「选区放大」模式恢复悬停高亮(仍不允许拖信号) OnMouseMove 去掉 ZoomMode() == NONE 的门控;OnLButtonDown 在 SELECT 模式下仍直接进入 RUBBER_SELECT。 该模式下的提示文案只显示信号名(去掉 “· 按住拖拽可移入其它网格” 尾缀)。 五、自动点线误判(MF4 + VERY_BIG_DATA 同时加载时 MF4 信号默认就被切点线) 根因:MinorCellSparse 把整个视界切成小格。VERY_BIG_DATA 跨度 ~130s、MF4 数据只覆盖 ~11s ⇒ MF4 信号在 90% 的格子里本来就没有任何采样点 ⇒ “存在一个格子内 < 5 个点”恒成立。 (用户猜测是“用了抽稀点”,实际是“空格子”,但现象一致。) 修法:先用可见数据的显示时间跨度 [dataMin, dataMax] 收窄参与的格子(firstCell..lastCell), 鸽巢判定的分母改用参与格子数;端点 NaN 时做 64 步有界探测并回退到轴区间。 实测:248 个 MF4/中等信号被误判的数量 248 → 0。 六、自动点线规则收窄(用户本次要求) 只有 DrawMode::LINE 的信号在放大时自动切 LINE_SCATTER;SCATTER 不切换(散点已足够提示数据点位置)、 LINE_SCATTER 不动;用户手动改过样式(autoScatterUserOverride)时不切换,避免“改完下一帧又被改回去”。 退出时(用户未手动改过)恢复原来的 LINE。 实测:LINE → 放大后 mode=2 auto=1 → 适应视图后 mode=0 auto=0;SCATTER → 放大后 mode=1 auto=0。 验证(全部离屏,不占用鼠标/键盘/屏幕) - 新增 .preflight/perf/hoverdrag_main.cpp(hoverdrag.exe)20/20:三明治加载后的点选跳转 + 拖拽逐帧耗时、 线段中点命中、散点高亮像素、选区放大悬停命中、自动点线判定与规则。 - 既有回归:verify 49/49、panelanim 158/158、datacheck 69/69、edgecheck 46/46、errcheck 19/19、 gridanim 93/93、lanescroll 23/23。 - 探针的绝对毫秒阈值改为相对基准(同一基线代码在不同时段可差 2~3 倍,避免假失败)。 - make release / make debug 零错误零警告(用 TARGET_FILE_NAME=TargetCheck/TargetCheckD 避免与运行中实例冲突)。 文档:Documents/agent_mem.md 新增 §9.45、§11.2 第 141–150 条与变更日志一行。
This commit is contained in:
1 parent
6b15575829
commit
fd606a6f80
5 files changed
+394
-70
No files matched your search
@@ -65,6 +65,40 @@ namespace jdi
|
||||
*/
|
||||
inline const int kLayerRollQuantum = 16;
|
||||
|
||||
/**
|
||||
* @brief 图层**横向滚动**的量化阀值(位图像素)。
|
||||
*
|
||||
* `BlitWideBuffer` 贴图时按 `(ViewMin - layer.wideMin) * scale` 算源偏移,因此图层
|
||||
* **不需要每帧重新居中**:只要视界仍在位图覆盖范围内,直接按偏移贴就够了。
|
||||
* 旧实现每帧都把图层滚回“居中”位置(补一条 2px 宽的竖带),而每次补条都要重跑
|
||||
* 一次 `BuildLaneVisuals()`(O(网格数))⇒ 253 个网格、30 个可视网格时
|
||||
* **单帧 26.8ms**(用户 2026-10-17 报告:三明治加载后拖拽视界卡顿)。
|
||||
* 改成“位移达到一个量子才滚一次”后,正常拖动几乎不会触发补条。
|
||||
*/
|
||||
inline const int kLayerRollQuantumX = 32;
|
||||
|
||||
/**
|
||||
* @brief 图层横向位移超过该值(位图像素)时就**作废图层**(而不是同步整块重画)。
|
||||
*
|
||||
* ⚠️⚠️ 在前台同步重画一条**巨型信号**的图层实测 **20~130ms**;
|
||||
* 拖拽时只要有一个“离屏累积了大位移、刚进入预取带”的网格就会卡一下。
|
||||
* 作废后本帧由 `BlitWideBuffer` 的**网格底衬**兜底(廉价),波形等视界停下后
|
||||
* 由 `RenderPendingLaneRebuilds` 按预算逐个补 —— 这正是用户要求的
|
||||
* “没来得及画信号时就按只有网格叠底的状态继续滚动”。
|
||||
*/
|
||||
inline const int kLayerRollMaxShiftPixels = 160;
|
||||
|
||||
/**
|
||||
* @brief 每帧最多为多少个网格做**横向重新居中**(补细条)。
|
||||
*
|
||||
* ⚠️ 重新居中**纯粹是优化**:`BlitWideBuffer` 本来就按 `(ViewMin - layer.wideMin)` 算源偏移,
|
||||
* 不滚动也照样能正确贴图(只要还在位图覆盖范围内)。因此完全可以分摊到多帧。
|
||||
* 每条补条的固定开销 ~1.5ms(含 `m_lanes` 快照/还原与 GDI+ 调用),
|
||||
* 30 个可见网格同时滚就是 45ms —— 取 3 个 ⇒ 最坏单帧约 4~5ms,
|
||||
* 拖拽时既不会卡顿、也不会让位移累积到需要作废图层的程度。
|
||||
*/
|
||||
inline const int kLayerRollsPerFrame = 3;
|
||||
|
||||
/**
|
||||
* @brief 「图层预热」两次请求重绘之间的最小间隔(毫秒)。
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user