问题
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