106 lines
4.6 KiB
C++
106 lines
4.6 KiB
C++
#pragma once
|
|
#include "../Axis/Axis_p.h"
|
|
#include "../architecture/Bounded_Input_Buffer.h"
|
|
#include "../base/Frame_Memory.h"
|
|
#include "../base/Geometry.h"
|
|
#include "../base/Style.h"
|
|
#include "../event/Pointer_Event.h"
|
|
#include "../render/Canvas.h"
|
|
#include "../primitive/Curve.h"
|
|
#include "../primitive/Curve_Utils_p.h"
|
|
#include "Sweep_Spectrum.h"
|
|
namespace renderive {
|
|
struct Sweep_Spectrum_Render_State : renderive::Render_State, Sweep_Spectrum_Prop {};
|
|
struct Sweep_Spectrum_Input_Data : renderive::Input_Data {
|
|
static constexpr std::size_t Latest_Only_Count = 1;
|
|
Bounded_Vector_Double_Input_Buffer data;
|
|
void clear() override {
|
|
data.clear();
|
|
}
|
|
};
|
|
struct Sweep_Spectrum_Private : renderive::Typed_Render_Data<Sweep_Spectrum, Sweep_Spectrum_Render_State, Sweep_Spectrum_Input_Data> {
|
|
std::vector<PointF> sweep_points;
|
|
int next_block_index{};
|
|
int bins_per_block{};
|
|
int block_count{};
|
|
Range frequency_range;
|
|
bool first_sweep_incomplete = true;
|
|
void reset_sweep_grid(int block_frequency_point_size, int block_num, Range frequency_range) {
|
|
this->bins_per_block = block_frequency_point_size;
|
|
this->block_count = block_num;
|
|
this->frequency_range = frequency_range;
|
|
int total_point_count = block_num * block_frequency_point_size;
|
|
if (total_point_count <= 0) {
|
|
sweep_points.clear();
|
|
first_sweep_incomplete = true;
|
|
return;
|
|
}
|
|
sweep_points.resize(total_point_count);
|
|
int interval_count = total_point_count - 1;
|
|
if (interval_count == 0) {
|
|
sweep_points[0].x = frequency_range.origin;
|
|
first_sweep_incomplete = true;
|
|
return;
|
|
}
|
|
double step = frequency_range.length() / interval_count;
|
|
double frequency = frequency_range.origin;
|
|
for (int i = 0; i < interval_count; ++i) {
|
|
sweep_points[i].x = frequency;
|
|
frequency += step;
|
|
}
|
|
sweep_points.back().x = frequency_range.target;
|
|
first_sweep_incomplete = true;
|
|
}
|
|
void prepare_data(const Render_Frame_Snapshot&, const Renderable_Frame_View& frame_view) override {
|
|
Sweep_Spectrum_Render_State* s = render_state(frame_view);
|
|
Sweep_Spectrum_Input_Data* d = render_input_data(frame_view);
|
|
if (!s || !d)
|
|
return;
|
|
if (
|
|
bins_per_block != s->bins_per_block ||
|
|
block_count != s->block_num ||
|
|
frequency_range != s->frequency_range) {
|
|
reset_sweep_grid(s->bins_per_block, s->block_num, s->frequency_range);
|
|
next_block_index = 0;
|
|
}
|
|
d->data.read_all([this, d](const auto& data) {
|
|
if ((int)data.size() != bins_per_block || sweep_points.empty()) {
|
|
return;
|
|
}
|
|
PointF* start = &sweep_points[next_block_index * bins_per_block];
|
|
for (int i = 0; i < bins_per_block; ++i) {
|
|
start[i].y = data[i];
|
|
}
|
|
next_block_index++;
|
|
if (next_block_index == block_count) {
|
|
next_block_index = 0;
|
|
first_sweep_incomplete = false;
|
|
}
|
|
});
|
|
frame_view.consume_input();
|
|
}
|
|
void draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) override {
|
|
Sweep_Spectrum_Render_State* s = render_state(frame_view);
|
|
if (!s)
|
|
return;
|
|
auto frequency_axis = s->frequency_axis.lock();
|
|
auto power_axis = s->power_axis.lock();
|
|
if (!frequency_axis || !power_axis)
|
|
return;
|
|
Axis_Mapping_2D mapping = Axis_Render_Access::mapping(frequency_axis.get(), power_axis.get(), snapshot);
|
|
int total_point_count = (int)sweep_points.size();
|
|
int available_count = !first_sweep_incomplete ? total_point_count : next_block_index * bins_per_block;
|
|
std::pmr::vector<PointF> data(frame_memory_resource());
|
|
data = Curve_Utils::build_resampled_points(mapping, s->frequency_range, total_point_count, available_count, s->visible_range_only, s->interpolation_mode, [this](int i) {
|
|
return sweep_points.at(i).y;
|
|
});
|
|
Curve_Utils::draw_polyline(&canvas, data, s->pen);
|
|
canvas.set_pen(s->current_frequency_pen);
|
|
double current_frequency = block_count > 1 ? frequency_range.origin + next_block_index * frequency_range.length() / (block_count - 1.0) : frequency_range.origin;
|
|
canvas.draw_line(
|
|
mapping.map(current_frequency, mapping.value.coord_range.origin),
|
|
mapping.map(current_frequency, mapping.value.coord_range.target));
|
|
}
|
|
};
|
|
} // namespace renderive
|