Jspice3
graf.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1988 Jeffrey M. Hsu
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * "plot" command graphics.
10  */
11 
12 #include "spice.h"
13 #include "ftedefs.h"
14 #include "plotdefs.h"
15 
16 /* invariant: currentgraph contains the current graph */
17 
18 /* These are what gets plotted as points when you specify point plots */
19 static char pointchars[128];
20 #define DEFPOINTCHARS "oxabcdefhgijklmnpqrstuvwyz"
21 
22 #ifdef __STDC__
23 extern void plottrace(struct dvec*,struct dvec*,int);
24 static void do_plot_trace(struct dvec*,struct dvec*,int);
25 static void plotinterval(struct dvec*,double,double,double*,int,bool);
26 static GRDATA copydveclist(GRDATA);
27 static void freedveclist(GRDATA);
28 static void initdvecs(GRAPH*);
29 static void drawlegend(int,struct dvec*);
30 static void resize(GRAPH*);
31 static void redraw(GRAPH*);
32 static void restoretext(GRAPH*);
33 #else
34 extern void plottrace();
35 static void do_plot_trace();
36 static void plotinterval();
37 static GRDATA copydveclist();
38 static void freedveclist();
39 static void initdvecs();
40 static void drawlegend();
41 static void resize();
42 static void redraw();
43 static void restoretext();
44 #endif
45 
46 
47 /* ARGSUSED */
48 GRAPH *
49 gr_init(dl0,grp)
50 
51 /*
52  * Start of a new graph.
53  * Fill in the data that gets displayed.
54  * Difference from old gr_init:
55  * we don't try to determine the look of the screen from here
56  * leave to lower level routines
57  *
58  */
59 struct dvlist *dl0; /* List of dvecs to plot. */
60 char *grp;
61 {
62  struct grinit *gr = (struct grinit*)grp;
63  GRAPH *graph;
64  int b;
65  char *comb_title;
66  struct dvec *d;
67  extern char *kw_polydegree, *kw_pointchars, *kw_ticmarks;
68 
69  if (!gr->xlims || !gr->ylims) {
70  internalerror("gr_init: no range specified");
71  return (NULL);
72  }
73 
74  if (!(graph = NewGraph())) {
75  return (NULL);
76  }
77 
78  graph->graphtype = GR_PLOT;
79  graph->onevalue = (gr->xname ? false : true);
80 
81  /* communicate filename to hardcopy driver */
82  if (gr->hcopy) {
83  graph->devdep = gr->hcopy;
84  }
85 
86  if (!cp_getvar(kw_polydegree, VT_NUM, (char *) &graph->degree))
87  graph->degree = 1;
88 
89  if (!cp_getvar(kw_pointchars, VT_STRING, pointchars))
91 
92  if (!cp_getvar(kw_ticmarks, VT_NUM, (char *) &graph->ticmarks)) {
93  if (cp_getvar(kw_ticmarks, VT_BOOL, (char *) &b))
94  graph->ticmarks = 10;
95  else
96  graph->ticmarks = 0;
97  }
98 
99  /* set upper and lower limits */
100  graph->datawindow.xmin = gr->xlims[0];
101  graph->datawindow.xmax = gr->xlims[1];
102  graph->datawindow.ymin = gr->ylims[0];
103  graph->datawindow.ymax = gr->ylims[1];
104 
105  graph->grid.gridtype = gr->gridtype;
106  graph->plottype = gr->plottype;
107  graph->grid.xdatatype = gr->xtype;
108  graph->grid.ydatatype = gr->ytype;
109  graph->grid.xdelta = gr->xdelta;
110  graph->grid.ydelta = gr->ydelta;
111 
112  if (!graph->onevalue) {
113  if (gr->xlabel) {
114  graph->grid.xlabel = copy(gr->xlabel);
115  }
116  else {
117  graph->grid.xlabel = copy(gr->xname);
118  }
119  if (gr->ylabel) {
120  graph->grid.ylabel = copy(gr->ylabel);
121  }
122  }
123  else {
124  if (gr->xlabel) {
125  graph->grid.xlabel = copy(gr->xlabel);
126  }
127  else {
128  graph->grid.xlabel = copy("real");
129  }
130  if (gr->ylabel) {
131  graph->grid.ylabel = copy(gr->ylabel);
132  }
133  else {
134  graph->grid.ylabel = copy("imag");
135  }
136  }
137 
138  if (!gr->pname)
139  gr->pname = "(unknown)";
140  if (!gr->plotname)
141  gr->plotname = "(unknown)";
142  comb_title = tmalloc(strlen(gr->plotname) + strlen(gr->pname) + 3);
143  sprintf(comb_title, "%s: %s", gr->pname, gr->plotname);
144  graph->plotname = comb_title;
145  graph->commandline = copy(gr->commandline);
146 
147  graph->destroy = freedveclist;
148  graph->copydata = copydveclist;
149  graph->redraw = redraw;
150 
151  graph->plotdata = (GRDATA)dl0;
152  initdvecs(graph);
153 
154  if (DevNewViewport(graph) == 1) {
155  fprintf(cp_err, "Can't open viewport for graphics.\n");
156  DestroyGraph(graph->graphid);
157  return (NULL);
158  }
159 
160  if (!dispdev->windows) {
161  redraw(graph);
162  }
163  return (graph);
164 }
165 
166 
167 void
169 
170 /* end a plot */
171 {
172  char buf[BSIZE_SP];
173  char *text = "Enter p for hardcopy, return to continue";
174  char *text1 = "Hit p for hardcopy, any other key to continue";
175  char c;
176  int x, y;
179  extern char *kw_device;
180 
181  buf[0] = 0;
182  DevUpdate();
183  if (!dispdev->windows && !dispdev->hardcopy) {
184 
185  if (cp_getvar(kw_device, VT_STRING, buf)
186  && prefix("/dev/tty", buf)) {
187  fprintf(cp_err, "%s", text);
188  fflush(cp_err);
189  c = getchar();
190  }
191  else {
192  x = (currentgraph->absolute.width -
193  strlen(text1)*currentgraph->fontwidth)/2;
194  if (x < 0) x = 0;
196  DevSetColor(8);
197  DevText(text1,x,y);
198  request.option = char_option;
199  request.fp = (FILE*)0;
200  DevInput(&request, &response);
201  c = response.reply.ch;
202  DevSetColor(0);
203  DevBox(x,y,x + strlen(text1)*currentgraph->fontwidth,
204  y + currentgraph->fontheight);
205  DevUpdate();
206  }
207  if (c == 'p') {
208  ft_hardcopy(NULL,currentgraph,true,NULL,false);
209  }
210  }
211 }
212 
213 
214 void
215 plottrace(v, xs, plotno)
216 
217 struct dvec *v, *xs;
218 int plotno;
219 {
220  int i, blsize, nblks, size, len;
221  char *sdata, *vdata;
222 
223  /* Take care of multi-dimensional vectors here. We know that the
224  * vectors have been coerced to the same data length. The scale
225  * sets the block length, and we plot according to the dimensionality
226  * of the vector, block by block.
227  */
228 
229  if (!xs || xs->v_numdims <= 1) {
230  /* if the scale has unit dimension, ignore dimensionality
231  * of vector.
232  */
233  do_plot_trace(v,xs,plotno);
234  return;
235  }
236 
237  blsize = xs->v_dims[xs->v_numdims-1];
238  nblks = 1;
239  for (i = 0; i < v->v_numdims - 1; i++)
240  nblks *= v->v_dims[i];
241 
242  sdata = (isreal(xs) ? (char*)xs->v_realdata : (char*)xs->v_compdata);
243  vdata = (isreal(v) ? (char*)v->v_realdata : (char*)v->v_compdata);
244  len = xs->v_length;
245  xs->v_length = blsize;
246  v->v_length = blsize;
247 
248  size = 0;
249  for (i = 0; i < nblks; i++) {
250  size += blsize;
251  if (size > len) {
252  /* unfinished block */
253  blsize = len - (size - blsize);
254  xs->v_length = blsize;
255  v->v_length = blsize;
256  do_plot_trace(v,xs,plotno);
257  break;
258  }
259  do_plot_trace(v,xs,plotno);
260 
261  if (isreal(xs))
262  xs->v_realdata += blsize;
263  else
264  xs->v_compdata += blsize;
265  if (isreal(v))
266  v->v_realdata += blsize;
267  else
268  v->v_compdata += blsize;
269  }
270  xs->v_length = len;
271  if (isreal(xs))
272  xs->v_realdata = (double*) sdata;
273  else
274  xs->v_compdata = (complex*) sdata;
275  v->v_length = len;
276  if (isreal(v))
277  v->v_realdata = (double*) vdata;
278  else
279  v->v_compdata = (complex*) vdata;
280 }
281 
282 
283 static void
284 do_plot_trace(v, xs, plotno)
285 
286 /* Plot the vector v, with scale xs. If we are doing curve-fitting, then
287  * do some tricky stuff.
288  */
289 struct dvec *v, *xs;
290 int plotno;
291 {
292  int degree, gridsize, length;
293  int i, j, l;
294  double *scratch, *result, *gridbuf, *mm;
295  double *xdata, *ydata;
296  bool rot, increasing;
297  double dx, dy, lx = 0, ly = 0;
298  extern char *kw_gridsize;
299 
300  degree = currentgraph->degree;
301 
302  drawlegend(plotno, v);
303 
304  if (degree > v->v_length)
305  degree = v->v_length;
306  if (degree < 1) {
307  fprintf(cp_err, "Error: polydegree is %d, can't plot...\n",
308  degree);
309  return;
310  }
311 
312  if (!cp_getvar(kw_gridsize, VT_NUM, (char *) &gridsize))
313  gridsize = 0;
314  if ((gridsize < 0) || (gridsize > 10000)) {
315  fprintf(cp_err, "Error: bad grid size %d\n", gridsize);
316  return;
317  }
318  if (gridsize && xs) {
319  if (isreal(xs)) {
320  increasing = (xs->v_realdata[0] < xs->v_realdata[1]);
321  for (i = 0; i < xs->v_length - 1; i++)
322  if (increasing != (xs->v_realdata[i] <
323  xs->v_realdata[i + 1])) {
324  fprintf(cp_err,
325  "Warning: scale not monotonic, gridsize not relevant.\n");
326  gridsize = 0;
327  break;
328  }
329  }
330  else {
331  increasing = (realpart (&xs->v_compdata[0]) <
332  realpart( &xs->v_compdata[1]));
333  for (i = 0; i < xs->v_length - 1; i++)
334  if (increasing != (realpart( &xs->v_compdata[i]) <
335  realpart( &xs->v_compdata[i + 1]))) {
336  fprintf(cp_err,
337  "Warning: scale not monotonic, gridsize not relevant.\n");
338  gridsize = 0;
339  break;
340  }
341  }
342  }
343 
344  /* Do the one value case */
345 
346  if (!xs) {
347  for (i = 0; i < v->v_length; i++) {
348 
349  /* We should do the one - point case too!
350  * Important for polar plots of pole-zero for example
351  */
352  if (v->v_length == 1) {
353  j = 0;
354  }
355  else {
356  j = i-1;
357  if (i == 0)
358  continue;
359  }
360 
361  if (isreal(v)) {
362  gr_point(v, v->v_realdata[i],
363  0.0,
364  v->v_realdata[j],
365  0.0, (j==i ? 1 : i));
366  }
367  else {
368  gr_point(v, realpart(&v->v_compdata[i]),
369  imagpart(&v->v_compdata[i]),
370  realpart(&v->v_compdata[j]),
371  imagpart(&v->v_compdata[j]), (j==i ? 1 : i));
372  }
373  }
374  DevUpdate();
375  return;
376  }
377 
378  xs->v_flags |= VF_PERMANENT;
379 
380  /* First check the simple case, where we don't have to do any
381  * interpolation.
382  */
383  if ((degree == 1) && (gridsize == 0)) {
384  for (i = 0, j = v->v_length; i < j; i++) {
385  dx = isreal(xs) ? xs->v_realdata[i] :
386  realpart(&xs->v_compdata[i]);
387  dy = isreal(v) ? v->v_realdata[i] :
388  realpart(&v->v_compdata[i]);
389  gr_point(v, dx, dy, lx, ly, i);
390  lx = dx;
391  ly = dy;
392  }
393  if (v->v_length == 1)
394  gr_point(v, dx, dy, lx, ly, 1);
395  DevUpdate();
396  return;
397  }
398 
399  if (gridsize < degree + 1)
400  gridsize = 0;
401 
402  if (gridsize) {
403  /* This is done quite differently from what we do below... */
404  gridbuf = (double *) tmalloc(gridsize * sizeof (double));
405  result = (double *) tmalloc(gridsize * sizeof (double));
406  if (isreal(v))
407  ydata = v->v_realdata;
408  else {
409  ydata = (double *) tmalloc(v->v_length *
410  sizeof (double));
411  for (i = 0; i < v->v_length; i++)
412  ydata[i] = realpart(&v->v_compdata[i]);
413  }
414  if (isreal(xs))
415  xdata = xs->v_realdata;
416  else {
417  xdata = (double *) tmalloc(xs->v_length *
418  sizeof (double));
419  for (i = 0; i < xs->v_length; i++)
420  xdata[i] = realpart(&xs->v_compdata[i]);
421  }
422 
423  mm = ft_minmax(xs, true);
424  dx = (mm[1] - mm[0]) / gridsize;
425  if (increasing)
426  for (i = 0, dy = mm[0]; i < gridsize; i++, dy += dx)
427  gridbuf[i] = dy;
428  else
429  for (i = 0, dy = mm[1]; i < gridsize; i++, dy -= dx)
430  gridbuf[i] = dy;
431  if (!ft_interpolate(ydata, result, xdata, v->v_length, gridbuf,
432  gridsize, degree)) {
433  fprintf(cp_err, "Error: can't put %s on gridsize %d\n",
434  v->v_name, gridsize);
435  return;
436  }
437  /* Now this is a problem. There's no way that we can
438  * figure out where to put the tic marks to correspond with
439  * the actual data...
440  */
441  for (i = 0; i < gridsize; i++)
442  gr_point(v, gridbuf[i], result[i], gridbuf[i ? (i - 1)
443  : i], result[i ? (i - 1) : i], -1);
444  DevUpdate();
445  tfree(gridbuf);
446  tfree(result);
447  if (!isreal(v))
448  tfree(ydata);
449  if (!isreal(xs))
450  tfree(xdata);
451  return;
452  }
453 
454  /* We need to do curve fitting now. First get some scratch
455  * space
456  */
457  scratch = (double *) tmalloc((degree + 1) * (degree + 2) *
458  sizeof (double));
459  result = (double *) tmalloc((degree + 1) * sizeof (double));
460  xdata = (double *) tmalloc((degree + 1) * sizeof (double));
461  ydata = (double *) tmalloc((degree + 1) * sizeof (double));
462 
463 
464  /* Plot the first degree segments... */
465  if (isreal(v)) {
466  DCOPY(v->v_realdata, ydata, degree + 1);
467  }
468  else
469  for (i = 0; i <= degree; i++)
470  ydata[i] = realpart(&v->v_compdata[i]);
471  if (isreal(xs)) {
472  DCOPY(xs->v_realdata, xdata, degree + 1);
473  }
474  else
475  for (i = 0; i <= degree; i++)
476  xdata[i] = realpart(&xs->v_compdata[i]);
477 
478  rot = false;
479  while (!ft_polyfit(xdata, ydata, result, degree, scratch)) {
480  /* Rotate the coordinate system 90 degrees and try again.
481  * If it doesn't work this time, bump the interpolation
482  * degree down by one...
483  */
484  if (ft_polyfit(ydata, xdata, result, degree, scratch)) {
485  rot = true;
486  break;
487  }
488  if (--degree == 0) {
489  fprintf(cp_err, "plotcurve: Internal Error: ack...\n");
490  return;
491  }
492  }
493 
494  /* Plot this part of the curve... */
495  for (i = 0; i < degree; i++)
496  if (rot)
497  plotinterval(v, ydata[i], ydata[i + 1], result, degree,
498  true);
499  else
500  plotinterval(v, xdata[i], xdata[i + 1], result, degree,
501  false);
502 
503  /* Now plot the rest, piece by piece... l is the
504  * last element under consideration.
505  */
506  length = v->v_length;
507  for (l = degree + 1; l < length; l++) {
508 
509  /* Shift the old stuff by one and get another value. */
510  for (i = 0; i < degree; i++) {
511  xdata[i] = xdata[i + 1];
512  ydata[i] = ydata[i + 1];
513  }
514  if (isreal(v))
515  ydata[i] = v->v_realdata[l];
516  else
517  ydata[i] = realpart(&v->v_compdata[l]);
518  if (isreal(xs))
519  xdata[i] = xs->v_realdata[l];
520  else
521  xdata[i] = realpart(&xs->v_compdata[l]);
522 
523  rot = false;
524  while (!ft_polyfit(xdata, ydata, result, degree, scratch)) {
525  if (ft_polyfit(ydata, xdata, result, degree, scratch)) {
526  rot = true;
527  break;
528  }
529  if (--degree == 0) {
530  fprintf(cp_err,
531  "plotcurve: Internal Error: ack...\n");
532  return;
533  }
534  }
535  if (rot)
536  plotinterval(v, ydata[degree - 1], ydata[degree],
537  result, degree, true);
538  else
539  plotinterval(v, xdata[degree - 1], xdata[degree],
540  result, degree, false);
541  }
542  tfree(scratch);
543  tfree(xdata);
544  tfree(ydata);
545  tfree(result);
546  DevUpdate();
547  return;
548 }
549 
550 
551 #define GRANULARITY 10
552 
553 static void
554 plotinterval(v, lo, hi, coeffs, degree, rotated)
555 
556 struct dvec *v;
557 double lo, hi;
558 double *coeffs;
559 int degree;
560 bool rotated;
561 {
562  double incr, dx, dy, lx, ly;
563  register int i;
564  int steps;
565  extern char *kw_polysteps;
566 
567  /*
568  fprintf(cp_err, "plotinterval(%s, %G, %G, [ ", v->v_name, lo, hi);
569  for (i = 0; i <= degree; i++)
570  fprintf(cp_err, "%G ", coeffs[i]);
571  fprintf(cp_err, "], %d, %s)\n\r", degree, rotated ? "true" : "false");
572  */
573 
574  /* This is a problem -- how do we know what granularity to use? If
575  * the guy cares about this he will use gridsize.
576  */
577  if (!cp_getvar(kw_polysteps, VT_NUM, (char *) &steps))
578  steps = GRANULARITY;
579 
580  incr = (hi - lo) / (double) (steps + 1);
581  dx = lo + incr;
582  lx = lo;
583  ly = ft_peval(lo, coeffs, degree);
584  for (i = 0; i <= steps; i++, dx += incr) {
585  dy = ft_peval(dx, coeffs, degree);
586  if (rotated)
587  gr_point(v, dy, dx, ly, lx, -1);
588  else
589  gr_point(v, dx, dy, lx, ly, -1);
590  lx = dx;
591  ly = dy;
592  /* fprintf(cp_err, "plot (%G, %G)\n\r", dx, dy); */
593  }
594  return;
595 }
596 
597 
598 void
599 gr_point(dv, newx, newy, oldx, oldy, np)
600 
601 /*
602  * Add a point to the curve we're currently drawing.
603  */
604 struct dvec *dv;
605 double newx, newy, oldx, oldy;
606 int np;
607 {
608  int oldtox, oldtoy; /* value before clipping */
609 
610  char pointc[2];
611 
612  int fromx, fromy, tox, toy;
613  int ymin, dummy;
614 
615  /* If it's a linear plot, ignore first point since we don't want
616  to connect with oldx and oldy. */
617  if (dv->v_plottype == PLOT_LIN && !np) return;
618 
619  DevDatatoScreen(currentgraph, oldx, oldy, &fromx, &fromy);
620  DevDatatoScreen(currentgraph, newx, newy, &tox, &toy);
621 
622 /* note: we do not particularly want to clip here */
623  oldtox = tox; oldtoy = toy;
624  if (!currentgraph->grid.circular) {
625  if (clip_line(&fromx, &fromy, &tox, &toy,
629  return;
630  }
631  else {
632  if (clip_to_circle(&fromx, &fromy, &tox, &toy,
633  currentgraph->grid.xaxis.circular.center,
634  currentgraph->grid.yaxis.circular.center,
635  currentgraph->grid.xaxis.circular.radius))
636  return;
637  }
638 
639  if (currentgraph->plottype != PLOT_POINT) {
640  DevSetLinestyle(dv->v_linestyle);
641  }
642  else {
643  /* if PLOT_POINT,
644  don't want to plot an endpoint which have been clipped */
645  if (tox != oldtox || toy != oldtoy)
646  return;
647  }
648  DevSetColor(dv->v_color);
649 
650  switch (currentgraph->plottype) {
651  case PLOT_LIN:
652  DevLine(fromx, fromy, tox, toy);
653  if ((currentgraph->ticmarks >0) && (np > -1)
654  && (np % currentgraph->ticmarks == 0)) {
655  /* Draw an 'x' */
656  DevText("x", (int) (tox - currentgraph->fontwidth / 2),
657  (int) (toy - currentgraph->fontheight / 2));
658  SaveText(currentgraph, "x",
659  (int) (tox - currentgraph->fontwidth / 2),
660  (int) (toy - currentgraph->fontheight / 2));
661  }
662  break;
663  case PLOT_COMB:
665  (double) 0, currentgraph->datawindow.ymin,
666  &dummy, &ymin);
667  DevLine(tox, ymin, tox, toy);
668  break;
669  case PLOT_POINT:
670  /* Here, gi_linestyle is the character used for the point. */
671  pointc[0] = dv->v_linestyle;
672  pointc[1] = '\0';
673  DevText(pointc, (int) (tox - currentgraph->fontwidth / 2),
674  (int) (toy - currentgraph->fontheight / 2));
675  /* redraw will redraw this w/o our having to save it */
676  /* SaveText(currentgraph, pointc,
677  (int) (tox - currentgraph->fontwidth / 2),
678  (int) (toy - currentgraph->fontheight / 2)); */
679  default:
680  break;
681  }
682 }
683 
684 
685 static GRDATA
687 
688 /* copy dvecs */
689 GRDATA linkp;
690 {
691 
692  struct dvlist *dl, *dn;
693  struct dvec *new;
694 
695  if (linkp == NULL)
696  return (NULL);
697 
698  dl = (struct dvlist*)linkp;
699  dn = alloc(struct dvlist);
700  linkp = (GRDATA)dn;
701 
702  for ( ; dl; dl = dl->dl_next) {
703 
704  /* the copy is not linked into any plot */
705  new = vec_copy(dl->dl_dvec);
706  /* vec_copy doesn't set v_color or v_linestyle */
707  new->v_color = dl->dl_dvec->v_color;
708  new->v_linestyle = dl->dl_dvec->v_linestyle;
709  if (new->v_scale)
710  new->v_scale = vec_copy(new->v_scale);
711  dn->dl_dvec = new;
712  if (dl->dl_next) {
713  dn->dl_next = alloc(struct dvlist);
714  dn = dn->dl_next;
715  }
716  }
717  return (linkp);
718 }
719 
720 
721 static void
723 
724 /* de-allocate dveclist */
725 GRDATA linkp;
726 {
727  struct dvlist *dl, *dn;
728  struct dvec *d;
729 
730  for (dl = (struct dvlist*)linkp; dl; dl = dn) {
731  dn = dl->dl_next;
732  d = dl->dl_dvec;
733  txfree(d->v_name);
734  if (isreal(d)) {
735  txfree((char*)d->v_realdata);
736  }
737  else {
738  txfree((char*)d->v_compdata);
739  }
740  if (d->v_scale) {
741  txfree(d->v_scale->v_name);
742  if (isreal(d->v_scale)) {
743  txfree((char*)d->v_scale->v_realdata);
744  }
745  else {
746  txfree((char*)d->v_scale->v_compdata);
747  }
748  txfree((char*)d->v_scale);
749  }
750  txfree((char*)d);
751  txfree((char*)dl);
752  }
753 }
754 
755 
756 static void
758 
759 GRAPH *graph;
760 {
761  char *s;
762  int curlst;
763  int curcolor;
764  int curptchar = 1;
765  struct dvec *v;
766  struct dvlist *dl, *dl0 = (struct dvlist *)graph->plotdata;;
767 
768  if (graph->graphtype != GR_PLOT)
769  return;
770 
771  /* Set up colors and line styles. */
772  if (dispdev->numlinestyles == 1)
773  curlst = 0; /* Use the same one all the time. */
774  else
775  curlst = 1;
776  if (dispdev->numcolors > 2)
777  curcolor = (graph->grid.gridtype == GRID_SMITH) ? 3 : 1;
778  else
779  curcolor = 1;
780 
781  for (dl = dl0; dl; dl = dl->dl_next) {
782  v = dl->dl_dvec;
783 
784  /* Do something special with poles and zeros. Poles are 'x's, and
785  * zeros are 'o's.
786  */
787  s = ft_typenames(v->v_type);
788  if (eq(s, "pole")) {
789  v->v_linestyle = 'x';
790  continue;
791  }
792  else if (eq(s, "zero")) {
793  v->v_linestyle = 'o';
794  continue;
795  }
796 
797  /* Find a (hopefully) new line style and color. */
798  if (graph->plottype == PLOT_POINT) {
799  if (pointchars[curptchar + 1])
800  curptchar++;
801  else
802  curptchar = 2;
803  }
804  else if ((curlst > 0) && (++curlst == dispdev->numlinestyles))
805  curlst = 2;
806  if ((curcolor > 0) && (++curcolor == dispdev->numcolors))
807  curcolor = ((graph->grid.gridtype == GRID_SMITH &&
808  (dispdev->numcolors > 3)) ? 4 : 2);
809 
810  if (graph->plottype == PLOT_POINT)
811  v->v_linestyle = pointchars[curptchar];
812  else {
813  if (dispdev->numcolors > 2)
814  /* use solid lines in color */
815  v->v_linestyle = 0;
816  else
817  v->v_linestyle = curlst;
818  }
819  v->v_color = curcolor;
820  }
821 }
822 
823 
824 static void
825 drawlegend(plotno, dv)
826 
827 int plotno;
828 struct dvec *dv;
829 {
830 
831  int x, y, i;
832  char buf[16];
833 
834  x = ((plotno % 2) ? (currentgraph->viewport.width / 2) :
837  - ((plotno + 2) / 2) * (currentgraph->fontheight);
838  i = y + currentgraph->fontheight / 2 + 1;
839  DevSetColor(dv->v_color);
840  if (currentgraph->plottype == PLOT_POINT) {
841  (void) sprintf(buf, "%c : ", dv->v_linestyle);
842  DevText(buf, x + currentgraph->viewport.width / 20
843  - 3 * currentgraph->fontwidth, y);
844  }
845  else {
847  DevLine(x, i, x + currentgraph->viewport.width / 20, i);
848  }
849  DevSetColor(1);
850  DevText(dv->v_name, x + currentgraph->viewport.width / 20
851  + currentgraph->fontwidth, y);
852 }
853 
854 
855 static void
857 
858 /* call this routine after viewport size changes */
859 GRAPH *graph;
860 {
861 
862  double oldxratio, oldyratio;
863  double scalex, scaley;
864  struct _keyed *k;
865 
866  oldxratio = graph->aspectratiox;
867  oldyratio = graph->aspectratioy;
868  graph->viewportxoff = graph->fontwidth * 8; /* 8 lines on left */
869  graph->viewportyoff = graph->fontheight * 4; /* 4 on bottom */
870 
871  graph->viewport.width = graph->absolute.width -
872  2 * graph->viewportxoff;
873  graph->viewport.height = graph->absolute.height -
874  2 * graph->viewportyoff;
875 
876  /* shrink datawindow slightly to avoid numerical strangeness */
877  if (graph->grid.gridtype != GRID_LOGLOG &&
878  graph->grid.gridtype != GRID_XLOG &&
879  graph->grid.gridtype != GRID_SMITH) {
880  scalex = 1e-3*(graph->datawindow.xmax - graph->datawindow.xmin);
881  graph->datawindow.xmin += scalex;
882  graph->datawindow.xmax -= scalex;
883  }
884  if (graph->grid.gridtype != GRID_LOGLOG &&
885  graph->grid.gridtype != GRID_YLOG &&
886  graph->grid.gridtype != GRID_SMITH) {
887  scaley = 1e-3*(graph->datawindow.ymax - graph->datawindow.ymin);
888  graph->datawindow.ymin += scaley;
889  graph->datawindow.ymax -= scaley;
890  }
891 
892  gr_fixgrid(graph, graph->grid.xdelta, graph->grid.ydelta,
893  graph->grid.xdatatype, graph->grid.ydatatype);
894 
895  /* cache width and height info to make DevDatatoScreen go fast */
896  /* note: XXX see if this is actually used anywhere */
897  graph->datawindow.width = graph->datawindow.xmax -
898  graph->datawindow.xmin;
899  graph->datawindow.height = graph->datawindow.ymax -
900  graph->datawindow.ymin;
901 
902  /* cache (datawindow size) / (viewport size) */
903  graph->aspectratiox = graph->datawindow.width / graph->viewport.width;
904  graph->aspectratioy = graph->datawindow.height / graph->viewport.height;
905 
906  /* scale keyed text */
907  scalex = oldxratio / graph->aspectratiox;
908  scaley = oldyratio / graph->aspectratioy;
909  for (k = graph->keyed; k; k = k->next) {
910  k->x = (k->x - graph->viewportxoff) * scalex + graph->viewportxoff;
911  k->y = (k->y - graph->viewportyoff) * scaley + graph->viewportyoff;
912  }
913 }
914 
915 
916 static void
918 
919 /* redraw everything in struct graph */
920 GRAPH *graph;
921 {
922  struct dvlist *link;
923  int plotno;
924 
925  /* establish current graph so default graphic calls will work right */
926  PushGraphContext(graph);
927 
928  DevClear();
929 
930  resize(graph);
931 
932  /* redraw grid */
933  gr_redrawgrid(graph);
934 
935  for (link = (struct dvlist*)graph->plotdata, plotno = 0; link;
936  link = link->dl_next, plotno++) {
937 
938  /* replot data
939  * if onevalue, pass it a NULL scale
940  * otherwise, if vec has its own scale, pass that
941  * else pass vec's plot's scale
942  */
943  plottrace(link->dl_dvec,
944  graph->onevalue ? (struct dvec *) NULL :
945  (link->dl_dvec->v_scale ?
946  link->dl_dvec->v_scale :
947  link->dl_dvec->v_plot->pl_scale), plotno);
948  }
949 
950  restoretext(graph);
951 
952  PopGraphContext();
953 }
954 
955 
956 static void
958 GRAPH *graph;
959 {
960  struct _keyed *k;
961 
962  /* restore text */
963  for (k = graph->keyed; k; k = k->next) {
964  DevSetColor(k->colorindex);
965  DevText(k->text, k->x, k->y);
966  }
967 }
char * kw_device
Definition: options.c:351
static char buf[MAXPROMPT]
Definition: arg.c:18
static void plotinterval()
static void restoretext()
#define BSIZE_SP
Definition: misc.h:19
#define eq(a, b)
Definition: misc.h:29
static void resize()
void DevDatatoScreen()
#define DEFPOINTCHARS
Definition: graf.c:20
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
char * kw_ticmarks
Definition: options.c:424
PLOTTYPE plottype
Definition: plotdefs.h:38
int xdatatype
Definition: ftegraph.h:104
char * GRDATA
Definition: ftegraph.h:26
struct graph::@2 absolute
void gr_end()
Definition: graf.c:168
FILE * fp
Definition: ftegraph.h:188
#define prefix(x, y)
Definition: readhelp.c:39
char * strcpy()
Definition: cddefs.h:119
OPTION option
Definition: ftegraph.h:187
void DevSetColor()
if(TDesc==NULL)
Definition: cd.c:1326
int numlinestyles
Definition: plotdev.h:67
static void dummy()
Definition: mfbcursr.c:550
Definition: ftedata.h:49
double aspectratiox
Definition: ftegraph.h:79
void DevText()
double ft_peval()
internalerror(char *message)
Definition: error.c:91
DISPDEVICE * dispdev
Definition: display.c:112
char * kw_gridsize
Definition: options.c:358
double ymin
Definition: ftegraph.h:58
union graph::@4::@7 yaxis
char * ylabel
Definition: plotdefs.h:40
char * kw_pointchars
Definition: options.c:403
double * ylims
Definition: plotdefs.h:30
char * plotname
Definition: plotdefs.h:32
bool ft_polyfit()
Definition: cpstd.h:29
static double e
Definition: vectors.c:17
int height
Definition: ftegraph.h:45
bool hardcopy
Definition: plotdev.h:64
static void drawlegend()
void DevSetLinestyle()
int degree
Definition: ftegraph.h:39
bool ft_interpolate()
struct graph::@3 datawindow
Definition: cddefs.h:312
GRDATA(* copydata)()
Definition: ftegraph.h:72
#define VF_PERMANENT
Definition: fteconst.h:46
double xdelta
Definition: plotdefs.h:35
int DevNewViewport()
int viewportyoff
Definition: ftegraph.h:48
int ch
Definition: ftegraph.h:196
void DevClear()
Definition: display.c:234
#define alloc(type)
Definition: cdmacs.h:21
double xdelta
Definition: ftegraph.h:105
complex * v_compdata
Definition: ftedata.h:29
#define DCOPY(s, d, n)
Definition: ftedefs.h:55
static void do_plot_trace()
char * copy()
union response::@11 reply
struct dvlist * dl_next
Definition: ftedata.h:51
FILE * cp_err
Definition: help.c:101
GRIDTYPE gridtype
Definition: plotdefs.h:37
bool windows
Definition: plotdev.h:61
void gr_point(struct dvec *dv, double newx, double newy, double oldx, double oldy, int np)
Definition: graf.c:599
char * tmalloc()
int v_linestyle
Definition: ftedata.h:37
void SaveText()
void DevBox()
int fontwidth
Definition: ftegraph.h:82
static void redraw()
Definition: cddefs.h:237
#define tfree(x)
Definition: cdmacs.h:22
void txfree()
struct dvec * pl_scale
Definition: ftedata.h:68
void PushGraphContext()
#define NULL
Definition: spdefs.h:121
int graphtype
Definition: ftegraph.h:31
char * xname
Definition: plotdefs.h:31
int graphid
Definition: ftegraph.h:30
bool clip_to_circle()
GRDATA plotdata
Definition: ftegraph.h:33
#define VT_NUM
Definition: cpstd.h:61
struct plot * v_plot
Definition: ftedata.h:42
static GRDATA copydveclist()
int viewportxoff
Definition: ftegraph.h:47
struct dvec * v_scale
Definition: ftedata.h:45
Definition: ftegraph.h:29
static void freedveclist()
void DevLine()
int fontheight
Definition: ftegraph.h:82
static int steps
Definition: breakp.c:40
static double c
Definition: vectors.c:16
#define VT_STRING
Definition: cpstd.h:63
#define isreal(v)
Definition: ftedata.h:54
Definition: ftedata.h:24
struct dvec * dl_dvec
Definition: ftedata.h:50
double * xlims
Definition: plotdefs.h:29
char * v_name
Definition: ftedata.h:25
#define imagpart(cval)
Definition: cpstd.h:36
char * pname
Definition: plotdefs.h:43
GRAPH * gr_init(struct dvlist *dl0, char *grp)
Definition: graf.c:49
#define VT_BOOL
Definition: cpstd.h:60
char * hcopy
Definition: plotdefs.h:33
char * ft_typenames()
int ydatatype
Definition: ftegraph.h:104
#define GRANULARITY
Definition: graf.c:551
GRIDTYPE gridtype
Definition: ftegraph.h:86
union graph::@4::@7 xaxis
void DevUpdate()
Definition: display.c:359
char * xlabel
Definition: ftegraph.h:106
void gr_fixgrid()
char * plotname
Definition: ftegraph.h:35
char * xlabel
Definition: plotdefs.h:39
void(* destroy)()
Definition: ftegraph.h:71
char * devdep
Definition: ftegraph.h:144
int onevalue
Definition: ftegraph.h:36
int circular
Definition: ftegraph.h:87
void PopGraphContext()
Definition: graphdb.c:270
int DestroyGraph()
void DevInput()
int numcolors
Definition: plotdev.h:67
void gr_redrawgrid()
bool clip_line()
double ydelta
Definition: plotdefs.h:36
static char pointchars[128]
Definition: graf.c:19
int v_type
Definition: ftedata.h:26
int ticmarks
Definition: ftegraph.h:81
char * kw_polysteps
Definition: options.c:405
#define GR_PLOT
Definition: ftegraph.h:20
char * commandline
Definition: ftegraph.h:133
static void initdvecs()
PLOTTYPE plottype
Definition: ftegraph.h:84
GRAPH * currentgraph
Definition: graphdb.c:21
int width
Definition: ftegraph.h:45
int v_color
Definition: ftedata.h:38
void(* redraw)()
Definition: ftegraph.h:70
double * ft_minmax()
char * commandline
Definition: plotdefs.h:44
double ydelta
Definition: ftegraph.h:105
double xmax
Definition: ftegraph.h:58
char * ylabel
Definition: ftegraph.h:106
void plottrace()
struct graph::@4 grid
double * v_realdata
Definition: ftedata.h:28
struct graph::@1 viewport
char * kw_polydegree
Definition: options.c:404
double ymax
Definition: ftegraph.h:58
double xmin
Definition: ftegraph.h:58
int xtype
Definition: plotdefs.h:41
struct dvec * vec_copy()
void ft_hardcopy()
int ytype
Definition: plotdefs.h:42
GRAPH * NewGraph()
Definition: graphdb.c:59
#define realpart(cval)
Definition: cpstd.h:35