Files
Renderive/YSGraphic_Core/plottable/Spectrum.cpp
T
2026-07-23 18:11:07 +08:00

374 lines
15 KiB
C++

#include "Spectrum_p.h"
namespace YSG {
using Spectrum_Binding = Renderable_Binding<Spectrum, Spectrum_Private, Spectrum_Render_State, Spectrum_Input_Data>;
Spectrum::Spectrum() {
Spectrum_Binding::init(this, "Spectrum");
}
Spectrum_Private* Spectrum::d() {
return Spectrum_Binding::d(this);
}
Render_Data* Spectrum::create_render_data() {
return Spectrum_Binding::create_render_data();
}
Render_State* Spectrum::create_render_state() {
return Spectrum_Binding::create_render_state();
}
Input_Data* Spectrum::create_input_data() {
return Spectrum_Binding::create_input_data();
}
Frequent_Axis* Spectrum::frequent_axis(SRC src) {
return d()->state_value(&Spectrum_Render_State::frequent_axis, src);
}
void Spectrum::set_frequent_axis(Frequent_Axis* value) {
d()->set_state_value(&Spectrum_Render_State::frequent_axis, value);
}
Axis* Spectrum::power_axis(SRC src) {
return d()->state_value(&Spectrum_Render_State::power_axis, src);
}
void Spectrum::set_power_axis(Axis* value) {
d()->set_state_value(&Spectrum_Render_State::power_axis, value);
}
int Spectrum::frequent_point_size(SRC src) {
return d()->state_value(&Spectrum_Render_State::frequent_point_size, src);
}
Range Spectrum::frequent_range(SRC src) {
return d()->state_value(&Spectrum_Render_State::frequent_range, src);
}
double Spectrum::middle_sweep_frequent(SRC src) {
return d()->state_value(&Spectrum_Render_State::middle_sweep_frequent, src);
}
void Spectrum::set_middle_sweep_frequent(double value) {
d()->set_state_value(&Spectrum_Render_State::middle_sweep_frequent, value);
}
Range Spectrum::sweep_frequent_range(SRC src) {
return d()->state_value(&Spectrum_Render_State::sweep_frequent_range, src);
}
void Spectrum::set_sweep_frequent_range(Range value) {
d()->set_state_value(&Spectrum_Render_State::sweep_frequent_range, std::move(value));
}
bool Spectrum::use_max_line(SRC src) {
return d()->state_value(&Spectrum_Render_State::use_max_line, src);
}
void Spectrum::set_use_max_line(bool value) {
d()->set_state_value(&Spectrum_Render_State::use_max_line, value);
}
bool Spectrum::use_min_line(SRC src) {
return d()->state_value(&Spectrum_Render_State::use_min_line, src);
}
void Spectrum::set_use_min_line(bool value) {
d()->set_state_value(&Spectrum_Render_State::use_min_line, value);
}
bool Spectrum::use_max_marker(SRC src) {
return d()->state_value(&Spectrum_Render_State::use_max_marker, src);
}
void Spectrum::set_use_max_marker(bool value) {
d()->set_state_value(&Spectrum_Render_State::use_max_marker, value);
}
bool Spectrum::use_min_marker(SRC src) {
return d()->state_value(&Spectrum_Render_State::use_min_marker, src);
}
void Spectrum::set_use_min_marker(bool value) {
d()->set_state_value(&Spectrum_Render_State::use_min_marker, value);
}
bool Spectrum::use_sweep_frequent_rect(SRC src) {
return d()->state_value(&Spectrum_Render_State::use_sweep_frequent_rect, src);
}
void Spectrum::set_use_sweep_frequent_rect(bool value) {
d()->set_state_value(&Spectrum_Render_State::use_sweep_frequent_rect, value);
}
QBrush Spectrum::max_brush(SRC src) {
return d()->state_value(&Spectrum_Render_State::max_brush, src);
}
void Spectrum::set_max_brush(QBrush value) {
d()->set_state_value(&Spectrum_Render_State::max_brush, std::move(value));
}
QBrush Spectrum::cur_brush(SRC src) {
return d()->state_value(&Spectrum_Render_State::cur_brush, src);
}
void Spectrum::set_cur_brush(QBrush value) {
d()->set_state_value(&Spectrum_Render_State::cur_brush, std::move(value));
}
QBrush Spectrum::min_brush(SRC src) {
return d()->state_value(&Spectrum_Render_State::min_brush, src);
}
void Spectrum::set_min_brush(QBrush value) {
d()->set_state_value(&Spectrum_Render_State::min_brush, std::move(value));
}
QPen Spectrum::max_pen(SRC src) {
return d()->state_value(&Spectrum_Render_State::max_pen, src);
}
void Spectrum::set_max_pen(QPen value) {
d()->set_state_value(&Spectrum_Render_State::max_pen, std::move(value));
}
QPen Spectrum::cur_pen(SRC src) {
return d()->state_value(&Spectrum_Render_State::cur_pen, src);
}
void Spectrum::set_cur_pen(QPen value) {
d()->set_state_value(&Spectrum_Render_State::cur_pen, std::move(value));
}
QPen Spectrum::min_pen(SRC src) {
return d()->state_value(&Spectrum_Render_State::min_pen, src);
}
void Spectrum::set_min_pen(QPen value) {
d()->set_state_value(&Spectrum_Render_State::min_pen, std::move(value));
}
QPen Spectrum::select_marker_pen(SRC src) {
return d()->state_value(&Spectrum_Render_State::select_marker_pen, src);
}
void Spectrum::set_select_marker_pen(QPen value) {
d()->set_state_value(&Spectrum_Render_State::select_marker_pen, std::move(value));
}
QPen Spectrum::marker_pen(SRC src) {
return d()->state_value(&Spectrum_Render_State::marker_pen, src);
}
void Spectrum::set_marker_pen(QPen value) {
d()->set_state_value(&Spectrum_Render_State::marker_pen, std::move(value));
}
QPen Spectrum::middle_frequent_pen(SRC src) {
return d()->state_value(&Spectrum_Render_State::middle_frequent_pen, src);
}
void Spectrum::set_middle_frequent_pen(QPen value) {
d()->set_state_value(&Spectrum_Render_State::middle_frequent_pen, std::move(value));
}
QBrush Spectrum::sweep_rect_brush(SRC src) {
return d()->state_value(&Spectrum_Render_State::sweep_rect_brush, src);
}
void Spectrum::set_sweep_rect_brush(QBrush value) {
d()->set_state_value(&Spectrum_Render_State::sweep_rect_brush, std::move(value));
}
void Spectrum::set_frequent_point_size(int frequent_point_size) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->frequent_point_size = frequent_point_size;
}
void Spectrum::set_frequent_range(Range frequent_range) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->frequent_range = frequent_range;
}
Spectrum::Builder::Builder(Frequent_Axis* frequent_axis, Axis* power_axis) {
ASSERT(frequent_axis->mPlot != nullptr, "Afterglow build error! frequent_axis->mPlot == nullptr");
ASSERT(frequent_axis->mPlot == power_axis->mPlot, "Afterglow build error! frequent_axis->mPlot != power_axis->mPlot");
plot = frequent_axis->mPlot;
this->frequent_axis = frequent_axis;
this->power_axis = power_axis;
}
Spectrum* Spectrum::Builder::build() {
auto ret = new Spectrum;
ret->init(plot, layerName);
Spectrum_Private* pd = ret->d();
Spectrum_Render_State* sc = reinterpret_cast<Spectrum_Render_State*>(pd->state(State_Edit));
PROP_R(FrequentAxis *, frequent_axis)
PROP_R(Axis *, power_axis);
PROP_R(int, frequent_point_size);
PROP_R(Range, frequent_range);
PROP_R(double, middle_sweep_frequent);
PROP_R(Range, sweep_frequent_range);
PROP_R(bool, use_max_line);
PROP_R(bool, use_min_line);
PROP_R(bool, use_max_marker);
PROP_R(bool, use_min_marker);
PROP_R(bool, use_sweep_frequent_rect);
PROP_R(QBrush, max_brush);
PROP_R(QBrush, cur_brush);
PROP_R(QBrush, min_brush);
PROP_R(QPen, max_pen);
PROP_R(QPen, cur_pen);
PROP_R(QPen, min_pen);
PROP_R(QPen, select_marker_pen);
PROP_R(QPen, marker_pen);
PROP_R(QPen, middle_frequent_pen);
PROP_R(QBrush, sweep_rect_brush);
return ret;
}
void Spectrum_Private::update_frequent_point_size(int frequent_point_size, Range frequent_range) {
if (frequent_point_size == 0) return;
cacheFrequentPointSize = frequent_point_size;
cacheFrequentRange = frequent_range;
maxPowers.resize(frequent_point_size);
curPowers.resize(frequent_point_size);
minPowers.resize(frequent_point_size);
frequents.resize(frequent_point_size);
double cur = frequent_range.lower;
double step = frequent_range.length() / (frequent_point_size - 1);
frequents[0] = frequent_range.lower;
for (int i = 1; i < frequent_point_size; ++i) {
cur += step;
frequents[i] = cur;
}
maxPowers.fill(frequent_range.lower);
minPowers.fill(frequent_range.upper);
}
void Spectrum_Private::set_frequent_data(const QVector<double>& lineData, const Spectrum_Render_State* s) {
if (lineData.size() != s->frequent_point_size) {
qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << s->frequent_point_size;
return;
}
curPowers = lineData;
curPowers.detach();
double min = std::numeric_limits<double>::max();
double max = std::numeric_limits<double>::min();
int minIndex = 0, maxIndex = 0;
for (int i = 0; i < s->frequent_point_size; ++i) {
double& curData = curPowers[i];
if (s->use_max_line && curData > maxPowers.at(i)) {
maxPowers[i] = curData;
}
if (s->use_min_line && curData < minPowers.at(i)) {
minPowers[i] = curData;
}
if (s->use_max_marker && curData > max) {
max = curData;
maxIndex = i;
}
if (s->use_min_marker && curData < min) {
min = curData;
minIndex = i;
}
}
maxMarkerKey = frequents[maxIndex];
maxMarkerValue = curPowers[maxIndex];
minMarkerKey = frequents[minIndex];
minMarkerValue = curPowers[minIndex];
}
double Spectrum_Private::get_y(const double& x, bool& ok) {
int i = binary_search(x, frequents, ok);
if (!ok) return -1;
const double& x1 = frequents.at(i);
const double& x2 = frequents.at(i + 1);
const double& y1 = curPowers.at(i);
const double& y2 = curPowers.at(i + 1);
double k = (y2 - y1) / (x2 - x1);
double b = y1 - k * x1;
return (int)(k * x + b);
}
void Spectrum_Private::draw_line(QPainter* painter, const Spectrum_Render_State* s, const QVector<double>& ys, const QPen& pen, const QBrush& brush) {
if (frequents.empty()) return;
int n = frequents.size();
QVector<QPointF> points(n + 2);
double upperBoundPixel = s->power_axis->coord_to_pixel(s->power_axis->coord_range().upper, SRC::Render);
points.first() = QPointF(s->frequent_axis->coord_to_pixel(frequents.first(), SRC::Render), upperBoundPixel);
points.last() = QPointF(s->frequent_axis->coord_to_pixel(frequents.last(), SRC::Render), upperBoundPixel);
for (int i = 0; i < n; ++i) {
double x = s->frequent_axis->coord_to_pixel(frequents.at(i), SRC::Render);
double y = s->power_axis->coord_to_pixel(ys.at(i), SRC::Render);
points[i + 1] = QPointF(x, y);
}
painter->setPen(pen);
if (pen.style() != Qt::NoPen) painter->drawPolyline(points.data() + 1, n);
painter->setBrush(brush);
if (brush.style() != Qt::NoBrush) painter->drawPolygon(points.data(), n + 2);
}
void Spectrum_Private::draw_spectrum(QPainter* painter, Spectrum_Render_State* s) {
if (s->use_max_line) draw_line(painter, s, maxPowers, s->max_pen, s->max_brush);
draw_line(painter, s, curPowers, s->cur_pen, s->cur_brush);
if (s->use_min_line) draw_line(painter, s, minPowers, s->min_pen, s->min_brush);
if (s->use_max_marker) s->draw_marker(painter, maxMarkerKey, maxMarkerValue, false, false);
if (s->use_min_marker) s->draw_marker(painter, minMarkerKey, minMarkerValue, false, false);
for (Marker& customMarker : s->markerList) {
bool ok;
double value = get_y(customMarker.frequent, ok);
if (ok) s->draw_marker(painter, customMarker.frequent, value, customMarker.drawLine, s->markerList.indexOf(customMarker) == s->curSelectIndex);
}
if (s->use_sweep_frequent_rect) {
s->draw_axis_rect(painter, s->sweep_frequent_range, s->middle_sweep_frequent);
}
}
void Spectrum_Private::draw(QPainter* painter) {
auto s = render_state();
Performance_Shower* shower = q()->mPlot->d->mShower;
if (shower) {
shower->set_performance_line("mFrequentPointSize", Performance_Line(QString("mFrequentPointSize:%1").arg(s->frequent_point_size)));
}
draw_spectrum(painter, s);
if (q()->hover_ok(q())) {
q()->draw_hover(painter, s->frequent_axis, s->power_axis);
}
}
void Spectrum::give_data(const QVector<double>& lineData) {
if (!ok()) return;
Spectrum_Private* pd = d();
Render_State_Lease<Spectrum_Private, Spectrum_Render_State> state(pd);
int frequent_point_size = state->frequent_point_size;
if (lineData.size() != frequent_point_size) {
qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << frequent_point_size;
return;
}
Render_Input_Lease<Spectrum_Private, Spectrum_Input_Data> input(pd);
input->mDataList.push_back(lineData);
}
void Spectrum::add_custom_marker(double frequent) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->markerList.append(Marker{frequent, false});
}
void Spectrum::add_custom_line_marker(double frequent) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->markerList.append(Marker{frequent, true});
}
void Spectrum::remove_custom_marker(double frequent) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
for (Marker& marker : edit->markerList) {
if (qFuzzyCompare(marker.frequent, frequent)) {
edit->markerList.removeOne(marker);
break;
}
}
}
void Spectrum::remove_current_marker(SRC src) {
Q_UNUSED(src)
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->markerList.removeAt(edit->curSelectIndex);
}
void Spectrum::clear_all_custom_marker(SRC src) {
Q_UNUSED(src)
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->markerList.clear();
}
double Spectrum::get_mark_frequent(int markIndex, SRC src) {
auto render_state = d()->state_data(src);
if (markIndex < 0 || markIndex >= render_state->markerList.size())
return -1;
return render_state->markerList[markIndex].frequent;
}
void Spectrum::set_marker_frequent(int markerIndex, double frequent) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
QVector<Marker>& markers = edit->markerList;
if (markerIndex < 0 || markerIndex >= markers.size())
return;
markers[markerIndex].frequent = frequent;
}
void Spectrum::set_current_marker_frequent(double frequent) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->set_cur_frequent(frequent);
}
int Spectrum::select_line_marker_size(SRC src) {
auto render_state = d()->state_data(src);
return render_state->markerList.size();
}
int Spectrum::cur_select_marker_index(SRC src) {
auto render_state = d()->state_data(src);
return render_state->curSelectIndex;
}
void Spectrum::set_selected_line_marker(int markerIndex) {
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->set_select_index(markerIndex);
}
void Spectrum::select_next(SRC src) {
Q_UNUSED(src)
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->select_next_marker();
}
void Spectrum::select_previous(SRC src) {
Q_UNUSED(src)
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->select_prev_marker();
}
void Spectrum::un_select_marker(SRC src) {
Q_UNUSED(src)
Render_Edit_Lease<Spectrum_Private, Spectrum_Render_State> edit(d());
edit->un_select();
}
double Spectrum::get_power(double frequent, bool& ok, SRC src) {
Q_UNUSED(src)
return d()->get_y(frequent, ok);
}
}