feat(style): 「系数/偏移」改为「映射/偏移」并新增「公式映射」

- 按钮文案改为「映射/偏移」;激活态 = 公式非空 或 系数≠1 或 任一偏移≠0
- 二级面板顶部新增「公式映射」(标题栏带还原图标):Y = + 表达式输入框,默认 f(t)
- 结算顺序固定:公式映射 -> 系数 -> 绝对值 -> 垂直镜像 -> Y 偏移 -> 时间轴偏移
- 表达式规则:支持 + - * / ( ) 一元正负、常量 pi、自变量 X/x/f/f(t);保存前把 X 归一化为 f(t)
- 非法表达式不写入样式,警告走 SignalPanel::TakePendingHint -> PlotView::ShowPersistentHint(自绘浮层,不用 MessageBox)
- 公式参与折线缓存键 / SceneContentHash / SceneStyleEntry / HaloLayerCache;
  DrawTransformOrderPreserving 返回 false(非保序),自适应幅值在 HasFormula() 时逐点扫描
- 派生信号与克隆的烘焙自动包含公式(时间轴偏移除外)
- Documents/agent_mem.md 追加「第二十四轮」硬约束
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-11-02 20:42:58 +08:00
1 parent 1e1c2432ae
commit 955b233e63
3 files changed
+127 -6

No files matched your search

+66 -3
View File
@@ -20,12 +20,32 @@ namespace jdi
return false;
}
// 二级面板:两张“标题(带还原图标)+ 输入框”的组合:
// 1. 「系数调整」:一整行系数输入框;
// 2. 「偏移调整」:下方两行分别为「Y轴」与「时间轴」的偏移输入框。
// 二级面板:三组“标题(带还原图标)+ 输入框”的组合:
// 1. 「公式映射」:`Y =` + 表达式输入框(自变量写作 f(t));
// 2. 「系数调整」:一整行系数输入框;
// 3. 「偏移调整」:下方两行分别为「Y轴」与「时间轴」的偏移输入框。
//(与网格 Y 轴上下限的菜单内联编辑同一套做法:提交后面板保持打开,可连续微调。)
// ⚠️ 结算顺序固定为「公式映射 → 系数 → 偏移」(用户 2026-11-02 明确要求)。
std::vector<MenuItem> items;
// 「公式映射」:默认 `f(t)`(= 等值照搬)。
MenuItem formulaHeader;
formulaHeader.kind = MenuItemKind::HEADER_ACTION;
formulaHeader.label = L"公式映射";
formulaHeader.id = CMD_FORMULA_RESET; // 点击还原图标 → 恢复为 f(t)
items.push_back(formulaHeader);
const std::wstring formulaText =
style->formula.empty() ? std::wstring(L"f(t)") : style->formula;
MenuItem formulaEdit;
formulaEdit.kind = MenuItemKind::EDIT;
formulaEdit.label = L"Y ="; // 输入框独占右侧剩余整行
formulaEdit.id = CMD_FORMULA_EDIT;
formulaEdit.value = formulaText;
formulaEdit.editValue = formulaText;
formulaEdit.filter = EditFilter::ANY;
items.push_back(formulaEdit);
MenuItem gainHeader;
gainHeader.kind = MenuItemKind::HEADER_ACTION;
gainHeader.label = L"系数调整";
@@ -337,6 +357,35 @@ namespace jdi
const bool valid = !trimmed.empty() && stop != trimmed.c_str() && std::isfinite(parsed);
switch (result.id)
{
case CMD_FORMULA_EDIT:
{
// 「公式映射」:把自变量写法统一为 `f(t)`,非法表达式**不写入**并给出警告
//(警告走自绘浮层,见 `TakePendingHint`;不使用 Windows 消息框)。
const std::wstring normalized = NormalizeFormulaText(trimmed);
if (normalized.empty())
{
style->formula.clear();
}
else
{
std::wstring error;
if (!ValidateFormula(normalized, &error))
{
m_pendingHint = L"公式无法解析:" + error;
}
else
{
style->formula = normalized;
}
}
if (m_menu != nullptr)
{
const std::wstring display =
style->formula.empty() ? std::wstring(L"f(t)") : style->formula;
m_menu->UpdateItemValue(CMD_FORMULA_EDIT, display, display);
}
return false;
}
case CMD_GAIN_EDIT:
{
if (valid)
@@ -391,6 +440,20 @@ namespace jdi
}
}
// 标题栏右侧的「还原」图标:公式恢复为默认的 `f(t)`(= 等值照搬)。
if (result.id == CMD_FORMULA_RESET)
{
if (SignalStyle* style = StyleOf(SelectedRef()))
{
style->formula.clear();
if (m_menu != nullptr)
{
m_menu->UpdateItemValue(CMD_FORMULA_EDIT, L"f(t)", L"f(t)");
}
}
return false;
}
// 标题栏右侧的「还原」图标:系数重置为默认值 1(面板保持打开,输入框立即回显)。
if (result.id == CMD_GAIN_RESET)
{
@@ -904,9 +904,10 @@ namespace jdi
UiText(g, label, m_fonts->uiSmall, rect,
checked ? m_theme->textStrong : m_theme->text, TextAlign::CENTER);
};
// 系数/偏移:系数不等于默认值 1、或任一偏移不为 0 时显示为"已启用"。
paintToggle(kAdjustGain, L"系数/偏移",
!GainIsDefault(style->gain) || style->Offset(), StyleHit::GAIN_ADJUST);
// 映射/偏移:公式映射非空、系数不等于默认值 1、或任一偏移不为 0 时显示为"已启用"。
paintToggle(kAdjustGain, L"映射/偏移",
style->HasFormula() || !GainIsDefault(style->gain) || style->Offset(),
StyleHit::GAIN_ADJUST);
// 镜像:水平或垂直任一被勾选即显示为激活态。
paintToggle(kAdjustMirror, L"镜像", style->Mirrored(), StyleHit::MIRROR_ADJUST);
paintToggle(kAdjustAbsolute, L"绝对值", style->absolute, StyleHit::ABSOLUTE_TOGGLE);