Browse Source

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.

pre-master-46
Jim Monte 6 years ago
committed by Holger Vogt
parent
commit
57ffe1769f
  1. 41
      src/frontend/plotting/gnuplot.c
  2. 16
      src/frontend/plotting/gnuplot.h
  3. 199
      src/frontend/plotting/graf.c
  4. 24
      src/frontend/plotting/graf.h
  5. 1024
      src/frontend/plotting/plotit.c
  6. 2
      src/frontend/plotting/plotit.h
  7. 2
      src/include/ngspice/graph.h

41
src/frontend/plotting/gnuplot.c

@ -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; FILE *file, *file_data;
struct dvec *v, *scale = NULL; 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]); 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; terminal_type = 1;
} else {
}
else {
terminal_type = 1; terminal_type = 1;
if (cieq(terminal,"png"))
if (cieq(terminal,"png")) {
terminal_type = 2; terminal_type = 2;
if (cieq(terminal,"png/quit"))
}
else if (cieq(terminal,"png/quit")) {
terminal_type = 3; terminal_type = 3;
if (cieq(terminal, "eps"))
}
else if (cieq(terminal, "eps")) {
terminal_type = 4; terminal_type = 4;
if (cieq(terminal, "eps/quit"))
}
else if (cieq(terminal, "eps/quit")) {
terminal_type = 5; terminal_type = 5;
if (cieq(terminal, "xterm"))
}
else if (cieq(terminal, "xterm")) {
terminal_type = 6; terminal_type = 6;
}
} }
if (!cp_getvar("xbrushwidth", CP_NUM, &linewidth, 0)) 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); fprintf(cp_out, "writing plot to file %s.eps\n", filename);
(void) sprintf(buf, "gnuplot %s", filename_plt); (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); (void) sprintf(buf, "xterm -e gnuplot %s - &", filename_plt);
else
}
else {
(void) sprintf(buf, "gnuplot -p %s - &", filename_plt); (void) sprintf(buf, "gnuplot -p %s - &", filename_plt);
}
#endif #endif
err = system(buf); 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!). if scale vectors are of same length (there is little risk here!).
Width of numbers printed is set by option 'numdgt'. 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; FILE *file_data;
struct dvec *v; struct dvec *v;

16
src/frontend/plotting/gnuplot.h

@ -6,13 +6,17 @@
#ifndef ngspice_GNUPLOT_H #ifndef ngspice_GNUPLOT_H
#define 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 #endif

199
src/frontend/plotting/graf.c

@ -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. */ 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; GRAPH *graph;
wordlist *wl; wordlist *wl;
char *comb_title;
NG_IGNORE(nplots); 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. 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); graph->onevalue = (xname ? FALSE : TRUE);
/* communicate filename to plot 5 driver */ /* 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; cur.plotno = 0;
@ -108,23 +111,26 @@ gr_init(double *xlims, double *ylims, /* The size of the screen. */
(void) strcpy(pointchars, DEFPOINTCHARS); (void) strcpy(pointchars, DEFPOINTCHARS);
if (!cp_getvar("ticmarks", CP_NUM, &graph->ticmarks, 0)) { 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; graph->ticmarks = 10;
else
}
else {
graph->ticmarks = 0; graph->ticmarks = 0;
}
} }
if (cp_getvar("ticlist", CP_LIST, ticlist, 0)) { if (cp_getvar("ticlist", CP_LIST, ticlist, 0)) {
wl = vareval("ticlist"); wl = vareval("ticlist");
ticlist = wl_flatten(wl); ticlist = wl_flatten(wl);
graph->ticdata = readtics(ticlist); graph->ticdata = readtics(ticlist);
} else {
}
else {
graph->ticdata = NULL; graph->ticdata = NULL;
} }
if (!xlims || !ylims) { if (!xlims || !ylims) {
internalerror("gr_init: no range specified"); internalerror("gr_init: no range specified");
return (FALSE);
return FALSE;
} }
/* save upper and lower limits */ /* 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]; graph->data.ymax = ylims[1];
/* get title into plot window */ /* get title into plot window */
if (!pname)
if (!pname) {
pname = "(unknown)"; pname = "(unknown)";
if (!plotname)
}
if (!plotname) {
plotname = "(unknown)"; 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 */ /* note: have enum here or some better convention */
if (NewViewport(graph) == 1) { if (NewViewport(graph) == 1) {
@ -167,47 +174,60 @@ gr_init(double *xlims, double *ylims, /* The size of the screen. */
graph->grid.xsized = 0; graph->grid.xsized = 0;
if (!graph->onevalue) { 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_resize_internal(graph);
gr_redrawgrid(graph); gr_redrawgrid(graph);
/* Set up colors and line styles. */ /* Set up colors and line styles. */
if (dispdev->numlinestyles == 1)
if (dispdev->numlinestyles == 1) {
cur.linestyle = 0; /* Use the same one all the time. */ cur.linestyle = 0; /* Use the same one all the time. */
else
}
else {
cur.linestyle = 1; cur.linestyle = 1;
}
/* XXX Special exception for SMITH */ /* XXX Special exception for SMITH */
if (dispdev->numcolors > 2 && 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; cur.color = 3;
} else {
}
else {
cur.color = 1; cur.color = 1;
} }
graph->commandline = copy(commandline); 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; struct dveclist *link;
@ -325,34 +344,41 @@ gr_start_internal(struct dvec *dv, bool copyvec)
if (dv->v_type == SV_POLE) { if (dv->v_type == SV_POLE) {
dv->v_linestyle = 'x'; dv->v_linestyle = 'x';
return; return;
} else if (dv->v_type == SV_ZERO) {
}
else if (dv->v_type == SV_ZERO) {
dv->v_linestyle = 'o'; dv->v_linestyle = 'o';
return; return;
} }
/* Find a (hopefully) new line style and color. */ /* Find a (hopefully) new line style and color. */
if (currentgraph->plottype == PLOT_POINT) { if (currentgraph->plottype == PLOT_POINT) {
if (pointchars[cur.linestyle - 1])
if (pointchars[cur.linestyle - 1]) {
cur.linestyle++; cur.linestyle++;
else
}
else {
cur.linestyle = 2; cur.linestyle = 2;
} else if ((cur.linestyle > 0) && (++cur.linestyle == dispdev->numlinestyles)) {
}
}
else if ((cur.linestyle > 0) &&
(++cur.linestyle == dispdev->numlinestyles)) {
cur.linestyle = 2; cur.linestyle = 2;
} }
if ((cur.color > 0) && (++cur.color == dispdev->numcolors)) if ((cur.color > 0) && (++cur.color == dispdev->numcolors))
cur.color = (((currentgraph->grid.gridtype == GRID_SMITH || 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]; dv->v_linestyle = pointchars[cur.linestyle - 2];
else
}
else {
dv->v_linestyle = cur.linestyle; dv->v_linestyle = cur.linestyle;
}
dv->v_color = cur.color; 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 = TMALLOC(struct dveclist, 1);
link->next = currentgraph->plotdata; link->next = currentgraph->plotdata;
@ -368,17 +394,36 @@ gr_start_internal(struct dvec *dv, bool copyvec)
currentgraph->plotdata = link; 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. */ /* Put the legend entry on the screen. */
drawlegend(currentgraph, cur.plotno++, dv); 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); gr_start_internal(dv, TRUE);
}
} /* end of function gr_start */
/* make sure the linestyles in this graph don't exceed the number of /* make sure the linestyles in this graph don't exceed the number of
@ -400,30 +445,28 @@ gr_relinestyle(GRAPH *graph)
/* PN static */ /* 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); - ((plotno + 2) / 2) * (graph->fontheight);
i = y + graph->fontheight / 2 + 1;
const int i = y + graph->fontheight / 2 + 1;
SetColor(dv->v_color); SetColor(dv->v_color);
if (graph->plottype == PLOT_POINT) { if (graph->plottype == PLOT_POINT) {
char buf[16];
(void) sprintf(buf, "%c : ", dv->v_linestyle); (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); SetLinestyle(dv->v_linestyle);
DevDrawLine(x, i, x + graph->viewport.width / 20, i);
DevDrawLine(x, i, x_base, i);
} }
SetColor(1); 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 */ /* end one plot of a graph */

24
src/frontend/plotting/graf.h

@ -9,18 +9,20 @@
#include "ngspice/graph.h" #include "ngspice/graph.h"
int gr_init(double *xlims, double *ylims, 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, 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_start(struct dvec *dv);
void gr_relinestyle(GRAPH *graph); void gr_relinestyle(GRAPH *graph);
void drawlegend(GRAPH *graph, int plotno, struct dvec *dv); void drawlegend(GRAPH *graph, int plotno, struct dvec *dv);

1024
src/frontend/plotting/plotit.c
File diff suppressed because it is too large
View File

2
src/frontend/plotting/plotit.h

@ -1,6 +1,6 @@
#ifndef ngspice_PLOTIT_H #ifndef ngspice_PLOTIT_H
#define 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 #endif

2
src/include/ngspice/graph.h

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

Loading…
Cancel
Save