#include #include "../base/Memory.h" #include "Waterfall_p.h" namespace renderive { RENDERIVE_DEFINE_RENDERABLE_BINDING(Waterfall, Waterfall_Private, Waterfall_Render_State, Waterfall_Input_Data, "Waterfall") std::shared_ptr Waterfall::frequency_axis() { return d()->edit_state_value(&Waterfall_Render_State::frequency_axis).lock(); } void Waterfall::set_frequency_axis(std::shared_ptr value) { d()->set_state_value(&Waterfall_Render_State::frequency_axis, std::weak_ptr(value)); } std::shared_ptr Waterfall::time_axis() { return d()->edit_state_value(&Waterfall_Render_State::time_axis).lock(); } void Waterfall::set_time_axis(std::shared_ptr value) { d()->set_state_value(&Waterfall_Render_State::time_axis, std::weak_ptr(value)); } Range Waterfall::frequency_range() { return d()->edit_state_value(&Waterfall_Render_State::frequency_range); } void Waterfall::set_frequency_range(Range value) { if (value.length() == 0.0) return; d()->set_state_value(&Waterfall_Render_State::frequency_range, std::move(value)); } Range Waterfall::power_range() { return d()->edit_state_value(&Waterfall_Render_State::color_scale).range(); } void Waterfall::set_power_range(Range value) { if (value.size() == 0.0) return; Render_Edit_Lease edit(d()); edit->color_scale.set_range(value); } int Waterfall::frequency_bin_count() { return d()->edit_state_value(&Waterfall_Render_State::frequency_bin_count); } void Waterfall::set_frequency_bin_count(int value) { d()->set_state_value(&Waterfall_Render_State::frequency_bin_count, std::max(1, value)); } bool Waterfall::visible_range_only() { return d()->edit_state_value(&Waterfall_Render_State::visible_range_only); } void Waterfall::set_visible_range_only(bool value) { d()->set_state_value(&Waterfall_Render_State::visible_range_only, value); } Image_Interpolation_Mode Waterfall::interpolation_mode() { return d()->edit_state_value(&Waterfall_Render_State::interpolation_mode); } void Waterfall::set_interpolation_mode(Image_Interpolation_Mode value) { d()->set_state_value(&Waterfall_Render_State::interpolation_mode, value); } Waterfall_Row_Update_Policy Waterfall::row_update_policy() { return d()->edit_state_value(&Waterfall_Render_State::row_update_policy); } void Waterfall::set_row_update_policy(Waterfall_Row_Update_Policy value) { d()->set_state_value(&Waterfall_Render_State::row_update_policy, value); } int Waterfall::latest_row_min_interval_ms() { return d()->edit_state_value(&Waterfall_Render_State::latest_row_min_interval_ms); } void Waterfall::set_latest_row_min_interval_ms(int value) { d()->set_state_value(&Waterfall_Render_State::latest_row_min_interval_ms, std::max(1, value)); } Color_Map Waterfall::color_map() { return d()->edit_state_value(&Waterfall_Render_State::color_scale).color_map(); } void Waterfall::set_color_map(Color_Map value) { Render_Edit_Lease edit(d()); edit->color_scale.set_color_map(std::move(value)); } std::shared_ptr Waterfall::get_color_bar() const { return const_cast(this)->d()->color_bar.lock(); } void Waterfall::append_row(int tick, std::span data) { if (!ok()) return; d()->enqueue_row(tick, data); } void Waterfall::append_row(int tick, std::pmr::vector&& data) { if (!ok()) return; d()->enqueue_row(tick, std::move(data)); } void Waterfall::append_row(Time_Of_Day time, std::span data) { if (!ok()) return; auto axis = time_axis(); if (!axis) return; auto stream = axis->timeline_stream(); if (!stream) return; int tick = stream->append_time(time); d()->enqueue_row(tick, data); } void Waterfall::append_row(Time_Of_Day time, std::pmr::vector&& data) { if (!ok()) return; auto axis = time_axis(); if (!axis) return; auto stream = axis->timeline_stream(); if (!stream) return; int tick = stream->append_time(time); d()->enqueue_row(tick, std::move(data)); } Update_Ticket Waterfall::submit_data(int tick, std::span data) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); return Update_Ticket(state); } d()->enqueue_row(tick, data, state); return Update_Ticket(state); } Update_Ticket Waterfall::submit_data(int tick, std::pmr::vector&& data) { auto state = make_update_state(); if (!ok()) { state->complete_all(std::make_error_code(std::errc::operation_canceled), Update_Outcome::Cancelled); return Update_Ticket(state); } d()->enqueue_row(tick, std::move(data), state); return Update_Ticket(state); } Waterfall::Builder::Builder(std::shared_ptr parent, std::shared_ptr frequency_axis, std::shared_ptr time_axis) { ASSERT(parent && parent->attached_to_plot(), "Waterfall build error! parent invalid"); ASSERT(frequency_axis && time_axis, "Waterfall build error! axis == nullptr"); ASSERT(frequency_axis->attached_to_plot(), "Waterfall build error! frequency_axis->plot == nullptr"); ASSERT(frequency_axis->shares_plot_with(*time_axis), "Waterfall build error! frequency_axis->plot != time_axis->plot"); ASSERT(parent->shares_plot_with(*frequency_axis), "Waterfall build error! parent->plot != frequency_axis->plot"); ASSERT(frequency_axis->orientation() != time_axis->orientation(), "Waterfall build error! axes must be orthogonal"); this->parent = parent; this->frequency_axis = frequency_axis; this->time_axis = time_axis; } std::shared_ptr Waterfall::Builder::build() { auto ret = renderive::make_shared(); ret->init(parent); Waterfall_Private* pd = ret->d(); Render_Edit_Lease edit(pd); Waterfall_Render_State* sc = edit.operator->(); PROP_R(std::weak_ptr, frequency_axis) PROP_R(std::weak_ptr, time_axis) PROP_R(Range, frequency_range) PROP_R(int, frequency_bin_count) PROP_R(bool, visible_range_only) PROP_R(Image_Interpolation_Mode, interpolation_mode) PROP_R(Waterfall_Row_Update_Policy, row_update_policy) PROP_R(int, latest_row_min_interval_ms) sc->color_scale = color_scale.clone(); sc->frequency_bin_count = std::max(1, sc->frequency_bin_count); sc->latest_row_min_interval_ms = std::max(1, sc->latest_row_min_interval_ms); if (color_bar_enabled) { auto bar = Color_Bar::Builder(ret).set_color_scale(sc->color_scale).set_name("Waterfall").build(); pd->color_bar = bar; } return ret; } } // namespace renderive