修复缩放后平移的绘制错误/抖动与前台卡顿;弱波增强改名弱峰增强并支持 0~200%
渲染(根因与修法)
- 根因:后台图层线程渲染时会临时改写共享渲染状态(m_area/m_plotRect/视界/网格矩形),
与 UI 线程无锁的平移(OnMouseMove)和命中测试相冲 → 后台的"保存→改写→恢复"会把
用户刚做的平移弹回、命中测试读到错位网格;同时 RollWideBuffer 用单一全局锚点给所有
图层算同一位移,而各图层可能是在不同视界下渲染的(后台逐网格)→ 网格之间时间错位、
贴回像素互相矛盾;补细条又误用"当前视界"的映射(与旧像素不同源)→ ≤0.5px 接缝与拖动抖动。
- 修法:
* 删除后台图层线程(m_layerWorker 及任务队列、EnsureLayerWorker、StopLayerWorker、
LayerWorkerLoop、ScheduleStaleLayerRenders、m_layerBack、m_layerAnchorMin/Valid、
m_lastPaintTick、m_layerRescheduleStreak)。图层渲染一律在 UI 线程内同步完成。
* 逐网格独立锚点与滚动:以 LaneLayer::wideMin 为准,补细条沿用该图层自己的映射。
* RenderLaneLayerRegion 新增 wideMin 形参;新增 LayerDefaultWideMin()。
* RollWideBuffer 逐网格:内容指纹不一致或锚点离视界太远 → 该网格整块重画;
否则整数像素自贴图平移 + 只补新暴露的细条。
* Paint 宽基底分支:!LayersReadyForView() 时先同步 RebuildWideBuffer() 再滚动。
* BackgroundLayerRenderCount() 保留为"同步图层区域渲染次数"的诊断计数。
- 效果:平移不再出现网格时间错位、视界被弹回或波形抖动;居中图层与整幅重绘逐像素一致。
弱峰增强(原「弱波增强」)
- 功能改名:界面文案与标识符统一为 WeakPeak/weakPeak(ComputeWeakPeakBoost、
SetLaneWeakPeak*、EdgePanelKind::PEAK、PlotDragMode::PEAK_LEVEL/PEAK_ITERATIONS、
PLOT_CMD_LANE_WEAK_PEAK、PeakExtremum 等),导出信号名 "<原信号> (弱峰增强 M% N次迭代)"。
- 等级范围改为 0~200%,目标值分段插值:
* 0~100%:在"目标极值自身的值"与"左右同类极值中较温和的一侧"之间插值
(0% 目标就是当前值 → 完全不动,允许用户做极小幅度调整);
* 100~200%:与原先 0~100% 的插值方式一致(200% 完全拉平到另一侧)。
两段在 100% 处连续。新 1.5 == 旧 0.5,新 2.0 == 旧 1.0。
- Lane::weakPeakLevel 默认 1.5;levelPercent(构建请求/曲线缓存键)范围 0~200、默认 150;
新增 kWeakPeakLevelMax = 2.0 与 kWeakPeakPercentMax = 200;滑块轨道比例 = level / 2。
测试
- 同步更新离屏测试 .preflight/uitest:等级期望改为 0/50/100/150/200 五档;阶数扫描与
"完全恢复"块改用 150%/200% 以保持旧期望;派生信号名校验改用新名;
[J] 改为"补丁帧标记降级 → 渲染到缓存重新有效后用修复帧与整幅重绘比对(0 差异)";
[AF] 面板像素容差 32→96(面板 96% 不透明,底层 ≤0.5px 残留会透出,实测最多 6 像素/72 级);
[X] 预览曲线像素计数的颜色容差 6→40。
- 新增离屏检查 .preflight/layercheck:居中图层与整幅重绘逐像素对比、平移逐网格对齐位移、
视界覆盖检测、跨度抖动下的视界保持检测。
- make release 零警告;uitest 380/380 通过(exit=0)。
This commit is contained in:
1 parent
800c8b835b
commit
da83dc2987
7 files changed
+649
-739
No files matched your search
+50
-41
@@ -374,13 +374,13 @@ namespace jdi
|
||||
using EdgeCenterItem = MeanFilterItem;
|
||||
|
||||
/**
|
||||
* @brief 「弱波增强」中某个信号自己的条目。
|
||||
* @brief 「弱峰增强」中某个信号自己的条目。
|
||||
*
|
||||
* 目前只用到 `ref`(增强等级属于整个网格,统一保存在 `weakBoostLevel` 中);
|
||||
* 目前只用到 `ref`(增强等级属于整个网格,统一保存在 `weakPeakLevel` 中);
|
||||
* 复用 `MeanFilterItem` 结构是为了与均值滤波/中心轴共享
|
||||
* 「条目查找 + 信号插入/删除时的引用重映射」等既有实现。
|
||||
*/
|
||||
using WeakBoostItem = MeanFilterItem;
|
||||
using WeakPeakItem = MeanFilterItem;
|
||||
|
||||
std::wstring name; /**< 网格名称。 */
|
||||
std::vector<SignalRef> signals; /**< 该网格包含的信号(按加入顺序)。 */
|
||||
@@ -501,53 +501,58 @@ namespace jdi
|
||||
double meanFilterPanelY = -1.0;
|
||||
|
||||
/**
|
||||
* @brief 「实验性功能 → 弱波增强」开关。
|
||||
* @brief 「实验性功能 → 弱峰增强」开关。
|
||||
*
|
||||
* 开启后为本网格内**被勾选**的信号额外绘制一条「弱波增强」曲线:
|
||||
* 开启后为本网格内**被勾选**的信号额外绘制一条「弱峰增强」曲线:
|
||||
* 识别纹波的波峰/波谷,把“比左右同类极值更弱”的波峰上拉、波谷下拉,
|
||||
* 并按「弱波增强等级」在左右两个同类极值之间取目标值,使其恢复与周边一致的振幅。
|
||||
* 并按「弱峰增强等级」在左右两个同类极值之间取目标值,使其恢复与周边一致的振幅。
|
||||
* 这条曲线只是叠加显示,不会作为信号加入左侧列表。
|
||||
*/
|
||||
bool weakBoost = false;
|
||||
|
||||
/** 弱波增强等级(0–1),0% = 目标取左右极值中较小/较大的那一个,100% = 取另一个。 */
|
||||
double weakBoostLevel = 0.5;
|
||||
bool weakPeak = false;
|
||||
|
||||
/**
|
||||
* @brief 弱波增强的迭代次数 N(1–10)。
|
||||
* @brief 弱峰增强等级(0–2,面板上显示为 0%–200%)。
|
||||
*
|
||||
* 0 = 目标就是当前值(完全不动);1 = 拉到较温和的一侧(波峰取较低的左/右波峰,
|
||||
* 波谷取较高的左/右波谷);2 = 拉到另一侧(完全拉平)。默认 1.5,等价于旧版的 50%。
|
||||
*/
|
||||
double weakPeakLevel = 1.5;
|
||||
|
||||
/**
|
||||
* @brief 弱峰增强的迭代次数 N(1–10)。
|
||||
*
|
||||
* 与「均值滤波」的迭代次数 N 一样表示“把同一处理重复应用 N 次”(每一阶以上一阶为输入):
|
||||
* 一阶时改定量就已严格等于「等级」对应的目标值;多阶会把相邻弱波互相抬高
|
||||
* 彼此的基准,从而把较宽的弱波区逐步恢复。
|
||||
* 一阶时改定量就已严格等于「等级」对应的目标值;多阶会把相邻弱峰互相抬高
|
||||
* 彼此的基准,从而把较宽的弱峰区逐步恢复。
|
||||
*/
|
||||
int weakBoostIterations = 1;
|
||||
int weakPeakIterations = 1;
|
||||
|
||||
/** 参与弱波增强预览的信号条目(只包含被勾选的信号)。 */
|
||||
std::vector<WeakBoostItem> weakBoostItems;
|
||||
/** 参与弱峰增强预览的信号条目(只包含被勾选的信号)。 */
|
||||
std::vector<WeakPeakItem> weakPeakItems;
|
||||
|
||||
/** 取某个信号的弱波增强条目(未勾选时返回空指针)。 */
|
||||
const WeakBoostItem* FindWeakBoostItem(const SignalRef& ref) const;
|
||||
/** 取某个信号的弱峰增强条目(未勾选时返回空指针)。 */
|
||||
const WeakPeakItem* FindWeakPeakItem(const SignalRef& ref) const;
|
||||
|
||||
/** 取得或创建某信号的弱波增强条目(用于勾选)。 */
|
||||
WeakBoostItem& EnsureWeakBoostItem(const SignalRef& ref);
|
||||
/** 取得或创建某信号的弱峰增强条目(用于勾选)。 */
|
||||
WeakPeakItem& EnsureWeakPeakItem(const SignalRef& ref);
|
||||
|
||||
/** 取消某信号的弱波增强勾选。 */
|
||||
void RemoveWeakBoostItem(const SignalRef& ref);
|
||||
/** 取消某信号的弱峰增强勾选。 */
|
||||
void RemoveWeakPeakItem(const SignalRef& ref);
|
||||
|
||||
/** 取某信号的弱波增强勾选状态。 */
|
||||
bool WeakBoostEnabled(const SignalRef& ref) const
|
||||
/** 取某信号的弱峰增强勾选状态。 */
|
||||
bool WeakPeakEnabled(const SignalRef& ref) const
|
||||
{
|
||||
return FindWeakBoostItem(ref) != nullptr;
|
||||
return FindWeakPeakItem(ref) != nullptr;
|
||||
}
|
||||
|
||||
/** 弱波增强浮动面板是否展开。 */
|
||||
bool weakBoostPanelOpen = true;
|
||||
/** 弱峰增强浮动面板是否展开。 */
|
||||
bool weakPeakPanelOpen = true;
|
||||
|
||||
/** 弱波增强面板左上角位置(客户区像素;<0 表示自动定位)。 */
|
||||
double weakBoostPanelX = -1.0;
|
||||
/** 弱峰增强面板左上角位置(客户区像素;<0 表示自动定位)。 */
|
||||
double weakPeakPanelX = -1.0;
|
||||
|
||||
/** 弱波增强面板左上角纵坐标(<0 表示自动定位)。 */
|
||||
double weakBoostPanelY = -1.0;
|
||||
/** 弱峰增强面板左上角纵坐标(<0 表示自动定位)。 */
|
||||
double weakPeakPanelY = -1.0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -592,32 +597,36 @@ namespace jdi
|
||||
std::vector<float>& out);
|
||||
|
||||
/**
|
||||
* @brief 「弱波增强」:把比周边更弱的纹波波峰/波谷恢复(自适应弱波增强)。
|
||||
* @brief 「弱峰增强」:把比周边更弱的纹波波峰/波谷恢复(自适应弱峰增强)。
|
||||
*
|
||||
* 本算法**不做任何前置滤波**:需要平滑时用户可以先用「均值滤波」构建一条
|
||||
* 滤波后的信号,再对它做弱波增强。极值点直接在输入采样上识别。
|
||||
* 滤波后的信号,再对它做弱峰增强。极值点直接在输入采样上识别。
|
||||
*
|
||||
* 单阶处理(全 O(n)):
|
||||
* 1. **识别趋势与极值**:扫描单调段,方向发生翻转处的上一个采样点即为
|
||||
* 波峰(先升后降)或波谷(先降后升);波峰与波谷交替出现。
|
||||
* 2. **判定“弱”**:对第 k 个波峰,取同类的左右相邻波峰(k−2、k+2)。
|
||||
* 若本波峰低于两者的均值,说明它是被削弱的那个;波谷反之(高于两者均值)。
|
||||
* 3. **目标值**(`level` = 弱波增强等级,0–1):
|
||||
* * 波峰:左右两个波峰中较小者为 0%、较大者为 100%,
|
||||
* 目标 = min + level × (max − min);
|
||||
* * 波谷:左右两个波谷中较大者为 0%、较小者为 100%,
|
||||
* 目标 = max − level × (max − min)。
|
||||
* 3. **目标值**(`level` = 弱峰增强等级,0–2,对应面板上的 0%–200%):
|
||||
* * 波峰:左右两个波峰中较小者记为 `lower`、较大者记为 `upper`;
|
||||
* 0 ≤ level ≤ 1 → 目标 = 当前值 + level × (`lower` − 当前值);
|
||||
* 1 < level ≤ 2 → 目标 = `lower` + (level − 1) × (`upper` − `lower`)。
|
||||
* * 波谷:左右两个波谷中较大者记为 `upper`、较小者记为 `lower`;
|
||||
* 0 ≤ level ≤ 1 → 目标 = 当前值 + level × (`upper` − 当前值);
|
||||
* 1 < level ≤ 2 → 目标 = `upper` − (level − 1) × (`upper` − `lower`)。
|
||||
* 即 **0% 完全不动**(可做极小幅度调整)、**100% 拉到较温和的一侧**、
|
||||
* **200% 完全拉平**;两段在 100% 处连续。
|
||||
* 4. **平滑偏移**:极值点本身取其目标值,两侧的数据点按相邻两个极值点的偏移量
|
||||
* 平滑过渡(平滑步进,两端导数为 0),使波形整体趋势不变、只在弱波附近被推回。
|
||||
* 平滑过渡(平滑步进,两端导数为 0),使波形整体趋势不变、只在弱峰附近被推回。
|
||||
*
|
||||
* 正常周期的极值不满足条件、偏移量恒为 0,因此输出与输入逐位相同。
|
||||
*
|
||||
* @param [IN] values 原始采样值。
|
||||
* @param [IN] level 弱波增强等级(0–1,超出范围会被夹取)。
|
||||
* @param [IN] level 弱峰增强等级(0–2,对应 0%–200%,超出范围会被夹取)。
|
||||
* @param [IN] iterations 迭代次数 N(重复应用次数,至少为 1)。
|
||||
* @param [OUT] out 输出数组(长度与 values 相同;原值为 NaN 处保持 NaN)。
|
||||
*/
|
||||
void ComputeWeakWaveBoost(const std::vector<double>& values, double level, int iterations,
|
||||
void ComputeWeakPeakBoost(const std::vector<double>& values, double level, int iterations,
|
||||
std::vector<float>& out);
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user