#include "Frequency_Trace.h" #include "Plottable_Real_Time_Data.h" #include "Heatmap_Utils.h" #include "../render/Blend2D_Cache.h" #include "../renderable/Renderable_p.h" #include #include #include #include namespace renderive { namespace detail { namespace { using Frequency_Trace_History = Plottable_History_Real_Time_Data, std::deque>>; } struct Frequency_Trace_Control::Impl : Renderable::Impl { struct Prepare_Buffer { std::vector points; }; Impl(renderive_Owner time, renderive_Owner value) : time_axis(std::move(time)), value_axis(std::move(value)) {} renderive_Owner time_axis; renderive_Owner value_axis; std::optional samples; Prepare_Buffer prepare_buffer; }; Frequency_Trace_Control::Frequency_Trace_Control(const Frequency_Trace_Properties& properties, renderive_Owner time_axis, renderive_Owner value_axis) : Plottable_State(properties, std::make_unique( std::move(time_axis), std::move(value_axis))) { d_func().samples.emplace(*this); } Frequency_Trace_Control::~Frequency_Trace_Control() = default; void Frequency_Trace_Control::append_sample(int tick, double value) { auto& d = d_func(); const int limit = std::max(2, d.time_axis->get<&Time_Axis_Properties::visible_count>()); d.samples->update({tick, value}, static_cast(limit)); changed(); } void Frequency_Trace_Control::append_sample(Time_Of_Day time, double value) { append_sample(d_func().time_axis->append_time(time), value); } std::size_t Frequency_Trace_Control::sample_count() const { return d_func().samples->size(); } std::size_t Frequency_Trace_Control::rendered_point_count() const { const std::size_t count = sample_count(); return count >= 2 ? count : 0; } void Frequency_Trace_Control::publish() { publish_properties(); } void Frequency_Trace_Control::prepare_frame(const Prepare_Render_Context& context) { const auto& view = context.frame.render_state; const auto& state = render_properties(view); auto& d = d_func(); const auto& samples = view.get(*d.samples); auto& output = d.prepare_buffer; output = {}; if (samples.size() < 2) return; const Axis_Transform x = d.time_axis->transform(view); const Axis_Transform y = d.value_axis->transform(view); output.points.reserve(samples.size()); for (const auto& [tick, value] : samples) output.points.push_back(mapped_point(x, tick, y, value)); } void Frequency_Trace_Control::paint(Painter& painter, const Paint_Render_Context& context) { const auto& view = context.frame.render_state; painter.polyline(d_func().prepare_buffer.points, render_properties(view).pen); } } }