Fixed "phantom vector" issue with plots and crash when plots are resized. See bugs #419 and #423 for details. Also several parameters were changed from char * to const char * in the plotting functions.

This commit is contained in:
Jim Monte 2019-12-10 19:47:00 -05:00 committed by Holger Vogt
parent 8021566265
commit 10415875f4
7 changed files with 785 additions and 529 deletions

View File

@ -47,8 +47,11 @@ quote_gnuplot_string(FILE *stream, char *s)
}
void
ft_gnuplot(double *xlims, double *ylims, char *filename, char *title, char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype, struct dvec *vecs)
void ft_gnuplot(double *xlims, double *ylims,
const char *filename, const char *title,
const char *xlabel, const char *ylabel,
GRIDTYPE gridtype, PLOTTYPE plottype,
struct dvec *vecs)
{
FILE *file, *file_data;
struct dvec *v, *scale = NULL;
@ -82,20 +85,27 @@ ft_gnuplot(double *xlims, double *ylims, char *filename, char *title, char *xlab
extrange = 0.05 * (ylims[1] - ylims[0]);
if (!cp_getvar("gnuplot_terminal", CP_STRING, terminal, sizeof(terminal))) {
if (!cp_getvar("gnuplot_terminal", CP_STRING,
terminal, sizeof(terminal))) {
terminal_type = 1;
} else {
}
else {
terminal_type = 1;
if (cieq(terminal,"png"))
if (cieq(terminal,"png")) {
terminal_type = 2;
if (cieq(terminal,"png/quit"))
}
else if (cieq(terminal,"png/quit")) {
terminal_type = 3;
if (cieq(terminal, "eps"))
}
else if (cieq(terminal, "eps")) {
terminal_type = 4;
if (cieq(terminal, "eps/quit"))
}
else if (cieq(terminal, "eps/quit")) {
terminal_type = 5;
if (cieq(terminal, "xterm"))
}
else if (cieq(terminal, "xterm")) {
terminal_type = 6;
}
}
if (!cp_getvar("xbrushwidth", CP_NUM, &linewidth, 0))
@ -344,10 +354,12 @@ ft_gnuplot(double *xlims, double *ylims, char *filename, char *title, char *xlab
fprintf(cp_out, "writing plot to file %s.eps\n", filename);
(void) sprintf(buf, "gnuplot %s", filename_plt);
}
else if (terminal_type == 6)
else if (terminal_type == 6) {
(void) sprintf(buf, "xterm -e gnuplot %s - &", filename_plt);
else
}
else {
(void) sprintf(buf, "gnuplot -p %s - &", filename_plt);
}
#endif
err = system(buf);
@ -379,8 +391,11 @@ ft_gnuplot(double *xlims, double *ylims, char *filename, char *title, char *xlab
if scale vectors are of same length (there is little risk here!).
Width of numbers printed is set by option 'numdgt'.
*/
void
ft_writesimple(double *xlims, double *ylims, char *filename, char *title, char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype, struct dvec *vecs)
void ft_writesimple(double *xlims, double *ylims,
const char *filename, const char *title,
const char *xlabel, const char *ylabel,
GRIDTYPE gridtype, PLOTTYPE plottype,
struct dvec *vecs)
{
FILE *file_data;
struct dvec *v;

View File

@ -6,13 +6,17 @@
#ifndef ngspice_GNUPLOT_H
#define ngspice_GNUPLOT_H
void ft_gnuplot(double *xlims, double *ylims, char *filename, char *title,
char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype,
struct dvec *vecs);
void ft_gnuplot(double *xlims, double *ylims,
const char *filename, const char *title,
const char *xlabel, const char *ylabel,
GRIDTYPE gridtype, PLOTTYPE plottype,
struct dvec *vecs);
void ft_writesimple(double *xlims, double *ylims, char *filename, char *title,
char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype,
struct dvec *vecs);
void ft_writesimple(double *xlims, double *ylims,
const char *filename, const char *title,
const char *xlabel, const char *ylabel,
GRIDTYPE gridtype, PLOTTYPE plottype,
struct dvec *vecs);
#endif

View File

@ -68,27 +68,28 @@ static char *ticlist = ticbuf;
*
*/
int
gr_init(double *xlims, double *ylims, /* The size of the screen. */
char *xname, char *plotname, /* What to label things. */
char *hcopy, /* The raster file. */
int nplots, /* How many plots there will be. */
int gr_init(double *xlims, double *ylims, /* The size of the screen. */
const char *xname,
const char *plotname, /* What to label things. */
const char *hcopy, /* The raster file. */
int nplots, /* How many plots there will be. */
double xdelta, double ydelta, /* Line increments for the scale. */
GRIDTYPE gridtype, /* The grid type */
PLOTTYPE plottype, /* and the plot type. */
char *xlabel, char *ylabel, /* Labels for axes. */
int xtype, int ytype, /* The types of the data graphed. */
char *pname,
char *commandline) /* For xi_zoomdata() */
GRIDTYPE gridtype, /* The grid type */
PLOTTYPE plottype, /* and the plot type. */
const char *xlabel,
const char *ylabel, /* Labels for axes. */
int xtype, int ytype, /* The types of the data graphed. */
const char *pname,
const char *commandline) /* For xi_zoomdata() */
{
GRAPH *graph;
wordlist *wl;
char *comb_title;
NG_IGNORE(nplots);
if ((graph = NewGraph()) == NULL)
return (FALSE);
if ((graph = NewGraph()) == (GRAPH *) NULL) {
return FALSE;
}
/*
The global currentgraph will always be the current graph.
@ -98,8 +99,10 @@ gr_init(double *xlims, double *ylims, /* The size of the screen. */
graph->onevalue = (xname ? FALSE : TRUE);
/* communicate filename to plot 5 driver */
if (hcopy)
graph->devdep = hcopy;
if (hcopy) {
graph->devdep = copy(hcopy);
graph->n_byte_devdep = strlen(hcopy) + 1;
}
cur.plotno = 0;
@ -108,23 +111,26 @@ gr_init(double *xlims, double *ylims, /* The size of the screen. */
(void) strcpy(pointchars, DEFPOINTCHARS);
if (!cp_getvar("ticmarks", CP_NUM, &graph->ticmarks, 0)) {
if (cp_getvar("ticmarks", CP_BOOL, NULL, 0))
if (cp_getvar("ticmarks", CP_BOOL, NULL, 0)) {
graph->ticmarks = 10;
else
}
else {
graph->ticmarks = 0;
}
}
if (cp_getvar("ticlist", CP_LIST, ticlist, 0)) {
wl = vareval("ticlist");
ticlist = wl_flatten(wl);
graph->ticdata = readtics(ticlist);
} else {
}
else {
graph->ticdata = NULL;
}
if (!xlims || !ylims) {
internalerror("gr_init: no range specified");
return (FALSE);
return FALSE;
}
/* save upper and lower limits */
@ -134,13 +140,14 @@ gr_init(double *xlims, double *ylims, /* The size of the screen. */
graph->data.ymax = ylims[1];
/* get title into plot window */
if (!pname)
if (!pname) {
pname = "(unknown)";
if (!plotname)
}
if (!plotname) {
plotname = "(unknown)";
}
comb_title = tprintf("%s: %s", pname, plotname);
graph->plotname = comb_title;
graph->plotname = tprintf("%s: %s", pname, plotname);
/* note: have enum here or some better convention */
if (NewViewport(graph) == 1) {
@ -167,47 +174,60 @@ gr_init(double *xlims, double *ylims, /* The size of the screen. */
graph->grid.xsized = 0;
if (!graph->onevalue) {
if (xlabel)
graph->grid.xlabel = xlabel;
else
graph->grid.xlabel = xname;
if (xlabel) {
graph->grid.xlabel = copy(xlabel);
}
else {
graph->grid.xlabel = copy(xname);
}
if (ylabel)
graph->grid.ylabel = ylabel;
} else {
if (xlabel)
graph->grid.xlabel = xlabel;
else
graph->grid.xlabel = "real";
if (ylabel) {
graph->grid.ylabel = copy(ylabel);
}
else {
graph->grid.ylabel = (char *) NULL;
}
}
else {
if (xlabel) {
graph->grid.xlabel = copy(xlabel);
}
else {
graph->grid.xlabel = copy("real");
}
if (ylabel)
graph->grid.ylabel = ylabel;
else
graph->grid.ylabel = "imag";
if (ylabel) {
graph->grid.ylabel = copy(ylabel);
}
else {
graph->grid.ylabel = copy("imag");
}
}
gr_resize_internal(graph);
gr_redrawgrid(graph);
/* Set up colors and line styles. */
if (dispdev->numlinestyles == 1)
if (dispdev->numlinestyles == 1) {
cur.linestyle = 0; /* Use the same one all the time. */
else
}
else {
cur.linestyle = 1;
}
/* XXX Special exception for SMITH */
if (dispdev->numcolors > 2 &&
(graph->grid.gridtype == GRID_SMITH ||
graph->grid.gridtype == GRID_SMITHGRID))
{
(graph->grid.gridtype == GRID_SMITH ||
graph->grid.gridtype == GRID_SMITHGRID)) {
cur.color = 3;
} else {
}
else {
cur.color = 1;
}
graph->commandline = copy(commandline);
return (TRUE);
return TRUE;
}
@ -315,8 +335,7 @@ gr_point(struct dvec *dv,
}
static void
gr_start_internal(struct dvec *dv, bool copyvec)
static void gr_start_internal(struct dvec *dv, bool copyvec)
{
struct dveclist *link;
@ -325,34 +344,41 @@ gr_start_internal(struct dvec *dv, bool copyvec)
if (dv->v_type == SV_POLE) {
dv->v_linestyle = 'x';
return;
} else if (dv->v_type == SV_ZERO) {
}
else if (dv->v_type == SV_ZERO) {
dv->v_linestyle = 'o';
return;
}
/* Find a (hopefully) new line style and color. */
if (currentgraph->plottype == PLOT_POINT) {
if (pointchars[cur.linestyle - 1])
if (pointchars[cur.linestyle - 1]) {
cur.linestyle++;
else
}
else {
cur.linestyle = 2;
} else if ((cur.linestyle > 0) && (++cur.linestyle == dispdev->numlinestyles)) {
}
}
else if ((cur.linestyle > 0) &&
(++cur.linestyle == dispdev->numlinestyles)) {
cur.linestyle = 2;
}
if ((cur.color > 0) && (++cur.color == dispdev->numcolors))
cur.color = (((currentgraph->grid.gridtype == GRID_SMITH ||
currentgraph->grid.gridtype == GRID_SMITHGRID) &&
(dispdev->numcolors > 3)) ? 4 : 2);
currentgraph->grid.gridtype == GRID_SMITHGRID) &&
(dispdev->numcolors > 3)) ? 4 : 2);
if (currentgraph->plottype == PLOT_POINT)
if (currentgraph->plottype == PLOT_POINT) {
dv->v_linestyle = pointchars[cur.linestyle - 2];
else
}
else {
dv->v_linestyle = cur.linestyle;
}
dv->v_color = cur.color;
/* save the data so we can refresh */
/* Save the data so we can refresh */
link = TMALLOC(struct dveclist, 1);
link->next = currentgraph->plotdata;
@ -368,17 +394,36 @@ gr_start_internal(struct dvec *dv, bool copyvec)
currentgraph->plotdata = link;
/* Add the scale vector to the list of vectors associated with the plot
* and use the copy instead of the original scale vector */
link = TMALLOC(struct dveclist, 1);
link->next = currentgraph->plotdata;
if (copyvec) {
link->vector = vec_copy(dv->v_scale);
link->vector->v_flags |= VF_PERMANENT;
link->next->vector->v_scale = link->vector;
}
else {
link->vector = dv->v_scale;
}
/* Make the new vector the start of the list of vectors */
currentgraph->plotdata = link;
/* Put the legend entry on the screen. */
drawlegend(currentgraph, cur.plotno++, dv);
}
} /* end of function gr_start_internal */
/* start one plot of a graph */
void
gr_start(struct dvec *dv)
/* Start one plot of a graph */
void gr_start(struct dvec *dv)
{
gr_start_internal(dv, TRUE);
}
} /* end of function gr_start */
/* make sure the linestyles in this graph don't exceed the number of
@ -400,30 +445,28 @@ gr_relinestyle(GRAPH *graph)
/* PN static */
void
drawlegend(GRAPH *graph, int plotno, struct dvec *dv)
void drawlegend(GRAPH *graph, int plotno, struct dvec *dv)
{
int x, y, i;
char buf[16];
x = ((plotno % 2) ? graph->viewportxoff :
((graph->viewport.width) / 2));
y = graph->absolute.height - graph->fontheight
const int x = (plotno % 2) ?
graph->viewportxoff : (graph->viewport.width / 2);
const int x_base = x + graph->viewport.width / 20;
const int y = graph->absolute.height - graph->fontheight
- ((plotno + 2) / 2) * (graph->fontheight);
i = y + graph->fontheight / 2 + 1;
const int i = y + graph->fontheight / 2 + 1;
SetColor(dv->v_color);
if (graph->plottype == PLOT_POINT) {
char buf[16];
(void) sprintf(buf, "%c : ", dv->v_linestyle);
DevDrawText(buf, x + graph->viewport.width / 20
- 3 * graph->fontwidth, y, 0);
} else {
DevDrawText(buf, x_base - 3 * graph->fontwidth, y, 0);
}
else {
SetLinestyle(dv->v_linestyle);
DevDrawLine(x, i, x + graph->viewport.width / 20, i);
DevDrawLine(x, i, x_base, i);
}
SetColor(1);
DevDrawText(dv->v_name, x + graph->viewport.width / 20
+ graph->fontwidth, y, 0);
}
DevDrawText(dv->v_name, x_base + graph->fontwidth, y, 0);
} /* end of function drawlegend */
/* end one plot of a graph */

View File

@ -9,18 +9,20 @@
#include "ngspice/graph.h"
int gr_init(double *xlims, double *ylims,
char *xname, char *plotname,
char *hcopy,
int nplots,
double xdelta, double ydelta,
GRIDTYPE gridtype,
PLOTTYPE plottype,
char *xlabel, char *ylabel,
int xtype, int ytype,
char *pname, char *commandline);
const char *xname,
const char *plotname,
const char *hcopy,
int nplots,
double xdelta, double ydelta,
GRIDTYPE gridtype,
PLOTTYPE plottype,
const char *xlabel,
const char *ylabel, /* Labels for axes. */
int xtype, int ytype,
const char *pname, const char *commandline);
void gr_point(struct dvec *dv,
double newx, double newy,
double oldx, double oldy, int np);
double newx, double newy,
double oldx, double oldy, int np);
void gr_start(struct dvec *dv);
void gr_relinestyle(GRAPH *graph);
void drawlegend(GRAPH *graph, int plotno, struct dvec *dv);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
#ifndef ngspice_PLOTIT_H
#define ngspice_PLOTIT_H
bool plotit(wordlist *wl, char *hcopy, char *devname);
bool plotit(wordlist *wl, const char *hcopy, const char *devname);
#endif

View File

@ -108,7 +108,7 @@ struct graph {
and de-allocated by DestroyGraph.
*/
void *devdep;
size_t n_byte_devdep; /* Size of devdep. Needed to allow copying */
};