test_sdk/gui/spgr/gtl_gui_spgr_series.cpp

459 lines
15 KiB
C++
Raw Normal View History

#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, &gtl::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<std::vector<qreal>>(*_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<qreal> 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<qreal> 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