Esc 行为(用户要求): - 网格内按 Esc 在取消拖拽选区的同时,退出全部缩放模式(时间轴缩放 / Y 轴缩放), 工具栏两个缩放按钮随之回到未选中态;时间光标按钮不受影响。 - 新增 PlotView::ExitZoomModes(),由 Application 的 VK_ESCAPE 分支与 CancelDrag 一起调用。 修复拖拽时波形变模糊(用户报告): - 上一轮为提升拖拽帧率引入了"交互降级":拖拽期间关闭抗锯齿 + 顶点预算减半 + 每列只扫 32 个采样点。实测这会让包络丢掉峰值、线条失去抗锯齿, 在选区放大 / 拖拽信号 / 拖拽光标时明显变"糊"。现已**全部移除**, 任何交互期间都按全质量绘制。 - 用"粗粒度包络层"替代降级来保证交互帧率: SignalData 新增 coarseMin/coarseMax/coarseStride(每 256 个采样一组存 min/max, 额外内存约为采样数据的 0.8%),在 BuildDataFile 统计 min/max 的同一个循环里顺带构建 (不额外扫数据)。折线包络改为读取"每列覆盖到的分组", 数据读取量从 O(可见采样数) 降到 O(像素列数 × 少量分组),**绘制结果与全量扫描完全一致**。 - 实测(VERY_BIG_DATA.CSV = 1.77GB、2580 万行 × 5 信号,全选显示): 视图变化时的包络构建由 176~196ms 降到 ≈0ms;平移拖拽整帧由约 336ms 降到 90~120ms。 - 注意:包络路径按分组判断无效值(整组无有效值才断线), 因此密集视图中孤立的 NaN 不再把波形切成两段(原先会),视觉上更干净。 加速超大文件的显示模式切换(用户报告): - 散点绘制由逐点 FillEllipse 改为把全部散点合并进一条 GraphicsPath 后一次 FillPath: 实测 2500 点由 63ms 降到 7ms(基准),程序内单条密集信号由约 51ms 降到约 22ms, 仍是抗锯齿圆形,观感与逐点绘制一致。 - 线段/散点/点线切换时不再有卡顿感;空闲 CPU 仍为 0.00%。 验证: - Esc:分别启用时间轴缩放 / Y 轴缩放后按 Esc,两个按钮均回到未选中(截图对比), 时间光标按钮保持选中;框选拖拽中按 Esc 时间轴保持 0.2~1.2 不变。 - 清晰度:光标拖拽中与静止时对同一区域做像素哈希,结果完全一致; 框选拖拽同样一致;信号拖拽中间态截图中源波形与虚影均为抗锯齿全质量。 - 超大文件:线段/散点/点线切换与拖拽的正常渲染(截图),1.77GB 文件加载过渡动画正常。 - 回归:菜单内联编辑 Y 轴上下限、选区 Y 轴自适应、图例点击选中、面板改名均正常。 - 内存:BIG_DATA 全选 122MB(粗粒度层约 +1MB);VERY_BIG 全选 1224MB(理论下限 1.25GB)。 - make clean && make all 零警告零错误。
583 lines
20 KiB
C++
583 lines
20 KiB
C++
#ifndef __DATA_MODEL_HPP__
|
|
#define __DATA_MODEL_HPP__
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "CsvTable.hpp"
|
|
|
|
namespace jdi
|
|
{
|
|
|
|
/**
|
|
* @brief 波形绘制方式。
|
|
*/
|
|
enum class DrawMode : int
|
|
{
|
|
LINE = 0, /**< 相邻采样点之间以插值直线连接。 */
|
|
SCATTER = 1, /**< 仅绘制采样点散点。 */
|
|
LINE_SCATTER = 2 /**< 同时绘制插值直线与采样点散点。 */
|
|
};
|
|
|
|
/**
|
|
* @brief 绘图区拖拽缩放模式(由工具栏按钮切换)。
|
|
*/
|
|
enum class PlotZoomMode : int
|
|
{
|
|
NONE = 0, /**< 常规模式:拖拽平移时间轴,光标为箭头。 */
|
|
TIME = 1, /**< 时间轴缩放:在绘图区拖拽竖向选区,放大时间范围。 */
|
|
VALUE = 2 /**< Y 轴缩放:在某个网格内拖拽横向选区,放大该网格幅值范围。 */
|
|
};
|
|
|
|
/**
|
|
* @brief 将绘制方式转换为中文显示名称。
|
|
* @param [IN] mode 绘制方式。
|
|
* @return 显示名称。
|
|
*/
|
|
const wchar_t* DrawModeName(DrawMode mode);
|
|
|
|
/**
|
|
* @brief 网格划分策略:决定信号可见性与网格数量的联动方式。
|
|
*/
|
|
enum class LaneMode : int
|
|
{
|
|
PER_SIGNAL = 0, /**< 每条可见信号独占一个网格(随可见性自动增删)。 */
|
|
MERGED = 1, /**< 全部可见信号叠加在同一网格。 */
|
|
CUSTOM = 2 /**< 由用户手动指定归属;可见性变化时仅清理空网格。 */
|
|
};
|
|
|
|
/**
|
|
* @brief 全局信号引用:文件下标 + 文件内信号下标。
|
|
*/
|
|
struct SignalRef
|
|
{
|
|
int fileIndex = -1; /**< 所属文件下标。 */
|
|
int signalIndex = -1; /**< 文件内信号下标。 */
|
|
|
|
/**
|
|
* @brief 判断引用是否指向有效位置。
|
|
* @return 两个下标均非负返回 true。
|
|
*/
|
|
bool IsValid() const { return fileIndex >= 0 && signalIndex >= 0; }
|
|
|
|
/**
|
|
* @brief 相等比较。
|
|
* @param [IN] other 另一引用。
|
|
* @return 指向同一信号返回 true。
|
|
*/
|
|
bool operator==(const SignalRef& other) const
|
|
{
|
|
return fileIndex == other.fileIndex && signalIndex == other.signalIndex;
|
|
}
|
|
|
|
/**
|
|
* @brief 不等比较。
|
|
* @param [IN] other 另一引用。
|
|
* @return 指向不同信号返回 true。
|
|
*/
|
|
bool operator!=(const SignalRef& other) const { return !(*this == other); }
|
|
};
|
|
|
|
/**
|
|
* @brief 单个信号的显示外观(颜色/透明度/线宽/绘制方式)。
|
|
*
|
|
* 外观属于信号自身而非某个标签页——同一信号在所有标签页中必须显示效果一致,
|
|
* 因此在任一视图里修改颜色/线宽/透明度/样式,其它视图会自动同步。
|
|
* 信号是否可见则属于各标签页自己的配置(见 `TabConfig`)。
|
|
*/
|
|
struct SignalStyle
|
|
{
|
|
std::uint32_t color = 0xFF268BD2; /**< 波形颜色,格式 0xAARRGGBB。 */
|
|
std::uint32_t customColor = 0xFF6C71C4; /**< 自定义颜色记忆值(切换预设色后仍保留)。 */
|
|
float opacity = 1.0f; /**< 不透明度,取值 0.0-1.0,默认 1.0。 */
|
|
float lineWidth = 1.6f; /**< 线宽(逻辑像素,未乘 DPI 缩放)。 */
|
|
DrawMode mode = DrawMode::LINE; /**< 绘制方式。 */
|
|
};
|
|
|
|
/**
|
|
* @brief 单条信号的元数据与采样值(纯数据,不含可见性配置)。
|
|
*/
|
|
struct SignalData
|
|
{
|
|
std::wstring name; /**< 名称(取自文件列名,完全保留原样)。 */
|
|
std::wstring displayName; /**< 用户重命名的显示名;为空时使用 name。 */
|
|
std::wstring rawHeader; /**< 原始列名。 */
|
|
std::wstring unit; /**< 从列名括号中提取的单位,可能为空。 */
|
|
std::vector<double> values; /**< 采样值,缺失处为 NaN。 */
|
|
double minValue = 0.0; /**< 有限采样值最小值。 */
|
|
double maxValue = 0.0; /**< 有限采样值最大值。 */
|
|
std::size_t finiteCount = 0; /**< 有限采样点数量。 */
|
|
|
|
/**
|
|
* @brief 粗粒度包络层:每 coarseStride 个采样一组的 min/max。
|
|
*
|
|
* 大文件(千万级采样)的折线包络构建是 O(可见采样数) 的,每次视图变化都要重算,
|
|
* 实测 1770 万行 × 5 信号需要约 200ms/帧,拖拽时严重掉帧。
|
|
* 有了这一层(额外内存 ≈ 采样数的 0.8%),构建包络时只需读取“每列覆盖到的分组”,
|
|
* 读取量降到约 1/5000,且**绘制结果与全量扫描完全一致**(分组内已存真实极值)。
|
|
* 分组内没有有效值时存 ±inf,读取时跳过。
|
|
*/
|
|
std::vector<double> coarseMin; /**< 分组最小值。 */
|
|
std::vector<double> coarseMax; /**< 分组最大值。 */
|
|
std::size_t coarseStride = 0; /**< 分组的采样跨度;0 表示未构建。 */
|
|
|
|
SignalStyle style; /**< 显示外观(全局共享,跨标签页同步)。 */
|
|
|
|
/**
|
|
* @brief 获取用于界面展示的名称。
|
|
* @return 用户重命名后的显示名,未重命名时返回文件中的原始名称。
|
|
*/
|
|
const std::wstring& Title() const { return displayName.empty() ? name : displayName; }
|
|
};
|
|
|
|
/**
|
|
* @brief 一个已加载的数据文件及其自有时间轴。
|
|
*/
|
|
struct DataFile
|
|
{
|
|
std::wstring filePath; /**< 文件完整路径(仅用于状态提示)。 */
|
|
std::wstring fileName; /**< 文件名称。 */
|
|
std::wstring displayName; /**< 用户重命名的分组名;为空时使用 fileName。 */
|
|
std::wstring timeColumnName; /**< 时间列列名。 */
|
|
std::vector<double> time; /**< 时间轴数值。 */
|
|
std::vector<SignalData> signals; /**< 该文件包含的信号。 */
|
|
double minTime = 0.0; /**< 时间轴最小值。 */
|
|
double maxTime = 0.0; /**< 时间轴最大值。 */
|
|
bool timeMonotonic = true; /**< 时间轴是否单调不减。 */
|
|
|
|
/**
|
|
* @brief 获取用于界面展示的分组名。
|
|
* @return 用户重命名后的显示名,未重命名时返回文件名。
|
|
*/
|
|
const std::wstring& Title() const { return displayName.empty() ? fileName : displayName; }
|
|
};
|
|
|
|
/**
|
|
* @brief 由 CSV 解析结果构建可入库的数据文件。
|
|
*
|
|
* 该函数**不访问 DataSet**(只依赖传入的 CsvTable 与调色板基准序号),
|
|
* 因此可以在工作线程上执行:大文件的解析与列重组占整个加载耗时的大头,
|
|
* 放到工作线程后主线程只需做一次 O(1) 的移动入队,加载过程中的界面不会卡住。
|
|
*
|
|
* table 按右值传入:每列会被**移动**进对应信号的 values(零拷贝)。
|
|
*
|
|
* @param [IN,OUT] table CSV 解析结果(列会被移走)。
|
|
* @param [IN] filePath 源文件路径。
|
|
* @param [IN] paletteBase 调色板起始序号(通常传入当前已有信号数)。
|
|
* @param [OUT] file 构建结果。
|
|
* @param [OUT] error 失败原因描述(成功时清空)。
|
|
* @param [IN] progress 进度回调(0-1),返回 false 表示取消,可为空。
|
|
* @return 构建成功返回 true。
|
|
*/
|
|
bool BuildDataFile(CsvTable&& table, const std::wstring& filePath, std::size_t paletteBase, DataFile& file,
|
|
std::wstring& error, const CsvProgress& progress = CsvProgress());
|
|
|
|
/**
|
|
* @brief 数据集合:统一管理全部已加载文件,与视图配置无关。
|
|
*/
|
|
class DataSet
|
|
{
|
|
public:
|
|
/**
|
|
* @brief 清空全部已加载文件。
|
|
*/
|
|
void Clear();
|
|
|
|
/**
|
|
* @brief 依据 CSV 解析结果追加一个数据文件。
|
|
* @param [IN] table CSV 解析结果。
|
|
* @param [IN] filePath 源文件路径。
|
|
* @param [OUT] error 失败原因描述(成功时清空)。
|
|
* @param [OUT] fileIndex 新文件下标,失败时为 -1。
|
|
* @return 追加成功返回 true。
|
|
*/
|
|
bool AddFromTable(const CsvTable& table, const std::wstring& filePath, std::wstring& error, int& fileIndex);
|
|
|
|
/**
|
|
* @brief 追加一个已构建好的数据文件(仅做一次移动,不拷贝采样数据)。
|
|
* @param [IN,OUT] file 数据文件(内部缓冲会被移走)。
|
|
* @param [OUT] fileIndex 新文件下标。
|
|
* @return 追加成功返回 true。
|
|
*/
|
|
bool AddPreparedFile(DataFile&& file, int& fileIndex);
|
|
|
|
/**
|
|
* @brief 移除指定下标的文件,并立即释放其占用的全部采样内存。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @return 移除成功返回 true。
|
|
*/
|
|
bool RemoveFile(int fileIndex);
|
|
|
|
/**
|
|
* @brief 判断数据集合是否为空。
|
|
* @return 未加载任何文件返回 true。
|
|
*/
|
|
bool Empty() const { return m_files.empty(); }
|
|
|
|
/**
|
|
* @brief 获取文件数量。
|
|
* @return 文件数量。
|
|
*/
|
|
std::size_t FileCount() const { return m_files.size(); }
|
|
|
|
/**
|
|
* @brief 获取信号总数。
|
|
* @return 信号总数。
|
|
*/
|
|
std::size_t SignalCount() const;
|
|
|
|
/**
|
|
* @brief 获取全部文件(只读)。
|
|
* @return 文件集合。
|
|
*/
|
|
const std::vector<DataFile>& Files() const { return m_files; }
|
|
|
|
/**
|
|
* @brief 按下标获取文件。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @return 文件指针,下标非法时返回 nullptr。
|
|
*/
|
|
const DataFile* FileAt(int fileIndex) const;
|
|
|
|
/**
|
|
* @brief 修改某个信号在界面上的显示名称。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @param [IN] signalIndex 文件内信号下标。
|
|
* @param [IN] name 新的显示名;传入空串表示恢复使用原始列名。
|
|
* @return 修改成功返回 true。
|
|
*/
|
|
bool SetSignalDisplayName(int fileIndex, int signalIndex, const std::wstring& name);
|
|
|
|
/**
|
|
* @brief 修改某个文件分组的显示名称。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @param [IN] name 新的分组名;传入空串表示恢复使用文件名。
|
|
* @return 修改成功返回 true。
|
|
*/
|
|
bool SetFileDisplayName(int fileIndex, const std::wstring& name);
|
|
|
|
/**
|
|
* @brief 解析信号引用。
|
|
* @param [IN] ref 信号引用。
|
|
* @return 信号数据指针,引用无效时返回 nullptr。
|
|
*/
|
|
const SignalData* Resolve(const SignalRef& ref) const;
|
|
|
|
/**
|
|
* @brief 获取指定信号的显示外观(只读)。
|
|
* @param [IN] ref 信号引用。
|
|
* @return 外观指针,引用无效时返回 nullptr。
|
|
*/
|
|
const SignalStyle* Style(const SignalRef& ref) const;
|
|
|
|
/**
|
|
* @brief 获取指定信号的显示外观(可写)。
|
|
* @param [IN] ref 信号引用。
|
|
* @return 外观指针,引用无效时返回 nullptr。
|
|
*/
|
|
SignalStyle* Style(const SignalRef& ref);
|
|
|
|
/**
|
|
* @brief 计算全部文件时间范围的并集下限。
|
|
* @return 时间下限。
|
|
*/
|
|
double MinTime() const;
|
|
|
|
/**
|
|
* @brief 计算全部文件时间范围的并集上限。
|
|
* @return 时间上限。
|
|
*/
|
|
double MaxTime() const;
|
|
|
|
/**
|
|
* @brief 获取当前选中的信号(全标签页共享)。
|
|
* @return 信号引用。
|
|
*/
|
|
const SignalRef& Selected() const { return m_selected; }
|
|
|
|
/**
|
|
* @brief 设置当前选中的信号(全标签页共享)。
|
|
* @param [IN] ref 信号引用;传入无效值表示取消选择。
|
|
*/
|
|
void SetSelected(const SignalRef& ref) { m_selected = ref; }
|
|
|
|
/**
|
|
* @brief 在数据层移除某文件之前,按旧下标修正选中引用。
|
|
* @param [IN] fileIndex 即将被移除的文件下标。
|
|
*/
|
|
void RemapSelectionAfterFileRemoval(int fileIndex);
|
|
|
|
/**
|
|
* @brief 校验选中引用是否仍指向存在的信号,失效则取消选中。
|
|
* @return 选中状态发生变化返回 true。
|
|
*/
|
|
bool ValidateSelection();
|
|
|
|
private:
|
|
std::vector<DataFile> m_files; /**< 已加载文件集合。 */
|
|
SignalRef m_selected; /**< 当前选中信号(跨标签页共享)。 */
|
|
};
|
|
|
|
/**
|
|
* @brief 一个波形网格(纵向泳道),可容纳多条信号叠加显示。
|
|
*/
|
|
struct Lane
|
|
{
|
|
std::wstring name; /**< 网格名称。 */
|
|
std::vector<SignalRef> signals; /**< 该网格包含的信号(按加入顺序)。 */
|
|
bool autoRange = true; /**< 是否依据信号取值范围自动计算 Y 轴。 */
|
|
double yMin = -1.0; /**< 手动 Y 轴下限。 */
|
|
double yMax = 1.0; /**< 手动 Y 轴上限。 */
|
|
};
|
|
|
|
/**
|
|
* @brief 计算某条信号在给定时刻的取值。
|
|
* @param [IN] file 信号所属文件。
|
|
* @param [IN] signal 目标信号。
|
|
* @param [IN] time 采样时刻。
|
|
* @param [IN] interpolate 是否在相邻采样点之间做线性插值。
|
|
* @param [OUT] value 输出采样值,缺失时为 NaN。
|
|
* @return 时间点落在数据范围内且取到有效值返回 true。
|
|
*/
|
|
bool SampleFileAt(const DataFile& file, const SignalData& signal, double time, bool interpolate, double& value);
|
|
|
|
/**
|
|
* @brief 在指定文件的时间轴上查找与给定时刻最接近的采样点。
|
|
* @param [IN] file 目标文件。
|
|
* @param [IN] time 采样时刻。
|
|
* @return 采样点下标,文件为空时返回 -1。
|
|
*/
|
|
int FindNearestSample(const DataFile& file, double time);
|
|
|
|
/**
|
|
* @brief 单个标签页的独立视图配置(信号可见性、网格划分与视图范围)。
|
|
*
|
|
* 仅保存「本页看到哪些信号」与视图状态;信号的显示外观(颜色/线宽/透明度/样式)
|
|
* 保存在 `DataSet` 中并被所有标签页共享,因此同一个信号在各视图中的显示效果一致。
|
|
*/
|
|
class TabConfig
|
|
{
|
|
public:
|
|
TabConfig();
|
|
|
|
/**
|
|
* @brief 获取标签页名称。
|
|
* @return 名称。
|
|
*/
|
|
const std::wstring& Name() const { return m_name; }
|
|
|
|
/**
|
|
* @brief 设置标签页名称。
|
|
* @param [IN] name 新名称。
|
|
*/
|
|
void SetName(const std::wstring& name) { m_name = name; }
|
|
|
|
/**
|
|
* @brief 依据数据集合调整配置容量(新增文件补默认配置,移除文件清理配置)。
|
|
* @param [IN] dataSet 数据集合。
|
|
*/
|
|
void SyncToDataSet(const DataSet& dataSet);
|
|
|
|
/**
|
|
* @brief 在数据层移除某文件之前,按旧下标修正本配置(不重建网格)。
|
|
* @param [IN] fileIndex 即将被移除的文件下标。
|
|
* @note 调用顺序必须为:各标签页 RemapAfterFileRemoval → 数据层 RemoveFile → 各标签页 SyncToDataSet。
|
|
*/
|
|
void RemapAfterFileRemoval(int fileIndex);
|
|
|
|
/**
|
|
* @brief 判断指定信号是否可见。
|
|
* @param [IN] ref 信号引用。
|
|
* @return 可见返回 true。
|
|
*/
|
|
bool IsVisible(const SignalRef& ref) const;
|
|
|
|
/**
|
|
* @brief 设置指定信号的可见性,并同步网格划分。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] ref 信号引用。
|
|
* @param [IN] visible 目标可见状态。
|
|
*/
|
|
void SetVisible(const DataSet& dataSet, const SignalRef& ref, bool visible);
|
|
|
|
/**
|
|
* @brief 切换指定信号的可见性,并同步网格划分。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] ref 信号引用。
|
|
*/
|
|
void ToggleVisible(const DataSet& dataSet, const SignalRef& ref);
|
|
|
|
/**
|
|
* @brief 设置某个文件全部信号的可见性,并同步网格划分。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @param [IN] visible 目标可见状态。
|
|
*/
|
|
void SetFileVisible(const DataSet& dataSet, int fileIndex, bool visible);
|
|
|
|
/**
|
|
* @brief 设置全部信号可见性,并同步网格划分。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] visible 目标可见状态。
|
|
*/
|
|
void SetAllVisible(const DataSet& dataSet, bool visible);
|
|
|
|
/**
|
|
* @brief 仅显示指定信号,其余全部隐藏。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] ref 需要保持可见的信号。
|
|
*/
|
|
void SoloSignal(const DataSet& dataSet, const SignalRef& ref);
|
|
|
|
/**
|
|
* @brief 判断某文件是否存在可见信号。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @return 存在可见信号返回 true。
|
|
*/
|
|
bool FileHasVisible(const DataSet& dataSet, int fileIndex) const;
|
|
|
|
/**
|
|
* @brief 判断某文件是否全部信号可见。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @return 全部可见且至少有一条信号返回 true。
|
|
*/
|
|
bool FileAllVisible(const DataSet& dataSet, int fileIndex) const;
|
|
|
|
/**
|
|
* @brief 判断是否存在任何可见信号。
|
|
* @return 存在返回 true。
|
|
*/
|
|
bool AnyVisible() const;
|
|
|
|
/**
|
|
* @brief 统计可见信号数量。
|
|
* @return 可见信号数量。
|
|
*/
|
|
int VisibleCount() const;
|
|
|
|
/**
|
|
* @brief 获取网格划分策略。
|
|
* @return 策略枚举。
|
|
*/
|
|
LaneMode Mode() const { return m_laneMode; }
|
|
|
|
/**
|
|
* @brief 设置网格划分策略并同步网格。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] mode 目标策略。
|
|
*/
|
|
void SetMode(const DataSet& dataSet, LaneMode mode);
|
|
|
|
/**
|
|
* @brief 依据当前可见性与策略重新生成网格划分。
|
|
* @param [IN] dataSet 数据集合。
|
|
*/
|
|
void SyncLanes(const DataSet& dataSet);
|
|
|
|
/**
|
|
* @brief 获取网格集合(只读)。
|
|
* @return 网格集合。
|
|
*/
|
|
const std::vector<Lane>& Lanes() const { return m_lanes; }
|
|
|
|
/**
|
|
* @brief 获取网格集合(可写)。
|
|
* @return 网格集合。
|
|
*/
|
|
std::vector<Lane>& Lanes() { return m_lanes; }
|
|
|
|
/**
|
|
* @brief 查询某信号所属网格下标。
|
|
* @param [IN] ref 信号引用。
|
|
* @return 网格下标,未找到返回 -1。
|
|
*/
|
|
int LaneOfSignal(const SignalRef& ref) const;
|
|
|
|
/**
|
|
* @brief 将信号移动到指定网格,并切换为自定义划分策略。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] ref 信号引用。
|
|
* @param [IN] laneIndex 目标网格下标,传入负值表示新建网格。
|
|
* @return 移动后该信号所在的网格下标。
|
|
*/
|
|
int MoveSignalToLane(const DataSet& dataSet, const SignalRef& ref, int laneIndex);
|
|
|
|
/**
|
|
* @brief 查询某文件的分组是否处于折叠状态。
|
|
* @param [IN] fileIndex 文件下标。
|
|
* @return 折叠状态。
|
|
*/
|
|
bool IsCollapsed(int fileIndex) const;
|
|
|
|
/**
|
|
* @brief 切换某文件分组的折叠状态。
|
|
* @param [IN] fileIndex 文件下标。
|
|
*/
|
|
void ToggleCollapsed(int fileIndex);
|
|
|
|
/**
|
|
* @brief 计算某网格的 Y 轴显示范围。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [IN] laneIndex 网格下标。
|
|
* @param [OUT] yMin 输出下限。
|
|
* @param [OUT] yMax 输出上限。
|
|
*/
|
|
void ComputeLaneRange(const DataSet& dataSet, int laneIndex, double& yMin, double& yMax) const;
|
|
|
|
/**
|
|
* @brief 计算全部可见信号覆盖的时间范围。
|
|
* @param [IN] dataSet 数据集合。
|
|
* @param [OUT] minTime 输出下限。
|
|
* @param [OUT] maxTime 输出上限。
|
|
* @return 存在可见信号返回 true。
|
|
*/
|
|
bool ComputeVisibleTimeBounds(const DataSet& dataSet, double& minTime, double& maxTime) const;
|
|
|
|
/// @brief 视图左边界时间(可读写)。
|
|
double& ViewMin() { return m_viewMin; }
|
|
/// @brief 视图左边界时间(只读)。
|
|
double ViewMin() const { return m_viewMin; }
|
|
/// @brief 视图右边界时间(可读写)。
|
|
double& ViewMax() { return m_viewMax; }
|
|
/// @brief 视图右边界时间(只读)。
|
|
double ViewMax() const { return m_viewMax; }
|
|
/// @brief 视图范围是否已初始化(可读写)。
|
|
bool& ViewInitialized() { return m_viewInitialized; }
|
|
/// @brief 网格纵向滚动偏移量(可读写)。
|
|
float& LaneScroll() { return m_laneScroll; }
|
|
/// @brief 时间光标是否启用(可读写)。
|
|
bool& CursorEnabled() { return m_cursorEnabled; }
|
|
/// @brief 时间光标是否启用(只读)。
|
|
bool CursorEnabled() const { return m_cursorEnabled; }
|
|
/// @brief 时间光标位置(可读写)。
|
|
double& CursorTime() { return m_cursorTime; }
|
|
/// @brief 时间光标位置(只读)。
|
|
double CursorTime() const { return m_cursorTime; }
|
|
/// @brief 绘图区拖拽缩放模式(可读写)。
|
|
PlotZoomMode& ZoomMode() { return m_zoomMode; }
|
|
/// @brief 绘图区拖拽缩放模式(只读)。
|
|
PlotZoomMode ZoomMode() const { return m_zoomMode; }
|
|
|
|
private:
|
|
std::wstring m_name; /**< 标签页名称。 */
|
|
std::vector<std::vector<bool>> m_visible; /**< 信号可见性,按 [文件][信号] 索引(本页独立)。 */
|
|
std::vector<bool> m_collapsed; /**< 文件分组折叠状态,按文件索引。 */
|
|
std::vector<Lane> m_lanes; /**< 网格划分。 */
|
|
LaneMode m_laneMode = LaneMode::PER_SIGNAL; /**< 网格划分策略。 */
|
|
double m_viewMin = 0.0; /**< 视图左边界时间。 */
|
|
double m_viewMax = 1.0; /**< 视图右边界时间。 */
|
|
bool m_viewInitialized = false; /**< 视图范围是否已初始化。 */
|
|
float m_laneScroll = 0.0f; /**< 网格纵向滚动偏移量。 */
|
|
bool m_cursorEnabled = false; /**< 时间光标是否启用(由工具栏按钮切换)。 */
|
|
double m_cursorTime = 0.0; /**< 时间光标位置。 */
|
|
PlotZoomMode m_zoomMode = PlotZoomMode::NONE; /**< 绘图区拖拽缩放模式。 */
|
|
};
|
|
|
|
} // namespace jdi
|
|
|
|
#endif // __DATA_MODEL_HPP__
|