从 C++ 传递数据gnuplot 示例(使用 Gnuplot-iostream 接口)

发布于 2024-10-12 06:15:22 字数 522 浏览 3 评论 0原文

我刚刚接触到 Dan Stahlke 的 gnuplot C++ I/O 接口,它使我免于“自己动手”。不幸的是,没有太多的例子,并且 ios 没有真正的文档。

我的 C++ 项目中有以下数据类型:

struct Data
{
  std::string datestr;  // x axis value
  float f1;             // y axis series 1
  float f2;             // y axis series 2
  float f3;             // y axis series 3
};


typedef std::vector<Data> Dataset;

我想从 C++ 传递一个数据集变量,以便我可以绘制数据(X 轴上的日期,Y 轴上绘制为时间序列的 3 个数字)。

谁能告诉我如何将 Dataset 变量从 C++ 传输到 gnuplot (使用 Gnuplot-iostream 接口)并使用传入的数据制作一个简单的绘图?

I have just come accross Dan Stahlke's gnuplot C++ I/O interface, which saves me from "rolling my own". Unfortunately, there are not too may examples and there ios no real documentation.

I have the following data types in my C++ project:

struct Data
{
  std::string datestr;  // x axis value
  float f1;             // y axis series 1
  float f2;             // y axis series 2
  float f3;             // y axis series 3
};


typedef std::vector<Data> Dataset;

I want to pass a Dataset variable from C++, so that I can plot the data (dates on the X axis, and the 3 numbers plotted as time series on the Y axis).

Can anyone show me how to transfer the Dataset variable from C++ to gnuplot (using the Gnuplot-iostream interface) and make a simple plot using the passed in data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

骄兵必败 2024-10-19 06:15:22

我最近向 git 推送了一个新版本,这使得支持这样的自定义数据类型变得很容易。为了支持您的struct Data,您可以提供 TextSender 类的特化。这是一个完整的示例,使用您定义的结构。

#include <vector>
#include "gnuplot-iostream.h"

struct Data {
    std::string datestr;  // x axis value
    float f1;             // y axis series 1
    float f2;             // y axis series 2
    float f3;             // y axis series 3
};

typedef std::vector<Data> Dataset;

namespace gnuplotio {
    template<>
    struct TextSender<Data> {
        static void send(std::ostream &stream, const Data &v) {
            TextSender<std::string>::send(stream, v.datestr);
            stream << " ";
            TextSender<float>::send(stream, v.f1);
            stream << " ";
            TextSender<float>::send(stream, v.f2);
            stream << " ";
            TextSender<float>::send(stream, v.f3);

            // This works too, but the longer version above gives
            // gnuplot-iostream a chance to format the numbers itself (such as
            // using a platform-independent 'nan' string).
            //stream << v.datestr << " " << v.f1 << " " << v.f2 << " " << v.f3;
        }
    };
}

int main() {
    Dataset x(2);
    // The http://www.gnuplot.info/demo/timedat.html example uses a tab between
    // date and time, but this doesn't seem to work (gnuplot interprets it as
    // two columns).  So I use a comma.
    x[0].datestr = "01/02/2003,12:34";
    x[0].f1 = 1;
    x[0].f2 = 2;
    x[0].f3 = 3;
    x[1].datestr = "02/04/2003,07:11";
    x[1].f1 = 10;
    x[1].f2 = 20;
    x[1].f3 = 30;

    Gnuplot gp;
    gp << "set timefmt \"%d/%m/%y,%H:%M\"\n";
    gp << "set xdata time\n";
    gp << "plot '-' using 1:2 with lines\n";
    gp.send1d(x);

    return 0;
}

可以执行类似的操作来支持以二进制格式发送数据。有关示例,请参阅 git 存储库中的 example-data-1d.cc

或者,可以通过重写运算符<<(std::ostream &, ...)来支持这样的自定义数据类型。

另一种选择是使用 std::tuple (在 C++11 中提供)或 boost::tuple 而不是定义自己的结构。这些都是开箱即用的支持(好吧,现在是了,但在您提出问题时还没有)。

I have recently pushed a new version to git which makes it easy to support custom datatypes such as this. To support your struct Data, you can provide a specialization of the TextSender class. Here is a complete example, using the struct you defined.

#include <vector>
#include "gnuplot-iostream.h"

struct Data {
    std::string datestr;  // x axis value
    float f1;             // y axis series 1
    float f2;             // y axis series 2
    float f3;             // y axis series 3
};

typedef std::vector<Data> Dataset;

namespace gnuplotio {
    template<>
    struct TextSender<Data> {
        static void send(std::ostream &stream, const Data &v) {
            TextSender<std::string>::send(stream, v.datestr);
            stream << " ";
            TextSender<float>::send(stream, v.f1);
            stream << " ";
            TextSender<float>::send(stream, v.f2);
            stream << " ";
            TextSender<float>::send(stream, v.f3);

            // This works too, but the longer version above gives
            // gnuplot-iostream a chance to format the numbers itself (such as
            // using a platform-independent 'nan' string).
            //stream << v.datestr << " " << v.f1 << " " << v.f2 << " " << v.f3;
        }
    };
}

int main() {
    Dataset x(2);
    // The http://www.gnuplot.info/demo/timedat.html example uses a tab between
    // date and time, but this doesn't seem to work (gnuplot interprets it as
    // two columns).  So I use a comma.
    x[0].datestr = "01/02/2003,12:34";
    x[0].f1 = 1;
    x[0].f2 = 2;
    x[0].f3 = 3;
    x[1].datestr = "02/04/2003,07:11";
    x[1].f1 = 10;
    x[1].f2 = 20;
    x[1].f3 = 30;

    Gnuplot gp;
    gp << "set timefmt \"%d/%m/%y,%H:%M\"\n";
    gp << "set xdata time\n";
    gp << "plot '-' using 1:2 with lines\n";
    gp.send1d(x);

    return 0;
}

A similar thing can be done to support sending the data in a binary format. See example-data-1d.cc from the git repo for an example.

Alternatively, custom datatypes like this can be supported by overriding operator<<(std::ostream &, ...).

Another option is to use std::tuple (available in C++11) or boost::tuple instead of defining your own struct. These are supported out of the box (well, now they are, they weren't at the time that you asked the question).

左耳近心 2024-10-19 06:15:22

您看过 gnuplot-iostream 附带的示例吗?

它们有点稀疏,但它们展示了如何从一系列数据点创建绘图:

Gnuplot gp;

gp << "set terminal png\n";

std::vector<double> y_pts;
for(int i=0; i<1000; i++) {
    double y = (i/500.0-1) * (i/500.0-1);
    y_pts.push_back(y);
}

gp << "set output 'my_graph_1.png'\n";
gp << "plot '-' with lines, sin(x/200) with lines\n";
gp.send(y_pts);

Did you have a look the examples that come with gnuplot-iostream?

They are a bit sparse but they show how to create a plot from a series of data points:

Gnuplot gp;

gp << "set terminal png\n";

std::vector<double> y_pts;
for(int i=0; i<1000; i++) {
    double y = (i/500.0-1) * (i/500.0-1);
    y_pts.push_back(y);
}

gp << "set output 'my_graph_1.png'\n";
gp << "plot '-' with lines, sin(x/200) with lines\n";
gp.send(y_pts);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文