修复展示数据
This commit is contained in:
@@ -31,7 +31,12 @@ public:
|
||||
void update(Value value, std::size_t retain_latest_count);
|
||||
void clear();
|
||||
std::size_t retain_latest(std::size_t count);
|
||||
struct Snapshot {
|
||||
Container values;
|
||||
Real_Time_Data_Update_State update_state;
|
||||
};
|
||||
Container snapshot() const;
|
||||
Snapshot snapshot_with_update_state() const;
|
||||
std::size_t size() const;
|
||||
std::uint64_t revision() const;
|
||||
Real_Time_Data_Retention retention() const noexcept override;
|
||||
@@ -49,6 +54,7 @@ private:
|
||||
void reserve_update_times(std::size_t capacity);
|
||||
void publish_render_state() override;
|
||||
const Container& render_state_value() const noexcept;
|
||||
const Real_Time_Data_Update_State& render_update_state_value() const noexcept;
|
||||
mutable Mutex mutex_;
|
||||
std::recursive_mutex mutation_mutex_;
|
||||
Observer observer_;
|
||||
@@ -61,7 +67,7 @@ private:
|
||||
std::size_t update_times_size_{};
|
||||
std::size_t update_times_capacity_{};
|
||||
std::uint64_t revision_{};
|
||||
std::uint64_t render_revision_{};
|
||||
Real_Time_Data_Update_State render_update_state_{};
|
||||
std::uint64_t total_update_count_{};
|
||||
std::uint64_t last_update_time_ns_{};
|
||||
};
|
||||
|
||||
@@ -101,6 +101,15 @@ auto History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::snapshot()
|
||||
return *cache_state_;
|
||||
}
|
||||
template <class Value_Type, class Container, Mutex_Type Mutex, class Observer>
|
||||
auto History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::snapshot_with_update_state() const -> Snapshot {
|
||||
std::lock_guard < Mutex > lock(mutex_);
|
||||
const Real_Time_Data_Update_State update_state{
|
||||
this, Real_Time_Data_Retention::history, revision_, last_update_time_ns_,
|
||||
total_update_count_, cache_state_->size()
|
||||
};
|
||||
return {*cache_state_, update_state};
|
||||
}
|
||||
template <class Value_Type, class Container, Mutex_Type Mutex, class Observer>
|
||||
std::size_t History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::size() const {
|
||||
std::lock_guard < Mutex > lock(mutex_);
|
||||
return cache_state_->size();
|
||||
@@ -144,12 +153,20 @@ std::size_t History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::disc
|
||||
template <class Value_Type, class Container, Mutex_Type Mutex, class Observer>
|
||||
void History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::publish_render_state() {
|
||||
std::lock_guard < Mutex > lock(mutex_);
|
||||
if (render_revision_ == revision_) return;
|
||||
if (render_update_state_.revision == revision_) return;
|
||||
*scratch_state_ = *cache_state_;
|
||||
std::swap(render_state_, scratch_state_);
|
||||
render_revision_ = revision_;
|
||||
render_update_state_ = {
|
||||
this, Real_Time_Data_Retention::history, revision_, last_update_time_ns_,
|
||||
total_update_count_, render_state_->size()
|
||||
};
|
||||
}
|
||||
template <class Value_Type, class Container, Mutex_Type Mutex, class Observer>
|
||||
auto History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::render_state_value() const noexcept -> const Container& {
|
||||
return *render_state_;
|
||||
}
|
||||
template <class Value_Type, class Container, Mutex_Type Mutex, class Observer>
|
||||
auto History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::render_update_state_value() const noexcept
|
||||
-> const Real_Time_Data_Update_State& {
|
||||
return render_update_state_;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ public:
|
||||
[[nodiscard]] const auto& get(const Source& source) const noexcept {
|
||||
return source.render_state_value();
|
||||
}
|
||||
template <class Source>
|
||||
[[nodiscard]] const auto& update_state(const Source& source) const noexcept {
|
||||
return source.render_update_state_value();
|
||||
}
|
||||
private:
|
||||
friend class Renderable_Base;
|
||||
friend class Frame_Render_Snapshot;
|
||||
|
||||
@@ -3,18 +3,37 @@
|
||||
#include "Plottable_Real_Time_Data.h"
|
||||
#include "../render/Blend2D_Cache.h"
|
||||
#include "../renderable/Renderable_p.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
namespace renderive::detail {
|
||||
namespace {
|
||||
using Sweep_Spectrum_History = Plottable_History_Real_Time_Data<std::vector<double>, std::deque<std::vector<double>>>;
|
||||
std::vector<double> flatten(const std::deque<std::vector<double>>& blocks) {
|
||||
std::size_t current_sweep_block_count(std::uint64_t total_update_count,
|
||||
std::size_t block_count) {
|
||||
if (total_update_count == 0) return 0;
|
||||
return static_cast<std::size_t>((total_update_count - 1) % block_count) + 1;
|
||||
}
|
||||
std::vector<double> flatten_latest(const std::deque<std::vector<double>>& blocks,
|
||||
std::size_t block_count) {
|
||||
std::vector<double> values;
|
||||
for (const auto& block : blocks) values.insert(values.end(), block.begin(), block.end());
|
||||
const std::size_t first = blocks.size() - block_count;
|
||||
std::size_t value_count{};
|
||||
for (std::size_t index = first; index < blocks.size(); ++index) {
|
||||
value_count += blocks[index].size();
|
||||
}
|
||||
values.reserve(value_count);
|
||||
for (std::size_t index = first; index < blocks.size(); ++index) {
|
||||
values.insert(values.end(), blocks[index].begin(), blocks[index].end());
|
||||
}
|
||||
return values;
|
||||
}
|
||||
Range completed_frequency_range(Range frequency_range,
|
||||
std::size_t completed_block_count,
|
||||
std::size_t block_count) {
|
||||
const double completed = static_cast<double>(completed_block_count) / static_cast<double>(block_count);
|
||||
return {frequency_range.origin, frequency_range.origin + frequency_range.length() * completed};
|
||||
}
|
||||
}
|
||||
struct Sweep_Spectrum::Impl
|
||||
: Base::next_Impl<Impl> {
|
||||
@@ -71,8 +90,17 @@ std::size_t Sweep_Spectrum::stored_point_count() const {
|
||||
}
|
||||
std::size_t Sweep_Spectrum::rendered_point_count() const {
|
||||
const auto state = Renderable::state<State>();
|
||||
const auto values = flatten(d_func<Impl>().blocks->snapshot());
|
||||
return curve_points(values, state.frequency_range, d_func<Impl>().frequency_axis->transform(), d_func<Impl>().power_axis->transform(), state.visible_range_only, state.interpolation_mode).size();
|
||||
const auto snapshot = d_func<Impl>().blocks->snapshot_with_update_state();
|
||||
const std::size_t block_count = static_cast<std::size_t>(state.block_count.get());
|
||||
const std::size_t completed_block_count =
|
||||
current_sweep_block_count(snapshot.update_state.total_update_count, block_count);
|
||||
const auto values = flatten_latest(snapshot.values, completed_block_count);
|
||||
const Range frequency_range = completed_frequency_range(
|
||||
state.frequency_range, completed_block_count, block_count);
|
||||
return curve_points(values, frequency_range,
|
||||
d_func<Impl>().frequency_axis->transform(),
|
||||
d_func<Impl>().power_axis->transform(),
|
||||
state.visible_range_only, state.interpolation_mode).size();
|
||||
}
|
||||
Sweep_Spectrum::Observer Sweep_Spectrum::capture_observation() const {
|
||||
const auto value = Renderable::published_state<State>();
|
||||
@@ -88,16 +116,21 @@ void Sweep_Spectrum::Impl::prepare_frame(const Prepare_Render_Context& context)
|
||||
const auto& view = context.frame.render_state;
|
||||
const auto& state = control.render_state<State>(view);
|
||||
const auto& published_blocks = view.get(*blocks);
|
||||
const auto values = flatten(published_blocks);
|
||||
const auto& published_update_state = view.update_state(*blocks);
|
||||
const std::size_t block_count = static_cast<std::size_t>(state.block_count.get());
|
||||
const std::size_t completed_block_count = current_sweep_block_count(
|
||||
published_update_state.total_update_count, block_count);
|
||||
const auto values = flatten_latest(published_blocks, completed_block_count);
|
||||
auto& output = prepare_buffer;
|
||||
output = {};
|
||||
if (values.size() < 2) return;
|
||||
const Axis_Transform x = frequency_axis->transform(view);
|
||||
const Axis_Transform y = power_axis->transform(view);
|
||||
output.points = curve_points(values, state.frequency_range, x, y,
|
||||
const Range frequency_range = completed_frequency_range(
|
||||
state.frequency_range, completed_block_count, block_count);
|
||||
output.points = curve_points(values, frequency_range, x, y,
|
||||
state.visible_range_only, state.interpolation_mode);
|
||||
const double completed = std::min(1.0, static_cast<double>(published_blocks.size()) / state.block_count.get());
|
||||
const double frequency = state.frequency_range.origin + state.frequency_range.length() * completed;
|
||||
const double frequency = frequency_range.target;
|
||||
output.current_first = mapped_point(x, frequency, y, y.coordinate_range.origin);
|
||||
output.current_second = mapped_point(x, frequency, y, y.coordinate_range.target);
|
||||
output.valid = true;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <numbers>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -35,6 +36,8 @@ struct Observer_Pfr_Adapter<Render_Scene_2D::Observer> {
|
||||
Render_Scene_2D::Observer, Render_Scene_2D::Observer_Fields>;
|
||||
};
|
||||
namespace {
|
||||
constexpr std::size_t sweep_bins_per_block = 64;
|
||||
constexpr std::size_t sweep_block_count = 8;
|
||||
std::shared_ptr<Frame_Control_Strategy_Base> make_strategy(
|
||||
Gallery_Frame_Mode mode) {
|
||||
switch (mode) {
|
||||
@@ -349,8 +352,8 @@ private:
|
||||
} else if (case_id_ == "sweep_spectrum") {
|
||||
Sweep_Spectrum::State state;
|
||||
state.frequency_range = {0.0, 300.0};
|
||||
state.bins_per_block = 64;
|
||||
state.block_count = 8;
|
||||
state.bins_per_block = static_cast<int>(sweep_bins_per_block);
|
||||
state.block_count = static_cast<int>(sweep_block_count);
|
||||
Sweep_Spectrum::Builder builder{state, &attach};
|
||||
sweep_ = build<Sweep_Spectrum>(
|
||||
builder, root, domain_axis_, value_axis_);
|
||||
@@ -382,9 +385,16 @@ private:
|
||||
}
|
||||
|
||||
void update_samples() {
|
||||
const std::size_t count = waterfall_ ? 256U : afterglow_ ? 192U : 512U;
|
||||
const std::size_t count =
|
||||
waterfall_ ? 256U :
|
||||
afterglow_ ? 192U :
|
||||
sweep_ ? sweep_bins_per_block * sweep_block_count : 512U;
|
||||
std::vector<double> values(count);
|
||||
const double time = static_cast<double>(sample_sequence_++) * 0.075;
|
||||
const std::uint64_t sample_sequence = sample_sequence_++;
|
||||
const std::uint64_t time_sequence = sweep_
|
||||
? sample_sequence / sweep_block_count * sweep_block_count
|
||||
: sample_sequence;
|
||||
const double time = static_cast<double>(time_sequence) * 0.075;
|
||||
for (std::size_t index = 0; index < count; ++index) {
|
||||
const double x = static_cast<double>(index) / (count - 1);
|
||||
const auto gaussian = [](double value, double center, double width) {
|
||||
@@ -402,15 +412,26 @@ private:
|
||||
if (waterfall_) waterfall_->append_row(current_time_of_day(), values);
|
||||
if (afterglow_) afterglow_->append_spectrum(values);
|
||||
if (sweep_) {
|
||||
values.resize(64);
|
||||
sweep_->append_block(values);
|
||||
const std::size_t block_index = static_cast<std::size_t>(
|
||||
sample_sequence % sweep_block_count);
|
||||
const std::size_t first = block_index * sweep_bins_per_block;
|
||||
sweep_->append_block(std::span<const double>(
|
||||
values.data() + first, sweep_bins_per_block));
|
||||
}
|
||||
if (trace_) trace_->append_sample(current_time_of_day(), std::sin(time));
|
||||
if (constellation_) {
|
||||
const double phase = time * 1.7;
|
||||
constexpr std::size_t symbol_count =
|
||||
static_cast<std::size_t>(Constellation_Diagram_Type::Psk8);
|
||||
const std::size_t symbol_index = sample_sequence % symbol_count;
|
||||
const double phase = 2.0 * std::numbers::pi *
|
||||
static_cast<double>(symbol_index) /
|
||||
static_cast<double>(symbol_count);
|
||||
const double i_noise =
|
||||
std::sin(time * 17.0 + static_cast<double>(symbol_index) * 0.73) * 0.04;
|
||||
const double q_noise =
|
||||
std::cos(time * 19.0 + static_cast<double>(symbol_index) * 1.11) * 0.04;
|
||||
constellation_->append_point(
|
||||
{std::cos(phase) + std::sin(time * 9.0) * 0.08,
|
||||
std::sin(phase) + std::cos(time * 7.0) * 0.08});
|
||||
{std::cos(phase) + i_noise, std::sin(phase) + q_noise});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user