修复展示数据

This commit is contained in:
2026-08-17 17:21:51 +08:00
parent 5e976b27dd
commit 3881beea69
5 changed files with 103 additions and 22 deletions
@@ -31,7 +31,12 @@ public:
void update(Value value, std::size_t retain_latest_count); void update(Value value, std::size_t retain_latest_count);
void clear(); void clear();
std::size_t retain_latest(std::size_t count); std::size_t retain_latest(std::size_t count);
struct Snapshot {
Container values;
Real_Time_Data_Update_State update_state;
};
Container snapshot() const; Container snapshot() const;
Snapshot snapshot_with_update_state() const;
std::size_t size() const; std::size_t size() const;
std::uint64_t revision() const; std::uint64_t revision() const;
Real_Time_Data_Retention retention() const noexcept override; Real_Time_Data_Retention retention() const noexcept override;
@@ -49,6 +54,7 @@ private:
void reserve_update_times(std::size_t capacity); void reserve_update_times(std::size_t capacity);
void publish_render_state() override; void publish_render_state() override;
const Container& render_state_value() const noexcept; const Container& render_state_value() const noexcept;
const Real_Time_Data_Update_State& render_update_state_value() const noexcept;
mutable Mutex mutex_; mutable Mutex mutex_;
std::recursive_mutex mutation_mutex_; std::recursive_mutex mutation_mutex_;
Observer observer_; Observer observer_;
@@ -61,7 +67,7 @@ private:
std::size_t update_times_size_{}; std::size_t update_times_size_{};
std::size_t update_times_capacity_{}; std::size_t update_times_capacity_{};
std::uint64_t revision_{}; 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 total_update_count_{};
std::uint64_t last_update_time_ns_{}; 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_; return *cache_state_;
} }
template <class Value_Type, class Container, Mutex_Type Mutex, class Observer> 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::size_t History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::size() const {
std::lock_guard < Mutex > lock(mutex_); std::lock_guard < Mutex > lock(mutex_);
return cache_state_->size(); 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> template <class Value_Type, class Container, Mutex_Type Mutex, class Observer>
void History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::publish_render_state() { void History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::publish_render_state() {
std::lock_guard < Mutex > lock(mutex_); std::lock_guard < Mutex > lock(mutex_);
if (render_revision_ == revision_) return; if (render_update_state_.revision == revision_) return;
*scratch_state_ = *cache_state_; *scratch_state_ = *cache_state_;
std::swap(render_state_, scratch_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> 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& { auto History_Real_Time_Data<Value_Type, Container, Mutex, Observer>::render_state_value() const noexcept -> const Container& {
return *render_state_; 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 { [[nodiscard]] const auto& get(const Source& source) const noexcept {
return source.render_state_value(); 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: private:
friend class Renderable_Base; friend class Renderable_Base;
friend class Frame_Render_Snapshot; friend class Frame_Render_Snapshot;
@@ -3,18 +3,37 @@
#include "Plottable_Real_Time_Data.h" #include "Plottable_Real_Time_Data.h"
#include "../render/Blend2D_Cache.h" #include "../render/Blend2D_Cache.h"
#include "../renderable/Renderable_p.h" #include "../renderable/Renderable_p.h"
#include <algorithm> #include <cstdint>
#include <cmath>
#include <deque> #include <deque>
#include <optional> #include <optional>
namespace renderive::detail { namespace renderive::detail {
namespace { namespace {
using Sweep_Spectrum_History = Plottable_History_Real_Time_Data<std::vector<double>, std::deque<std::vector<double>>>; 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; 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; 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 struct Sweep_Spectrum::Impl
: Base::next_Impl<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 { std::size_t Sweep_Spectrum::rendered_point_count() const {
const auto state = Renderable::state<State>(); const auto state = Renderable::state<State>();
const auto values = flatten(d_func<Impl>().blocks->snapshot()); const auto snapshot = d_func<Impl>().blocks->snapshot_with_update_state();
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 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 { Sweep_Spectrum::Observer Sweep_Spectrum::capture_observation() const {
const auto value = Renderable::published_state<State>(); 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& view = context.frame.render_state;
const auto& state = control.render_state<State>(view); const auto& state = control.render_state<State>(view);
const auto& published_blocks = view.get(*blocks); 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; auto& output = prepare_buffer;
output = {}; output = {};
if (values.size() < 2) return; if (values.size() < 2) return;
const Axis_Transform x = frequency_axis->transform(view); const Axis_Transform x = frequency_axis->transform(view);
const Axis_Transform y = power_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); 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 = frequency_range.target;
const double frequency = state.frequency_range.origin + state.frequency_range.length() * completed;
output.current_first = mapped_point(x, frequency, y, y.coordinate_range.origin); 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.current_second = mapped_point(x, frequency, y, y.coordinate_range.target);
output.valid = true; output.valid = true;
+30 -9
View File
@@ -19,6 +19,7 @@
#include <chrono> #include <chrono>
#include <cmath> #include <cmath>
#include <memory> #include <memory>
#include <numbers>
#include <span> #include <span>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -35,6 +36,8 @@ struct Observer_Pfr_Adapter<Render_Scene_2D::Observer> {
Render_Scene_2D::Observer, Render_Scene_2D::Observer_Fields>; Render_Scene_2D::Observer, Render_Scene_2D::Observer_Fields>;
}; };
namespace { 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( std::shared_ptr<Frame_Control_Strategy_Base> make_strategy(
Gallery_Frame_Mode mode) { Gallery_Frame_Mode mode) {
switch (mode) { switch (mode) {
@@ -349,8 +352,8 @@ private:
} else if (case_id_ == "sweep_spectrum") { } else if (case_id_ == "sweep_spectrum") {
Sweep_Spectrum::State state; Sweep_Spectrum::State state;
state.frequency_range = {0.0, 300.0}; state.frequency_range = {0.0, 300.0};
state.bins_per_block = 64; state.bins_per_block = static_cast<int>(sweep_bins_per_block);
state.block_count = 8; state.block_count = static_cast<int>(sweep_block_count);
Sweep_Spectrum::Builder builder{state, &attach}; Sweep_Spectrum::Builder builder{state, &attach};
sweep_ = build<Sweep_Spectrum>( sweep_ = build<Sweep_Spectrum>(
builder, root, domain_axis_, value_axis_); builder, root, domain_axis_, value_axis_);
@@ -382,9 +385,16 @@ private:
} }
void update_samples() { 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); 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) { for (std::size_t index = 0; index < count; ++index) {
const double x = static_cast<double>(index) / (count - 1); const double x = static_cast<double>(index) / (count - 1);
const auto gaussian = [](double value, double center, double width) { 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 (waterfall_) waterfall_->append_row(current_time_of_day(), values);
if (afterglow_) afterglow_->append_spectrum(values); if (afterglow_) afterglow_->append_spectrum(values);
if (sweep_) { if (sweep_) {
values.resize(64); const std::size_t block_index = static_cast<std::size_t>(
sweep_->append_block(values); 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 (trace_) trace_->append_sample(current_time_of_day(), std::sin(time));
if (constellation_) { 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( constellation_->append_point(
{std::cos(phase) + std::sin(time * 9.0) * 0.08, {std::cos(phase) + i_noise, std::sin(phase) + q_noise});
std::sin(phase) + std::cos(time * 7.0) * 0.08});
} }
} }