#include "gtl_gui_spgr_series.h" namespace gtl { namespace gui { namespace spgr{ series::series(QWidget* parent, gtl::math::spec* spec, ::chart::axis_horz* axis_x, ::chart::axis_vert* axis_y) : ::chart::series::series(axis_x, axis_y) , _parent(parent) , _spec(spec) , _is_updating(true) , _time(1) , _size(10) , _spec_time(_time/_size) , _max(1) , _min(0) , _spec_size(10) , _spec_res(10) , _x_log(false) , _t_chart(false) , _f_chart(false) , _pos(QPointF(0,0)) , _t_idx(0) , _f_idx(0) , _t_widget(nullptr) , _f_widget(nullptr) { if(_spec) { _ad = _spec->ad(); if(_ad) { connect(_ad, >l::analog_data::color_changed, this, &series::set_icolor); set_icolor(); } init(); connect(_spec, &math::spec::changed, this, &series::handle_spec_changed); connect(_spec, &math::spec::frequency_changed, this, &series::init); connect(_spec, &math::spec::lines_changed, this, &series::init); connect(_spec, &math::spec::resolution_changed, this, &series::init); connect(_spec, &math::spec::unit_changed, this, &series::init); connect(_spec, &math::spec::overlap_changed, this, &series::init); connect(_spec, &math::spec::average_changed, this, &series::init); } } series::~series() { if(_t_widget) delete _t_widget; if(_f_widget) delete _f_widget; _data.clear(); } void series::set_updating(bool value) { _is_updating = value; } analog_data *series::ad() { return _ad; } void series::autoscale() { prepareGeometryChange(); if(_data.empty()) return; if(_data[0].empty()) return; _max = _data[0][0]; _min = _data[0][0]; qreal max, min = 0; for (int i = 0; i < _data.size(); ++i) { max = *std::max_element(_data[i].begin(), _data[i].end()); min = *std::min_element(_data[i].begin(), _data[i].end()); if(max > _max) _max = max; if(min < _min) _min = min; } _axis_horz->set_range(0, _spec->frequency(), 0); _axis_vert->set_range(0, _time, 0); emit min_changed(); } void series::set_pos(QPointF pos) { _pos = pos; _t_idx = std::round(_pos.x()/_spec_res); _f_idx = /*std::round*/(_pos.y()*_size/_time); // if(_t_widget) // _t_widget->setWindowTitle(name() + tr(" - time chart (f = ") + QString::number((qreal)_t_idx*_spec_res) + tr(")")); // if(_f_widget) // _f_widget->setWindowTitle(name() + tr(" - freq chart (t = ") + QString::number((qreal)_f_idx*_time/_size) + tr(")")); } qreal series::time() { return _time; } void series::set_time(qreal value) { if(_time != value && value > 0) { _time = value; init(); } } qreal series::spec_time() const { return _spec_res; } qreal series::spec_res() const { return _spec_time; } qreal series::min() { return _min; } void series::set_min(qreal value) { if(_min != value) _min = value; } qreal series::max() { return _max; } void series::set_max(qreal value) { if(_max != value) _max = value; } bool series::x_log() { return _x_log; } void series::set_x_log(bool value) { if(_x_log != value) _x_log = value; if(_x_log) { _axis_horz->set_boundaries(_spec_res, _axis_horz->max_boundary()); _axis_horz->set_scale(::chart::axis::logarithmic); } else { _axis_horz->set_boundaries(0, _axis_horz->max_boundary()); _axis_horz->set_scale(::chart::axis::linear); } } bool series::time_chart() { return _t_chart; } void series::set_time_chart(bool value) { if(_t_chart != value) _t_chart = value; if(_t_chart && !_t_widget) { ::chart::axis_horz* axis_x = new /*::chart::axis_horz()*/chart_axis_x(); axis_x->set_range(0, _time - _time/_size, 0); ::chart::axis_vert* axis_y = new chart_axis_y()/*::chart::axis_vert()*/; axis_y->set_range(_min, _max*1.1, 0); axis_y->set_fixed(false); _t_widget = new line_widget(_parent, axis_x, axis_y, _ad); // _t_widget->setWindowTitle(name() + tr(" - time chart (f = ") + QString::number((qreal)_t_idx*_spec_res) + tr(")")); // _t_widget->show(); // connect(_t_widget, &spgr_line_widget::closed, [=]{ // set_time_chart(false); // emit time_chart_changed(); // }); } else { if(_t_widget) delete _t_widget; _t_widget = nullptr; } emit time_chart_changed(); } bool series::freq_chart() { return _f_chart; } void series::set_freq_chart(bool value) { if(_f_chart != value) _f_chart = value; if(_f_chart && !_f_widget) { ::chart::axis_horz* axis_x = new /*::chart::axis_horz()*/chart_axis_x(); axis_x->set_range(0, _spec->frequency(), 0); ::chart::axis_vert* axis_y = new /*::chart::axis_vert()*/chart_axis_y(); axis_y->set_range(_min, _max*1.1, 0); // axis_y->set_fixed(false); _f_widget = new line_widget(_parent, axis_x, axis_y, _ad); // _f_widget->setWindowTitle(name() + tr(" - freq chart (t = ") + QString::number((qreal)_f_idx*_time/_size) + tr(")")); // _f_widget->show(); // connect(_f_widget, &spgr_line_widget::closed, [=]{ // set_freq_chart(false); // emit freq_chart_changed(); // }); } else { if(_f_widget) delete _f_widget; _f_widget = nullptr; } emit freq_chart_changed(); } line_widget *series::time_widget() { return _t_widget; } line_widget *series::freq_widget() { return _f_widget; } QString series::name() const { if(_ad) return _ad->name(); return ""; } void series::set_tool_tip(QPoint pos) { setToolTip(""); } void series::update_series() { prepareGeometryChange(); } void series::set_icolor() { if(_ad) set_color(QColor(_ad->color())); } void series::handle_spec_changed() { _data.pop_front(); _data.push_back(static_cast>(*_spec)); if(_t_chart && _t_idx < _data[0].size() && _t_widget) { if(_t_widget->isHidden()) { set_time_chart(false); emit time_chart_changed(); } else { std::vector data; for(int i = 0; i < _data.size(); ++i) data.push_back(_data[i][_t_idx]); _t_widget->set_data(data.data(), data.size(), _time/_size); } } if(_f_chart && _f_idx < _data.size() && _f_widget) { if(_f_widget->isHidden()) { set_freq_chart(false); emit freq_chart_changed(); } else _f_widget->set_data(_data[_f_idx].data(), _data[_f_idx].size(), _spec_res); } update_series(); // qDebug() << _spec->acq_time(); } void series::init() { if(_spec) { blockSignals(true); _data.clear(); _spec_time = _spec->acq_time()/_spec->average()/(1. - _spec->overlap()/100.); _size = _time/_spec_time; _spec_res = _spec->resolution(); _spec_size = _spec->size(); std::vector tmp(_spec_size); for (int i = 0; i < _size; ++i) _data.push_back(tmp); _axis_horz->set_range(0, _spec->frequency(), 0); _axis_horz->set_fixed(true); set_x_log(_x_log); _axis_vert->set_range(0, _time, 0); _axis_vert->set_fixed(true); blockSignals(false); } } QColor series::get_color(qreal value) { qreal range = (_max - _min)/4; int r = 0; int g = 0; int b = 0; if(value <= (range + _min)) { if(value < _min) value = _min; qreal ratio = qAbs((value - _min)/range); r = 0; g = (int)(ratio*255); b = 255; } else if(value > (range + _min) && value <= (range*2 + _min)) { qreal ratio = qAbs((value - (range + _min))/range); r = 0; g = (int)(ratio*255); b = (int)((1-ratio)*255); } else if(value > (range*2 + _min) && value <= (range*3 + _min)) { qreal ratio = qAbs((value - (range*2 + _min))/range); r = (int)(ratio*255); g = 255; b = 0; } else { if(value > _max) value = _max; qreal ratio = qAbs((value - (range*3 + _min))/range); r = 255; g = (int)((1-ratio)*255); b = 0; } if(r > 255) r = 255; else if(r < 0) r = 0; if(g > 255) g = 255; else if(g < 0) g = 0; if(b > 255) b = 255; else if(b < 0) b = 0; return QColor::fromRgb(r, g, b); } void series::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if(_data.empty()) return; if(!_spec) return; qreal ratio = _size/_time; QRectF boundary = boundingRect(); painter->setClipRect(_axis_vert->boundingRect()); painter->setTransform(QTransform().translate( boundary.left(), boundary.top() ) .scale( boundary.width() / _axis_horz->range_scaled(), -boundary.height() / _axis_vert->range_scaled() * (1./ratio) ) .translate( -_axis_horz->min_scaled(), - (_size) ) ); QColor color; QRectF rect; qreal x; qreal w; for (int i = 0; i < _data.size(); ++i) for (int j = 0; j < _data[i].size(); ++j) { color = get_color(_data[i][j]); painter->setPen(QPen(color, 0)); painter->setBrush(color); if(!_x_log) { x = (j-0.5)*_spec_res; w = std::ceil(_spec_res); } else { x = _axis_horz->get_paint_value((j-0.5)*_spec_res); w = std::ceil(_axis_horz->get_paint_value((j+0.5)*_spec_res) - _axis_horz->get_paint_value((j-0.5)*_spec_res)); } rect.setRect(x,i,w,1); painter->drawRect(rect); } } } } // namespace gui } // namespace gtl