391 lines
11 KiB
C++
391 lines
11 KiB
C++
#include "orbit/gtl_gui_orbit_series.h"
|
|
#include <QDebug>
|
|
|
|
namespace gtl {
|
|
namespace gui {
|
|
|
|
namespace orbit {
|
|
|
|
series::series(QWidget* parent, ::chart::axis_horz* axis_x, ::chart::axis_vert* axis_y)
|
|
: ::chart::series::series(axis_x, axis_y),
|
|
_x(nullptr),
|
|
_y(nullptr),
|
|
_time(0.1),
|
|
_start(0.),
|
|
_stop(_time),
|
|
_turns(1),
|
|
_is_updating(true),
|
|
_max(1.5),
|
|
_device(nullptr),
|
|
_freq(nullptr),
|
|
_samples_x(0),
|
|
_samples_y(0),
|
|
_size(0)
|
|
{
|
|
_axis_horz->set_range(-_max, _max, 0);
|
|
_axis_vert->set_range(-_max, _max, 0);
|
|
|
|
init();
|
|
}
|
|
|
|
series::~series()
|
|
{
|
|
_data_x.clear();
|
|
_data_y.clear();
|
|
_points.clear();
|
|
|
|
if(_freq)
|
|
delete _freq;
|
|
}
|
|
|
|
void series::save(QDomElement &root_element)
|
|
{
|
|
root_element.setAttribute("time", _time);
|
|
root_element.setAttribute("start", _start);
|
|
root_element.setAttribute("stop", _stop);
|
|
root_element.setAttribute("turns", _turns);
|
|
root_element.setAttribute("max", _max);
|
|
}
|
|
|
|
void series::load(const QDomElement &root_element)
|
|
{
|
|
_time = root_element.attribute("time", "1").toDouble();
|
|
_start = root_element.attribute("start", "0").toDouble();
|
|
_stop = root_element.attribute("stop", "1").toDouble();
|
|
_turns = root_element.attribute("turns", "1").toDouble();
|
|
_max = root_element.attribute("max", "1").toDouble();
|
|
}
|
|
|
|
void series::set_updating(bool value)
|
|
{
|
|
_is_updating = value;
|
|
}
|
|
|
|
void series::autoscale()
|
|
{
|
|
if(_x && _y)
|
|
{
|
|
prepareGeometryChange();
|
|
|
|
qreal x_max = *std::max_element(_x->begin(), _x->end());
|
|
qreal y_max = *std::max_element(_y->begin(), _y->end());
|
|
|
|
_max = std::max(x_max, y_max);
|
|
_max *= 1.5;
|
|
|
|
_axis_horz->set_range(-_max, _max, 0);
|
|
_axis_vert->set_range(-_max, _max, 0);
|
|
}
|
|
}
|
|
|
|
void series::set_pos(QPointF pos)
|
|
{
|
|
// _pos = pos;
|
|
}
|
|
|
|
QString series::name() const
|
|
{
|
|
if(_x)
|
|
return _x->name();
|
|
return "";
|
|
}
|
|
|
|
void series::set_tool_tip(QPoint pos)
|
|
{
|
|
|
|
}
|
|
|
|
void series::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
{
|
|
if(!_x || !_y)
|
|
return;
|
|
|
|
if(_samples_x != _samples_y)
|
|
return;
|
|
|
|
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()
|
|
)
|
|
.translate(
|
|
-_axis_horz->min_scaled(),
|
|
- _axis_vert->max_scaled()
|
|
)
|
|
);
|
|
|
|
painter->setPen(QPen(QColor(_x->color()), 0));
|
|
int start = _start * _x->get_rate();
|
|
int size = (_stop - _start) * _x->get_rate();
|
|
if( (start + size) <= _points.size())
|
|
painter->drawPolyline(_points.data() + start, size);
|
|
else
|
|
painter->drawPolyline(_points.data(), _points.size());
|
|
}
|
|
|
|
gtl::analog_data *series::x() const
|
|
{
|
|
return _x;
|
|
}
|
|
|
|
void series::set_x(gtl::analog_data *value)
|
|
{
|
|
if (_x == value)
|
|
return;
|
|
|
|
if(_x)
|
|
disconnect(_x, >l::analog_data::data_changed, this, &series::handle_x_changed);
|
|
|
|
_x = value;
|
|
|
|
if(_freq)
|
|
{
|
|
delete _freq;
|
|
_freq = nullptr;
|
|
}
|
|
|
|
if(_x)
|
|
{
|
|
_freq = new gtl::math::freq(_x);
|
|
_freq->set_time(_time);
|
|
connect(_freq, >l::math::freq::value_changed, [=]{emit freq_changed();});
|
|
|
|
init();
|
|
connect(_x, >l::analog_data::data_changed, this, &series::handle_x_changed);
|
|
}
|
|
|
|
|
|
emit x_changed();
|
|
}
|
|
|
|
gtl::analog_data *series::y() const
|
|
{
|
|
return _y;
|
|
}
|
|
|
|
void series::set_y(gtl::analog_data *value)
|
|
{
|
|
if (_y == value)
|
|
return;
|
|
|
|
if(_y)
|
|
disconnect(_y, >l::analog_data::data_changed, this, &series::handle_y_changed);
|
|
|
|
_y = value;
|
|
|
|
if(_y)
|
|
{
|
|
if(_device)
|
|
disconnect(_device, >l::device::recieved_data, this, &series::update_series);
|
|
_device = static_cast<gtl::device*>(_y->root());
|
|
|
|
init();
|
|
|
|
connect(_y, >l::analog_data::data_changed, this, &series::handle_y_changed);
|
|
if(_device)
|
|
connect(_device, >l::device::recieved_data, this, &series::update_series);
|
|
}
|
|
|
|
emit y_changed();
|
|
}
|
|
|
|
qreal series::time() const
|
|
{
|
|
return _time;
|
|
}
|
|
|
|
void series::set_time(qreal value)
|
|
{
|
|
if (qFuzzyCompare(_time, value))
|
|
return;
|
|
_time = value;
|
|
|
|
if(_freq)
|
|
_turns = _time*_freq->value();
|
|
|
|
if(_stop > _time)
|
|
_stop = _time;
|
|
|
|
if(_start > _time)
|
|
_start = 0;
|
|
init();
|
|
|
|
emit time_changed();
|
|
}
|
|
|
|
qreal series::start() const
|
|
{
|
|
return _start;
|
|
}
|
|
|
|
void series::set_start(qreal value)
|
|
{
|
|
if (qFuzzyCompare(_start, value))
|
|
return;
|
|
_start = value;
|
|
|
|
if(_start >= _time)
|
|
_start = 0;
|
|
|
|
emit start_changed();
|
|
}
|
|
|
|
qreal series::stop() const
|
|
{
|
|
return _stop;
|
|
}
|
|
|
|
void series::set_stop(qreal value)
|
|
{
|
|
if (qFuzzyCompare(_stop, value))
|
|
return;
|
|
_stop = value;
|
|
|
|
if(_stop >= _time)
|
|
_stop = _time;
|
|
|
|
emit stop_changed();
|
|
}
|
|
|
|
qreal series::turns() const
|
|
{
|
|
return _turns;
|
|
}
|
|
|
|
void series::set_turns(qreal value)
|
|
{
|
|
if (qFuzzyCompare(_turns, value))
|
|
return;
|
|
_turns = value;
|
|
|
|
if(_freq)
|
|
{
|
|
if(_freq->value() > 0)
|
|
_time = _turns/_freq->value();
|
|
init();
|
|
}
|
|
|
|
emit turns_changed();
|
|
}
|
|
|
|
qreal series::freq() const
|
|
{
|
|
if(_freq)
|
|
return _freq->value();
|
|
return 0;
|
|
}
|
|
|
|
QColor series::color()
|
|
{
|
|
if(_x)
|
|
return _x->color();
|
|
|
|
return QColor(Qt::black);
|
|
}
|
|
|
|
void series::update_series()
|
|
{
|
|
if(_samples_x != _samples_y)
|
|
{
|
|
_data_x.clear();
|
|
_data_y.clear();
|
|
_points.clear();
|
|
|
|
_samples_x = 0;
|
|
_samples_y = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
int size = std::min(_data_x.size(), _data_y.size());
|
|
|
|
if((_points.size() + size) > _size)
|
|
{
|
|
int psize = size + _points.size() - _size;
|
|
if(psize > 0 && _points.size() >= psize)
|
|
_points.erase(_points.begin(), _points.begin() + psize);
|
|
}
|
|
|
|
for(int i = 0; i < size; i++)
|
|
{
|
|
QPointF point(_data_x.at(i), _data_y.at(i));
|
|
_points.push_back(point);
|
|
}
|
|
|
|
if(size)
|
|
{
|
|
_data_x.erase(_data_x.begin(), _data_x.begin() + size);
|
|
_data_y.erase(_data_y.begin(), _data_y.begin() + size);
|
|
}
|
|
|
|
prepareGeometryChange();
|
|
}
|
|
|
|
void series::set_icolor()
|
|
{
|
|
|
|
}
|
|
|
|
void series::handle_x_changed()
|
|
{
|
|
_x->lock_device();
|
|
|
|
_samples_x += _x->size();
|
|
|
|
std::copy(_x->begin(), _x->end(), std::back_inserter(_data_x));
|
|
|
|
_x->unlock_device();
|
|
}
|
|
|
|
void series::handle_y_changed()
|
|
{
|
|
_y->lock_device();
|
|
|
|
_samples_y += _y->size();
|
|
|
|
std::copy(_y->begin(), _y->end(), std::back_inserter(_data_y));
|
|
|
|
_y->unlock_device();
|
|
}
|
|
|
|
void series::init()
|
|
{
|
|
if(_x && _y)
|
|
{
|
|
_x->lock_device();
|
|
_y->lock_device();
|
|
|
|
_samples_x = 0;
|
|
_samples_y = 0;
|
|
|
|
_data_x.clear();
|
|
_data_y.clear();
|
|
_points.clear();
|
|
|
|
if(_freq)
|
|
{
|
|
if(_freq->value() > 0)
|
|
_turns = _time*_freq->value();
|
|
if(_time > 0)
|
|
_freq->set_time(_time);
|
|
}
|
|
|
|
_size = _x->get_rate()*_time;
|
|
|
|
_points.reserve(_size);
|
|
|
|
_x->unlock_device();
|
|
_y->unlock_device();
|
|
}
|
|
}
|
|
|
|
}
|
|
} // namespace gui
|
|
} // namespace gtl
|
|
|