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
@@ -145,6 +145,7 @@ namespace jdi
|
||||
purgeRefs(lane.meanFilterItems);
|
||||
purgeRefs(lane.edgeCenterItems);
|
||||
purgeRefs(lane.weakPeakItems);
|
||||
purgeRefs(lane.resampleItems);
|
||||
}
|
||||
// 被移除信号若独占了某个网格,该网格随之消失(与取消勾选的行为一致)。
|
||||
m_lanes.erase(std::remove_if(m_lanes.begin(), m_lanes.end(),
|
||||
@@ -449,6 +450,9 @@ namespace jdi
|
||||
lane.freeMarkerShowEnum = source.freeMarkerShowEnum;
|
||||
lane.freeMarkerPanel = source.freeMarkerPanel;
|
||||
lane.freeMarkerOpacity = source.freeMarkerOpacity;
|
||||
lane.resample = source.resample;
|
||||
lane.resamplePanel = source.resamplePanel;
|
||||
lane.resampleScroll = source.resampleScroll;
|
||||
// 拆分后每个子网格只保留自己那个信号的均值滤波 / 中心轴 / 弱峰调整 / 自由标记条目。
|
||||
for (const Lane::MeanFilterItem& item : source.meanFilterItems)
|
||||
{
|
||||
@@ -487,6 +491,13 @@ namespace jdi
|
||||
lane.freeMarkerItems.push_back(item);
|
||||
}
|
||||
}
|
||||
for (const Lane::ResampleItem& item : source.resampleItems)
|
||||
{
|
||||
if (item.ref == ref)
|
||||
{
|
||||
lane.resampleItems.push_back(item);
|
||||
}
|
||||
}
|
||||
for (const SignalRef& collapsed : source.freeMarkerCollapsedGroups)
|
||||
{
|
||||
if (collapsed == ref)
|
||||
@@ -557,6 +568,14 @@ namespace jdi
|
||||
++item.ref.signalIndex;
|
||||
}
|
||||
}
|
||||
// 「重采样」条目同样持有信号引用。
|
||||
for (Lane::ResampleItem& item : lane.resampleItems)
|
||||
{
|
||||
if (item.ref.groupIndex == groupIndex && item.ref.signalIndex >= insertPos)
|
||||
{
|
||||
++item.ref.signalIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,7 +710,36 @@ namespace jdi
|
||||
double signalHigh = signal->maxValue;
|
||||
if (style != nullptr)
|
||||
{
|
||||
TransformValueRange(*style, signalLow, signalHigh);
|
||||
if (style->HasFormula())
|
||||
{
|
||||
// ⚠️ 「公式映射」不保证单调(`x*x` / `1/x`)⇒ 端点映射会算错,
|
||||
// 只能逐点扫描(只在自适应重算时发生,不是每帧路径)。
|
||||
double formulaLow = std::numeric_limits<double>::infinity();
|
||||
double formulaHigh = -std::numeric_limits<double>::infinity();
|
||||
for (const double raw : signal->values)
|
||||
{
|
||||
if (!std::isfinite(raw))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const double mapped = ApplyDrawTransform(*style, raw);
|
||||
if (!std::isfinite(mapped))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
formulaLow = std::min(formulaLow, mapped);
|
||||
formulaHigh = std::max(formulaHigh, mapped);
|
||||
}
|
||||
if (std::isfinite(formulaLow) && std::isfinite(formulaHigh))
|
||||
{
|
||||
signalLow = formulaLow;
|
||||
signalHigh = formulaHigh;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformValueRange(*style, signalLow, signalHigh);
|
||||
}
|
||||
}
|
||||
low = std::min(low, signalLow);
|
||||
high = std::max(high, signalHigh);
|
||||
|
||||
Reference in new issue
Block a user