📄 plotit.c
字号:
/* $Id: plotit.c,v 1.6 2005/05/28 17:31:49 sjborley Exp $ */#include <ngspice.h>#include <bool.h>#include <wordlist.h>#include <graph.h>#include <cpdefs.h>#include <pnode.h>#include <sim.h>#include <fteext.h>#include <circuits.h>#include <variable.h>#include "plotit.h"#include "agraf.h"#include "xgraph.h"#include "graf.h"static wordlist *wl_root;static bool sameflag;/* This routine gets parameters from the command line, which are of * the form "name number ..." It returns a pointer to the parameter * values. */static double *getlims(wordlist *wl, char *name, int number){ double *d, *td; wordlist *beg, *wk; char *ss; int n; for (beg = wl; beg; beg = beg->wl_next) { if (eq(beg->wl_word, name)) { if (beg == wl) { fprintf(cp_err, "Syntax error: looking for plot parameters \"%s\".\n", name); return (NULL); } wk = beg; if (number) { d = (double *) tmalloc(sizeof (double) * number); for (n = 0; n < number; n++) { wk = wk->wl_next; if (!wk) { fprintf(cp_err, "Syntax error: not enough parameters for \"%s\".\n", name); return (NULL); } ss = wk->wl_word; td = ft_numparse(&ss, FALSE); if (td == NULL) goto bad; d[n] = *td; } } else /* Minor hack... */ d = (double *) 1; if (beg->wl_prev) beg->wl_prev->wl_next = wk->wl_next; if (wk->wl_next) { wk->wl_next->wl_prev = beg->wl_prev; wk->wl_next = NULL; } if (beg != wl_root) wl_free(beg); return (d); } } return (NULL);bad: fprintf(cp_err, "Syntax error: bad parameters for \"%s\".\n", name); return (NULL);}/* Extend a data vector to length by replicating the last element, or * truncate it if it is too long. */static voidxtend(struct dvec *v, int length){ int i; complex c, *oc; double d, *od; if (v->v_length == length) return; if (v->v_length > length) { v->v_length = length; return; } if (isreal(v)) { od = v->v_realdata; v->v_realdata = (double *) tmalloc(length * sizeof (double)); for (i = 0; i < v->v_length; i++) v->v_realdata[i] = od[i]; d = od[--i]; while (i < length) v->v_realdata[i++] = d; tfree(od); } else { oc = v->v_compdata; v->v_compdata = (complex *) tmalloc(length * sizeof (complex)); for (i = 0; i < v->v_length; i++) { realpart(&v->v_compdata[i]) = realpart(&oc[i]); imagpart(&v->v_compdata[i]) = imagpart(&oc[i]); } realpart(&c) = realpart(&oc[--i]); imagpart(&c) = imagpart(&oc[i]); while (i < length) { realpart(&v->v_compdata[i]) = realpart(&c); imagpart(&v->v_compdata[i++]) = imagpart(&c); tfree(oc); } } v->v_length = length; return;}/* Collapse every *xcomp elements into one, and use only the elements * between xind[0] and xind[1]. */static voidcompress(struct dvec *d, double *xcomp, double *xind){ int cfac, ihi, ilo, newlen, i; int sz = isreal(d) ? sizeof (double) : sizeof (complex); double *dd; complex *cc; if (xind) { ilo = (int) xind[0]; ihi = (int) xind[1]; if ((ilo <= ihi) && (ilo > 0) && (ilo < d->v_length) && (ihi > 1) && (ihi <= d->v_length)) { newlen = ihi - ilo; dd = (double *) tmalloc(newlen * sz); cc = (complex *) dd; if (isreal(d)) { bcopy((char *) (d->v_realdata + ilo), (char *) dd, newlen * sz); tfree(d->v_realdata); d->v_realdata = dd; } else { bcopy((char *) (d->v_compdata + ilo), (char *) cc, newlen * sz); tfree(d->v_compdata); d->v_compdata = cc; } d->v_length = newlen; } } if (xcomp) { cfac = (int) *xcomp; if ((cfac > 1) && (cfac < d->v_length)) { for (i = 0; i * cfac < d->v_length; i++) if (isreal(d)) d->v_realdata[i] = d->v_realdata[i * cfac]; else d->v_compdata[i] = d->v_compdata[i * cfac]; d->v_length = i; } } return;}/* Check for and remove a one-word keyword. */static boolgetflag(wordlist *wl, char *name){ while (wl) { if (eq(wl->wl_word, name)) { if (wl->wl_prev) wl->wl_prev->wl_next = wl->wl_next; if (wl->wl_next) wl->wl_next->wl_prev = wl->wl_prev; return (TRUE); } wl = wl->wl_next; } return (FALSE);}/* Return a parameter of the form "xlabel foo" */static char *getword(wordlist *wl, char *name){ wordlist *beg; char *s; for (beg = wl; beg; beg = beg->wl_next) { if (eq(beg->wl_word, name)) { if ((beg == wl) || !beg->wl_next) { fprintf(cp_err, "Syntax error: looking for plot keyword at \"%s\".\n", name); return (NULL); } s = copy(beg->wl_next->wl_word); beg->wl_prev->wl_next = beg->wl_next->wl_next; if (beg->wl_next->wl_next) beg->wl_next->wl_next->wl_prev = beg->wl_prev; beg->wl_next->wl_next = NULL; wl_free(beg); return (s); } } return (NULL);}/* The common routine for all plotting commands. This does hardcopy * and graphics plotting. */boolplotit(wordlist *wl, char *hcopy, char *devname){ /* All these things are static so that "samep" will work. */ static double *xcompress = NULL, *xindices = NULL; static double *xlim = NULL, *ylim = NULL; static double *xdelta = NULL, *ydelta = NULL; static char *xlabel = NULL, *ylabel = NULL, *title = NULL; static bool nointerp = FALSE; static GRIDTYPE gtype = GRID_LIN; static PLOTTYPE ptype = PLOT_LIN; bool gfound = FALSE, pfound = FALSE, oneval = FALSE; double *dd, ylims[2], xlims[2]; struct pnode *n, *names; struct dvec *dv, *d = NULL, *vecs = NULL, *lv, *lastvs = NULL; char *xn; int i, j, xt; double tt, mx, my, rad; wordlist *wwl, *tw; char cline[BSIZE_SP], buf[BSIZE_SP], *pname; int newlen; struct dvec *v, *newv_scale; double *newdata, *newscale; double tstep, tstart, tstop, ttime; /* return value, error by default */ bool rtn = FALSE; if (!wl) goto quit1; wl_root = wl; /* First get the command line, without the limits. */ wwl = wl_copy(wl); (void) getlims(wwl, "xl", 2); (void) getlims(wwl, "xlimit", 2); (void) getlims(wwl, "yl", 2); (void) getlims(wwl, "ylimit", 2); pname = wl_flatten(wwl); (void) sprintf(cline, "plot %s", pname); tfree(pname); wl_free(wwl); /* Now extract all the parameters. */ /* In case the parameter is the first on the line, we need a * "buffer" word. Use previous word up the chain if available, * Otherwise create one. */ if(wl->wl_prev) { wl = wl->wl_prev; tw = NULL; /* Not used, so must be NULL */ } else { tw = alloc(struct wordlist); wl->wl_prev = tw; tw->wl_next = wl; wl = tw; tw->wl_word = ""; } sameflag = getflag(wl, "samep"); if (!sameflag || !xlim) { xlim = getlims(wl, "xl", 2); if (!xlim) xlim = getlims(wl, "xlimit", 2); } else { (void) getlims(wl, "xl", 2); (void) getlims(wl, "xlimit", 2); } if (!sameflag || !ylim) { ylim = getlims(wl, "yl", 2); if (!ylim) ylim = getlims(wl, "ylimit", 2); } else { (void) getlims(wl, "yl", 2); (void) getlims(wl, "ylimit", 2); } if (!sameflag || !xcompress) { xcompress = getlims(wl, "xcompress", 1); if (!xcompress) xcompress = getlims(wl, "xcomp", 1); } else { (void) getlims(wl, "xcompress", 1); (void) getlims(wl, "xcomp", 1); } if (!sameflag || !xindices) { xindices = getlims(wl, "xindices", 2); if (!xindices) xindices = getlims(wl, "xind", 2); } else { (void) getlims(wl, "xindices", 2); (void) getlims(wl, "xind", 2); } if (!sameflag || !xdelta) { xdelta = getlims(wl, "xdelta", 1); if (!xdelta) xdelta = getlims(wl, "xdel", 1); } else { (void) getlims(wl, "xdelta", 1); (void) getlims(wl, "xdel", 1); } if (!sameflag || !ydelta) { ydelta = getlims(wl, "ydelta", 1); if (!ydelta) ydelta = getlims(wl, "ydel", 1); } else { (void) getlims(wl, "ydelta", 1); (void) getlims(wl, "ydel", 1); } /* Get the grid type and the point type. Note we can't do if-else * here because we want to catch all the grid types. */ if (getflag(wl, "lingrid")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_LIN; gfound = TRUE; } } if (getflag(wl, "loglog")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_LOGLOG; gfound = TRUE; } } if (getflag(wl, "nogrid")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_NONE; gfound = TRUE; } } if (getflag(wl, "linear")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_LIN; gfound = TRUE; } } if (getflag(wl, "xlog")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_XLOG; gfound = TRUE; } } if (getflag(wl, "ylog")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_YLOG; gfound = TRUE; } } if (getflag(wl, "polar")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_POLAR; gfound = TRUE; } } if (getflag(wl, "smith")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_SMITH; gfound = TRUE; } } if (getflag(wl, "smithgrid")) { if (gfound) fprintf(cp_err, "Warning: too many grid types given\n"); else { gtype = GRID_SMITHGRID; gfound = TRUE; } } if (!sameflag && !gfound) { if (cp_getvar("gridstyle", VT_STRING, buf)) { if (eq(buf, "lingrid")) gtype = GRID_LIN; else if (eq(buf, "loglog")) gtype = GRID_LOGLOG; else if (eq(buf, "xlog")) gtype = GRID_XLOG; else if (eq(buf, "ylog")) gtype = GRID_YLOG; else if (eq(buf, "smith")) gtype = GRID_SMITH; else if (eq(buf, "smithgrid")) gtype = GRID_SMITHGRID; else if (eq(buf, "polar")) gtype = GRID_POLAR; else if (eq(buf, "nogrid")) gtype = GRID_NONE; else { fprintf(cp_err, "Warning: strange grid type %s\n", buf); gtype = GRID_LIN; } gfound = TRUE; } else gtype = GRID_LIN; } /* Now get the point type. */ if (getflag(wl, "linplot")) { if (pfound) fprintf(cp_err, "Warning: too many plot types given\n"); else { ptype = PLOT_LIN; pfound = TRUE; } } if (getflag(wl, "combplot")) { if (pfound) fprintf(cp_err, "Warning: too many plot types given\n"); else { ptype = PLOT_COMB; pfound = TRUE; } } if (getflag(wl, "pointplot")) { if (pfound) fprintf(cp_err, "Warning: too many plot types given\n"); else { ptype = PLOT_POINT; pfound = TRUE; } } if (!sameflag && !pfound) { if (cp_getvar("plotstyle", VT_STRING, buf)) { if (eq(buf, "linplot")) ptype = PLOT_LIN; else if (eq(buf, "combplot")) ptype = PLOT_COMB; else if (eq(buf, "pointplot"))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -