#include "orbit/gtl_gui_orbit_series.h" #include 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(_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