问题
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?
回答1:
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).
回答2:
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);
来源:https://stackoverflow.com/questions/4705435/passing-data-from-c-to-gnuplot-example-using-gnuplot-iostream-interface