#ifndef __SIGNAL_SET_HPP__ #define __SIGNAL_SET_HPP__ #include #include #include #include #include "CsvTable.hpp" namespace jdi { /** * @brief 波形绘制方式。 */ enum class DrawMode : int { LINE = 0, /**< 相邻采样点之间以插值直线连接。 */ SCATTER = 1, /**< 仅绘制采样点散点。 */ LINE_SCATTER = 2, /**< 同时绘制插值直线与采样点散点。 */ STEP = 3 /**< 阶梯保持(零阶保持)连线。 */ }; /** * @brief 将绘制方式转换为中文显示名称。 * @param [IN] mode 绘制方式。 * @return 显示名称。 */ const wchar_t* DrawModeName(DrawMode mode); /** * @brief 单条信号(一列数据及其显示属性)。 */ struct Signal { std::wstring name; /**< 显示名称(已剥离 "[n]" 序号前缀)。 */ std::wstring rawHeader; /**< CSV 原始列名。 */ std::wstring unit; /**< 从列名括号中提取的单位,可能为空。 */ std::vector values; /**< 采样值,缺失处为 NaN。 */ bool visible = true; /**< 是否参与绘制。 */ std::uint32_t color = 0xFF268BD2; /**< 波形颜色,格式 0xAARRGGBB。 */ float lineWidth = 1.6f; /**< 线宽(逻辑像素,未乘 DPI 缩放)。 */ DrawMode mode = DrawMode::LINE; /**< 绘制方式。 */ double minValue = 0.0; /**< 有限采样值最小值。 */ double maxValue = 0.0; /**< 有限采样值最大值。 */ std::size_t finiteCount = 0; /**< 有限采样点数量。 */ }; /** * @brief 一个波形网格(纵向泳道),可容纳多条信号叠加显示。 */ struct Lane { std::wstring name; /**< 网格名称。 */ std::vector signalIndices; /**< 该网格包含的信号下标(按加入顺序)。 */ bool autoRange = true; /**< 是否依据信号取值范围自动计算 Y 轴。 */ double yMin = -1.0; /**< 手动 Y 轴下限。 */ double yMax = 1.0; /**< 手动 Y 轴上限。 */ }; /** * @brief 仿真数据集合:时间轴 + 多条信号 + 网格划分。 */ class SignalSet { public: SignalSet(); /** * @brief 清空全部数据与显示状态。 */ void Clear(); /** * @brief 依据 CSV 解析结果构建数据集(自动识别时间列与信号列)。 * @param [IN] table CSV 解析结果。 * @param [IN] filePath 源文件路径,用于界面展示。 * @param [OUT] error 失败原因描述。 * @return 构建成功返回 true。 */ bool BuildFromTable(const CsvTable& table, const std::wstring& filePath, std::wstring& error); /** * @brief 判断数据集是否已加载数据。 * @return 已加载返回 true。 */ bool IsLoaded() const { return !m_signals.empty(); } /// @brief 信号集合(可读写)。 std::vector& Signals() { return m_signals; } /// @brief 信号集合(只读)。 const std::vector& Signals() const { return m_signals; } /// @brief 网格集合(可读写)。 std::vector& Lanes() { return m_lanes; } /// @brief 网格集合(只读)。 const std::vector& Lanes() const { return m_lanes; } /// @brief 时间轴数值(只读)。 const std::vector& Time() const { return m_time; } /// @brief 时间轴列名(只读)。 const std::wstring& TimeColumnName() const { return m_timeColumnName; } /// @brief 源文件路径(只读)。 const std::wstring& FilePath() const { return m_filePath; } /// @brief 源文件名称(只读)。 const std::wstring& FileName() const { return m_fileName; } /// @brief 采样点数量(只读)。 std::size_t SampleCount() const { return m_time.size(); } /// @brief 时间轴最小值(只读)。 double MinTime() const { return m_minTime; } /// @brief 时间轴最大值(只读)。 double MaxTime() const { return m_maxTime; } /// @brief 时间轴是否单调不减(只读)。 bool TimeMonotonic() const { return m_timeMonotonic; } /// @brief 当前选中信号下标,-1 表示未选中(只读)。 int SelectedSignal() const { return m_selectedSignal; } /** * @brief 设置当前选中信号。 * @param [IN] index 信号下标,传入越界值等价于取消选择。 */ void SetSelectedSignal(int index); /** * @brief 查询某信号所属网格下标。 * @param [IN] signalIndex 信号下标。 * @return 网格下标,未找到返回 -1。 */ int LaneOfSignal(int signalIndex) const; /** * @brief 将信号移动到指定网格,必要时创建新网格并回收空网格。 * @param [IN] signalIndex 信号下标。 * @param [IN] laneIndex 目标网格下标,传入负值表示新建网格。 * @return 移动后该信号所在的网格下标。 */ int MoveSignalToLane(int signalIndex, int laneIndex); /** * @brief 将所有可见信号合并到同一个网格中。 */ void MergeIntoSingleLane(); /** * @brief 为每条信号创建独立网格。 */ void SplitIntoLanes(); /** * @brief 设置全部信号的可见状态。 * @param [IN] visible 目标可见状态。 */ void SetAllVisible(bool visible); /** * @brief 仅显示指定信号,其余全部隐藏。 * @param [IN] signalIndex 需要保持可见的信号下标。 */ void SoloSignal(int signalIndex); /** * @brief 计算某网格的 Y 轴显示范围。 * @param [IN] laneIndex 网格下标。 * @param [OUT] yMin 输出下限。 * @param [OUT] yMax 输出上限。 */ void ComputeLaneRange(int laneIndex, double& yMin, double& yMax) const; /** * @brief 在当前时间轴上采样指定信号的值。 * @param [IN] signalIndex 信号下标。 * @param [IN] time 采样时刻。 * @param [IN] interpolate 是否在相邻采样点之间做线性插值。 * @param [OUT] value 输出采样值,缺失时为 NaN。 * @return 时间点落在数据范围内且取到有效值返回 true。 */ bool SampleAt(int signalIndex, double time, bool interpolate, double& value) const; /** * @brief 在当前数据集中查找时间最为接近的采样点下标。 * @param [IN] time 采样时刻。 * @return 采样点下标,数据集为空时返回 -1。 */ int FindNearestSample(double time) const; private: /** * @brief 移除没有包含任何信号的网格(至少保留一个)。 */ void PruneEmptyLanes(); /** * @brief 为新增信号分配默认颜色。 * @param [IN] index 信号序号。 * @return 0xAARRGGBB 颜色值。 */ std::uint32_t PickDefaultColor(std::size_t index) const; std::vector m_time; /**< 时间轴数值。 */ std::vector m_signals; /**< 信号集合。 */ std::vector m_lanes; /**< 网格集合。 */ std::wstring m_timeColumnName; /**< 时间列列名。 */ std::wstring m_filePath; /**< 源文件完整路径。 */ std::wstring m_fileName; /**< 源文件名称。 */ double m_minTime = 0.0; /**< 时间轴最小值。 */ double m_maxTime = 0.0; /**< 时间轴最大值。 */ bool m_timeMonotonic = true; /**< 时间轴是否单调不减。 */ int m_selectedSignal = -1; /**< 当前选中信号下标。 */ }; } // namespace jdi #endif // __SIGNAL_SET_HPP__