修复上下拖动后的绘制错误(图层条带 GDI 裁剪)+「弱峰调整」定义/默认值/符号显示
一、绘制错误真因:图层条带渲染时 GDI 网格线越界作画并烘进图层 上一轮把图层条带从"只有横向条"扩展到"横向条 + 纵向条"(纵向滚动补画)。但 PaintLane 里 GDI (网格线/分界线)的裁剪矩形 RectF(m_area.X, clipTop, m_area.Width, clipBottom - clipTop) 只把 x 限制在条带内、y 仍是整个网格可见范围。纵向条带(全宽 × 窄 y)渲染时: * GDI 网格线被画到条带之外(那儿的像素由滚动而来、本来是正确的); * 那些行原本是"波形盖在网格线之上",变成"网格线盖在波形之上",与正确渲染不一致; * 错误像素就在图层位图里,会被后续每次平移带着移动 → "拖到哪儿都有绘制错误"。 修法:把"本次允许改动的区域"算成 laneClip = IntersectRect(m_area, 网格可见矩形),同时用于 Graphics::SetClip 与 GDI 的 gridClip(横向补条本来就没问题,所以此前只有纵向/斜向暴露)。 二、新增探针 .preflight/dragcheck(复现用户手势) 注入真实中键消息:先把最上方网格向上拖半个网格高(触发纵向滚动),再保持按住拖左右/上下/斜向、 最后拖出窗口;每帧把图层画布的有效条带(marginY + vOffset 起、网格高行)与"用同一 wideMin 新渲染 的画布"逐像素比较(滚动是纯整数平移,必须逐像素相同;用 FromHBITMAP + LockBits 直接读像素)。 修复前:被拖网格整行不一致(2410 px ≈ 2 行全宽,错误行固定在 canvas 行 138 = 某条横向网格线, 直接指向 GDI 网格线);修复后:最差 ≤171 px(仅补条边界的抗锯齿边缘),0 处绘制错误。 三、「弱峰调整」定义 "是否偏弱"改为(正/负幅度一致):波峰必须同时低于左右两侧各自的「相邻波峰 + 相邻波谷」均值; 波谷必须同时高于上述两个均值。与旧实现(只与左右两个同类极值比较)不同:整段均匀偏弱的纹波 不再被判为弱峰,因此合成测试波形重设计(分段线性、谷恒 500、弱峰 520、健康峰 620/640)。 四、默认幅度与符号显示 默认幅度改为 0%(面板提出即不改动波形);滑块右侧数值始终显示符号(+150% / -150% / 0%), 数值列按 "+200%" 取宽避免跳动。 五、验证(全部离屏,不占用鼠标/键盘/屏幕) - uitest 441/441:[X] 正幅度 0/50/100/150/200% → 峰 520/570/620/630/640、弱谷 580/540/500/500/500; 负幅度 -50/-100/-200% → 峰 510/500/500、谷 590/600/620;超范围夹取;"未反向增强"(极值点); 健康段逐位不变;30% 幅度下 N=1/2/3/10 → 550/571/571/571(收敛);默认 0%;滑块中间 = 0%、 两端 = ±200%;数值带符号(+150% 与 -150% 墨迹等宽、都比 0% 宽 ≥8px)。 - [Y] 端到端:合成 ripple(谷恒 500、一个弱峰 520)弱峰区间 20 → 70(健康 120)。 - dragcheck PASS(0 绘制错误);panperf 竖直中位 5.1ms、水平 7.1ms、20 面板竖直 25.0ms / 水平 41.3ms; layercheck clobbers=0/24、pan frames wrong=0/4;cursorcheck 30/30;make clean && make all 零警告。
This commit is contained in:
1 parent
ff3319b842
commit
14b60f5d9e
6 files changed
+125
-40
No files matched your search
+27
-17
@@ -1160,10 +1160,30 @@ namespace jdi
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const double mean = (left.value + right.value) * 0.5;
|
||||
const double lower = std::min(left.value, right.value);
|
||||
const double upper = std::max(left.value, right.value);
|
||||
if (!(current.type > 0 ? (current.value < mean) : (current.value > mean)))
|
||||
// 「是否偏弱」的判定(用户明确定义,正/负幅度**完全一致**):
|
||||
// 波峰:必须**同时**低于
|
||||
// 「左侧相邻的第一个波谷与第一个波峰的均值」(= k-1 与 k-2 的均值) 与
|
||||
// 「右侧相邻的第一个波谷与第一个波峰的均值」(= k+1 与 k+2 的均值);
|
||||
// 波谷:必须**同时**高于上述两个均值。
|
||||
// 即:与"两侧各自相邻的一个波峰+一个波谷"的平均水平比较,
|
||||
// 而不是旧实现只与左右两个**同类**极值比较。
|
||||
const PeakExtremum& leftNear = extremes[k - 1];
|
||||
const PeakExtremum& rightNear = extremes[k + 1];
|
||||
if (leftNear.type == current.type || rightNear.type == current.type)
|
||||
{
|
||||
continue; // 极值序列本应交替;异常时不动这一点
|
||||
}
|
||||
if (!std::isfinite(leftNear.value) || !std::isfinite(rightNear.value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const double leftMean = (left.value + leftNear.value) * 0.5;
|
||||
const double rightMean = (rightNear.value + right.value) * 0.5;
|
||||
const bool weak = (current.type > 0) ? ((current.value < leftMean) && (current.value < rightMean))
|
||||
: ((current.value > leftMean) && (current.value > rightMean));
|
||||
if (!weak)
|
||||
{
|
||||
// 不是弱峰:本极值点不动。
|
||||
continue;
|
||||
@@ -1194,22 +1214,12 @@ namespace jdi
|
||||
else
|
||||
{
|
||||
// ---- 负幅度(削弱)----
|
||||
// 参照物改为相邻的**异类**极值(波峰看相邻波谷、波谷看相邻波峰),
|
||||
// 参照物为相邻的**异类**极值(波峰看相邻波谷、波谷看相邻波峰),
|
||||
// 并且"较近的那个"对波峰是较高的波谷、对波谷是较低的波峰。
|
||||
const PeakExtremum& nearLeft = extremes[k - 1];
|
||||
const PeakExtremum& nearRight = extremes[k + 1];
|
||||
if (nearLeft.type == current.type || nearRight.type == current.type)
|
||||
{
|
||||
continue; // 极值序列本应交替;异常时不动这一点
|
||||
}
|
||||
if (!std::isfinite(nearLeft.value) || !std::isfinite(nearRight.value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const double nearValue = (current.type > 0) ? std::max(nearLeft.value, nearRight.value)
|
||||
: std::min(nearLeft.value, nearRight.value);
|
||||
const double farValue = (current.type > 0) ? std::min(nearLeft.value, nearRight.value)
|
||||
: std::max(nearLeft.value, nearRight.value);
|
||||
const double nearValue = (current.type > 0) ? std::max(leftNear.value, rightNear.value)
|
||||
: std::min(leftNear.value, rightNear.value);
|
||||
const double farValue = (current.type > 0) ? std::min(leftNear.value, rightNear.value)
|
||||
: std::max(leftNear.value, rightNear.value);
|
||||
const double magnitude = std::min(2.0, -amount);
|
||||
destination = (magnitude <= 1.0)
|
||||
? (current.value + magnitude * (nearValue - current.value))
|
||||
|
||||
Reference in new issue
Block a user