Files
Renderive/Core/plottable/Spectrum.h
T
2026-08-02 12:15:48 +08:00

195 lines
7.5 KiB
C++

#pragma once
#include <cstddef>
#include <memory_resource>
#include <span>
#include <utility>
#include <vector>
#include "../architecture/Update_Completion.h"
#include "../base/Color.h"
#include "../base/Memory.h"
#include "../base/Style.h"
#include "../primitive/Curve.h"
#include "Hover_Tooltip.h"
#include "Interpolation.h"
namespace renderive {
struct Spectrum_Private;
class Label;
class Marker;
/// @brief 单条频谱线图元,支持可见范围裁剪和多种线插值策略。
class LIB_DECL Spectrum : public Renderable, public Hover_Tooltip_Mixin<Spectrum> {
public:
/// @brief 创建频谱线图元。
Spectrum();
/// @brief 绑定频率轴。
PROP(std::shared_ptr<Frequency_Axis>, frequency_axis)
/// @brief 绑定功率轴。
PROP(std::shared_ptr<Axis>, power_axis);
/// @brief 频率采样点数。
PROP(int, frequency_point_size);
/// @brief 频率数据范围。
PROP(Range, frequency_range);
/// @brief 中心扫频频率。
PROP(double, center_frequency);
/// @brief 扫频高亮频率范围。
PROP(Range, sweep_frequency_range);
/// @brief 是否绘制最大保持线。
PROP(bool, max_hold_visible);
/// @brief 是否绘制最小保持线。
PROP(bool, min_hold_visible);
/// @brief 是否显示最大值标记。
bool max_marker_visible();
void set_max_marker_visible(bool);
/// @brief 是否显示最小值标记。
PROP(bool, use_min_marker);
/// @brief 是否显示扫频高亮区域。
bool sweep_region_visible();
void set_sweep_region_visible(bool);
/// @brief 是否只生成当前可见频率范围。
PROP(bool, visible_range_only);
/// @brief 折线插值模式。
PROP(Line_Interpolation_Mode, interpolation_mode);
/// @brief 采样降采样模式。
PROP(Line_Sampling_Strategy, sample_mode);
/// @brief 最大保持线填充刷。
PROP(Brush, max_brush);
/// @brief 当前频谱线填充刷。
Brush current_brush();
void set_current_brush(Brush);
/// @brief 最小保持线填充刷。
PROP(Brush, min_brush);
/// @brief 最大保持线画笔。
PROP(Pen, max_pen);
/// @brief 当前频谱线画笔。
Pen current_pen();
void set_current_pen(Pen);
/// @brief 最小保持线画笔。
PROP(Pen, min_pen);
/// @brief 选中标记画笔。
Pen selected_marker_pen();
void set_selected_marker_pen(Pen);
/// @brief 普通标记画笔。
PROP(Pen, marker_pen);
/// @brief 中心频率线画笔。
PROP(Pen, middle_frequency_pen);
/// @brief 扫频区域填充刷。
Brush sweep_region_brush();
void set_sweep_region_brush(Brush);
/// @brief 写入一帧频谱线数据。
void update_samples(std::span<const double> line_data);
/// @brief 移动写入一帧频谱线数据。
void update_samples(std::pmr::vector<double>&& line_data);
/// @brief 提交一帧频谱线数据并返回完成票据。
Update_Ticket submit_data(std::span<const double> line_data);
/// @brief 移动提交一帧频谱线数据并返回完成票据。
Update_Ticket submit_data(std::pmr::vector<double>&& line_data);
/// @brief 用 writer 填充并写入一帧频谱线数据。
template <typename Writer>
void write_data(std::size_t count, Writer&& writer) {
std::pmr::vector<double> values(memory_resource(Memory_Domain::Spectrum));
values.resize(count);
std::forward<Writer>(writer)(std::span<double>(values.data(), values.size()));
update_samples(std::move(values));
}
/// 查询指定频率位置的功率值。
double power_at(double frequency, bool& ok);
/// 添加自定义频率标记。
void add_custom_marker(double frequency);
/// 添加自定义线标记。
void add_custom_line_marker(double frequency);
/// 删除指定频率附近的自定义标记。
void remove_custom_marker(double frequency);
/// 删除当前选中的标记。
void remove_selected_marker();
/// 清空所有自定义标记。
void clear_custom_markers();
/// 返回可选择线标记数量。
int selectable_line_marker_count();
/// 返回当前选中线标记索引。
int selected_marker_index();
/// 设置当前选中线标记索引。
void set_selected_marker_index(int marker_index);
/// 选择下一个线标记。
void select_next_marker();
/// 取消当前线标记选择。
void clear_marker_selection();
/// 选择上一个线标记。
void select_previous_marker();
/// 返回指定标记索引对应频率。
double marker_frequency(int mark_index);
/// 设置指定标记频率。
void set_marker_frequency(int marker_index, double frequency);
/// 设置当前选中标记频率。
void set_current_marker_frequency(double frequency);
struct Builder;
private:
Spectrum_Private* d();
Render_Object_Owner create_render_data() override;
Render_Object_Owner create_render_state() override;
Render_Object_Owner create_input_data() override;
};
struct Spectrum_Prop {
std::weak_ptr<Frequency_Axis> frequency_axis{};
std::weak_ptr<Axis> power_axis{};
int frequency_point_size{};
Range frequency_range{};
double center_frequency = 50;
Range sweep_frequency_range{40, 60};
bool max_hold_visible = false;
bool min_hold_visible = false;
bool max_marker_visible = false;
bool use_min_marker = false;
bool sweep_region_visible = false;
bool visible_range_only = true;
Line_Interpolation_Mode interpolation_mode = Line_Interpolation_Mode::Linear_Value;
Line_Sampling_Strategy sampling_strategy = Line_Sampling_Strategy::All_Samples;
Brush max_brush;
Brush current_brush;
Brush min_brush;
Pen max_pen = Pen{Color::red()};
Pen cur_pen = Pen{Color::green()};
Pen min_pen = Pen{Color::white()};
Pen selected_marker_pen = Pen{Color{0, 0, 139, 255}, 2.0};
Pen marker_pen = Pen{Color::red()};
Pen middle_frequency_pen = Pen{Color::red()};
Brush sweep_region_brush = Brush{Color{255, 255, 0, 100}, Brush_Style::Solid};
Spectrum_Prop() {
max_brush = Brush{};
current_brush = Brush{};
min_brush = Brush{};
}
};
/// @brief 频谱线构造器。
struct LIB_DECL Spectrum::Builder : Spectrum_Prop {
PROP_B(std::shared_ptr<Renderable>, parent)
PROP_B(std::shared_ptr<Frequency_Axis>, frequency_axis)
PROP_B(std::shared_ptr<Axis>, power_axis);
PROP_B(int, frequency_point_size);
PROP_B(Range, frequency_range);
PROP_B(double, center_frequency);
PROP_B(Range, sweep_frequency_range);
PROP_B(bool, max_hold_visible);
PROP_B(bool, min_hold_visible);
PROP_B(bool, max_marker_visible);
PROP_B(bool, use_min_marker);
PROP_B(bool, sweep_region_visible);
PROP_B(bool, visible_range_only);
PROP_B(Line_Interpolation_Mode, interpolation_mode);
PROP_B(Line_Sampling_Strategy, sampling_strategy);
PROP_B(Brush, max_brush);
PROP_B(Brush, current_brush);
PROP_B(Brush, min_brush);
PROP_B(Pen, max_pen);
PROP_B(Pen, cur_pen);
PROP_B(Pen, min_pen);
PROP_B(Pen, selected_marker_pen);
PROP_B(Pen, marker_pen);
PROP_B(Pen, middle_frequency_pen);
PROP_B(Brush, sweep_region_brush);
/// 创建频谱线构造器。
Builder(std::shared_ptr<Renderable> parent, std::shared_ptr<Frequency_Axis> frequency_axis, std::shared_ptr<Axis> axis);
/// 构建并返回频谱线对象。
std::shared_ptr<Spectrum> build();
std::shared_ptr<Renderable> parent{};
};
} // namespace renderive