459 lines
15 KiB
C++
459 lines
15 KiB
C++
|
|
#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<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
|
|
|