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:
parent
8021566265
commit
10415875f4
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue