弱波增强:去掉前置滤波并新增「阶数 N」滑块;修复选区放大越界绘制与浮动面板 ✕ 交互

- 弱波增强不再做任何前置滤波(删除内部的 5 点滑动平均 BoostShapeAt):
  极值点直接在输入采样上识别。需要平滑时用户可以先用「均值滤波」构建一条
  滤波后的信号,再对它做弱波增强。
- 新增「阶数 N」参数(1~10,滑块输入),语义与均值滤波的阶数 N 一致 ——
  把同一处理重复应用 N 次,每阶以上一阶为输入:
  一阶时改定量严格等于「等级」对应的目标值;多阶会让相邻弱波互相抬高彼此的
  基准,从而把较宽的弱波区逐步恢复(实测三连弱波的中间峰 550→575→598.4)。
  某一阶若不再产生改动会提前结束迭代。
  `ComputeWeakWaveBoost(values, level, order, out)`;
  `Lane::weakBoostOrder`(默认 1)随 LaneCarry / SplitLane / 引用重映射同步,
  并进入 SceneContentHash;曲线缓存键变为「信号 + 等级 + 阶数」。
- 浮动面板同步新增一行「阶数 N」滑块(新拖拽模式 BOOST_ORDER、
  EdgePanelLayout::sliderOrder);「构建为新信号」命名带上阶数
  (形如 `<原信号> (弱波增强 60%×2阶)`)。
- 修复:选区放大时鼠标被捕获到绘图区之外(工具栏 / 信号面板 / 时间轴)会把
  选区块画到绘图区之外,而拖拽期间只失效绘图区 → 留下无法擦除的墨迹。
  现在拖拽时把选区夹在绘图区内,PaintRubberBand 再对 m_plotRect 求交一次。
- 修复:浮动面板的 ✕ 位于标题栏矩形内部,按下后会继续落到「标题栏 → 拖动面板」
  分支,表现为「按住 ✕ 却把面板拖走了」;现在按下 ✕ 直接消费该次点击(抬起时
  仍按原语义确认关闭),并把 ✕ 的光标改为手型,与其它关闭按钮一致。
- 修复:✕ / 滑块 / 底部按钮的悬停高亮依赖鼠标坐标,但从同一网格的波形移到面板上
  时悬停状态毫无变化 → OnMouseMove 返回 false → 宿主不重绘 → 高亮不出现。
  现在「进入 / 离开 / 在面板内移动」都会请求重绘。
- 离屏验证(窗口隐藏,不占用鼠标/键盘/屏幕):345 项检查全部通过,含
  阶数扫描(N=1 只改外侧弱峰、N=2 传导到中间弱峰、高 N 逼近健康幅值且不越界、
  健康峰在任何阶数下逐位不变)、两个滑块的按压/拖拽/钳制、选区越界零墨迹
  (绘图区外像素差 0)、面板 ✕ 悬停高亮与按下不拖动、光标拖拽始终在视界内,
  以及真实 20K 电机纹波录波(信号范围保持不变、20%+ 采样被调整)。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-10-10 19:20:09 +08:00
1 parent 67f659ad23
commit 8c8508e5f8
5 files changed
+457 -240

No files matched your search

+30 -6
View File
@@ -31,6 +31,7 @@ namespace jdi
EDGE_MOVE, /**< 拖动「边沿计数」的横向光标(上下移动幅值)。 */
EDGE_PANEL_MOVE, /**< 拖动边沿计数浮动面板。 */
BOOST_LEVEL, /**< 拖动「弱波增强」面板中的等级滑块。 */
BOOST_ORDER, /**< 拖动「弱波增强」面板中的阶数 N 滑块。 */
LANE_REORDER /**< 拖动网格图例中的 GX 编号徽标:上下调整网格次序。 */
};
@@ -530,6 +531,7 @@ namespace jdi
int fileIndex = -1; /**< 信号所属文件下标。 */
int signalIndex = -1; /**< 文件内信号下标。 */
int levelPercent = 50; /**< 弱波增强等级(0–100)。 */
int order = 1; /**< 阶数 N(1–10)。 */
};
/**
@@ -569,6 +571,21 @@ namespace jdi
*/
double LaneWeakBoostLevel(int laneIndex) const;
/**
* @brief 读取某网格的弱波增强阶数 N(1–10)。
* @param [IN] laneIndex 网格下标。
* @return 阶数;网格不存在时返回 1。
*/
int LaneWeakBoostOrder(int laneIndex) const;
/**
* @brief 设置某网格的弱波增强阶数 N(1–10,超出范围会被夹取)。
* @param [IN] laneIndex 网格下标。
* @param [IN] order 阶数。
* @return 阶数发生变化返回 true。
*/
bool SetLaneWeakBoostOrder(int laneIndex, int order);
/**
* @brief 设置某网格的弱波增强等级(0–1,超出范围会被夹取)。
* @param [IN] laneIndex 网格下标。
@@ -578,23 +595,26 @@ namespace jdi
bool SetLaneWeakBoostLevel(int laneIndex, double level);
/**
* @brief 获取弱波增强曲线(按「信号 + 增强等级」缓存)。
* @brief 获取弱波增强曲线(按「信号 + 增强等级 + 阶数」缓存)。
* @param [IN] signal 目标信号。
* @param [IN] levelPercent 弱波增强等级(0–100,整数百分比)。
* @param [IN] order 阶数 N(1–10)。
* @return 曲线数值数组(长度与 `signal.values` 相同;缺失处为 NaN)。
*/
const std::vector<float>& WeakBoostCurveFor(const SignalData& signal, int levelPercent) const;
const std::vector<float>& WeakBoostCurveFor(const SignalData& signal, int levelPercent,
int order) const;
/**
* @brief 取某个时刻的弱波增强曲线取值(用于纵向光标的取值标注)。
* @param [IN] file 信号所属文件。
* @param [IN] signal 目标信号。
* @param [IN] levelPercent 弱波增强等级(0–100)。
* @param [IN] order 阶数 N(1–10)。
* @param [IN] time 采样时刻。
* @param [OUT] value 输出取值。
* @return 取到有效值返回 true。
*/
bool WeakBoostValueAt(const DataFile& file, const SignalData& signal, int levelPercent,
bool WeakBoostValueAt(const DataFile& file, const SignalData& signal, int levelPercent, int order,
double time, double& value) const;
/**
@@ -1064,6 +1084,7 @@ namespace jdi
gd::RectF edit; /**< 面板底部编辑行(无编辑内容时宽度为 0)。 */
gd::RectF button; /**< 面板底部按钮(无按钮时宽度为 0)。 */
gd::RectF slider; /**< 「弱波增强」等级滑块的轨道矩形(无滑块时宽度为 0)。 */
gd::RectF sliderOrder; /**< 「弱波增强」阶数 N 滑块的轨道矩形(无滑块时宽度为 0)。 */
int rows = 0; /**< 统计行数(每条可见信号一行)。 */
/**
* @brief 「逐条目」面板的矩形(MEAN 与 CENTER 面板共用同一套排布)。
@@ -1193,9 +1214,10 @@ namespace jdi
* @param [IN] resolved 信号视图。
* @param [IN] lane 网格绘制信息。
* @param [IN] levelPercent 弱波增强等级(0–100)。
* @param [IN] order 阶数 N(1–10)。
*/
void PaintWeakBoostCurve(gd::Graphics& g, const ResolvedSignal& resolved, const LaneVisual& lane,
int levelPercent) const;
int levelPercent, int order) const;
/**
* @brief 数据点标记的位置与"越界方向"(用于决定画圆点还是贴边三角)。
@@ -1414,7 +1436,8 @@ namespace jdi
int m_pendingWeakBoostLane = -1; /**< 待构建的弱波增强信号所属网格下标(-1 表示无请求)。 */
std::vector<MeanFilterBuild> m_pendingMeanFilterItems; /**< 待构建的信号及其参数。 */
std::vector<WeakBoostBuild> m_pendingWeakBoostItems; /**< 待构建的弱波增强信号及其参数。 */
int m_boostDragLane = -1; /**< 正在拖动等级滑块的面板所属网格。 */
int m_boostDragLane = -1; /**< 正在拖动滑块的面板所属网格。 */
bool m_mouseOverPanel = false; /**< 上一帧鼠标是否落在某个实验性功能面板上。 */
/**
* @brief 实验性功能浮动面板的 ✕ 处于"已按下、等待抬起确认"状态。
@@ -1470,11 +1493,12 @@ namespace jdi
};
mutable std::deque<MeanCurveEntry> m_meanCurveCache;
/** 弱波增强曲线缓存项(按「信号指针 + 增强等级百分比」标识)。 */
/** 弱波增强曲线缓存项(按「信号指针 + 增强等级百分比 + 阶数」标识)。 */
struct WeakBoostCurveEntry
{
const SignalData* signal = nullptr;
int levelPercent = 50; /**< 弱波增强等级(0–100)。 */
int order = 1; /**< 阶数 N(1–10)。 */
std::vector<float> values; /**< 与 signal->values 等长;缺失处为 NaN。 */
};
mutable std::deque<WeakBoostCurveEntry> m_weakBoostCurveCache;