如何使用wxMathPlot创建“实时”图?

时间:2021-04-19 03:56:01

I am thinking of using wxMathPlot for plotting/graphing some data that arrives continuously. I want to draw "Real-time" plot/graph using it. Is that possible?

我正在考虑使用wxMathPlot绘制/绘制一些连续到达的数据。我想用它绘制“实时”情节/图表。那可能吗?

I.E. I don't want just a static graph of a one-time read of a file - I want the streaming data plotted and continued out to the right of the graph - (and let the left side fall off/scroll out of view)

I.E.我不想只是一次性读取文件的静态图 - 我希望绘制流数据并继续到图的右侧 - (并让左侧掉落/滚出视图)

EDIT

I still have not gotten an answer for this. There is an interesting class in the wxmathPlot library called mpFXYVector but that appears just to draw one plot from a vector of data. What I want is something that can be fed a stream and scroll the graph horizontally (and also resize the scale if needed)

我还没有得到答案。 wxmathPlot库中有一个名为mpFXYVector的有趣类,但它只是从数据向量中绘制一个图。我想要的是可以输入流并水平滚动图形的东西(如果需要也可以调整比例尺)

6 个解决方案

#1


I think mpFXYVector is the way to go.

我认为mpFXYVector是要走的路。

The simplest way to deal with this might be to write a wrapper class for mpFXYVector which holds a FIFO buffer of recent data points. Each time a new datapoint arrives, add it to the FIFO buffer, which will drop the oldest point, then load mpFXYVector with the updated buffer. The wxMathPlot class mpWindow will look after the rest of what you need.

处理这个问题的最简单方法可能是为mpFXYVector编写一个包装类,它包含最近数据点的FIFO缓冲区。每次新的数据点到达时,将其添加到FIFO缓冲区,这将删除最旧的点,然后使用更新的缓冲区加载mpFXYVector。 wxMathPlot类mpWindow将照顾您需要的其余部分。

A more elegant approach would be a specialization of mpFXYVector which implements the FIFO buffer, using the simple vectors in mpFXYVector. The advantage of this would be that you are holding just one copy of the display data. Unless you are displaying many thousands of points, I doubt the advantage is worth the extra trouble of inheriting from mpFXYVector, rather than simply using the mpFXYVector documented interface.

更优雅的方法是使用mpFXYVector中的简单向量来实现FIFO缓冲区的mpFXYVector的特化。这样做的好处是您只持有一份显示数据。除非你显示了数千个点,否则我怀疑从mpFXYVector继承的额外麻烦,而不是简单地使用mpFXYVector文档界面。

After looking at the details, the only tricky bit is to replace mpFXYVector::SetData() with a new method Add() to add data points as they arrive. The new method needs to manage the mpFXYVector vectors as FIFO buffers, and to re-implement the code to update the bounding box ( which unfortunately was not written with inheritance in mind ).

在查看详细信息之后,唯一棘手的问题是用新方法Add()替换mpFXYVector :: SetData()以在数据到达时添加它们。新方法需要将mpFXYVector向量作为FIFO缓冲区进行管理,并重新实现代码以更新边界框(遗憾的是,这不是用继承编写的)。

The result is that specialization gives a solution with a smaller memory requirement and more flexibility than using a wrapper.

结果是,专业化提供的解决方案具有比使用包装器更小的内存要求和更大的灵活性。

#2


Thanks ravenspoint...!! I did what you said.. It works flawless! here is my AddData() function:

谢谢ravenspoint ...... !!我做了你说的..它完美无瑕!这是我的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;
        }
    }

in the Main() you only have to:

在Main()中你只需要:

m_Vector->AddData(xPos,yPos,vectorX, vectorY);
m_plot->Fit();

#3


I know this is an old thread but I needed to plot a scrolling X axis with wxMathPlot.

我知道这是一个旧线程,但我需要使用wxMathPlot绘制滚动X轴。

I've done a simple modification to jayjo's code to make X axis scrolling work.

我对jayjo的代码做了一个简单的修改,使X轴滚动工作。

I hoe this helps.

我这有帮助。

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;
    }
}

#4


I do not have any personal experience with wxMathPlot, but I have been working with wxWidgets for years and highly recommend it for cross platform gui programming in c++, with that said according to the wxWiki graphics page the Numerix Graphics Library can be used for real time data so maybe that can help you out. Good luck.

我对wxMathPlot没有任何个人经验,但我一直在使用wxWidgets多年,并强烈推荐它用于c ++中的跨平台gui编程,据说根据wxWiki图形页面,Numerix图形库可以实时使用数据也许可以帮助你。祝好运。

#5


Maybe someone will have same problem and will need it... I needed very fast plotting for showing the data from oscilloscope. I was getting the data in packets. I made few changes that made a code a lot of faster. First thing is to change the if state in function SetData from if (xs.size()>0) to if (!xs.empty). Then you should firstly add all of your data packet to the vector

也许有人会遇到同样的问题并需要它...我需要非常快速的绘图来显示示波器的数据。我正在收集数据包中的数据。我做了一些改动,使代码更快。首先是将函数SetData中的if状态从if(xs.size()> 0)更改为if(!xs.empty)。然后,您应该首先将所有数据包添加到向量中

