549 lines
23 KiB
C++
549 lines
23 KiB
C++
#pragma once
|
|
|
|
#include "../axis/Axis.h"
|
|
#include "Hover_Tooltip.h"
|
|
|
|
#include <chrono>
|
|
#include <deque>
|
|
#include <memory_resource>
|
|
#include <span>
|
|
#include <vector>
|
|
|
|
namespace renderive {
|
|
|
|
class LIB_DECL Spectrum final : public Renderable, public Event_Handler,
|
|
public Hover_Tooltip_Mixin<Spectrum> {
|
|
public:
|
|
Spectrum(Plot_Core& plot, std::shared_ptr<Frequency_Axis> frequency_axis,
|
|
std::shared_ptr<Axis> power_axis);
|
|
|
|
[[nodiscard]] std::shared_ptr<Frequency_Axis> frequency_axis() const;
|
|
void set_frequency_axis(std::shared_ptr<Frequency_Axis> value);
|
|
[[nodiscard]] std::shared_ptr<Axis> power_axis() const;
|
|
void set_power_axis(std::shared_ptr<Axis> value);
|
|
[[nodiscard]] int frequency_point_size() const;
|
|
void set_frequency_point_size(int value);
|
|
[[nodiscard]] Range frequency_range() const;
|
|
void set_frequency_range(Range value);
|
|
[[nodiscard]] double center_frequency() const;
|
|
void set_center_frequency(double value);
|
|
[[nodiscard]] Range sweep_frequency_range() const;
|
|
void set_sweep_frequency_range(Range value);
|
|
[[nodiscard]] bool max_hold_visible() const;
|
|
void set_max_hold_visible(bool value);
|
|
[[nodiscard]] bool min_hold_visible() const;
|
|
void set_min_hold_visible(bool value);
|
|
[[nodiscard]] bool max_marker_visible() const;
|
|
void set_max_marker_visible(bool value);
|
|
[[nodiscard]] bool use_min_marker() const;
|
|
void set_use_min_marker(bool value);
|
|
[[nodiscard]] bool sweep_region_visible() const;
|
|
void set_sweep_region_visible(bool value);
|
|
[[nodiscard]] bool visible_range_only() const;
|
|
void set_visible_range_only(bool value);
|
|
[[nodiscard]] Line_Interpolation_Mode interpolation_mode() const;
|
|
void set_interpolation_mode(Line_Interpolation_Mode value);
|
|
[[nodiscard]] Brush max_brush() const;
|
|
void set_max_brush(Brush value);
|
|
[[nodiscard]] Brush current_brush() const;
|
|
void set_current_brush(Brush value);
|
|
[[nodiscard]] Brush min_brush() const;
|
|
void set_min_brush(Brush value);
|
|
[[nodiscard]] Pen max_pen() const;
|
|
void set_max_pen(Pen value);
|
|
[[nodiscard]] Pen current_pen() const;
|
|
void set_current_pen(Pen value);
|
|
[[nodiscard]] Pen min_pen() const;
|
|
void set_min_pen(Pen value);
|
|
[[nodiscard]] Pen selected_marker_pen() const;
|
|
void set_selected_marker_pen(Pen value);
|
|
[[nodiscard]] Pen marker_pen() const;
|
|
void set_marker_pen(Pen value);
|
|
[[nodiscard]] Pen middle_frequency_pen() const;
|
|
void set_middle_frequency_pen(Pen value);
|
|
[[nodiscard]] Brush sweep_region_brush() const;
|
|
void set_sweep_region_brush(Brush value);
|
|
|
|
void update_samples(std::span<const double> values);
|
|
void update_samples(std::pmr::vector<double>&& values);
|
|
template <class Values> void update_samples(const Values& values) {
|
|
update_samples(std::span<const double>(values.data(), values.size()));
|
|
}
|
|
[[nodiscard]] std::size_t sample_count() const;
|
|
[[nodiscard]] std::size_t rendered_point_count() const;
|
|
[[nodiscard]] double power_at(double frequency, bool& ok) const;
|
|
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();
|
|
[[nodiscard]] int selectable_line_marker_count() const;
|
|
[[nodiscard]] int selected_marker_index() const;
|
|
void set_selected_marker_index(int index);
|
|
void select_next_marker();
|
|
void select_previous_marker();
|
|
void clear_marker_selection();
|
|
[[nodiscard]] double marker_frequency(int index) const;
|
|
void set_marker_frequency(int index, double frequency);
|
|
void set_current_marker_frequency(double frequency);
|
|
void handle_event(const Event& event) override;
|
|
void tooltip_changed() { changed(); }
|
|
|
|
class Builder {
|
|
public:
|
|
Builder(std::shared_ptr<Renderable> parent,
|
|
std::shared_ptr<Frequency_Axis> frequency_axis,
|
|
std::shared_ptr<Axis> power_axis);
|
|
Builder& set_frequency_range(Range value) { frequency_range_ = value; return *this; }
|
|
Builder& set_frequency_point_size(int value) { point_count_ = value; return *this; }
|
|
Builder& set_center_frequency(double value) { center_ = value; return *this; }
|
|
Builder& set_sweep_frequency_range(Range value) { sweep_range_ = value; return *this; }
|
|
Builder& set_max_hold_visible(bool value) { max_hold_ = value; return *this; }
|
|
Builder& set_min_hold_visible(bool value) { min_hold_ = value; return *this; }
|
|
Builder& set_max_marker_visible(bool value) { max_marker_ = value; return *this; }
|
|
Builder& set_use_min_marker(bool value) { min_marker_ = value; return *this; }
|
|
Builder& set_sweep_region_visible(bool value) { sweep_visible_ = value; return *this; }
|
|
Builder& set_visible_range_only(bool value) { visible_only_ = value; return *this; }
|
|
Builder& set_interpolation_mode(Line_Interpolation_Mode value) { interpolation_ = value; return *this; }
|
|
std::shared_ptr<Spectrum> build();
|
|
private:
|
|
std::shared_ptr<Renderable> parent_;
|
|
std::shared_ptr<Frequency_Axis> frequency_axis_;
|
|
std::shared_ptr<Axis> power_axis_;
|
|
Range frequency_range_{};
|
|
int point_count_{};
|
|
double center_ = 50.0;
|
|
Range sweep_range_{40.0, 60.0};
|
|
bool max_hold_{};
|
|
bool min_hold_{};
|
|
bool max_marker_{};
|
|
bool min_marker_{};
|
|
bool sweep_visible_{};
|
|
bool visible_only_{true};
|
|
Line_Interpolation_Mode interpolation_ = Line_Interpolation_Mode::Linear_Value;
|
|
};
|
|
|
|
protected:
|
|
void paint(detail::Painter& painter) override;
|
|
|
|
private:
|
|
struct State {
|
|
std::shared_ptr<Frequency_Axis> frequency_axis;
|
|
std::shared_ptr<Axis> power_axis;
|
|
int point_count{};
|
|
Range frequency_range{};
|
|
double center_frequency = 50.0;
|
|
Range sweep_range{40.0, 60.0};
|
|
bool max_hold{};
|
|
bool min_hold{};
|
|
bool max_marker{};
|
|
bool min_marker{};
|
|
bool sweep_visible{};
|
|
bool visible_only{true};
|
|
Line_Interpolation_Mode interpolation = Line_Interpolation_Mode::Linear_Value;
|
|
Brush max_brush;
|
|
Brush current_brush;
|
|
Brush min_brush;
|
|
Pen max_pen{Color::red()};
|
|
Pen current_pen{Color::green()};
|
|
Pen min_pen{Color::white()};
|
|
Pen selected_marker_pen{Color{0, 0, 139, 255}, 2.0};
|
|
Pen marker_pen{Color::red()};
|
|
Pen middle_pen{Color::red()};
|
|
Brush sweep_brush{Color{255, 255, 0, 100}, Brush_Style::Solid};
|
|
std::vector<double> samples;
|
|
std::vector<double> maxima;
|
|
std::vector<double> minima;
|
|
std::vector<double> markers;
|
|
int selected_marker = -1;
|
|
};
|
|
[[nodiscard]] State state_snapshot() const;
|
|
mutable std::mutex mutex_;
|
|
State state_;
|
|
};
|
|
|
|
class LIB_DECL Waterfall final : public Renderable, public Event_Handler,
|
|
public Hover_Tooltip_Mixin<Waterfall> {
|
|
public:
|
|
Waterfall(Plot_Core& plot, std::shared_ptr<Frequency_Axis> frequency_axis,
|
|
std::shared_ptr<Time_Axis> time_axis);
|
|
void append_row(int tick, std::span<const double> values);
|
|
void append_row(int tick, std::pmr::vector<double>&& values);
|
|
void append_row(Time_Of_Day time, std::span<const double> values);
|
|
void append_row(Time_Of_Day time, std::pmr::vector<double>&& values);
|
|
template <class Values> void append_row(Time_Of_Day time, const Values& values) {
|
|
append_row(time, std::span<const double>(values.data(), values.size()));
|
|
}
|
|
[[nodiscard]] std::shared_ptr<Frequency_Axis> frequency_axis() const;
|
|
[[nodiscard]] std::shared_ptr<Time_Axis> time_axis() const;
|
|
[[nodiscard]] Range frequency_range() const;
|
|
void set_frequency_range(Range value);
|
|
[[nodiscard]] Range power_range() const;
|
|
void set_power_range(Range value);
|
|
[[nodiscard]] int frequency_bin_count() const;
|
|
void set_frequency_bin_count(int value);
|
|
[[nodiscard]] std::size_t row_count() const;
|
|
[[nodiscard]] std::size_t stored_point_count() const;
|
|
[[nodiscard]] std::size_t rendered_cell_count() const;
|
|
[[nodiscard]] bool visible_range_only() const;
|
|
void set_visible_range_only(bool value);
|
|
[[nodiscard]] Image_Interpolation_Mode interpolation_mode() const;
|
|
void set_interpolation_mode(Image_Interpolation_Mode value);
|
|
void handle_event(const Event& event) override;
|
|
void tooltip_changed() { changed(); }
|
|
|
|
class Builder {
|
|
public:
|
|
Builder(std::shared_ptr<Renderable> parent,
|
|
std::shared_ptr<Frequency_Axis> frequency_axis,
|
|
std::shared_ptr<Time_Axis> time_axis);
|
|
Builder& set_frequency_range(Range value) { frequency_range_ = value; return *this; }
|
|
Builder& set_power_range(Range value) { power_range_ = value; return *this; }
|
|
Builder& set_frequency_bin_count(int value) { bin_count_ = value; return *this; }
|
|
Builder& set_visible_range_only(bool value) { visible_only_ = value; return *this; }
|
|
Builder& set_interpolation_mode(Image_Interpolation_Mode value) { interpolation_ = value; return *this; }
|
|
Builder& set_color_map(Color_Map value) { color_map_ = std::move(value); return *this; }
|
|
std::shared_ptr<Waterfall> build();
|
|
private:
|
|
std::shared_ptr<Renderable> parent_;
|
|
std::shared_ptr<Frequency_Axis> frequency_axis_;
|
|
std::shared_ptr<Time_Axis> time_axis_;
|
|
Range frequency_range_{0.0, 10.0};
|
|
Range power_range_{0.0, 10.0};
|
|
int bin_count_{};
|
|
bool visible_only_{true};
|
|
Image_Interpolation_Mode interpolation_ = Image_Interpolation_Mode::Nearest;
|
|
Color_Map color_map_;
|
|
};
|
|
|
|
protected:
|
|
void paint(detail::Painter& painter) override;
|
|
|
|
private:
|
|
struct Row { int tick{}; std::vector<double> values; };
|
|
struct State {
|
|
std::shared_ptr<Frequency_Axis> frequency_axis;
|
|
std::shared_ptr<Time_Axis> time_axis;
|
|
Range frequency_range{0.0, 10.0};
|
|
Range power_range{0.0, 10.0};
|
|
int bin_count{};
|
|
bool visible_only{true};
|
|
Image_Interpolation_Mode interpolation = Image_Interpolation_Mode::Nearest;
|
|
Color_Map color_map;
|
|
std::deque<Row> rows;
|
|
};
|
|
[[nodiscard]] State state_snapshot() const;
|
|
mutable std::mutex mutex_;
|
|
State state_;
|
|
};
|
|
|
|
class LIB_DECL Frequency_Trace final : public Renderable {
|
|
public:
|
|
Frequency_Trace(Plot_Core& plot, std::shared_ptr<Time_Axis> time_axis,
|
|
std::shared_ptr<Axis> value_axis);
|
|
void append_sample(int tick, double value);
|
|
void append_sample(Time_Of_Day time, double value);
|
|
[[nodiscard]] std::shared_ptr<Time_Axis> time_axis() const;
|
|
[[nodiscard]] std::shared_ptr<Axis> value_axis() const;
|
|
[[nodiscard]] std::size_t sample_count() const;
|
|
[[nodiscard]] std::size_t rendered_point_count() const;
|
|
|
|
class Builder {
|
|
public:
|
|
Builder(std::shared_ptr<Renderable> parent, std::shared_ptr<Time_Axis> time_axis,
|
|
std::shared_ptr<Axis> value_axis);
|
|
Builder& set_color(Color value) { pen_.color = value; return *this; }
|
|
Builder& set_pen(Pen value) { pen_ = value; return *this; }
|
|
std::shared_ptr<Frequency_Trace> build();
|
|
private:
|
|
std::shared_ptr<Renderable> parent_;
|
|
std::shared_ptr<Time_Axis> time_axis_;
|
|
std::shared_ptr<Axis> value_axis_;
|
|
Pen pen_{Color::yellow()};
|
|
};
|
|
|
|
protected:
|
|
void paint(detail::Painter& painter) override;
|
|
|
|
private:
|
|
mutable std::mutex mutex_;
|
|
std::shared_ptr<Time_Axis> time_axis_;
|
|
std::shared_ptr<Axis> value_axis_;
|
|
Pen pen_{Color::yellow()};
|
|
std::deque<std::pair<int, double>> samples_;
|
|
};
|
|
|
|
class LIB_DECL Afterglow final : public Renderable {
|
|
public:
|
|
Afterglow(Plot_Core& plot, std::shared_ptr<Frequency_Axis> frequency_axis,
|
|
std::shared_ptr<Axis> power_axis);
|
|
[[nodiscard]] std::shared_ptr<Frequency_Axis> frequency_axis() const;
|
|
[[nodiscard]] std::shared_ptr<Axis> power_axis() const;
|
|
[[nodiscard]] Range frequency_range() const;
|
|
void set_frequency_range(Range value);
|
|
[[nodiscard]] Range power_range() const;
|
|
void set_power_range(Range value);
|
|
[[nodiscard]] int frequency_point_size() const;
|
|
void set_frequency_point_size(int value);
|
|
[[nodiscard]] int power_point_size() const;
|
|
void set_power_point_size(int value);
|
|
[[nodiscard]] bool interpolate() const;
|
|
void set_interpolate(bool value);
|
|
[[nodiscard]] double attenuation_rate() const;
|
|
void set_attenuation_rate(double value);
|
|
[[nodiscard]] std::size_t history_count() const;
|
|
[[nodiscard]] std::size_t latest_spectrum_point_count() const;
|
|
[[nodiscard]] std::size_t rendered_cell_count() const;
|
|
void append_spectrum(std::span<const double> values);
|
|
void append_spectrum(std::pmr::vector<double>&& values);
|
|
template <class Values> void append_spectrum(const Values& values) {
|
|
append_spectrum(std::span<const double>(values.data(), values.size()));
|
|
}
|
|
|
|
class Builder {
|
|
public:
|
|
Builder(std::shared_ptr<Renderable> parent,
|
|
std::shared_ptr<Frequency_Axis> frequency_axis,
|
|
std::shared_ptr<Axis> power_axis);
|
|
Builder& set_frequency_range(Range value) { frequency_range_ = value; return *this; }
|
|
Builder& set_power_range(Range value) { power_range_ = value; return *this; }
|
|
Builder& set_frequency_bin_count(int value) { frequency_count_ = value; return *this; }
|
|
Builder& set_power_bin_count(int value) { power_count_ = value; return *this; }
|
|
Builder& set_interpolate_power_bins(bool value) { interpolate_ = value; return *this; }
|
|
Builder& set_decay_rate(double value) { attenuation_ = value; return *this; }
|
|
Builder& set_color_map(Color_Map value) { color_map_ = std::move(value); return *this; }
|
|
std::shared_ptr<Afterglow> build();
|
|
private:
|
|
std::shared_ptr<Renderable> parent_;
|
|
std::shared_ptr<Frequency_Axis> frequency_axis_;
|
|
std::shared_ptr<Axis> power_axis_;
|
|
Range frequency_range_{0.0, 10.0};
|
|
Range power_range_{0.0, 10.0};
|
|
int frequency_count_{};
|
|
int power_count_{};
|
|
bool interpolate_{true};
|
|
double attenuation_ = 0.2;
|
|
Color_Map color_map_;
|
|
};
|
|
|
|
protected:
|
|
void paint(detail::Painter& painter) override;
|
|
|
|
private:
|
|
struct State {
|
|
std::shared_ptr<Frequency_Axis> frequency_axis;
|
|
std::shared_ptr<Axis> power_axis;
|
|
Range frequency_range{0.0, 10.0};
|
|
Range power_range{0.0, 10.0};
|
|
int frequency_count{};
|
|
int power_count{};
|
|
bool interpolate{true};
|
|
double attenuation = 0.2;
|
|
Color_Map color_map;
|
|
std::deque<std::vector<double>> history;
|
|
};
|
|
[[nodiscard]] State state_snapshot() const;
|
|
mutable std::mutex mutex_;
|
|
State state_;
|
|
};
|
|
|
|
class LIB_DECL Sweep_Spectrum final : public Renderable {
|
|
public:
|
|
Sweep_Spectrum(Plot_Core& plot, std::shared_ptr<Axis> frequency_axis,
|
|
std::shared_ptr<Axis> power_axis);
|
|
void append_block(std::span<const double> values);
|
|
void append_block(std::pmr::vector<double>&& values);
|
|
template <class Values> void append_block(const Values& values) {
|
|
append_block(std::span<const double>(values.data(), values.size()));
|
|
}
|
|
[[nodiscard]] std::shared_ptr<Axis> frequency_axis() const;
|
|
[[nodiscard]] std::shared_ptr<Axis> power_axis() const;
|
|
[[nodiscard]] Range frequency_range() const;
|
|
void set_frequency_range(Range value);
|
|
[[nodiscard]] int bins_per_block() const;
|
|
void set_bins_per_block(int value);
|
|
[[nodiscard]] int block_count() const;
|
|
void set_block_count(int value);
|
|
[[nodiscard]] std::size_t stored_block_count() const;
|
|
[[nodiscard]] std::size_t stored_point_count() const;
|
|
[[nodiscard]] std::size_t rendered_point_count() const;
|
|
[[nodiscard]] Pen pen() const;
|
|
void set_pen(Pen value);
|
|
[[nodiscard]] Pen cur_frequency_pen() const;
|
|
void set_cur_frequency_pen(Pen value);
|
|
[[nodiscard]] bool visible_range_only() const;
|
|
void set_visible_range_only(bool value);
|
|
[[nodiscard]] Line_Interpolation_Mode interpolation_mode() const;
|
|
void set_interpolation_mode(Line_Interpolation_Mode value);
|
|
|
|
class Builder {
|
|
public:
|
|
Builder(std::shared_ptr<Renderable> parent, std::shared_ptr<Axis> frequency_axis,
|
|
std::shared_ptr<Axis> power_axis);
|
|
Builder& set_frequency_range(Range value) { frequency_range_ = value; return *this; }
|
|
Builder& set_bins_per_block(int value) { bins_ = value; return *this; }
|
|
Builder& set_block_num(int value) { blocks_ = value; return *this; }
|
|
Builder& set_pen(Pen value) { pen_ = value; return *this; }
|
|
Builder& set_current_frequency_pen(Pen value) { current_pen_ = value; return *this; }
|
|
Builder& set_visible_range_only(bool value) { visible_only_ = value; return *this; }
|
|
Builder& set_interpolation_mode(Line_Interpolation_Mode value) { interpolation_ = value; return *this; }
|
|
std::shared_ptr<Sweep_Spectrum> build();
|
|
private:
|
|
std::shared_ptr<Renderable> parent_;
|
|
std::shared_ptr<Axis> frequency_axis_;
|
|
std::shared_ptr<Axis> power_axis_;
|
|
Range frequency_range_{};
|
|
int bins_{};
|
|
int blocks_{};
|
|
Pen pen_{Color::yellow()};
|
|
Pen current_pen_{Color::red(), 2.0};
|
|
bool visible_only_{true};
|
|
Line_Interpolation_Mode interpolation_ = Line_Interpolation_Mode::Linear_Value;
|
|
};
|
|
|
|
protected:
|
|
void paint(detail::Painter& painter) override;
|
|
|
|
private:
|
|
struct State {
|
|
std::shared_ptr<Axis> frequency_axis;
|
|
std::shared_ptr<Axis> power_axis;
|
|
Range frequency_range{};
|
|
int bins{};
|
|
int blocks{};
|
|
Pen pen{Color::yellow()};
|
|
Pen current_pen{Color::red(), 2.0};
|
|
bool visible_only{true};
|
|
Line_Interpolation_Mode interpolation = Line_Interpolation_Mode::Linear_Value;
|
|
std::deque<std::vector<double>> data;
|
|
};
|
|
[[nodiscard]] State state_snapshot() const;
|
|
mutable std::mutex mutex_;
|
|
State state_;
|
|
};
|
|
|
|
class LIB_DECL Selection_Rectangle_Overlay final : public Renderable, public Event_Handler {
|
|
public:
|
|
Selection_Rectangle_Overlay(Plot_Core& plot, std::shared_ptr<Abs_Axis> horizontal_axis,
|
|
std::shared_ptr<Abs_Axis> vertical_axis);
|
|
void set_horizontal_axis(std::shared_ptr<Abs_Axis> axis);
|
|
void set_vertical_axis(std::shared_ptr<Abs_Axis> axis);
|
|
[[nodiscard]] Font label_font() const;
|
|
[[nodiscard]] Pen label_pen() const;
|
|
[[nodiscard]] Brush selection_brush() const;
|
|
[[nodiscard]] Pen selection_border_pen() const;
|
|
void set_label_font(Font value);
|
|
void set_label_pen(Pen value);
|
|
void set_selection_brush(Brush value);
|
|
void set_selection_border_pen(Pen value);
|
|
[[nodiscard]] std::vector<RectF> selected_regions() const;
|
|
void clear_selected_regions();
|
|
void handle_event(const Event& event) override;
|
|
|
|
class Builder {
|
|
public:
|
|
Builder(std::shared_ptr<Renderable> parent, std::shared_ptr<Abs_Axis> horizontal_axis,
|
|
std::shared_ptr<Abs_Axis> vertical_axis);
|
|
Builder& set_font(Font value) { font_ = value; return *this; }
|
|
Builder& set_font_pen(Pen value) { label_pen_ = value; return *this; }
|
|
Builder& set_rect_brush(Brush value) { brush_ = value; return *this; }
|
|
Builder& set_border_pen(Pen value) { border_ = value; return *this; }
|
|
std::shared_ptr<Selection_Rectangle_Overlay> build();
|
|
private:
|
|
std::shared_ptr<Renderable> parent_;
|
|
std::shared_ptr<Abs_Axis> horizontal_axis_;
|
|
std::shared_ptr<Abs_Axis> vertical_axis_;
|
|
Font font_;
|
|
Pen label_pen_{Color::white()};
|
|
Brush brush_{Color{0, 0, 255, 50}, Brush_Style::Solid};
|
|
Pen border_{Color::white(), 1.0, Line_Style::Dash};
|
|
};
|
|
|
|
protected:
|
|
void paint(detail::Painter& painter) override;
|
|
|
|
private:
|
|
mutable std::mutex mutex_;
|
|
std::shared_ptr<Abs_Axis> horizontal_axis_;
|
|
std::shared_ptr<Abs_Axis> vertical_axis_;
|
|
Font font_;
|
|
Pen label_pen_{Color::white()};
|
|
Brush brush_{Color{0, 0, 255, 50}, Brush_Style::Solid};
|
|
Pen border_{Color::white(), 1.0, Line_Style::Dash};
|
|
std::vector<RectF> regions_;
|
|
bool selecting_{};
|
|
PointF selection_start_{};
|
|
PointF selection_current_{};
|
|
};
|
|
|
|
enum class Constellation_Diagram_Type : std::uint8_t { Psk4 = 4, Psk8 = 8, Psk16 = 16 };
|
|
|
|
class LIB_DECL Constellation_Diagram final : public Renderable {
|
|
public:
|
|
Constellation_Diagram(Plot_Core& plot, std::shared_ptr<Axis> i_axis,
|
|
std::shared_ptr<Axis> q_axis);
|
|
void append_point(PointF point);
|
|
[[nodiscard]] std::shared_ptr<Axis> i_axis() const;
|
|
[[nodiscard]] std::shared_ptr<Axis> q_axis() const;
|
|
[[nodiscard]] Range i_range() const;
|
|
void set_i_range(Range value);
|
|
[[nodiscard]] Range q_range() const;
|
|
void set_q_range(Range value);
|
|
[[nodiscard]] Color point_color() const;
|
|
void set_point_color(Color value);
|
|
[[nodiscard]] Color anchor_color() const;
|
|
void set_anchor_color(Color value);
|
|
[[nodiscard]] int point_lifetime_ms() const;
|
|
void set_point_lifetime_ms(int value);
|
|
[[nodiscard]] std::size_t point_count() const;
|
|
void fit_square_to_axes();
|
|
|
|
class Builder {
|
|
public:
|
|
Builder(std::shared_ptr<Renderable> parent, std::shared_ptr<Axis> i_axis,
|
|
std::shared_ptr<Axis> q_axis);
|
|
Builder& set_i_range(Range value) { i_range_ = value; return *this; }
|
|
Builder& set_q_range(Range value) { q_range_ = value; return *this; }
|
|
Builder& set_point_color(Color value) { point_color_ = value; return *this; }
|
|
Builder& set_anchor_color(Color value) { anchor_color_ = value; return *this; }
|
|
Builder& set_point_lifetime_ms(int value) { lifetime_ = value; return *this; }
|
|
Builder& set_type(Constellation_Diagram_Type value) { type_ = value; return *this; }
|
|
Builder& set_phase_offset_radians(double value) { phase_ = value; return *this; }
|
|
std::shared_ptr<Constellation_Diagram> build();
|
|
private:
|
|
std::shared_ptr<Renderable> parent_;
|
|
std::shared_ptr<Axis> i_axis_;
|
|
std::shared_ptr<Axis> q_axis_;
|
|
Range i_range_{0.0, 100.0};
|
|
Range q_range_{0.0, 100.0};
|
|
Color point_color_ = Color::red();
|
|
Color anchor_color_ = Color::yellow();
|
|
int lifetime_ = 1000;
|
|
Constellation_Diagram_Type type_ = Constellation_Diagram_Type::Psk8;
|
|
double phase_{};
|
|
};
|
|
|
|
protected:
|
|
void paint(detail::Painter& painter) override;
|
|
|
|
private:
|
|
struct Timed_Point { PointF point; std::chrono::steady_clock::time_point time; };
|
|
struct State {
|
|
std::shared_ptr<Axis> i_axis;
|
|
std::shared_ptr<Axis> q_axis;
|
|
Range i_range{0.0, 100.0};
|
|
Range q_range{0.0, 100.0};
|
|
Color point_color = Color::red();
|
|
Color anchor_color = Color::yellow();
|
|
int lifetime_ms = 1000;
|
|
Constellation_Diagram_Type type = Constellation_Diagram_Type::Psk8;
|
|
double phase{};
|
|
std::deque<Timed_Point> points;
|
|
};
|
|
[[nodiscard]] State state_snapshot() const;
|
|
mutable std::mutex mutex_;
|
|
State state_;
|
|
};
|
|
|
|
} // namespace renderive
|