Here is a trivial example which should get you going:
Code:
gnuplot -p -e 'plot "-" u 1:2 notitle w points, (3*x*x-2*x*x*x) notitle w lines' <<ENDOFPOINTS
0.000000 -0.026221
0.050000 -0.013643
0.100000 0.062581
0.150000 0.025971
0.200000 0.112554
0.250000 0.125598
0.300000 0.247062
0.350000 0.249103
0.400000 0.350498
0.450000 0.390436
0.500000 0.486696
0.550000 0.573924
0.600000 0.689009
0.650000 0.694776
0.700000 0.823319
0.750000 0.815785
0.800000 0.909180
0.850000 0.946358
0.900000 0.955216
0.950000 0.953195
1.000000 1.000293
ENDOFPOINTS
Simply put, you execute gnuplot with
-p parameter (so that it'll keep the window persistent), and one or more
-e plotting-command , and feed the data to it via standard input.
From a C++ program, you can feed the data as native floats or doubles. Just use
"-" binary format="%float%float" or
"-" binary format="%double%double" to specify the binary format in the plotting command. You are not limited to 2D points, you can use as many columns as you like; gnuplot can even draw error bars and suchlike.
You can obviously use any file you like, as
- is just a special one which means standard input (when naming data files).
Getting gnuplot to fit the data to some analytical function is just as easy, except that you need to use two pipes: one to send the data, and the other to read the fitted parameters. (Or, again, you could use files instead just as well.) Fortunately, gnuplot will always read all data first, and only output the fitted afterwards afterwards, so you don't need to use nonblocking pipes or reads/writes. There is no risk of deadlock.
The basic plotting command sequence I use for fitting e.g. a cubic function to data is this:
Code:
set print "/dev/null" ;
set fit logfile "/dev/null" errorvariables ;
fit (C0+x*C1+x*x*C2+x*x*x*C3) "-" u 1:2 via C0,C1,C2,C3 ;
set print "-" ;
print C0_err, C1_err, C2_err, C3_err
print C0, C1, C2, C3
For the above data, it will output
Code:
0.0205712962722043 0.182606980227572 0.430512738744765 0.282680275112865
-0.0116818581783575 -0.0153765054167047 3.1346215868934 -2.12470703988004
to standard output. The errors are on the first line, the actual fitted values on the second line. It is useful to redirect standard error to /dev/null, so you don't need to read the verbose fitting stuff.
Assume you do the fit first, and retrieve the fit parameters. (You could do it all at once, if you use temporary files, or more pipes, but let's keep this simple, eh? I prefer pipes, mostly because I like the inherent data security compared to files, but it should not be an issue here.)
See the persistent window you get if you supply the same data to
Code:
gnuplot -p -e '
set title "Title of this plot" ;
set xlabel "Horizontal axis" ;
set ylabel "Vertical axis" ;
set xrange [0:1] ; set yrange [-0.1:1.1] ;
set key on inside center right ;
plot 0 notitle w dots lt -1, 1 notitle w dots lt -1, "-" u 1:2 t "Data points" w points lt -1, (3*x*x-2*x*x*x) t "Original" w lines lt 2, -0.0116818581783575+x*(-0.0153765054167047+x*(3.1346215868934+x*(-2.12470703988004))) t "Fit" w lines lt 1'
Pretty nice, I'd say. You can tune the plot to your heart's content, just head out to the
documentation for details. (The HTML one is for 4.2, see
here for the other manual formats and versions.)
Gnuplot has a pretty friendly command language; I recommend you play with it. You can run it without any parameters, and give it the above commands interactively. Instead of "-", use "
datafilename" to point it to the data to plot or fit.
If you want to save the plot as an SVG file for example, add
Code:
set terminal svg size 1280,720 dynamic enhanced
set output "output.svg"
at the start of the plotting commands. (If you want to put some example images onto a web page, SVG will give you the best quality. You can add a fallback image for Infernet Exploder 8 and prior versions.)
If you want the ability to close the window at will from your C++ program, I recommend you feed the plotting commands to it via standard input, and not in command-line parameters. That way the gnuplot window will close when you close the standard input, and you can update the plot whenever new data comes available, just by sending the plotting commands again (gnuplot will also re-read the data files, it won't cache them). If you do both fitting and plotting, it is usually better to use temporary files so that you only need to save the data once. I recommend using the binary format if you have very large datasets; printing and reading floating-point values from text is surprisingly slow compared to binary data.
If you are comfortable with simple shell scripts, I recommend you prototype the stuff with shell scripts first, considering all the different approaches (wrt. pipes or temporary files, persistent or input-controlled gnuplot window, and so on). It should be fun. Only start coding when you know the results will satisfy your needs.