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 使用)
This commit is contained in:
1 parent
30e9d65c30
commit
1e1c2432ae
19 files changed
+1979
-56
No files matched your search
@@ -65,7 +65,8 @@ namespace jdi
|
||||
MARKER_SCROLL, /**< 拖动「自由标记」面板内容的滚动条滑块。 */
|
||||
MEAN_POINTS, /**< 拖动「均值滤波」某信号的「均值点数」滑块(0 … 该信号自定义上限)。 */
|
||||
MEAN_ITERATIONS,/**< 拖动「均值滤波」某信号的「迭代次数」滑块(1 … 该信号自定义上限)。 */
|
||||
MEAN_SCROLL /**< 拖动「均值滤波」面板内容的滚动条滑块。 */
|
||||
MEAN_SCROLL,/**< 拖动「均值滤波」面板内容的滚动条滑块。 */
|
||||
RESAMPLE_SCROLL /**< 拖动「重采样」面板内容的滚动条滑块。 */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -103,6 +104,8 @@ namespace jdi
|
||||
MEAN_POINTS_MAX,
|
||||
/** @brief 编辑「均值滤波」某信号「迭代次数」滑块的**上限**(正整数)。 */
|
||||
MEAN_ITERATIONS_MAX,
|
||||
RESAMPLE_INTERVAL, /**< 编辑「重采样」某信号的**重采样间隔**(秒)。 */
|
||||
RESAMPLE_FREQUENCY, /**< 编辑「重采样」某信号的**重采样频率**(Hz,与间隔联动)。 */
|
||||
FREE_MARKER_TIME, /**< 编辑「自由标记」某固定点的**自身时间**(秒)。 */
|
||||
FREE_MARKER_DELTA /**< 编辑「自由标记」某固定点相对前一固定点的**时间间隔**(秒)。 */
|
||||
};
|
||||
@@ -123,7 +126,8 @@ namespace jdi
|
||||
PLOT_CMD_LANE_SPLIT = 9, /**< 拆分当前网格:把网格内信号按个拆成独立网格并顺次下移编号。 */
|
||||
PLOT_CMD_LANE_MEAN_FILTER = 10, /**< 切换本网格的「实验性功能 → 均值滤波」开关。 */
|
||||
PLOT_CMD_LANE_WEAK_PEAK = 11, /**< 切换本网格的「实验性功能 → 弱峰调整」开关。 */
|
||||
PLOT_CMD_LANE_FREE_MARKER = 12 /**< 切换本网格的「实验性功能 → 自由标记」开关。 */
|
||||
PLOT_CMD_LANE_FREE_MARKER = 12, /**< 切换本网格的「实验性功能 → 自由标记」开关。 */
|
||||
PLOT_CMD_LANE_RESAMPLE = 13 /**< 切换本网格的「实验性功能 → 重采样」开关。 */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -135,7 +139,8 @@ namespace jdi
|
||||
CENTER = 1, /**< 边沿计数(中心轴)。 */
|
||||
MEAN = 2, /**< 均值滤波。 */
|
||||
PEAK = 3, /**< 弱峰调整。 */
|
||||
MARK = 4 /**< 自由标记。 */
|
||||
MARK = 4, /**< 自由标记。 */
|
||||
RESAMPLE = 5 /**< 重采样(把非固定频率采样规整为固定频率)。 */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1022,6 +1027,66 @@ namespace jdi
|
||||
*/
|
||||
bool ToggleLaneFreeMarker(int laneIndex);
|
||||
|
||||
/**
|
||||
* @brief 「重采样 → 构建为新信号」的单个请求(一个被勾选的信号 + 自己的间隔)。
|
||||
*/
|
||||
struct ResampleBuild
|
||||
{
|
||||
int groupIndex = -1; /**< 信号所属分组下标。 */
|
||||
int signalIndex = -1; /**< 组内信号下标。 */
|
||||
double interval = 0.0; /**< 重采样间隔(秒,> 0)。 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 取出「重采样 → 构建为新信号」请求(由面板底部按钮触发)。
|
||||
* @param [OUT] laneIndex 触发该请求的网格下标。
|
||||
* @param [OUT] items 需要构建的信号及其间隔(按信号在网格内的顺序)。
|
||||
* @return 存在待处理请求返回 true(取出后清空)。
|
||||
*/
|
||||
bool TakePendingResampleBuild(int& laneIndex, std::vector<ResampleBuild>& items);
|
||||
|
||||
/**
|
||||
* @brief 开启 / 关闭某网格的「重采样」功能。
|
||||
* @param [IN] laneIndex 网格下标。
|
||||
* @param [IN] enabled 是否开启。
|
||||
* @return 状态发生变化返回 true。
|
||||
*/
|
||||
bool SetLaneResample(int laneIndex, bool enabled);
|
||||
|
||||
/** @brief 查询某网格的「重采样」开关。 */
|
||||
bool LaneResample(int laneIndex) const;
|
||||
|
||||
/**
|
||||
* @brief 切换某网格的「重采样」开关。
|
||||
* @param [IN] laneIndex 网格下标。
|
||||
* @return 切换后的状态。
|
||||
*/
|
||||
bool ToggleLaneResample(int laneIndex);
|
||||
|
||||
/** @brief 切换某信号是否参与重采样(面板条目栏右侧复选框)。 */
|
||||
bool ToggleLaneResampleSignal(int laneIndex, const SignalRef& ref);
|
||||
|
||||
/** @brief 查询某信号是否参与重采样。 */
|
||||
bool LaneResampleSignalEnabled(int laneIndex, const SignalRef& ref) const;
|
||||
|
||||
/**
|
||||
* @brief 设置「重采样」面板内容的滚动偏移(自动夹到合法范围)。
|
||||
* @param [IN] laneIndex 网格下标。 @param [IN] scroll 目标偏移(像素)。
|
||||
*/
|
||||
bool SetLaneResampleScroll(int laneIndex, float scroll);
|
||||
|
||||
/**
|
||||
* @brief 查询某信号的最大 / 最小数据间隔(相邻有效采样点的时间差极值)。
|
||||
*
|
||||
* 只统计**时间轴与采样值都有效**的相邻采样对;不足两个有效采样时返回 false。
|
||||
*
|
||||
* @param [IN] ref 目标信号。
|
||||
* @param [OUT] maxInterval 最大间隔(秒)。
|
||||
* @param [OUT] minInterval 最小间隔(秒)。
|
||||
* @return 至少存在一个有效间隔返回 true。
|
||||
*/
|
||||
bool SignalDataInterval(const SignalRef& ref, double& maxInterval, double& minInterval) const;
|
||||
|
||||
/**
|
||||
* @brief 设置某网格是否处于「自由标记点选取」(浮动面板底部的切换按钮)。
|
||||
*
|
||||
@@ -1902,6 +1967,17 @@ namespace jdi
|
||||
*/
|
||||
std::vector<gd::RectF> rowLevelResets;
|
||||
std::vector<gd::RectF> rowIterResets;
|
||||
/**
|
||||
* @brief 「重采样」面板每个被勾选信号的四行内容(与 `rowRefs` 同序)。
|
||||
*
|
||||
* `rowInfoMaxInterval` / `rowInfoMinInterval` = 只读统计(最大 / 最小数据间隔);
|
||||
* `rowIntervalField` / `rowFrequencyField` = 两行**联动输入框**(间隔秒 / 频率 Hz)。
|
||||
* 未勾选或非 RESAMPLE 面板时对应元素为空矩形(数组也可能为空)。
|
||||
*/
|
||||
std::vector<gd::RectF> rowInfoMaxInterval;
|
||||
std::vector<gd::RectF> rowInfoMinInterval;
|
||||
std::vector<gd::RectF> rowIntervalField;
|
||||
std::vector<gd::RectF> rowFrequencyField;
|
||||
/**
|
||||
* @brief 「均值滤波」面板每个信号的**信号色叠底标题栏**矩形(与 `rowRefs` 同序)。
|
||||
*
|
||||
@@ -2896,6 +2972,8 @@ namespace jdi
|
||||
int m_pendingWeakPeakLane = -1; /**< 待构建的弱峰调整信号所属网格下标(-1 表示无请求)。 */
|
||||
std::vector<MeanFilterBuild> m_pendingMeanFilterItems; /**< 待构建的信号及其参数。 */
|
||||
std::vector<WeakPeakBuild> m_pendingWeakPeakItems; /**< 待构建的弱峰调整信号及其参数。 */
|
||||
int m_pendingResampleLane = -1; /**< 待构建的重采样信号所属网格下标(-1 表示无请求)。 */
|
||||
std::vector<ResampleBuild> m_pendingResampleItems; /**< 待构建的重采样信号及其间隔。 */
|
||||
bool m_mouseOverPanel = false; /**< 上一帧鼠标是否落在某个实验性功能面板上。 */
|
||||
int m_peakDragLane = -1; /**< 正在拖动弱峰滑块的面板所属网格。 */
|
||||
SignalRef m_peakDragRef; /**< 正在拖动弱峰滑块的**信号**(每个信号一套参数)。 */
|
||||
@@ -3585,6 +3663,7 @@ namespace jdi
|
||||
bool mirrorHorizontal = false; /**< 是否水平镜像(数据反序)。 */
|
||||
float offsetY = 0.0f; /**< Y 轴偏移。 */
|
||||
double offsetTime = 0.0; /**< 时间轴偏移(秒)。 */
|
||||
std::wstring formula; /**< 「公式映射」表达式(空 = 不映射)。 */
|
||||
|
||||
/** @brief 相等比较(用于判断"逐信号外观样式是否变化")。 */
|
||||
bool operator==(const SceneStyleEntry& other) const
|
||||
@@ -3594,7 +3673,7 @@ namespace jdi
|
||||
gain == other.gain && absolute == other.absolute &&
|
||||
mirrorVertical == other.mirrorVertical &&
|
||||
mirrorHorizontal == other.mirrorHorizontal && offsetY == other.offsetY &&
|
||||
offsetTime == other.offsetTime;
|
||||
offsetTime == other.offsetTime && formula == other.formula;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3729,6 +3808,7 @@ namespace jdi
|
||||
bool mirrorHorizontal = false; /**< 是否水平镜像。 */
|
||||
float offsetY = 0.0f; /**< Y 偏移。 */
|
||||
double offsetTime = 0.0; /**< 时间偏移。 */
|
||||
std::wstring formula; /**< 「公式映射」表达式(空 = 不映射)。 */
|
||||
int originX = 0; /**< 位图左上角(屏幕 x)。 */
|
||||
int originY = 0; /**< 位图左上角(屏幕 y)。 */
|
||||
std::unique_ptr<gd::Bitmap> bitmap; /**< 32bpp ARGB 光晕图层(直通 alpha)。 */
|
||||
|
||||
@@ -587,6 +587,26 @@ namespace jdi
|
||||
inline const wchar_t* const kWeakPeakTitle = L"弱峰调整"; /**< 弱峰调整面板标题。 */
|
||||
inline const wchar_t* const kBuildSignalLabel = L"构建为新信号"; /**< 逐条目面板底部按钮文案(均值滤波 / 弱峰调整共用)。 */
|
||||
|
||||
// ---- 「重采样」面板 ----
|
||||
/** 「重采样」面板标题。 */
|
||||
inline const wchar_t* const kResampleTitle = L"重采样";
|
||||
/** 只读统计行标签:最大数据间隔。 */
|
||||
inline const wchar_t* const kResampleMaxIntervalLabel = L"最大数据间隔";
|
||||
/** 只读统计行标签:最小数据间隔。 */
|
||||
inline const wchar_t* const kResampleMinIntervalLabel = L"最小数据间隔";
|
||||
/** 输入行标签:重采样间隔(秒)。 */
|
||||
inline const wchar_t* const kResampleIntervalLabel = L"重采样间隔";
|
||||
/** 输入行标签:重采样频率(Hz)。 */
|
||||
inline const wchar_t* const kResampleFrequencyLabel = L"重采样频率";
|
||||
/**
|
||||
* @brief 重采样间隔的合法区间(秒)。
|
||||
*
|
||||
* 下限取 1ns(再小已经没有实际意义的采样率,且会让新信号的采样数爆炸);
|
||||
* 上限取 1e6 秒。
|
||||
*/
|
||||
inline const double kResampleIntervalMin = 1.0e-9;
|
||||
inline const double kResampleIntervalMax = 1.0e6;
|
||||
|
||||
// ---- 「均值滤波」面板的两行参数滑块(用户 2026-10-30 要求)----
|
||||
/**
|
||||
* 标签一律**不带 `X` / `N`**:滑块的量程本身已经说明是数值,符号只会让标签变长。
|
||||
@@ -1034,7 +1054,7 @@ namespace jdi
|
||||
*/
|
||||
inline const EdgePanelKind kEdgePanelKinds[] = {EdgePanelKind::COUNT, EdgePanelKind::CENTER,
|
||||
EdgePanelKind::MEAN, EdgePanelKind::PEAK,
|
||||
EdgePanelKind::MARK};
|
||||
EdgePanelKind::MARK, EdgePanelKind::RESAMPLE};
|
||||
|
||||
/** 实验性功能浮动面板的种类数(遍历与命中测试统一用它,避免新增功能时漏改)。 */
|
||||
inline const int kEdgePanelKindCount = static_cast<int>(sizeof(kEdgePanelKinds) / sizeof(kEdgePanelKinds[0]));
|
||||
@@ -1274,6 +1294,36 @@ namespace jdi
|
||||
return FormatValue(seconds) + L"s";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 时间间隔的显示文本(**不带** "Δt:" 前缀)。
|
||||
*
|
||||
* 「重采样」面板的「最大 / 最小数据间隔」两行用它:单位随间隔长短自适应
|
||||
*(`FormatDurationCompound`:1h 1min 2s / 5s 60ms / 120us …)。
|
||||
*
|
||||
* @param [IN] seconds 时间间隔(秒)。
|
||||
* @return 文本。
|
||||
*/
|
||||
inline std::wstring FormatIntervalText(double seconds)
|
||||
{
|
||||
if (!std::isfinite(seconds) || seconds <= 0.0)
|
||||
{
|
||||
return L"—";
|
||||
}
|
||||
return FormatDurationCompound(seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 频率的显示文本(单位在 Hz / kHz / MHz / GHz 之间自适应,保留小数)。
|
||||
*
|
||||
* @param [IN] hertz 频率(Hz)。
|
||||
* @return 形如 "1.2 kHz" 的文本;非法值返回 "—"。
|
||||
*/
|
||||
inline std::wstring FormatFrequencyText(double hertz)
|
||||
{
|
||||
// 唯一实现在 `Utf8Util::FormatFrequency`(宿主构建派生信号名时也用它)。
|
||||
return FormatFrequency(hertz);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 按比例缩放颜色的 alpha 通道(用于提示浮层淡出)。
|
||||
* @param [IN] argb 原始 0xAARRGGBB 颜色。
|
||||
|
||||
Reference in new issue
Block a user