Как я могу создавать графики «в реальном времени» с помощью wxMathPlot?
-
13-09-2019 - |
Вопрос
Я думаю использовать wxMathPlot для построения графиков некоторых данных, которые поступают непрерывно.Я хочу нарисовать график/график «в реальном времени», используя его.Это возможно?
И.Е.Мне не нужен просто статический график однократного чтения файла - я хочу, чтобы потоковые данные отображались и продолжались справа от графика - (и пусть левая сторона упадет/прокрутится вне поля зрения)
РЕДАКТИРОВАТЬ
Я до сих пор не получил ответа на этот вопрос.В библиотеке wxmathPlot есть интересный класс под названием mpFXYVector, но он, похоже, просто рисует один график из вектора данных.Мне нужно что-то, что можно подать в поток и прокрутить график по горизонтали (а также при необходимости изменить размер масштаба)
Решение
Я думаю, что mpFXYVector — это лучший вариант.
Самый простой способ справиться с этим — написать класс-оболочку для mpFXYVector, который будет содержать буфер FIFO последних точек данных.Каждый раз, когда поступает новая точка данных, добавляйте ее в буфер FIFO, при этом самая старая точка будет удалена, а затем загружайте mpFXYVector с обновленным буфером.Класс wxMathPlot mpWindow позаботится обо всем остальном, что вам нужно.
Более элегантным подходом была бы специализация mpFXYVector, которая реализует буфер FIFO, используя простые векторы из mpFXYVector.Преимущество этого заключается в том, что вы храните только одну копию отображаемых данных.Если вы не отображаете много тысяч точек, я сомневаюсь, что это преимущество стоит дополнительных хлопот по наследованию от mpFXYVector вместо простого использования документированного интерфейса mpFXYVector.
После рассмотрения деталей, единственная сложность заключается в замене mpFXYVector::SetData() новым методом Add() для добавления точек данных по мере их поступления.Новый метод должен управлять векторами mpFXYVector как буферами FIFO и повторно реализовывать код для обновления ограничивающего прямоугольника (который, к сожалению, не был написан с учетом наследования).
В результате специализация дает решение с меньшими требованиями к памяти и большей гибкостью, чем использование оболочки.
Другие советы
Спасибо, Рэйвенпойнт...!!Я сделал то, что ты сказал..Он работает безупречно!вот моя функция AddData():
void mpFXYVector::AddData(float x, float y, std::vector<double> &xs, std::vector<double> &ys)
{
// Check if the data vectora are of the same size
if (xs.size() != ys.size()) {
wxLogError(_("wxMathPlot error: X and Y vector are not of the same length!"));
return;
}
//Delete first point if you need a filo buffer (i dont need it)
//xs.erase(xs.begin());
//xy.erase(xy.begin());
//Add new Data points at the end
xs.push_back(x);
ys.push_back(y);
// Copy the data:
m_xs = xs;
m_ys = ys;
// Update internal variables for the bounding box.
if (xs.size()>0)
{
m_minX = xs[0];
m_maxX = xs[0];
m_minY = ys[0];
m_maxY = ys[0];
std::vector<double>::const_iterator it;
for (it=xs.begin();it!=xs.end();it++)
{
if (*it<m_minX) m_minX=*it;
if (*it>m_maxX) m_maxX=*it;
}
for (it=ys.begin();it!=ys.end();it++)
{
if (*it<m_minY) m_minY=*it;
if (*it>m_maxY) m_maxY=*it;
}
m_minX-=0.5f;
m_minY-=0.5f;
m_maxX+=0.5f;
m_maxY+=0.5f;
}
else
{
m_minX = -1;
m_maxX = 1;
m_minY = -1;
m_maxY = 1;
}
}
в Main() вам нужно только:
m_Vector->AddData(xPos,yPos,vectorX, vectorY);
m_plot->Fit();
Я знаю, что это старая тема, но мне нужно было построить прокрутку оси X с помощью wxMathPlot.
Я внес простую модификацию кода Jayjo, чтобы прокрутка по оси X работала.
Я думаю, это помогает.
void mpFXYVector::AddData(float x, float y, std::vector<double> &xs, std::vector<double> &ys)
{
// Check if the data vectora are of the same size
if (xs.size() != ys.size()) {
wxLogError(_("wxMathPlot error: X and Y vector are not of the same length!"));
return;
}
//After a certain number of points implement a FIFO buffer
//As plotting too many points can cause missing data
if (x > 300)
{
xs.erase(xs.begin());
ys.erase(ys.begin());
}
//Add new Data points at the end
xs.push_back(x);
ys.push_back(y);
// Copy the data:
m_xs = xs;
m_ys = ys;
// Update internal variables for the bounding box.
if (xs.size()>0)
{
m_minX = xs[0];
m_maxX = xs[0];
m_minY = ys[0];
m_maxY = ys[0];
std::vector<double>::const_iterator it;
for (it=xs.begin();it!=xs.end();it++)
{
if (*it<m_minX) m_minX=*it;
if (*it>m_maxX) m_maxX=*it;
}
for (it=ys.begin();it!=ys.end();it++)
{
if (*it<m_minY) m_minY=*it;
if (*it>m_maxY) m_maxY=*it;
}
m_minX-=0.5f;
m_minY-=0.5f;
m_maxX+=0.5f;
m_maxY+=0.5f;
}
else
{
m_minX = -1;
m_maxX = 1;
m_minY = -1;
m_maxY = 1;
}
}
У меня нет личного опыта работы с wxMathPlot, но я работаю с wxWidgets уже много лет и настоятельно рекомендую его для кроссплатформенного программирования графического интерфейса на C++, при этом согласно графическая страница wxWiki тот Графическая библиотека Numerix может использоваться для данных в реальном времени, так что, возможно, это вам поможет.Удачи.
Может быть у кого-то будет такая же проблема и это понадобится...Мне нужно было очень быстрое построение графиков для отображения данных осциллографа.Я получал данные пакетами.Я внес несколько изменений, которые сделали код много быстрее.Первое, что нужно сделать, это изменить состояние if в функции. SetData
от if (xs.size()>0)
к if (!xs.empty)
.Затем вам следует сначала добавить весь ваш пакет данных в вектор.
Vector1_X.push_back(x);
Vector1_Y.push_back(y);
И после этого следует подогнать и установить данные.
Vector1 ->SetData(Vector1_X,Vector1_Y); // add vectors to main vector
MathPlot1-> Fit(); //fit plot to the data
Vector1_X.clear(); //if you want to clear plot after every packet
Vector1_Y.clear(); //you should use it
Ваш код в основной функции будет длиннее, но функция будет быстрее, потому что вы добавляете все данные «сразу».
В итоге мы использовали ГрафикДиректор вместо.Он имеет большие возможности и работает быстро.