#include "Spectrum_p.h" namespace YSG { using Spectrum_Binding = Renderable_Binding; 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 edit(d()); edit->frequent_point_size = frequent_point_size; } void Spectrum::set_frequent_range(Range frequent_range) { Render_Edit_Lease 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(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& 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::max(); double max = std::numeric_limits::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& ys, const QPen& pen, const QBrush& brush) { if (frequents.empty()) return; int n = frequents.size(); QVector 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& lineData) { if (!ok()) return; Spectrum_Private* pd = d(); Render_State_Lease 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 input(pd); input->mDataList.push_back(lineData); } void Spectrum::add_custom_marker(double frequent) { Render_Edit_Lease edit(d()); edit->markerList.append(Marker{frequent, false}); } void Spectrum::add_custom_line_marker(double frequent) { Render_Edit_Lease edit(d()); edit->markerList.append(Marker{frequent, true}); } void Spectrum::remove_custom_marker(double frequent) { Render_Edit_Lease 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 edit(d()); edit->markerList.removeAt(edit->curSelectIndex); } void Spectrum::clear_all_custom_marker(SRC src) { Q_UNUSED(src) Render_Edit_Lease 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 edit(d()); QVector& 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 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 edit(d()); edit->set_select_index(markerIndex); } void Spectrum::select_next(SRC src) { Q_UNUSED(src) Render_Edit_Lease edit(d()); edit->select_next_marker(); } void Spectrum::select_previous(SRC src) { Q_UNUSED(src) Render_Edit_Lease edit(d()); edit->select_prev_marker(); } void Spectrum::un_select_marker(SRC src) { Q_UNUSED(src) Render_Edit_Lease edit(d()); edit->un_select(); } double Spectrum::get_power(double frequent, bool& ok, SRC src) { Q_UNUSED(src) return d()->get_y(frequent, ok); } }