/* Last edited on 2007-01-08 03:28:07 by stolfi * Mased on {wplot.cpp} by Margarete Domingues, date: 1/Aug/2006 * Converted to C by J. Stolfi and A. Gomide, 07/jan/2007 */ /* We need to define _GNU_SOURCE to get {asprintf} and {NAN}. */ #define _GNU_SOURCE #include #include #include #include #include "mwplot.h" struct mwplot_t { FILE *pp; /* Pipe to {stdin} of the {gnuplot} process. */ /* These {gnuplot} options apply to subsequent plot commands: */ char *setTerminalCmds; char *fileExtension; /* If not NULL, the current terminal type needs "set output". */ char *setPaletteCmds; char *setPlotStyleCmds; char *splotCommand; /* The {splot} command of {gnuplot}, with some options. */ int splotNeedsXY; /* TRUE iff the current plot style needs X and Y data besides Z */ char *xLabel; /* Label for the X axis. */ char *yLabel; /* Label for the Y axis. */ char *zLabel; /* Label for the Z axis. */ /* Ranges for {plot} or {splot} (NaN if autoscale): */ double xMin, xMax; double yMin, yMax; double zMin, zMax; }; /* INTERNAL PROTOTYPES */ void mwplot_write_set_range_cmd(FILE *pp, char *axis, double vMin, double vMax); /* Sends to {gnuplot} the command "set {axis}range [{vMin}:{vMax}]". If {vMin} or {vMax} is NAN, omits it from the "set range" command. */ void mwplot_write_set_axis_label_cmd(FILE *pp, char *axis, char *txt); /* Sends to {gnuplot} the command "set {axis}label \"{txt}\"", or "unset {axis}label" if {txt} is NULL. */ /* EXTERNAL IMPLEMENTATIONS */ mwplot_t *mwplot_start_gnuplot(int debug) { /* Create the plotter object {wp}: */ mwplot_t *wp = malloc(sizeof(mwplot_t)); assert(wp != NULL); /* Initialize fields of {wp} with sensible defaults: */ mwplot_set_terminal(wp, /*x11*/ 0); mwplot_set_palette(wp, /*blue--red*/ 20); mwplot_set_bivariate_plot_style(wp, /*surface*/ 0); mwplot_set_axis_labels(wp, "X", "Y", "Z"); mwplot_set_ranges(wp, NAN, NAN, NAN, NAN, NAN, NAN); /* Start {gnuplot} and set up a pipe {wp->pp} to it: */ char *execCommand; if (debug) { execCommand = "cat > mwplot.plt"; } else { execCommand = "gnuplot -geometry '800x600' -persist >& /dev/null"; } wp->pp = popen(execCommand, "w"); if (wp->pp == NULL) { fprintf(stderr, "failed starting gnuplot"); exit(-1); } return wp; } void mwplot_stop_gnuplot(mwplot_t *wp) { if (wp->pp != NULL) { pclose(wp->pp); wp->pp = NULL; } free(wp); } void mwplot_set_terminal(mwplot_t *wp, int terminalKind) { wp->setTerminalCmds = NULL; wp->fileExtension = NULL; switch(terminalKind) { case 0: wp->setTerminalCmds = "set terminal x11 0\n"; break; case 10: /*eps */ wp->setTerminalCmds = "set terminal postscript eps enhanced \"Times-Roman\" 12\n"; wp->fileExtension = "eps"; break; case 11: /*eps */ wp->setTerminalCmds = "set terminal postscript eps color enhanced \"Times-Roman\" 12\n"; wp->fileExtension = "eps"; break; case 101: wp->setTerminalCmds = "set terminal png medium " "size 600,600 " "xffffff x000000 " "x202020 x404040 x606060 " "x808080 xA0A0A0 xC0C0C0 xE0E0E0\n"; wp->fileExtension = "png"; break; case 111: wp->setTerminalCmds = "set terminal png " "font arial 14 " "size 600,600\n"; wp->fileExtension = "png"; break; case 200: wp->setTerminalCmds = "set terminal png medium" " size 600 , 600\n"; wp->fileExtension = "png"; break; default: fprintf(stderr, "invalid terminal kind = %d\n", terminalKind); exit(-1); } } void mwplot_set_palette(mwplot_t *wp, int paletteCode) { wp->setPaletteCmds = NULL; switch(paletteCode) { case 10: /* Field palette: dark-red to yellow: */ wp->setPaletteCmds = "set palette defined(" " 0.000 \"yellow\"," " 0.500 \"dark-red\"," " 1.000 \"red\")\n"; break; case 15: /* Field palette: dark-red to yellow: */ wp->setPaletteCmds = "set palette defined (" " 0.000 \"dark-red\"," " 0.300 \"red\"," " 0.600 \"orange\"," " 1.000 \"yellow\")\n"; break; case 20: /* Field palette: dark-blue, blue, yellow, dark red, red: */ wp->setPaletteCmds = "set palette defined (" "-1.000 \"dark-blue\"," "-0.500 \"blue\"," " 0.000 \"yellow\"," " 0.500 \"dark-red\"," " 1.000 \"red\")\n"; break; case 30: /* Field palette: dark-blue, blue, grey, yellow, grey dark red, red: */ wp->setPaletteCmds = "set palette defined (" "-1.000 \"dark-blue\"," "-0.500 \"blue\"," "-0.001 \"light-grey\"," " 0.000 \"yellow\"," " 0.001 \"light-grey\"," " 0.500 \"dark-red\"," " 1.000 \"red\")\n"; break; case 100: /* Palette for the grid points: */ wp->setPaletteCmds = "set palette defined (" "-1 'light-grey'," " 0 'light-grey'," " 0 'blue'," " 1 'blue'," " 2 'magenta'," " 3 'light-green'," " 4 'dark-green'," " 5 'yellow'," " 6 'orange'," " 7 'light-red'," " 8 'dark-red') \n"; break; default: fprintf(stderr, "invalid palette kind = %d\n", paletteCode); break; } } void mwplot_set_bivariate_plot_style(mwplot_t *wp, int splotStyle) { /* Set {wp->splotCommand} and {wp->splotNeedsXY}: */ switch(splotStyle) { case 0: /* 3D graph, painted surface, hidden parts removed. */ wp->splotCommand = "splot '-'\n"; wp->splotNeedsXY = 1; wp->setPlotStyleCmds = "set size square\n" "unset key\n" "set pm3d\n" "set grid\n" "set border\n" "set hidden3d\n" "unset surface\n"; break; case 10: /* 3D graph, painted surface, hidden parts visible. */ wp->splotCommand = "splot '-'\n"; wp->splotNeedsXY = 1; wp->setPlotStyleCmds = "set size square\n" "unset key\n" "set pm3d\n" "set grid\n" "set border\n" "unset hidden3d\n" "unset surface\n"; break; case 20: /* 3D graph, wire mesh. */ wp->splotCommand = "splot '-' w line\n"; wp->splotNeedsXY = 1; wp->setPlotStyleCmds = "set size square\n" "unset key\n" "unset pm3d\n" "unset grid\n" "set border\n" "unset hidden3d\n" "set surface\n"; break; case 100: /* 2D image of grid. */ wp->splotCommand = "splot '-' matrix with points ps 1 pt 5 palette\n"; wp->splotNeedsXY = 0; wp->setPlotStyleCmds = "set size square\n" "unset key\n" "unset pm3d\n" "unset grid\n" "unset border\n" "set ticscale 0 0\n" "set pm3d map\n"; break; default: fprintf(stderr, "invalid splot style = %d\n", splotStyle); break; } } void mwplot_set_axis_labels(mwplot_t *wp, char *xLabel, char *yLabel, char *zLabel) { wp->xLabel = xLabel; wp->yLabel = yLabel; wp->zLabel = zLabel; } void mwplot_set_ranges ( mwplot_t *wp, double xMin, double xMax, double yMin, double yMax, double zMin, double zMax ) { wp->xMin = xMin; wp->xMax = xMax; wp->yMin = yMin; wp->yMax = yMax; wp->zMin = zMin; wp->zMax = zMax; } void mwplot_plot_array ( mwplot_t *wp, char *fileName, int nx, int ny, double dx, double dy, double **A, char *title ) { fputs(wp->setTerminalCmds, wp->pp); if (wp->fileExtension != NULL) { if (fileName == NULL) { fprintf(stderr, "current terminal type requires a file name\n"); exit(-1); } fprintf(wp->pp, "set output \"%s.%s\"\n", fileName, wp->fileExtension); } fprintf(wp->pp, "set title \"%s\"\n", title); fputs(wp->setPaletteCmds, wp->pp); fputs(wp->setPlotStyleCmds,wp->pp); mwplot_write_set_axis_label_cmd(wp->pp, "x", wp->xLabel); mwplot_write_set_axis_label_cmd(wp->pp, "y", wp->yLabel); mwplot_write_set_axis_label_cmd(wp->pp, "z", wp->zLabel); mwplot_write_set_range_cmd(wp->pp, "x", wp->xMin, wp->xMax); mwplot_write_set_range_cmd(wp->pp, "y", wp->yMin, wp->yMax); mwplot_write_set_range_cmd(wp->pp, "z", wp->zMin, wp->zMax); mwplot_write_set_range_cmd(wp->pp, "cb", wp->zMin, wp->zMax); fputs(wp->splotCommand, wp->pp); /* Output the data to be visualized: */ int i, j; for (i = 0; i < nx; i++) { for (j = 0; j < ny; j++) { if (wp->splotNeedsXY) { fprintf(wp->pp, "%f\t%f\t%g\n", i*dx, j*dy, A[i][j]); } else { fprintf(wp->pp, "%3.0f ", A[i][j]); } /*for the grid */ } fputc('\n', wp->pp); } fputs("e\n", wp->pp); fflush(wp->pp); } /* INTERNAL IMPLEMENTATIONS */ void mwplot_write_set_range_cmd(FILE *pp, char *axis, double vMin, double vMax) { fprintf(pp, "set %srange [", axis); if (! isnan(vMin)) { fprintf(pp, "%g", vMin); } fprintf(pp, ":"); if (! isnan(vMax)) { fprintf(pp, "%g", vMax); } fprintf(pp, "]\n"); } void mwplot_write_set_axis_label_cmd(FILE *pp, char *axis, char *txt) { if (txt == NULL) { fprintf(pp, "unset %slabel\n", axis); } else { fprintf(pp, "set %slabel \"%s\"\n", axis, txt); } }