Vector1_X.push_back(x);
Vector1_Y.push_back(y);

And after that you should fit and set data.

之后你应该适合并设置数据。

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

Your code in main function will be longer but function will be faster because you add all data "at once".

主函数中的代码会更长,但函数会更快,因为您“一次”添加所有数据。

#6


We ended up using ChartDirector instead. It has a lot of capability and is fast.

我们最终使用了ChartDirector。它具有很多功能并且速度很快。

#1


I think mpFXYVector is the way to go.

我认为mpFXYVector是要走的路。

The simplest way to deal with this might be to write a wrapper class for mpFXYVector which holds a FIFO buffer of recent data points. Each time a new datapoint arrives, add it to the FIFO buffer, which will drop the oldest point, then load mpFXYVector with the updated buffer. The wxMathPlot class mpWindow will look after the rest of what you need.

处理这个问题的最简单方法可能是为mpFXYVector编写一个包装类,它包含最近数据点的FIFO缓冲区。每次新的数据点到达时,将其添加到FIFO缓冲区,这将删除最旧的点,然后使用更新的缓冲区加载mpFXYVector。 wxMathPlot类mpWindow将照顾您需要的其余部分。

A more elegant approach would be a specialization of mpFXYVector which implements the FIFO buffer, using the simple vectors in mpFXYVector. The advantage of this would be that you are holding just one copy of the display data. Unless you are displaying many thousands of points, I doubt the advantage is worth the extra trouble of inheriting from mpFXYVector, rather than simply using the mpFXYVector documented interface.

更优雅的方法是使用mpFXYVector中的简单向量来实现FIFO缓冲区的mpFXYVector的特化。这样做的好处是您只持有一份显示数据。除非你显示了数千个点,否则我怀疑从mpFXYVector继承的额外麻烦,而不是简单地使用mpFXYVector文档界面。

After looking at the details, the only tricky bit is to replace mpFXYVector::SetData() with a new method Add() to add data points as they arrive. The new method needs to manage the mpFXYVector vectors as FIFO buffers, and to re-implement the code to update the bounding box ( which unfortunately was not written with inheritance in mind ).

在查看详细信息之后,唯一棘手的问题是用新方法Add()替换mpFXYVector :: SetData()以在数据到达时添加它们。新方法需要将mpFXYVector向量作为FIFO缓冲区进行管理,并重新实现代码以更新边界框(遗憾的是,这不是用继承编写的)。

The result is that specialization gives a solution with a smaller memory requirement and more flexibility than using a wrapper.

结果是,专业化提供的解决方案具有比使用包装器更小的内存要求和更大的灵活性。

#2


Thanks ravenspoint...!! I did what you said.. It works flawless! here is my AddData() function:

谢谢ravenspoint ...... !!我做了你说的..它完美无瑕!这是我的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;
        }
    }

in the Main() you only have to:

在Main()中你只需要:

m_Vector->AddData(xPos,yPos,vectorX, vectorY);
m_plot->Fit();

#3


I know this is an old thread but I needed to plot a scrolling X axis with wxMathPlot.

我知道这是一个旧线程,但我需要使用wxMathPlot绘制滚动X轴。

I've done a simple modification to jayjo's code to make X axis scrolling work.

我对jayjo的代码做了一个简单的修改,使X轴滚动工作。

I hoe this helps.

我这有帮助。

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;
    }
}

#4


I do not have any personal experience with wxMathPlot, but I have been working with wxWidgets for years and highly recommend it for cross platform gui programming in c++, with that said according to the wxWiki graphics page the Numerix Graphics Library can be used for real time data so maybe that can help you out. Good luck.

我对wxMathPlot没有任何个人经验,但我一直在使用wxWidgets多年,并强烈推荐它用于c ++中的跨平台gui编程,据说根据wxWiki图形页面,Numerix图形库可以实时使用数据也许可以帮助你。祝好运。

#5


Maybe someone will have same problem and will need it... I needed very fast plotting for showing the data from oscilloscope. I was getting the data in packets. I made few changes that made a code a lot of faster. First thing is to change the if state in function SetData from if (xs.size()>0) to if (!xs.empty). Then you should firstly add all of your data packet to the vector

也许有人会遇到同样的问题并需要它...我需要非常快速的绘图来显示示波器的数据。我正在收集数据包中的数据。我做了一些改动,使代码更快。首先是将函数SetData中的if状态从if(xs.size()> 0)更改为if(!xs.empty)。然后,您应该首先将所有数据包添加到向量中

Vector1_X.push_back(x);
Vector1_Y.push_back(y);

And after that you should fit and set data.

之后你应该适合并设置数据。

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

Your code in main function will be longer but function will be faster because you add all data "at once".

主函数中的代码会更长,但函数会更快,因为您“一次”添加所有数据。

#6


We ended up using ChartDirector instead. It has a lot of capability and is fast.

我们最终使用了ChartDirector。它具有很多功能并且速度很快。